[
  {
    "path": "01-FE-learning-master/README.md",
    "content": "\n转载请注明出处: [https://github.com/qiu-deqing/FE-learning](https://github.com/qiu-deqing/FE-learning)\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [FE-learning](#fe-learning)\n  - [必备基础技能](#%E5%BF%85%E5%A4%87%E5%9F%BA%E7%A1%80%E6%8A%80%E8%83%BD)\n  - [基本开发工具](#%E5%9F%BA%E6%9C%AC%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7)\n  - [学习方法和学习目标](#%E5%AD%A6%E4%B9%A0%E6%96%B9%E6%B3%95%E5%92%8C%E5%AD%A6%E4%B9%A0%E7%9B%AE%E6%A0%87)\n  - [入门之路](#%E5%85%A5%E9%97%A8%E4%B9%8B%E8%B7%AF)\n  - [继续提高](#%E7%BB%A7%E7%BB%AD%E6%8F%90%E9%AB%98)\n  - [一些个人经历](#%E4%B8%80%E4%BA%9B%E4%B8%AA%E4%BA%BA%E7%BB%8F%E5%8E%86)\n    - [[LingyuCoder](https://github.com/LingyuCoder)的学习经历](#lingyucoderhttpsgithubcomlingyucoder%E7%9A%84%E5%AD%A6%E4%B9%A0%E7%BB%8F%E5%8E%86)\n      - [工具](#%E5%B7%A5%E5%85%B7)\n      - [技能](#%E6%8A%80%E8%83%BD)\n        - [语言基础](#%E8%AF%AD%E8%A8%80%E5%9F%BA%E7%A1%80)\n        - [进阶](#%E8%BF%9B%E9%98%B6)\n        - [项目](#%E9%A1%B9%E7%9B%AE)\n        - [未来](#%E6%9C%AA%E6%9D%A5)\n        - [其他](#%E5%85%B6%E4%BB%96)\n      - [入门书](#%E5%85%A5%E9%97%A8%E4%B9%A6)\n      - [一些不错的网站](#%E4%B8%80%E4%BA%9B%E4%B8%8D%E9%94%99%E7%9A%84%E7%BD%91%E7%AB%99)\n      - [历程](#%E5%8E%86%E7%A8%8B)\n    - [[MrRaindrop](https://github.com/MrRaindrop)的学习经历](#mrraindrophttpsgithubcommrraindrop%E7%9A%84%E5%AD%A6%E4%B9%A0%E7%BB%8F%E5%8E%86)\n      - [缘起](#%E7%BC%98%E8%B5%B7)\n      - [项目，下一个项目](#%E9%A1%B9%E7%9B%AE%EF%BC%8C%E4%B8%8B%E4%B8%80%E4%B8%AA%E9%A1%B9%E7%9B%AE)\n      - [收集癖和知识管理](#%E6%94%B6%E9%9B%86%E7%99%96%E5%92%8C%E7%9F%A5%E8%AF%86%E7%AE%A1%E7%90%86)\n      - [跟对神](#%E8%B7%9F%E5%AF%B9%E7%A5%9E)\n      - [读书](#%E8%AF%BB%E4%B9%A6)\n      - [前端的定位](#%E5%89%8D%E7%AB%AF%E7%9A%84%E5%AE%9A%E4%BD%8D)\n      - [最后](#%E6%9C%80%E5%90%8E)\n    - [byr论坛yiyizym的建议](#byr%E8%AE%BA%E5%9D%9Byiyizym%E7%9A%84%E5%BB%BA%E8%AE%AE)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n# FE-learning\n\n![FE](./img/FE.jpg)\n\n结合个人经历总结的前端入门方法，总结从零基础到具备前端基本技能的道路、学习方法、资料。由于能力有限，不能保证面面俱到，只是作为入门参考，面向初学者，让初学者少走弯路。\n\n互联网的快速发展和激烈竞争，用户体验成为一个重要的关注点，导致专业前端工程师成为热门职业，各大公司对前端工程师的需求量都很大，要求也越来越高，优秀的前端工程师更是稀缺。个人感觉前端入门相对容易，但是也需要系统地认真学习，在打好基础后坚持学习，成为优秀前端工程师也只是时间问题。\n\n学习任何知识最重要的都是**兴趣**，如果经过一段时间的学习感觉不喜欢，那可能强迫自己学习是很痛苦的，效果也不会好，毕竟这很可能就是以后很多年生存的技能。不过随着互联网行业的发展，前端必然是Web开发人员需要学习的知识，有时候是没有专业前端工程师一起合作的，所以即使不做专门的前端工程师，掌握基本的前端技能为工作带来方便。\n\n后期邀请了一些同学分享学习经历。如果有同学愿意分享,欢迎push\n\n## 必备基础技能\n\n[前端技能汇总](https://github.com/JacksonTian/fks)这个项目详细记录\n了前端工程师牵涉到的各方面知识。在具备基本技能之后可以在里面找到学习\n的方向，完善技能和知识面。\n\n[frontend-dev-bookmarks](https://github.com/dypsilon/frontend-dev-bookmarks)是老外总结的前端开发资源。覆盖面非常广。包括各种知识点、工具、技术，非常全面。\n\n以下是个人觉得入门阶段应该熟练掌握的基础技能：\n\n- [HTML4](http://www.w3.org/TR/html401/cover.html#minitoc)，[HTML5](http://www.w3.org/TR/html5/#contents)语法、标签、语义\n- [CSS2.1](http://www.w3.org/TR/CSS2/#minitoc)，[CSS3](http://www.w3.org/TR/2001/WD-css3-roadmap-20010523/#table)规范，与HTML结合实现各种布局、效果\n- [Ecma-262](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf)定义的javascript的语言核心，原生[客户端javascript](https://developer.mozilla.org/en-US/docs/Web/API)，[DOM操作](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)，[HTML5新增功能](https://developer.mozilla.org/en/docs/web/Guide/HTML/HTML5)\n- 一个成熟的客户端javascript库，推荐[jquery](http://jquery.com/)\n- 一门服务器端语言：如果有服务器端开发经验，使用已经会的语言即可，如果没有服务器端开发经验，熟悉Java可以选择Servlet，不熟悉的可以选PHP，能实现简单登陆注册功能就足够支持前端开发了，后续可能需要继续学习，最基本要求是实现简单的功能模拟，\n- [HTTP](http://www.w3.org/Protocols/rfc2616/rfc2616.html)\n\n在掌握以上基础技能之后，工作中遇到需要的技术也能快速学习。\n\n## 基本开发工具\n\n恰当的工具能有效提高学习效率，将重点放在知识本身，在出现问题时能快速定位并\n解决问题，以下是个人觉得必备的前端开发工具：\n\n- **文本编辑器**：推荐[Sublime Text](http://www.sublimetext.com/)，支持各种插件、主题、设置，使用方便\n- **浏览器**：推荐[Google Chrome](http://www.google.cn/chrome/?hl=zh-CN&standalone=1)，更新快，对前端各种标准提供了非常好的支持\n- **调试工具**：推荐Chrome自带的[Chrome develop tools](https://developer.chrome.com/devtools)，可以轻松查看DOM结构、样式，通过控制台输出调试信息，调试javascript，查看网络等\n- **辅助工具**：PhotoShop编辑图片、取色，fireworks量尺寸，AlloyDesigner对比尺寸，以及前面的到的Chrome develop tools，\n- **翻墙工具**：lantern, 壁虎漫步\n\n## 学习方法和学习目标\n\n方法：\n\n1. 入门阶段反复阅读**经典书籍的中文版**，书籍中的每一个例子都动手实现并在浏览器中查看效果\n2. 在具备一定基础之后可以上网搜各种教程、demo，了解各种功能的实际用法和常见功能的实现方法\n3. 阅读HTML，CSS，Javascript标准全面完善知识点\n4. 阅读前端牛人的博客、文章提升对知识的理解\n5. 善用搜索引擎\n\n目标：\n\n1. 熟记前面知识点部分的重要概念，结合学习经历得到自己的理解\n2. 熟悉常见功能的实现方法，如常见CSS布局，Tab控件等。\n\n## 入门之路\n\n以下是入门阶段不错的书籍和资料\n\n1. HTML先看[《HTML & CSS: Design and Build Websites》][]1-9章，然后[《HTML5: The Missing Manual》][]1-4章。\n2. CSS先看[《CSS: The Missing Manual》][]，然后[《CSS权威指南》][]\n3. javascript先看[《javascript高级程序设计》][]，然后[《javascript权威指南》][]\n4. HTTP看[HTTP权威指南][]\n5. 在整个学习过程中HTML CSS JavaScript会有很多地方需要互相结合，实际工作中也是这样，一个简单的功能模块都需要三者结合才能实现。\n6. 动手是学习的重要组成部分，书籍重点讲解知识点，例子可能不是很充足，这就需要利用搜索引擎寻找一些简单教程，照着教程实现功能。以下是一些比较好的教程网址\n    - 可以搜索各大公司前端校招笔试面试题作为练习题或者他人总结的[前端面试题][]还有[个人总结的面试题][]（带参考答案）\n    - <http://code.tutsplus.com>有各种各样的教程\n    - [MDN](https://developer.mozilla.org/en-US/docs/Web)也有很多教程，更重要的是里面有详细的文档，需要查找某个功能时在Google搜索：`xxx site:https://developer.mozilla.org`\n    - <http://www.html5rocks.com/zh/>也有很多优质教程\n    - <http://www.sitepoint.com/>\n    - <http://alistapart.com/>\n7. 原生javascript是需要重点掌握的技能，在掌握原生javascript的基础上推荐熟练掌握jQuery，在实际工作中用处很大，这方面的书籍有[《Learning jQuery》][]或者去[jQuery官网](http://learn.jquery.com/)\n8. 建一个<https://github.com/>账号，保存平时学习中的各种代码和项目。\n9. 有了一定基础之后可以搭建一个个人博客，记录学习过程中遇到的问题和解决方法，方便自己查阅也为其他人提供了帮助。也可以去<http://www.cnblogs.com/>或者<http://www.csdn.net/>这样的网站注册账号，方便实用\n10. 经常实用Google搜索英文资料应该经常找到来自<http://stackoverflow.com/>的高质量答案，与到问题可以直接在这里搜索，如果有精力，注册一个账号为别人解答问题也能极大提高个人能力。\n11. 经典书籍熟读之后，可以打开前面必备基础技能部分的链接。认真读对应标准，全面掌握知识\n\n\n[《HTML & CSS: Design and Build Websites》]: http://www.amazon.cn/gp/product/B00BMK4GKW/ref=s9_simh_gw_p14_d0_i2?pf_rd_m=A1AJ19PSB66TGU&pf_rd_s=center-2&pf_rd_r=1AH2NF64STS19GY8GR54&pf_rd_t=101&pf_rd_p=108773272&pf_rd_i=899254051\n[《HTML5: The Missing Manual》]: http://www.amazon.cn/HTML5%E7%A7%98%E7%B1%8D-Matthew-MacDonald/dp/B009DFCZAQ/ref=sr_1_1?ie=UTF8&qid=1414740812&sr=8-1&keywords=html5+the+missing+manual\n[《CSS: The Missing Manual》]: http://www.amazon.cn/CSS-The-Missing-Manual-Mcfarland-David-Sawyer/dp/0596802447/ref=sr_1_1?ie=UTF8&qid=1414742710&sr=8-1&keywords=css+the+missing+manual+2\n[《CSS权威指南》]: http://www.amazon.cn/CSS%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97-%E8%BF%88%E8%80%B6/dp/B0011F5SIC/ref=sr_1_1?ie=UTF8&qid=1414744248&sr=8-1&keywords=css+%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97\n[《javascript高级程序设计》]: http://www.amazon.cn/JavaScript%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1-%E6%B3%BD%E5%8D%A1%E6%96%AF/dp/B007OQQVMY/ref=sr_1_1?s=books&ie=UTF8&qid=1414744358&sr=1-1&keywords=javascript+%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1\n[《javascript权威指南》]: http://www.amazon.cn/O-Reilly%E7%B2%BE%E5%93%81%E5%9B%BE%E4%B9%A6%E7%B3%BB%E5%88%97-JavaScript%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97-%E5%BC%97%E5%85%B0%E7%BA%B3%E6%A0%B9/dp/B007VISQ1Y/ref=sr_1_1?s=books&ie=UTF8&qid=1414744401&sr=1-1&keywords=javascript+%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97\n[HTTP权威指南]: http://www.amazon.cn/HTTP%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97-%E5%90%89%E5%B0%94%E5%88%A9/dp/B008XFDQ14/ref=sr_1_1?s=books&ie=UTF8&qid=1414744440&sr=1-1&keywords=HTTP+%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97\n[前端面试题]: https://github.com/darcyclarke/Front-end-Developer-Interview-Questions/tree/master/Translations/Chinese\n[个人总结的面试题]: https://github.com/qiu-deqing/FE-interview\n[《Learning jQuery》]: http://www.amazon.com/Learning-jQuery-Fourth-Jonathan-Chaffer/dp/178216314X/ref=sr_1_1?s=books&ie=UTF8&qid=1410099243&sr=1-1&keywords=learning+jquery\n\n\n\n## 继续提高\n\n有了前面的基础之后，前端基本算是入门了，这时候可能每个人心中都有了一些学习方向，如果还是没有。\n可以参考前面必备技能部分提到的那两个项目，从里面选一些进行发展学习。以下是一些不错的方面：\n\n- [Grunt](http://gruntjs.com/)：前端自动化工具，提高工作效率\n- [less css](http://lesscss.org/)：优秀的CSS预处理器\n- [bootstrap](http://getbootstrap.com/)：优秀的CSS框架，对没有设计师的团队很不错，与less结合使用效果完美\n- [requirejs](http://requirejs.org/)：AMD规范的模块加载器，前端模块化趋势的必备工具\n- [Node.js](http://nodejs.org/)：JavaScript也可以做后台，前端工程师地位更上一步\n- [AngularJS](https://angularjs.org/)：做Single Page Application的好工具\n- [移动端web开发](https://developer.mozilla.org/en-US/docs/Web/Guide/Mobile)：智能手机的普及让移动端的流量正在逐步赶超PC端\n- [Javascript内存管理](https://developer.chrome.com/devtools/docs/javascript-memory-profiling?hl=figoogle)：SPA长期运行需要注意内存泄露的问题\n- [High Performance JavaScript(Build Faster Web Application Interfaces)](http://www.amazon.com/Performance-JavaScript-Faster-Application-Interfaces/dp/059680279X/ref=sr_1_1?s=books&ie=UTF8&qid=undefined&sr=1-1&keywords=high+performance+javascript)\n- [Best Practices for Speeding Up Your Web Site](https://developer.yahoo.com/performance/rules.html)：重要技能\n\n\n## 一些个人经历\n\n\n### [LingyuCoder](https://github.com/LingyuCoder)的学习经历\n\n上面的大神都总结得差不多了，我这里就胡扯一些吧\n\n####工具\n* chrome dev tools：前端开发调试利器，着重注意几个功能：\n    - console（废话）\n    - elements:元素样式调整，很常用\n    - sources：代码中添加断点，单步调试，以及单步调试过程中查看内存中的对象\n        + watch expression：通过表达式查看当前内存中的值\n        + call stack：查看调用栈，开启async，可以看异步调用栈（这个非常有用，尤其是ajax调试的时候）\n        + scope variables：作用域链上的变量，非常有用\n    - network：抓包查看每个请求，非常重要，前后端联调必备\n    - timeline：分析渲染、js执行等等各个阶段，性能优化利器\n    - emulation：模拟移动端环境，mobile页面开发必备\n    - 一些插件:\n        + liveload: 修改页面后自动刷新，不用按F5\n        + dimensions：直接在页面上测量的利器\n        + livestyle：css样式修改后自动起效果，不需要刷新，elements修改后也能同步到代码中\n        + image tool：测量，取色\n        + UC二维码：移动端调试扫码必备\n        + pagespeed，YSlow：页面性能分析和优化插件\n        + 马克飞象：优秀的在线markdown编辑器，快速写周报，做记录\n* sublime text2：编码方便，插件多，速度快，性能好\n    - emmet：提升html编码速度必备\n    - sublimelinter + 各种语言的lint和hint：代码纠错\n    - 一些snippets：自动补全，提升开发效率\n* Intellij IDEA和WebStorm：集成开发环境，集成了各种功能，开发比sublime要方便，但会比较吃性能\n* Mark Men：测量、取色、标注利器，拿到视觉稿之后第一个打开的软件\n* GFW Fucker：我用红杏，可以的话买个虚拟服务器当梯子\n* iHosts：非常优秀的hosts管理软件，轻松修改hosts，开发调试必备\n* Charles：Mac 平台最好用的抓包分析工具\n* Rythem：AlloyTeam出品的代理抓包软件，非常轻量，安装简单，移动端（真机）开发调试很好用\n* Wunderlist：一个非常不错的Todo List，任务、需求多的时候管理起来很方便\n\n####技能\n前端的技能其实除了JavaScript（包括NodeJS）、HTML、CSS以外，还有很多。其实前端的技能树很大，这里只能列一些我开发中见到的说一说\n#####语言基础\nJavaScript：\n* 作用域链、闭包、运行时上下文、this\n* 原型链、继承\n* NodeJS基础和常用API\n\nCSS：\n* 选择器\n* 浏览器兼容性及常见的hack处理\n* CSS布局的方式和原理（盒子模型、BFC、IFC等等）\n* CSS 3，如animation、gradient、等等\n\nHTML：\n* 语义化标签\n\n#####进阶\nJavaScript:\n* 异步控制（Promise、ES6 generator、Async）\n* 模块化的开发方式（AMD、CMD、KMD等等）\n* JavaScript解释器的一些相关知识\n    - 异步IO实现\n    - 垃圾回收\n    - 事件队列\n* 常用框架使用及其原理\n    - jQuery：基于选择器的框架，但个人认为不能叫框架，应该算工具库，因为不具备模块加载机制，其中源码很适合阅读钻研\n    - AngularJS/Avalon等MVVM框架：着重理解MVVM模式本身的理念和双向绑定的实现，如何解耦\n    - underscore：优秀的工具库，方便的理解常用工具代码片段的实现\n    - polymer/React: 组件化开发，面向未来，理解组件化开发的原理\n\nCSS和HTML：主要是CSS3的特性和HTML5的特性，以及浏览器处理的流程和绘制原理\n* DOM树、CSSOM树、渲染树的构建流程及页面渲染的过程\n* 解析HTML、CSS、JavaScript时造成的阻塞\n* HTML5相关\n    - SVG及矢量图原理\n    - Canvas开发及动画原理（帧动画）\n    - Video和Audio\n* flex box布局方式\n* icon fonts的使用\n\n常用NodeJs的package：\n* koa\n* express\n* underscore\n* async\n* gulp\n* grunt\n* connect\n* request\n\n一些理念：\n* 响应式Web\n* 优雅降级、渐进增强\n* don`t make me think\n* 网页可用性、可访问性、其中的意义\n* SEO搜索引擎优化，了解搜索引擎的原理\n* SPA的好处和问题\n\n性能优化：\n* 减少请求数量（sprite、combo）\n* 善用缓存（application cache、http缓存、CDN、localstorage、sessionstorage，备忘录模式）\n* 减少选择器消耗（从右到左），减少DOM操作（DOM和JavaScript解释器的分离）\n* CSS的回流与重绘\n\n#####项目\n* 版本管理：首推Git，用过Git都不会想用SVN了\n    - Git：本地版本管理的机制\n    - SVN：远程中心的版本管理机制\n* 自动化构建：主要就是less、模板、coffee等的预处理以及对代码压缩和合并\n    - Gulp：基于流构建，速度快、模块质量好\n    - Grunt：独立任务构建，速度慢，配置蛋疼，灵活性高\n* 预处理和模板引擎\n    - less：语法简单，但功能有限\n    - jade、ejs、velocity等模板引擎，各有各的长处\n    - coffee：python工程师最爱，我没用过\n* 环境搭建：主要是将线上代码映射到本地，并在本地启动一个demo服务器，至于模拟数据的mock，见仁见智了\n    - 本地代理：ihosts\n* 自动化测试：在业务较为稳定的情况下，可以通过自动化测试来减少测试的事件，但需求较多的时候，维护测试用例的成本会很高，可能用自动化测试会起到反效果\n    - jasmine\n    - mocha\n* 生态系统\n    - npm\n    - bower\n    - spm\n* 搭建一个属于自己的博客\n    - git pages\n    - hexo\n    - jekyll\n\n#####未来\n* Web Componets：面向未来的组件化开发方式\n    - HTML模板\n    - Shadow DOM\n    - Custom Elements\n    - HTML Import\n* 移动端Native开发：这也是需要了解的，以后前端工程师会经常地和webview打交道，也要了解native开发\n\n#####其他\n有些东西不是考敲码就能弄好的，我参与实习的时候感受到了很多，这些是我遇到的也是我感觉自己做的不好的地方\n* **对于业务的思考**：我个人这方面非常欠缺，所以放在最前面，在敲码前要多思考业务\n* 交流和沟通能力：这个非常重要，前端同时需要与项目经理、产品、交互、后台打交道，沟通不善会导致很多无用功，延缓项目\n* 知识管理、时间管理：input和output的平衡，output是最好的input。如何做好分享，参与社区，做好交流，作好记录\n* 对新技术的渴望，以及敢于尝试\n\n####入门书\n入门可以通过啃书，但书本上的东西很多都已经过时了，在啃书的同时，也要持续关注技术的新动态。这里推几本我觉着不错的书：\n\n* 《JavaScript高级编程》：可以作为入门书籍，但同时也是高级书籍，可以快速吸收基础，等到提升再回来重新看\n* 《JavaScript权威指南》：不太适合入门，但是必备，不理解的地方就去查阅一下，很有帮助\n* 《编写可维护的JavaScript》和：\n* 《Node.js开发指南》：不错的Nodejs入门书籍\n* 《深入浅出Node.js》：Nodejs进阶书籍，必备\n* 《JavaScript异步编程》：理解JS异步的编程理念\n* 《JavaScript模式》和《JavaScript设计模式》：JavaScript的代码模式和设计模式，将开发思维转变到JavaScript，非常好的书\n* 《JavaScript框架设计》：在用轮子同时，应当知道轮子是怎么转起来的，讲解很详细，从源码级别讲解框架的各个部分的实现，配合一个现有框架阅读，可以学到很多东西\n* 《Don`t make me think》：网页设计的理念，了解用户行为，非常不错\n* 《CSS禅意花园》：经久不衰的一部著作，同样传递了网页设计中的理念以及设计中需要注意的问题\n* 《高性能JavaScript》和《高性能HTML5》：强调性能的书，其中不只是性能优化，还有很多原理层面的东西值得学习\n* 《HTML5 Canvas核心技术》：我正在读的一本书，对于canvas的使用，动画的实现，以及动画框架的开发都非常有帮助\n* 《HTTP权威指南》：HTTP协议相关必备，前端开发调试的时候也会经常涉及到其中的知识\n* 《响应式Web设计》：技术本身不难，重要的是响应式网页的设计理念，以及移动先行的思想\n* 《JavaScript语言精粹》：老道的书，也是普及JavaScript的开发思维的一本好书，非常适合入门\n\n####一些不错的网站\n* [github](https://github.com)：没啥好说的，多阅读别人的源码，多上传自己的源码，向世界各地的大牛学习\n* [codepen](http://codepen.io/)：感受前端之美的必选之地，里面有很多酷炫的效果和优秀的插件\n* [echojs](http://www.echojs.com/)：快速了解js新资讯的网站\n* [stackoverflow](http://stackoverflow.com/)和[segmentfault](segmentfault.com)：基本上各种问题都能在上面获得解答\n* [google web fundamentals](https://developers.google.com/web/fundamentals/)：每篇文章都适合仔细阅读\n* [static files](http://www.staticfile.org/)：开放的CDN，很好用\n* [iconfont](http://www.iconfont.cn/)：阿里的矢量图标库，非常不错，支持CDN而且支持项目\n* [html5 rocks](http://www.html5rocks.com/): 一个不错的网站，很多浏览器的新特性以及前沿的技术，都能在这上面找到文章\n* [css tricks](http://css-tricks.com/)：如何活用CSS，以及了解CSS新特性，这里可以满足你\n* [JavaScript 秘密花园](http://bonsaiden.github.io/JavaScript-Garden/zh/#object.general) JavaScript初学必看，非常不错\n* [w3cplus](http://www.w3cplus.com/)：一个前端学习的网站，里面的文章质量都挺不错的\n* [node school](http://nodeschool.io/)：一个不错的node学习网站\n* [learn git branch](http://pcottle.github.io/learnGitBranching/?demo)：一个git学习网站，交互很棒\n* [前端乱炖](http://www.html-js.com/)：一个前端文章分享的社区，有很多优秀文章\n* [正则表达式](http://deerchao.net/tutorials/regex/regex.htm)：一个正则表达式入门教程，非常值得一看\n* [阮一峰的博客](http://www.ruanyifeng.com/blog/)和[张鑫旭的博客](http://www.zhangxinxu.com/wordpress/)：快速了解某些知识的捷径，但是如果需要深挖，还需要其他的资源\n* 各路大牛的博客：这个太多了，就不贴了，知乎上有很全的\n* 各种规范的官方网站，不懂得时候读规范\n\n####历程\n以前是做Java SSH的，半路出家做的前端，所以水平比较弱，遇到问题也比较多。基本上入门靠看书和[W3C School](http://www.w3school.com.cn/)上的教程，以及一些前端博客，如[汤姆大叔的博客](http://www.cnblogs.com/TomXu/)。以前也只是使用jQuery，原生js也没有太多的钻研，后来逐渐看了很多本动物书，比如老道的语言精粹等等。从这些书中学到了很多语言层面的知识。但这显然是不够的，所以我经常会去社区上看看大家在谈论什么，然后去看看相关的资料，感兴趣就会多找些资料看看，或者写一写demo。学CSS主要就是通过这种方式。后来开始更多的关注各路大牛的博客和一些比较深的书籍，以及关注一些新的知识和框架，并且不断地练手提交代码到github，这样也学到了很多知识。在实习的过程中，切身参与到实际项目开发之中，能学到很多在学校学不到的理念和思维，这点也有很大的帮助。不说了，我要去搬砖求offer了...\n\n\n### [MrRaindrop](https://github.com/MrRaindrop)的学习经历\n\n应[qiu神][1]的邀请分享一下前端学习经验，这里对前端知识体系架构就不做总结了，各位大神们的总结已经相当到位了，我就贡献几个个人认为还比较有用的链接大家研究研究就好，然后主要分享一下我在前端学习过程中遇到的问题和总结的经验教训吧，如果能帮到想要入门的FE初学者（我就姑且假定为本文的读者受众类型了），让他们少走点弯路，每走一步都知道自己下一步的方向，这是最好了。各位大神的总结和分享详见qiu神整理的[FE-learning][2]。\n\n先说下，前端这个东西每个人都可以有适合自己的学习方法，这篇仅作参考，写的有点乱，各位凑合看。\n\n#### 缘起\n\n我是属于误打误撞进了前端，之前一直往做游戏的方向去来着，搞过游戏网站，玩过游戏引擎，比如unity，unreal这种商业引擎，捣鼓了几个游戏原型，不过自打研一进了实验室，直接就被导师派去写了js，导师给了我半个月时间让我写个基于百度地图api的数据展示页面，虽然这个时间还是相当宽裕的，不过之前没怎么写过js，也不会用地图api，于是我就一边啃着[《Javascript权威指南》][3]（犀牛书）一边参考实验室前人留下的“代码”，总算是把功能都写出来了。那个页面算我的js入门作了，也是我前端学习路线的开始。\n\n> 现在想来，虽然指派了去做前端，但是一直做下去并做好还是得靠兴趣维持，当然前端是一个趣味性十足的技术领域，而且社区每天都很“热闹”。\n\n#### 项目，下一个项目\n\n我个人认为前端的学习，初学阶段你可以完全脱离开书本，以**项目驱动**。虽然我个人是从犀牛书开始啃的，不过如果你没有充足的时间，或者觉得啃大部头乏而无味的话，还是别像我这样。当然了如果决定啃书最好是把书里的例子都跟着敲一遍的。我上研之前没接触过js，4月份还没开学呢就被直接被导师甩了个百度地图api的项目到脸上，接着就是各种ERP，地图数据展示，虽然换着花样来一点不重样，不过基本上都是前端的活，SSH和android开发也打过酱油，整个实验室就我一个人写前端敢信？富客户端SPA时代的后端就是一个restful接口，代码量基本都在前端啊，写的我一个人怎一个爽字了得...期间跟着导师感受了一把创业，每天从7点搞到晚上10点，也算是经历了一段快速成长期。\n\n> 掌握一门技术先掌握它的大体框架，想一个能实现的点子，做一个能跑就行的demo，再去完善它的细节，等到demo完成了，对这门技术有了一个感性的认识，再去啃书，收获会大很多。我从开始原生js写到jquery，再到extjs，再到angularjs，从导师指定技术，到自己做技术选型，一个项目接着一个项目的练，就跟打怪升级似的。当然没有项目就去自己创造项目，动手实现自己的想法是件有乐趣和成就感的事。\n\n#### 收集癖和知识管理\n\n前端学习有个特点，很多东西都很零碎，分散，需要你自己去整理、归纳和总结。在微博、知乎上follow了众多的大神，你不仅仅是为了听八卦，大神们的只言片语有时候留下的是无尽的余味，很有可能一个不经意提到的一个词就成为你下一个学习的目标。**收集这些信息，善用google，提问，思考。**就像游戏里的收集要素，前端学习也是充满搜集要素的一个“游戏”，只不过你需要一个知识管理工具来充当物品栏和仓库，我所知道的大牛们无一不是知识管理工具的重度使用者。以前用的oneNote，那时候还没绑定到云存储，现在基本上用evernote，笔记已经累计到1200+篇。书签一直打算用delicious，因为它是基于tag管理的，但一直没用起来。当然重点不在于这些工具，但是趁手的工具可以提高你的学习效率。最关键当然是随时**保持旺盛的学习欲望**，你的目标是了解有关前端的一切（当然不是所有都要掌握，因为毕竟你的精力有限，而且现实的说这也不太可能）。\n\n#### 跟对神\n\n这个可控性貌似不大...跟对老大这个就不多说了，一定程度要看造化。不过话说回来，多跟身边的高手交流是王道，这个高手不一定要多高，但是一定要对技术有热情。研一的时候热情高涨，每天7点进实验室门，然后发现有个家伙居然比我还早到。后来发现这家伙上午就走了，下午又来了，而且导师对此习以为常，原来这家伙晚上不睡觉通宵写代码，上午才跑回去睡。后来经常和这位神讨论问题，每次感觉经验值蹭蹭蹭的往上涨。然后实验室还有一位神，被前面这位通宵神形容为“只能望其项背，一直在追赶，从来没赶上”，两位神的特点都是什么都了解一点，所以什么都能跟你讨论得起来，我有段时间做了个读书计划，从c/c++到vc/mfc再到unix网络编程，最后一路看到java核心技术和MSDN上的C#编程指南，和神们也能扯得很high了。\n\n> 总之就是这两位神把我拉进了坑，或者说从一个坑跳进另一坑，虽然两位神都不是搞前端的，不过技术之间总有相通之处。\n\n#### 读书\n\n读书，多读书，读好书。在[刘未鹏的博客][4]里看到过一个公式，**你第一个月的工资等于之前买过（读过）的技术书价格总和**（这里说的技术书指那些经典的公认的好书）。讨论这个公式的正确性似乎没什么意义，然而它的合理性是毋庸置疑的，那就是多读经典技术书。最极端的一个例子，google的徐宥在[我的大学][5]里面说他扫荡了图书馆的整个TP312书架...对于前端的经典书籍，后面列了一个我收集的[前端书列][13]（如果有遗漏的前端经典好书，还请留言告诉我），有条件可以尝试刷一遍这些书，我也是在找完整的时间去啃完它们。之前说的，前端知识点松散，收集零散的知识点，从博客里快速学习等，这些只是前端学习的一个方面，如果你要想深入理解一个知识体系，了解它的来龙去脉，对它建立系统认识，读经典书还是必不可少的。\n\n我从最开始啃完犀牛书，然后接着去看了其他一些和前端干系不大的经典技术书，再后来通过实验室的项目和自己弄的一些小项目逐渐对前端领域比较上路以后，又看了《Javascript模式》、《Javascript设计模式》、《编写可维护的Javascript》，后来了解到node并开始用node搞点小玩意儿，又看了本《NodeJS up and run》和《Mongodb权威指南》，不过感觉前者略坑。那会儿朴灵那本深入浅出（晒书么么哒）还没出，后来出了就去图书馆借来看完，这么看下来感觉还不错，不过感觉看的还是偏少了，还需要继续刷（参照上面的书列）。\n\n#### 前端的定位\n\n前端的定位关乎到你需要吸收什么样的知识和技能，决定在技术世界里你对什么需要格外敏感。如果你认为前端仅仅停留在切页面，实现交互和视觉的要求，那你对前端的认识还停留在初级阶段。阿里终面的时候我问了考官这么个问题：前端技术日新月异，范围越扩越宽，标准越来越丰富，似乎任何一个触角都能伸出很远。怎么给前端一个合适的定位？考官给我分析了半天，然后总结成一句话，就是用户和网站的联结者，用户体验的创造者（原话不是这样，但大体是这个意思）。也就是说前端的终极目标其实就是创造用户体验，提升用户体验，**以用户体验为中心**。不管你是从交互设计上下手，还是从性能优化出发，或者改进工作流提升工作流效率，最终都是为了创造和提升用户体验，最终都要体现到用户体验这一点上来。我认为这个总结非常有道理（当然“用户体验”这个词太宽泛了，并且不仅仅是前端工程师的范畴，比如开发后台的时候对一个数据处理过程进行优化，提升了整体性能，这也是对用户体验的一个提升）。\n\n现在的前端工程师做到一定阶段不可避免会接触到很多比切页面、实现视觉要求、实现交互等更深入的问题，比如前端自动化、图像编程、性能优化等等，再往后推一点就是PHP/JSP/ASP/nodeJs，过去后端模板一般属于后端的范畴，现在随着[前端架构的演进][6]，可能会让你去写后端模板的代码，需要用到后端语言（PHP/Java/C#等），这就是所谓**大前端**（然而这与前端的定位并不是相背离的，大前端处理的依然是与用户接触的部分，仍然是对用户体验的优化）。可能最常见或者被谈论最多的就是node，其实这几种技术选型都可以，bat三家据说百度用PHP比较多，阿里用node比较多。\n\n玉伯在[他的博客][7]里提过所谓全端是横向的，全栈是纵向的。**全端**即所有的终端说白了都是前端，因为都关乎到用户体验，直接和用户接触。适应多终端的开发，要求你在web前端的基础上，可能还要去扩展android开发和ios开发的知识，好在由于hybrid开发方式的流行，对使用native语言开发的技能会要求的不那么深入。\n\n**全栈**可以说是最适合初创公司的一种发展类型，广义上认为是从前端干到后端，从开发干到运维，这种就不说了，一般人应该不会想要去往这个方向发展，想要成为这种意义上的full-stack dev的，可能用不着来看我这篇文章了；而狭义上的全栈特指使用js语言从前端写到架设在nodeJs上的后端，前后端统一语言，统一编程模型，甚至公用同一套代码。更多了解全栈开发可以看看玉伯这篇[说说全栈工程师][8]。\n\n以上是我对前端以及衍生出来的技术路线的一些浅薄理解，学习一个领域掌握它的整体上的走向和趋势还是挺重要的。另外如果想要对前端学习方向、职业成长路径有一个整体的认识，推荐看看拔赤总结的这篇[前端开发十日谈][9]。\n\n#### 最后\n\n贡献几个对前端学习、面试有帮助的链接：\n\n* [前端面试问题合集（Front-end-Developer-Interview-Questions）][10]\n* [前端技能汇总（JacksonTian）][11]\n* [另一张前端技能汇总图][12]\n* [前端那点事儿（书列）][13]\n\n[1]: https://github.com/qiu-deqing\n[2]: https://github.com/qiu-deqing/FE-learning\n[3]: http://book.douban.com/subject/2228378/\n[4]: http://mindhacks.cn/topics/learning-method/\n[5]: http://blog.youxu.info/2009/08/06/my-undergraduate-year/\n[6]: https://github.com/lifesinger/lifesinger.github.com/issues/184\n[7]: https://github.com/lifesinger/lifesinger.github.com/labels/blog\n[8]: https://github.com/lifesinger/lifesinger.github.com/issues/185\n[9]: https://github.com/jayli/jayli.github.com/issues/1\n[10]: https://github.com/darcyclarke/Front-end-Developer-Interview-Questions\n[11]: https://github.com/JacksonTian/fks\n[12]: http://www.f2er.info/\n[13]: http://book.douban.com/doulist/13701898/\n\n### byr论坛yiyizym的建议\n\n与grunt相比，学习gulp会比较简单\n\n做SPA的话，推荐backbone.js和 backbone.marionette.js\n\n翻墙不用折腾，花十块钱买一个月的 红杏。\n\n把基础打扎实了再学这些都没问题。\n\nhtml 没什么好说的，有空学学html5。\n\ncss 尽量看[文档](http://www.w3.org/TR/CSS21/cover.html#minitoc) ，因为很多中文资料都各执一辞，看多了反而会糊涂。\n\n有个[网站](http://caniuse.com/)可以查找html/css标签、属性在各个浏览器中的支持情况，挺好用的。\n\njavascript 就看 javascript高级程序设计 。不过这么厚的书看过就会忘。对javascript核心概念的讲解：对象/原型链/         构造函数/执行上下文/作用域链/闭包/this，[这里](http://weizhifeng.net/javascript-the-core.html)有篇不错的文章。\n\n有闲情可以看看 ecmascript 6，计划明年6月就发布啦。[阮一峰的网站](http://es6.ruanyifeng.com/)有入门资料。\n\njquery 有很多 API,[这个网站](http://www.css88.com/jqapi-1.9/)可以方便查到。有时间弄清楚jquery deferred 的用法。\n\n多给 sublimetext 装插件，比如说检查代码错误的，新建目录文件的，整理代码的。\n"
  },
  {
    "path": "02-fedHandlebook-master/README.md",
    "content": "###前端开发者手册\n\n这是任何人都可以用来学习前端的实践手册, 它概述并讨论了前端工程的实践: 该如何学习以及实践时该使用什么工具.\n\n撰写该手册的目的有两个: 一是为潜在以及正在实践的前端开发人员提供一个包括学习资料和开发工具的专业资源; 二是该手册可以被管理者, CTO, 讲师和猎头用来作为洞察前端开发的实践.\n\n该手册的内容支持Web技术(HTML, CSS, DOM, 和 JavaScript), 并且手册提供的解决方案都直接建立在这些开放的技术之上. 手册中所引用的素材和讨论都是最好的或者当前前端开发者们需要面对的问题.\n\n该手册不应该被视为一个前端开发者对所有可用资源的综合大纲, 其价值在于简洁, 专注和及时管理足够的分类信息, 不致于任何人沉浸在任何一个特定的主题.\n\n该手册会每年发布一个更新内容.\n\n该手册分为三个部分:\n\n####第一部分：前端开发实践\n第一部分会大致描述前端工程的实践\n####第二部分：学习前端开发\n第二部分为成为一个前端开发人员确定了自主学习的直接资源\n####第三部分：前端开发工具\n第三部分会简单地讨论一些前端开发工具的使用\n\n---\n\n\n在线阅读: [前端开发者手册](https://dwqs.gitbooks.io/frontenddevhandbook/content/)\n\n资源下载: <a href='http://pan.baidu.com/s/1c0frhIS' target='_blank'>pdf</a>&nbsp;&nbsp;<a href='https://www.gitbook.com/book/dwqs/frontenddevhandbook/details' target='_blank'>mobi</a>\n\nIssues/Suggestions/Fixes: [Front-end Developer Handbook](https://github.com/dwqs/fedHandlebook)\n\n**说明**: 该手册参考 [Front-end Developer Handbook](http://www.frontendhandbook.com/index.html) 电子书所译, 不当之处, 欢迎 [pr](https://github.com/dwqs/fedHandlebook) 或提出 [issue](https://github.com/dwqs/fedHandlebook).\n\n联系译者:\n\n* 博客: <a href='https://github.com/dwqs/blog' target='_blank'>Blog</a>\n* 微博: <a href='http://weibo.com/rebgin' target='_blank'>会飞的Pikachu</a>\n* QQ交流群: [![259280570](http://pub.idqqimg.com/wpa/images/group.png)](http://shang.qq.com/wpa/qunwpa?idkey=457dead858ccbda1b670f91229e334695619cb9f891b433301ac3dd780d1ecaa)\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-nd/3.0/\"><img alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png\" /></a><br />This work is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-nd/3.0/\">Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License</a>\n"
  },
  {
    "path": "02-fedHandlebook-master/SUMMARY.md",
    "content": "# Summary\n\n* [前端开发者手册](README.md)\n* [什么是前端开发者？](what-is-a-fd.md)\n* [第一部分: 前端开发实践](practice.md)\n\t* [前端的工作职称](practice/front-end-jobs-titles.md)\n\t* [常用的网络技术](practice/tech-employed-by-fd.md)\n\t* [前端开发技术栈](practice/front-end-skills.md)\n\t* [前端开发做什么](practice/fd-dev-for.md)\n\t* [团队中的前端](practice/front-end-team-role.md)\n\t* [全才神话](practice/full-stack.md)\n\t* [前端的面试问题](practice/front-end-interview.md)\n\t* [前端工作版块](practice/front-end-jobs.md)\n\t* [前端薪资](practice/salaries.md)\n\t* [如何成为前端开发者?](practice/making-fd.md)\n* [第二部分: 前端开发学习](learning.md)\n\t* [自主学习](learning/self-direct-learning.md)\n\t\t* [Internet/Web](learning/internet.md)\n\t\t* [Web浏览器](learning/browsers.md)\n\t\t* [DNS](learning/dns.md)\n\t\t* [HTTP/网络](learning/networks.md)\n\t\t* [Web 主机](learning/web-hosting.md)\n\t\t* [前端开发综合学习](learning/general-front-end.md)\n\t\t* [用户界面和交互设计](learning/design.md)\n\t\t* [HTML & CSS](learning/html-css.md)\n\t\t* [SEO](learning/seo.md)\n\t\t* [JavaScript](learning/js.md)\n\t\t* [Web 动画](learning/animation.md)\n\t\t* [DOM, BOM & JQuery](learning/dom.md)\n\t\t* [Web 字体](learning/fonts.md)\n\t\t* [无障碍设计](learning/accessibility.md)\n\t\t* [Web/浏览器 API](learning/api.md)\n\t\t* [JSON](learning/json.md)\n\t\t* [静态网页生成器](learning/static.md)\n\t\t* [前端应用架构设计](learning/front-end-apps.md)\n\t\t* [接口/API 设计](learning/interface.md)\n\t\t* [Web 开发者工具](learning/dev-tools.md)\n\t\t* [命令行](learning/cli.md)\n\t\t* [Node.js](learning/node.md)\n\t\t* [React.js](learning/react.md)\n\t\t* [模块加载器](learning/module.md)\n\t\t* [包管理器](learning/package.md)\n\t\t* [版本控制](learning/version.md)\n\t\t* [构建 & 任务自动化](learning/build.md)\n\t\t* [网站性能优化](learning/optimizing.md)\n\t\t* [JS 测试](learning/test.md)\n\t\t* [无壳浏览器](learning/headless-browsers.md)\n\t\t* [离线开发](learning/offline.md)\n\t\t* [安全](learning/security.md)\n\t\t* [多平台开发](learning/multi-things-dev.md)\n\t* [指导学习](learning/direct-learning.md)\n\t\t* [前端指导学习](learning/courses.md)\n\t* [前端开发者从哪里学](learning/learn-from.md)\n\t* [前端简报, 资讯 & 博客](learning/news-podcasts.md)\n* [第三部分: 前端开发工具](tools.md)\n\t* [常用前端开发工具](tools/general-tools.md)\n\t* [DOC/API 浏览](tools/browserdocs.md)\n\t* [SEO](tools/seo.md)\n\t* [原型和框架](tools/proto.md)\n\t* [图表](tools/diagram.md)\n\t* [HTTP/网络](tools/http.md)\n\t* [代码编辑](tools/code-editor.md)\n\t* [浏览器](tools/browser.md)\n\t* [HTML](tools/html.md)\n\t* [CSS](tools/css.md)\n\t* [DOM](tools/dom.md)\n\t* [JavaScript](tools/js.md)\n\t* [静态网页生成器](tools/static.md)\n\t* [APP(桌面, 移动, 平板等) 管理](tools/app.md)\n\t* [脚手架](tools/scaffolding.md)\n\t* [模板](tools/templates.md)\n\t* [UI 部件 & 组件](tools/ui.md)\n\t* [数据可视化](tools/charts.md)\n\t* [图形](tools/graphics.md)\n\t* [动画](tools/animation.md)\n\t* [JSON](tools/json.md)\n\t* [测试框架](tools/test.md)\n\t* [数据存储](tools/data.md)\n\t* [模块/包加载](tools/loader.md)\n\t* [模块/包仓库](tools/repo.md)\n\t* [Web/云/静态主机托管](tools/hosting.md)\n\t* [项目管理 & 代码托管](tools/project.md)\n\t* [合作 & 交流](tools/coll.md)\n\t* [CMS 托管/API](tools/cms.md)\n\t* [BASS](tools/bass.md)\n\t* [离线](tools/offline.md)\n\t* [安全](tools/security.md)\n\t* [任务管理](tools/task.md)\n\t* [部署](tools/deploy.md)\n\t* [网站/APP 监控](tools/monitor.md)\n\t* [JS 错误监控](tools/error.md)\n\t* [性能](tools/perf.md)\n\t* [SVG](tools/svg.md)"
  },
  {
    "path": "02-fedHandlebook-master/learning/accessibility.md",
    "content": "###无障碍设计\n\n>无障碍设计是指产品, 设备, 服务, 或者环境是为残疾人设计的. 无障碍设计的概念意味着与一个人的辅助技术(例如, 电脑屏幕阅读器)相兼容, 确保直接访问(即独立)和\"间接访问\".\n\n>无障碍设计可以理解为 \"能够访问\", 并对一个系统或实体是有利的, 其侧重于使身体残障, 或有特殊需要, 或要依赖辅助技术的人群能够访问 Web. 然后, 研究和开发无障碍设计对每个人都带来了好处.\n\n>无障碍设计不应该和可用性混淆. 大多数情况下, 可用性是指产品(如: 设备, 服务, 或者环境)能在特定的环境下被特定的用户使用, 来高效地实现制定目标.\n\n>无障碍设计和通用性设计是息息相关的. 通用型设计是指产品的创造过程中, 产品对人们是可用的, 并尽可能最大范围覆盖各能力范围内的人群和各种情形下的操作, 即对所有人是可访问的(无论他们访问 Web 是否有障碍). - wikipedia\n\n**综合学习:**\n\n* [Web应用程序通用设计](http://www.amazon.cn/Web%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E9%80%9A%E7%94%A8%E8%AE%BE%E8%AE%A1-Wensy-Cbisbolm/dp/B002IIDICE/ref=sr_1_2?ie=UTF8&qid=1446345863&sr=8-2) [read][RMB]\n* [Web 无障碍设计入门](http://www.pluralsight.com/courses/web-accessibility-getting-started) [watch][$]\n* [Web 无障碍设计介绍](https://www.w3.org/WAI/intro/accessibility.php) [read]\n* [兼济天下·用户无障碍体验的可访问性设计](http://www.amazon.cn/UI-UE%E7%B3%BB%E5%88%97%E4%B8%9B%E4%B9%A6-%E5%85%BC%E6%B5%8E%E5%A4%A9%E4%B8%8B%C2%B7%E7%94%A8%E6%88%B7%E6%97%A0%E9%9A%9C%E7%A2%8D%E4%BD%93%E9%AA%8C%E7%9A%84%E5%8F%AF%E8%AE%BF%E9%97%AE%E6%80%A7%E8%AE%BE%E8%AE%A1-%E9%9C%8D%E5%B0%94%E9%A1%BF/dp/B00UT03YEU/ref=sr_1_1?ie=UTF8&qid=1446346063&sr=8-1) [read][RMB]\n* [UX 基础: 无障碍设计](http://www.lynda.com/Accessibility-tutorials/Foundations-UX-Accessibility/435008-2.html) [watch][$]\n* [Web 无障碍设计介绍](https://webaccessibility.withgoogle.com/course) [watch]\n\n**标准/规范:**\n\n* [无障碍设计网络倡议 (WAI)](http://www.w3.org/WAI/)\n* [网页内容无障碍设计指南 (WCAG) 的目前状态](http://www.w3.org/standards/techs/wcag#w3c_all)\n* [富 Internet 应用程序的无障碍设计 (WAI-ARIA) 的目前状态](http://www.w3.org/standards/techs/aria#w3c_all)\n"
  },
  {
    "path": "02-fedHandlebook-master/learning/animation.md",
    "content": "###Web 动画\n\n**综合学习:**\n\n* [Web 动画的历史](https://www.codeschool.com/courses/adventures-in-web-animations) [watch][$]\n* [Snap.svg 动画](https://webdesign.tutsplus.com/courses/animating-with-snapsvg) [watch][$]\n* [CSS3 和 HTML5 动画](https://frontendmasters.com/courses/animation-storytelling-html5-css3/) [watch][$]\n* [真实世界中的 CSS 动画](https://webdesign.tutsplus.com/courses/css-animation-in-the-real-world) [watch][$]\n* [HTML5+JavaScript 动画基础](http://www.amazon.cn/HTML5-JavaScript%E5%8A%A8%E7%94%BB%E5%9F%BA%E7%A1%80-%E5%85%B0%E8%B4%9D%E5%A1%94/dp/B00D69IJKA/ref=sr_1_2?ie=UTF8&qid=1446346650&sr=8-2) [read][RMB]\n* [Web Animation using JavaScript: Develop &amp; Design (Develop and Design)](http://www.amazon.com/Web-Animation-using-JavaScript-Develop-ebook/dp/B00UNKXVDU/ref=sr_1_1) [read][$]\n* [2014: 动画发展现状](http://www.smashingmagazine.com/2014/11/the-state-of-animation-2014/) [read]\n* [学会用 CSS 创建动画](http://www.kirupa.com/css_animations/index.htm) [read & watch]\n* [学会用 JavaScript 创建动画](http://www.kirupa.com/javascript_animations/index.htm) [read & watch]\n\n**标准/规范**\n\n* [Web 动画](https://w3c.github.io/web-animations/)\n\n**译者补充:**\n\n* [Pro CSS3 Animation](http://apress.jensimmons.com/v5/pro-css3-animation/ch2.html)"
  },
  {
    "path": "02-fedHandlebook-master/learning/api.md",
    "content": "###Web/浏览器 API\n\nBOM 和 DOM 并不是唯一的浏览器 API, 在浏览器内部的 Web 平台上, 它们是可用的. DOM 和 BOM 并不是一切, 但是一个用于浏览器编程的接口可以被认识一个 Web 或者 浏览器 API(悲剧的是, 这些 API 曾被称为 HTML 5 API, 这会和 HTML 5 自身的规范/标准混淆, 因为 HTML 5 规范特指 HTML 5 标记语言). Web 或浏览器 API 也会包括访问设备的 API(如: [`Navigator.getBattery()`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getBattery)), 通过平板和手机设备上的浏览器可以利用这些 API.\n\n![api](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/web-api.png)\n\n在适当情况下, 你应该了解和学习 Web/浏览器 API. 为了熟悉这些 API, 应该去研究[HTML5test.com](https://html5test.com/compare/browser/chrome-44/firefox-40/ie-11/safari-9.0.html) 对与 5 款常用浏览器对 API 新特性的支持结果, 这是一个很不错的方式.\n\n**学习文档:**\n\n* [DIVE INTO HTML5](http://diveintohtml5.info/) [read]\n* [HTML5 专业开发](http://apress.jensimmons.com/v5/pro-html5-programming/info.html) [read]\n* [HTML5 Canvas](http://chimera.labs.oreilly.com/books/1234000001654/index.html) [read]\n\n**学习视频:**\n\n* [Web Audio 的乐趣](https://code.tutsplus.com/courses/fun-with-web-audio/) [watch]\n* [用 Web Audio 给网站添加声音](https://code.tutsplus.com/courses/add-sound-to-your-site-with-web-audio) [watch]\n\n**其它学习资源:**\n\n* [Web Audio API](http://chimera.labs.oreilly.com/books/1234000001552/index.html) [read]\n\n此外, MDN 有很多关于 web/browser API 的信息:\n\n* [MDN Web API 参考](https://developer.mozilla.org/en-US/docs/Web/Reference/API)\n* [MDN WebAPI - 设备访问 API 和其它有用的 API](https://developer.mozilla.org/en-US/docs/WebAPI)\n* [MDN Web APIs 接口参考](https://developer.mozilla.org/en-US/docs/Web/API)\n\n时刻记住, 并不是每一个 API 都在 W3C 或 WHATWG 的规范之内.\n\n除了 MDN, 还列出了一些有用的资源:\n\n* [HTMl5-overview](https://github.com/dret/HTML5-overview)\n* [platform.html5.org](https://platform.html5.org/)\n* [HTML5 和 JavaScript API 索引](http://html5index.org/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/browsers.md",
    "content": "###Web浏览器\n\n>web 浏览器(通常被称为浏览器)是一个用于检索、展示和遍历在万维网上的信息资源的软件应用程序. 信息资源被定义成统一资源定位符(URI/URL). 它可能是网页, 图片, 视频或者一个内容片断. 超链接的出现使用户能轻松的将浏览器导航到相关的资源, 尽管浏览器主要是为了使用万维网, 但它们还可以用来访问 Web服务器在私人网络所提供的信息或文件在文件系统. - Wikipedia\n\n[主流的浏览器](http://www.sitepoint.com/browser-trends-april-2015-statcounter-vs-netmarketshare/) 如下:\n\n1. [Chrome](http://www.google.com/chrome/) (引擎: [Blink](https://en.wikipedia.org/wiki/Blink_%28layout_engine%29) + [V8](https://en.wikipedia.org/wiki/V8_%28JavaScript_engine%29))\n2. [Firefox](https://www.mozilla.org/en-US/firefox/new/) (引擎: [Gecko](https://en.wikipedia.org/wiki/Gecko_%28software%29) + [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey_%28software%29))\n3. [Internet Exploere](http://windows.microsoft.com/en-us/internet-explorer/download-ie) (引擎: [Trident](https://en.wikipedia.org/wiki/Trident_%28layout_engine%29) + [Chakra](https://en.wikipedia.org/wiki/Chakra_%28JScript_engine%29))\n4. [Safari](https://www.apple.com/safari/) (引擎: [Webkit](https://en.wikipedia.org/wiki/WebKit) + [SquirrelFish](https://trac.webkit.org/wiki/SquirrelFish))\n\n![statcounter](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/statcounter.png)\n\n**浏览器和web技术的演变(API 等):**\n\n* [www.evolutionoftheweb.com](http://www.evolutionoftheweb.com/) [read]\n* [Timeline of web browsers](https://en.wikipedia.org/wiki/Timeline_of_web_browsers) [read]\n\n**最常用的无壳浏览器:**\n\n* [PhantomJS](http://phantomjs.org/) (引擎: [Webkit](https://en.wikipedia.org/wiki/WebKit) + [SquirrelFish](https://trac.webkit.org/wiki/SquirrelFish))\n* [slimerjs](http://slimerjs.org/) (引擎: [Gecko](https://en.wikipedia.org/wiki/Gecko_%28software%29) + [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey_%28software%29))\n* [TrifleJS](http://triflejs.org/) (引擎: [Trident](https://en.wikipedia.org/wiki/Trident_%28layout_engine%29) + [Chakra](https://en.wikipedia.org/wiki/Chakra_%28JScript_engine%29))\n\n**浏览器怎么工作的**\n\n* [我所知道的关于浏览器和Web的20件事](http://www.20thingsilearned.com/en-US/foreword/1) [read]\n* [浏览器如何工作的: 现代浏览器背后的秘密](http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/) [read]\n* [快速 CSS: 浏览器是怎么组织网页的](http://dbaron.org/talks/2012-03-11-sxsw/master.xhtml) [read]\n* [浏览器是如何渲染一个网站的?](https://www.youtube.com/watch?v=SmE4OwHztCc) [watch]\n\n![browser-work](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/browsers-work.png)\n\n**浏览器优化**\n\n* [网站性能优化](https://www.udacity.com/course/website-performance-optimization--ud884) [watch]\n* [浏览器渲染优化](https://www.udacity.com/course/browser-rendering-optimization--ud860) [watch]\n\n**浏览器安全**\n\n* [浏览器安全手册](https://code.google.com/p/browsersec/wiki/Main) [read]\n* [HTML5 安全参考手册](https://html5sec.org/#javascript) [read]\n* [前端安全](https://mikewest.org/2013/09/frontend-security-frontendconf-2013) [watch]\n* [Web 安全: JavaScript, HTML, CSS 的使用](http://www.amazon.com/Security-Web-Developers-Using-JavaScript/dp/1491928646/) [read][$]\n* [网络混战: 现代 Web 应用安全指南](http://lcamtuf.coredump.cx/tangled/) [read]\n\n**浏览器比较**\n\n* [Web 浏览器的比较](https://en.wikipedia.org/wiki/Comparison_of_web_browsers) [read]\n\n**浏览器的发展**\n\n在过去, 前端开发者会花费大量的时间让代码在不同的浏览器中正常工作. 除非你必须写出兼容老版本浏览器的代码(如: IE6/IE7), 否则跟现在比起来, 这(浏览器兼容)在以前是一个很大的问题. 虽说浏览器兼容问题现在仍然存在, 但前端开发者并不用花费很多时间就能处理这类问题. 而实际上, 现代抽离出的框架(如: JQuery, pre-processors, transpilers)已经废除了很多浏览器不一致问题.\n\n**绿色浏览器**\n\n浏览器的最新版本被认为是绿色浏览器, 也就是说, 浏览器会自动更新而不用去提示用户更新. 浏览器的自动更新摒弃了老版本浏览器进程缓慢的问题, 因为对于老版本浏览器和现代浏览器之间的共性的差异化开发是很复杂的(如: 新规范和更新速度).\n\n**浏览器选择**\n\n现在大多数前端开发者使用 Chrome, \"Chrome 开发工具\"对开发者很有用, 然而, 所有浏览器都提供了开发者工具, 所以选择一个开发用的浏览器是一个主观的问题. 更重要的问题是要了解需要支持哪些浏览器, 当你在开发的时候, 要在每个浏览器中做测试, 但无论选择哪一款浏览器都能完成开发任务, 我建议使用 Chrome 是因为 Chrome 开发工具一直在改进, 并且包含了更健全地特性.\n\n**浏览器 Hacks**\n\n* [browserhacks.com](http://browserhacks.com/) [read]\n"
  },
  {
    "path": "02-fedHandlebook-master/learning/build.md",
    "content": "###构建和任务自动化\n\n>构建自动化是软件构建和相关流程的自动化过程, 包括: 将计算机源码编译成二进制代码, 打包二进制代码和运行自动化测试. - wikipedia\n\n**综合学习:**\n\n* [用 Gulp.js 进行 JavaScript 自动构建: ](http://www.pluralsight.com/courses/javascript-build-automation-gulpjs) [watch][$]\n* [Gulp 入门](https://www.packtpub.com/web-development/getting-started-gulp) [read][$]\n* [Gulp 快速入门](https://www.packtpub.com/web-development/rapid-gulp-video) [watch][$]\n* [学习 Gulp - 前端工厂入门](http://hmphry.com/gulp) [read]\n* [Gulp 基础](http://teamtreehouse.com/library/gulp-basics) [watch][$]\n* [使用 npm 作为任务运行器](http://teamtreehouse.com/library/using-npm-as-a-task-runner) [watch][$]\n\n**参考/文档:**\n\n* [gulp](https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md)\n\nGulp 是非常棒的构建工具, 然后, 你可能仅仅只需要 `npm run`. 在你的应用程序栈变得负责之前, 问问你自己, `npm run`是否能完成自动化构建. 如果你需要更多, 可以同时使用 `npm run`和 Gulp.\n\n推荐阅读:\n\n* [NPM 使用指南](http://www.sitepoint.com/guide-to-npm-as-a-build-tool/)\n* [NPM 的任务自动化管理](http://substack.net/task_automation_with_npm_run)\n* [构建工具 VS NPM 脚本: 为何不使用两者](http://engineering.hobsons.com/2015/06/26/build-tools-vs-npm-scripts-why-not-both/)\n* [使用 NPM 作为下一个项目的构建系统](https://drublic.de/blog/npm-builds)\n* [怎么将 NPM 作为构建工具使用](http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/)\n\n**译者补充:**\n\n* [Gulp不完全入门教程](http://www.ido321.com/1622.html)"
  },
  {
    "path": "02-fedHandlebook-master/learning/cli.md",
    "content": "###命令行\n\n>命令行接口或命令语言解译器(CLI), 也称命令行用户界面, 控制台用户界面和字符用户界面(CUI), 是一种用户以连续的文本(命令行)的形式向程序提出需求, 与计算机程序交互的方式. - wikipedia\n\n**入门学习:**\n\n* [codecademy: Learn the Command Line](https://www.codecademy.com/courses/learn-the-command-line) [watch]\n* [The Command Line Crash Course](http://cli.learncodethehardway.org/book/) [read]\n* [Meet the Command Line](http://www.pluralsight.com/courses/meet-command-line) [read][$]\n* [Learn Enough Command Line to Be Dangerous](http://www.learnenough.com/command-line-tutorial) [read][free tp $]\n* [Command Line Power User](http://commandlinepoweruser.com/) [watch]\n\n**进阶学习:**\n\n* [Advanced Command Line Techniques](https://code.tutsplus.com/courses/advanced-command-line-techniques) [watch][$]"
  },
  {
    "path": "02-fedHandlebook-master/learning/courses.md",
    "content": "###Directed learning\n\nThe table below contains instructor led, paid, front-end courses, programs, schools, and bootcamps.\n\nIf you can't afford a directed education, a self directed education using screencasts, books, and articles is a viable alternative to learn front-end development for the self-driven individual.\n\n<table>\n    <thead>\n        <tr>\n            <th data-field=\"company\">company</th>\n            <th data-field=\"model\">course</th>\n            <th data-field=\"year\">price</th>\n            <th data-field=\"onsite\">on site</th>\n            <th data-field=\"remote\">remote</th>\n        </tr>\n    </thead>\n    <tbody>\n        <tr>\n            <td>Iron Yard</td>\n            <td><a target=\"_blank\" href=\"http://theironyard.com/courses/front-end-engineering/\">Front End Engineering</a></td>\n            <td>12,000</td>\n            <td>multiple locations</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>Udacity</td>\n            <td><a target=\"_blank\" href=\"https://www.udacity.com/course/nd001\">Front-End Web Developer Nanodegree</a></td>\n            <td>200 monthly</td>\n            <td>multiple locations</td>\n            <td>yes</td>\n        </tr>\n        <tr>\n            <td>The New York Code + Design Academy</td>\n            <td><a target=\"_blank\" href=\"http://nycda.com/classes/front-end-101/\">Front End 101</a></td>\n            <td>2,000</td>\n            <td>New York, NY</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>Portland Code School</td>\n            <td><a target=\"_blank\" href=\"http://www.portlandcodeschool.com/advancedfe/\">Advanced Front-end Developer Tools</a></td>\n            <td>2,000</td>\n            <td>Portland, OR</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>BLOC</td>\n            <td><a target=\"_blank\" href=\"https://www.bloc.io/frontend-development-bootcamp\">Become a Frontend Developer</a></td>\n            <td>4,999</td>\n            <td></td>\n            <td>yes</td>\n        </tr>\n        <tr>\n            <td>Thinkful</td>\n            <td><a target=\"_blank\" href=\"http://www.thinkful.com/courses/learn-web-development-online\">Frontend Web Development</a></td>\n            <td>300 per month</td>\n            <td></td>\n            <td>yes</td>\n        </tr>\n        <tr>\n            <td>General Assembly</td>\n            <td><a target=\"_blank\" href=\"https://generalassemb.ly/education/front-end-web-development\">Frontend Web Development</a></td>\n            <td>3,500</td>\n            <td>multiple locations</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>Hackbright Academy</td>\n            <td><a target=\"_blank\" href=\"http://hackbrightacademy.com/courses/front-end-web-development/\">Front-End Web Development</a></td>\n            <td>3,000</td>\n            <td>San Francisco, CA</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>HackerYou</td>\n            <td><a target=\"_blank\" href=\"http://hackeryou.com/front-end-web-development-immersive/\">Front-end Web Development Immersive</a></td>\n            <td>7,000 - 7,910</td>\n            <td>Toronto, Canada</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>The Flatiron School</td>\n            <td><a target=\"_blank\" href=\"http://flatironschool.com/frontend\">Introduction to Front-End Web Development</a></td>\n            <td>3,500</td>\n            <td>New York, NY</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>Austin Coding Academy</td>\n            <td><a target=\"_blank\" href=\"http://www.austincodingacademy.com/front-end/\">The Front End Track</a></td>\n            <td>1,490 per class</td>\n            <td>Austin, TX</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>Codeup</td>\n            <td><a target=\"_blank\" href=\"http://codeup.com/night-bootcamp/\">Night Front-End Bootcamp</a></td>\n            <td>8,500</td>\n            <td>San Antonio, Texas</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>Betamore</td>\n            <td><a target=\"_blank\" href=\"http://betamore.com/academy/front-end-web-development/\">Front-end Web Development</a></td>\n            <td>8,500</td>\n            <td>Baltimore, MD</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>Codify Academy</td>\n            <td><a target=\"_blank\" href=\"http://codifyacademy.com/thecourse.php\">Front-end Web Development</a></td>\n            <td>4,000</td>\n            <td>multiple locations</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>DecodeMTL</td>\n            <td><a target=\"_blank\" href=\"http://www.decodemtl.com/\">Learn Front-end Web Development</a></td>\n            <td>2,500</td>\n            <td>Montreal, QC</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>gr8code</td>\n            <td><a target=\"_blank\" href=\"https://gr8code.com/our-programs/front-end-bootcamp/\">Front-End Bootcamp</a></td>\n            <td>10,000</td>\n            <td>Tampa, FL</td>\n            <td></td>\n        </tr>\n        <tr>\n            <td>LearningFuze</td>\n            <td><a target=\"_blank\" href=\"http://learningfuze.com/frontend-development/\">Part-Time Front-End Development Course</a></td>\n            <td>2,500</td>\n            <td>Irvine, CA</td>\n            <td></td>\n        </tr>\n    </tbody>\n</table>"
  },
  {
    "path": "02-fedHandlebook-master/learning/design.md",
    "content": "###用户界面和交互设计\n\n>**用户界面设计:** 用户界面设计(UI)或用户界面工程师是为机器或者软件做用户界面设计的, 如: 计算机, 家用器具, 移动设备和其它电子设备, 专注于最大限度地提高用户体验. 用户界面设计的目标是尽可能是使用户交互变得简单有效, 实现用户的操作目标(设计是以用户为中心的). - wikipedia\n\n>**交互设计模式:** 设计模式是一种记录解决常见设计问题解决方案的形式化方式. 建筑师 Christopher Alexander 在城市规划和建设体系结构中已经介绍了这种方式, 并已用于其他学科, 包括教学, 教育学和软件架构和设计. - wikipedia\n\n>**用户体验设计:** 用户体验设计(又称 UXD 或 UED 或 XD), 是通过提高可用性、可访问性以及在用户跟产品交互时的愉悦来提高用户体验的过程. 用户体验设计从完成传统的人机交互(HCI), 已经扩展到要处理产品或服务中能被用户感知的所有方面. - wikipedia\n\n>**人机交互:** 人机交互(HCI)不仅特别关注人和计算之间的界面, 也会研究设计和使用 Web 技术. 人机交互领域的研究人员都会去关注当前人类与计算机交互的方式和为人类与计算机提供新的交互方式的设计技术. - wikipedia\n\n若你想要建立适当的用户界面, 我会建议你阅读以下关于设计方面的书籍:\n\n* [Designing Interfaces](http://www.amazon.com/Designing-Interfaces-Jenifer-Tidwell/dp/1449379702/ref=sr_1_1) [read][$]\n* [About Face: The Essentials of Interaction Design](http://www.amazon.com/About-Face-Essentials-Interaction-Design/dp/1118766571/ref=pd_sim_14_3) [read][$]\n* [Don't Make Me Think, Revisited: A Common Sense Approach to Web Usability](http://www.amazon.com/Dont-Make-Think-Revisited-Usability/dp/0321965515/ref=pd_sim_14_2) [read][$]\n\n\n**译者补充:**\n\n* [简约至上:交互式设计四策略](http://www.amazon.cn/%E7%AE%80%E7%BA%A6%E8%87%B3%E4%B8%8A-%E4%BA%A4%E4%BA%92%E5%BC%8F%E8%AE%BE%E8%AE%A1%E5%9B%9B%E7%AD%96%E7%95%A5-%E7%A7%91%E5%B0%94%E4%BC%AF%E6%81%A9/dp/B004I91HCY/ref=sr_1_1?ie=UTF8&qid=1445948451&sr=8-1) [read][RMB]\n* [交互设计沉思录](http://www.amazon.cn/%E4%BA%A4%E4%BA%92%E8%AE%BE%E8%AE%A1%E6%B2%89%E6%80%9D%E5%BD%95-%E7%A7%91%E5%B0%94%E7%A7%91/dp/B009A7DAXI/ref=sr_1_3?ie=UTF8&qid=1445948451&sr=8-3) [read][RMB]"
  },
  {
    "path": "02-fedHandlebook-master/learning/dev-tools.md",
    "content": "###Web 开发者工具\n\n>Web 开发者工具允许开发者测试和调试代码, 它们不同于网站生成器和 IDE, 因为 Web 开发者工具不直接参与网页的创建, 而是用于测试网站或 Web 应用的用户界面接口的工具.\n\n>Web 开发者工具是浏览器的加载项或内置功能. 当今最流行的web浏览器, Google Chrome, Firefox, Opera, Internet Explorer, 和 Safari 都内置工具用于帮助开发者, 并且在各自的插件下载中心, 还提供很多额外的加载项.\n\n>Web 开发者工具允许开发者使用各种各样的 Web 技术, 包括 HTML, CSS, DOM, JavaScript 和 其它浏览器能够处理的组件. 由于日益增长的需求, 更多流行的 Web 浏览器包括了更多面向开发人员的功能.\n\n尽管大多数浏览器都配备了开发者工具, 但是 [谷歌开发者工具](https://developers.google.com/web/tools/chrome-devtools/) 是目前谈论最多, 应用最广泛的开发者工具.\n\n我建议学习和使用 [谷歌开发者工具](https://developers.google.com/web/tools/chrome-devtools/), 因为谷歌开发者工具周围有学习 Web 开发者工具最好的资源.\n\n**学习使用谷歌开发者工具:**\n\n* [Explore and Master Chrome DevTools](http://discover-devtools.codeschool.com/)\n* [Chrome 开发者工具](https://code.tutsplus.com/courses/chrome-developer-tools) [watch][$]\n* [使用 Chrome 开发者工具](http://www.pluralsight.com/courses/chrome-developer-tools) [watch][$]\n\n**谷歌开发者工具文档:**\n\n* [Per-Panel 文档](https://developers.google.com/web/tools/chrome-devtools/#docs)\n* [命令行接口参考](https://developers.google.com/web/tools/javascript/command-line/command-line-reference?hl=en)\n* [键盘 & UI 快捷键参考](https://developers.google.com/web/tools/iterate/inspect-styles/shortcuts)\n* [设置](https://developer.chrome.com/devtools/docs/settings)\n\n**新闻/简报/博客/建议:**\n\n* [Dev Tips](https://umaar.com/dev-tips/)\n\n**译者补充:**\n\n* [Chrome Devtools Tips & Tricks](http://mo.github.io/2015/10/19/chrome-devtools.html)\n* [Chrome开发者工具不完全指南](http://www.92fenxiang.com/121.html)\n* [Chrome 开发工具指南](http://wiki.jikexueyuan.com/project/chrome-devtools/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/direct-learning.md",
    "content": "###Directed learning\n\nThis section focuses on directed learning via schools, courses, programs and bootcamps."
  },
  {
    "path": "02-fedHandlebook-master/learning/dns.md",
    "content": "###域名系统(又称 DNS)\n\n>对于个人电脑、服务器或连接到互联网任何资源, 或专用网络而言, 域名系统(DNS)是一个分层分布式命名系统, 用给每个参与的实体分配域名的方式将各种信息联系起来, 更重要的是, 为能访问全球的计算机服务和设备, DNS 将所需的数字 IP 地址转变为人类容易记住的域名. DNS 是大多数互联网服务的必要功能, 因为这是主要的 IP 地址服务. - wikipedia\n\n![dns](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/dns.jpg)\n\n* [什么是 DNS](https://www.youtube.com/watch?v=72snZctFFtA) [watch]\n* [DNS 是怎么工作的?](https://howdns.works/ep1/) [read]"
  },
  {
    "path": "02-fedHandlebook-master/learning/dom.md",
    "content": "###DOM, BOM & JQuery\n\n>**DOM** - 文档对象模型(DOM)用于代表和对象交互的HTML, XHTML 和 XML 文档, 是一种跨平台和语言无关性的约定. 每一份文档的所有节点被组织成一种树结构, 称为 DOM 树. DOM 对象通过使用对象上的方法被处理和操作, 一个 DOM 对象的公共接口被指定为它的应用程序编程接口(API). - wikipedia.org\n\n>**BOM** - 浏览器对象模型(BOM)是一种浏览器规范, 代指 Web 浏览器暴露出的对象. 与文档对象模型不同的是, 目前并没有关于浏览器对象模型的标准和严格定义, 因而浏览器厂商可以按照他们的意愿, 采取任何方式来实现 BOM. - wikipedia.org\n\n>**JQuery** - JQuery 是一个跨平台的 JavaScript 库, 其设计目的是简化客户端的 HTML 脚本操作. JQuery 也是目前最流行的 JavaScript 库, 在目前排名前1000万的网站中, 65% 的网站安装了 JQuery. JQuery 是免费的, 基于 MIT 协议的开源软件. - wikipedia.org\n\n最理想但又难度最大的学习路径就是首先学习 JavaScript, 然后学习 DOM, 之后再学习 JQuery. 然后, 完全可以按照你所想的学习路径来安排学习的顺序. 大多数的前端开发者在了解 JavaScript 和 DOM 之后, 才会接触 JQuery. 无论采取什么学习路径, 都要确保 JavaScript, DOM 或者 JQuery 不要成为\"黑盒子\".\n\n**入门学习:**\n\n* [DOM](http://eloquentjavascript.net/13_dom.html) [read]\n* [codecademy.com jQuery](https://www.codecademy.com/tracks/jquery) [watch]\n* [jQuery 启蒙](http://jqueryenlightenment.com/) [read]\n* [JQuery 入门](http://www.pluralsight.com/courses/jquery-getting-started) [watch][$]\n\n**进阶学习:**\n\n* [DOM 启蒙](http://www.amazon.cn/DOM%E5%90%AF%E8%92%99-%E6%9E%97%E5%BE%B7%E5%88%A9/dp/B00JWXDB52/ref=sr_1_2?ie=UTF8&qid=1446477828&sr=8-2) [read][RMB] 或 [免费在线阅读](http://domenlightenment.com/)\n* [JS & DOM 进阶](https://frontendmasters.com/courses/javascript-jquery-dom/) [watch][$]\n* [DOM 进阶: 动态网页设计技术](http://www.amazon.com/gp/product/1590598563/ref=as_li_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590598563&amp;linkCode=as2&amp;tag=fronenddevejo-20&amp;linkId=VQZU5EQIQQXCF56Y) [read][$]\n* [常见 JQuery bugs 修复](http://www.pluralsight.com/courses/fixing-common-jquery-bugs) [watch][$]\n* [JQuery 技巧](http://www.pluralsight.com/courses/jquery-tips-and-tricks) [watch][$]\n* [jQuery-free JavaScript](http://www.pluralsight.com/courses/jquery-free-javascript) [watch][$]\n* [Douglas Crockford: DOM 理论--不可忽视的 API](https://www.youtube.com/watch?v=Y2Y0U-2qJMs&amp;list=PL5586336C26BDB324&amp;index=2) [watch]\n\n**参考/文档:**\n\n* [MDN: 文档对象模型](https://developer.mozilla.org/zh/docs/Web/API/Document_Object_Model)\n* [MDN: 事件参考](https://developer.mozilla.org/zh/docs/Web/Events)\n* [JQuery 文档](http://api.jquery.com/)\n* [MDN: 浏览器对象模型](https://developer.mozilla.org/en-US/docs/Web/API/Window)\n* [MSDN: 文档对象模型](https://msdn.microsoft.com/en-us/library/hh772384%28v=vs.85%29.aspx)\n\n**标准和规范:**\n\n* [W3C DOM4](http://www.w3.org/TR/2014/WD-dom-20140204/)\n* [DOM 在线标准](https://dom.spec.whatwg.org/)\n* [DOM 3 事件规范](http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/)\n* [DOM 技术报告](http://www.w3.org/DOM/DOMTR)\n\n\n**译者补充:**\n\n* [You Might Not Need JQuery(英)](http://youmightnotneedjquery.com/) [中文版](http://www.webhek.com/you-do-not-need-jquery)"
  },
  {
    "path": "02-fedHandlebook-master/learning/fonts.md",
    "content": "###Web 字体 & 图标\n\n>Web 字体是指在 WWW 上使用的字体. 当 HTML 文档第一次被创建时, 字体风格和样式会被每个 Web 浏览器的设置所控制, 因为直到 1995 年网景介绍了`<font>`标记之前, 个人网页没有控制字体显示的方式, 而`<font>`标记在 HTML 3.2 规范中被标准化. 然而, 被标记指定的字体必须安装在用户的电脑上, 或者是一种可以依赖的字体, 如: 浏览器默认的 sans-serif 字体或 monospace 字体. 在1996 年 发布的 CSS 1.0 规范也提供指定使用字体的功能.\n\n> 1998 年, CSS 2.0 规范发布, 意图通过字体匹配, 合成和下载技术, 改善字体的选择过程, 但这些技术并没有得到使用, 并在 CSS2.1 规范中被移除了. 然而, 在 1997 年发布的 IE 4.0 增加了对字体下载的支持, 随后, CSS 3 的字体模块变包含了字体下载, 并且 Safari 3.1, Opera 10 和 Mozilla Firefox 3.5 实现了这一功能, 随后便增加了 Web 字体和所使用字体的下载. - wikipedia\n\n**综合学习:**\n\n* [Web 字体排版](http://www.pluralsight.com/courses/typography-for-web-1790) [watch][$]\n* [@font-face 快速学习指南](http://www.html5rocks.com/en/tutorials/webfonts/quick/) [read]\n* [响应式排版](https://frontendmasters.com/courses/responsive-typography/) [watch][$]\n* [用最好的字体来美化网页](http://hellohappy.org/beautiful-web-type/) [read]\n"
  },
  {
    "path": "02-fedHandlebook-master/learning/front-end-apps.md",
    "content": "###前端应用架构设计\n\n* [JavaScript Web 应用开发](http://www.amazon.cn/JavaScript-Web%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91-%E9%98%BF%E6%A0%B9%E5%BB%B7-%E6%AF%94%E7%93%A6%E5%8D%A1/dp/B016I9T8QI/ref=sr_1_2) [read][RMB]\n* [用 React & Ampersand 构建 APP](http://learn.humanjavascript.com/react-ampersand) [watch][$]\n* [Human JavaScript](http://read.humanjavascript.com/) [read]\n* [JavaScript 应用程序编程](http://chimera.labs.oreilly.com/books/1234000000262/index.html) [read]\n* [构建现代单页应用](https://frontendmasters.com/workshops/web-apps/) [watch][$]\n* [JavaScript 函数式编程](https://frontendmasters.com/courses/organizing-javascript/) [watch][$]\n* [JavaScript: 模块](http://eloquentjavascript.net/10_modules.html) [read]\n* [Web UI 架构设计](https://frontendmasters.com/courses/web-ui-architecture/) [watch][$]\n* [Web 应用设计指南](http://www.html5rocks.com/webappfieldguide/toc/index/) [read]\n* [UI 架构设计](http://www.pluralsight.com/courses/web-ui-architecture) [watch][$]\n* [Terrific](http://terrifically.org/) [read]\n* [Nicholas Zakas: 可扩展的 JavaScript 应用架构](https://www.youtube.com/watch?v=vXjVFPosQHw) [watch]\n* [大型 JavaScript 应用架构设计模式](http://addyosmani.com/largescalejavascript/) [read]\n* [静态应用指南](http://www.staticapps.org/) [read]"
  },
  {
    "path": "02-fedHandlebook-master/learning/general-front-end.md",
    "content": "###前端开发综合学习\n\n**入门学习:**\n\n* [前端参考指南](https://github.com/bendc/frontend-guidelines) [read]\n* [Web 开发者](http://www.yellowshoe.com.au/standards) [read]\n* [前端代码标准](http://isobar-idev.github.io/code-standards/) [read]\n* [Web 基本原理](https://developers.google.com/web/fundamentals) [read]\n* [前端课程](https://gist.github.com/stevekinney/03027e71aac341af14a2) [read]\n* [FreeCodeCamp](http://freecodecamp.com/) [interact]\n* [开发前端 JS 应用](https://www.youtube.com/watch?v=q4zEGkjTBFA) [watch]\n* [前端工程师](https://www.youtube.com/watch?v=Lsg84NtJbmI) [watch]\n* [Web 前端开发的工作内容](http://www.pluralsight.com/courses/front-end-web-development-career-kickstart) [watch][$]\n* [Web 前端开发入门](http://www.pluralsight.com/courses/front-end-web-development-get-started) [watch][$]\n* [用 HTML5, CSS, 和 JavaScript 快速进行 Web 前端开发](http://www.pluralsight.com/courses/front-end-web-app-html5-javascript-css) [watch][$]\n* [Web 开发介绍](https://frontendmasters.com/courses/web-development/) [watch][$]\n* [Web 前端开发基础](https://www.udemy.com/foundations-of-front-end-development/) [watch][$]\n* [精益前端工程](https://frontendmasters.com/courses/lean-front-end-engineering/) [watch][$]\n* [前端(JS)开发基线: 2015](http://rmurphey.com/blog/2015/03/23/a-baseline-for-front-end-developers-2015/) [read]\n* [Web 前端开发入门学习](https://teamtreehouse.com/tracks/front-end-web-development) [watch][$]\n* [Web 前端开发进阶学习](https://mijingo.com/products/bundles/front-end-dev-mastery/) [watch][$]\n* [没有学位的 Web 前端开发者](https://www.udacity.com/course/front-end-web-developer-nanodegree--nd001) [watch][$\n\n**前端简报, 资讯和博客:**\n\n* [shoptalkshow.com](http://shoptalkshow.com/)\n* [frontendfront.com](http://frontendfront.com/)\n* [webtoolsweekly.com](http://webtoolsweekly.com/)\n* [O'Reilly Web Platform Radar](http://radar.oreilly.com/web-platform)\n* [The Web Platform Podcast](http://thewebplatform.libsyn.com/)\n* [The Web Ahead](http://thewebahead.net/)\n* [The Big Web Show](http://5by5.tv/bigwebshow)\n* [Fresh Brewed Frontend](https://freshbrewed.co/frontend/)\n* [Mobile Web Weekly](http://mobilewebweekly.co/)\n* [Open Web Platform Daily Digest](http://webplatformdaily.org/)\n* [FRONT-END DEV weekly](http://frontenddevweekly.com/)\n\n**译者补充:**\n\n* [前端工程系列文章](https://github.com/fouber/blog/issues/10)\n* [前端知识体系](http://qianduanfan.com/index.php/topic/show/231)\n* [前端资源大总结](http://qianduanfan.com/index.php/topic/show/234)\n* [前端入门](https://github.com/qiu-deqing/FE-learning)\n* [WebPlatForm](http://www.webplatform.org/)\n* [前端开发规范手册](http://zhibimo.com/read/Ashu/front-end-style-guide/)\n* [Web 开发电子书下载(英)](http://www.allitebooks.com/web-development/)\n* 对前端开发者有用的文档和指南: [1](http://www.sitepoint.com/20-docs-guides-front-end-developers/) [2](http://www.sitepoint.com/20-more-docs-guides-front-end-developers/) [3](http://www.sitepoint.com/another-20-docs-guides-front-end-developers/) [4](http://www.sitepoint.com/20-docs-guides-front-end-developers-4/) [5](http://www.sitepoint.com/20-docs-guides-front-end-developers-5/) [6](http://www.sitepoint.com/20-docs-guides-front-end-developers-6/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/headless-browsers.md",
    "content": "###无壳浏览器\n\n>无壳浏览器是指没有图形用户界面的 Web 浏览器.\n\n>无壳浏览器拥有一个和受欢迎的 Web 浏览器相似的环境, 并提供了网页的自动化控制, 但要通过命令行接口或使用网络通信工具执行. 对于测试网页, 无壳浏览器是非常有用的, 因为和普通浏览器一样, 它们能渲染和理解 HTML, 包括样式元素, 如: 页面布局, 颜色, 字体选择, JavaScript 的执行和 AJAX, 但是当使用其它方法时, Ajax 通常就不可用了. 在 2009 年, 谷歌声称使用无壳浏览器有助于搜索引擎使用 Ajax 从其它网站索引内容. - wikipedia\n\n* [PhantomJS Cookbook](http://www.amazon.com/PhantomJS-Cookbook-Rob-Friesel/dp/178398192X) [read][$]\n* [Getting Started with PhantomJS](http://www.amazon.com/Getting-Started-PhantomJS-Aries-Beltran/dp/1782164227) [read][$]\n* [Rapid PhantomJS](https://www.packtpub.com/web-development/rapid-phantomjs-video) [watch][$]\n* [PhantomJS for Web Automation](https://www.youtube.com/watch?v=OqEcn_6GBDI) [watch]"
  },
  {
    "path": "02-fedHandlebook-master/learning/html-css.md",
    "content": "###HTML & CSS\n\n>**HTML** - 超文本标记语言, 通常被称为 HTML, 是被用于创建网页的标准标记语言. Web浏览器能将 HTML 文件渲染成可见的或者可听到的. HTML 随着线索提示, 语义化地描述了网站的结构, 使它成为一种标记语言, 而不是编程语言. - wikipedia.org\n\n>**CSS** - 层叠式样式表(CSS)是用于描述外观和格式化标记语言编写的文档的样式表语言. 尽管经常被用来改变用 HTML 和 XHTML 编写的网页和用户界面的样式, 但也可用于任何 XML 文档, 包括纯 XML, SVG 和 XUL. 跟 JavaScript 和 HTML 一样, CSS是被大多数网站用于为Web应用程序创建富有吸引力的网页, 用户界面的一种基础技术, 也为许多移动应用程序创建用户界面. - wikipedia.org\n\n就像建造房子, 你可以认为 HTML 是骨架, 而 CSS 是油漆和装饰. \n\n**入门学习:**\n\n* [codecademy.com HTML & CSS](https://www.codecademy.com/tracks/web) [interact]\n* [HTML/CSS 介绍: 网页制作](https://www.khanacademy.org/computing/computer-programming/html-css) [watch]\n* [HTML & CSS 编码学习](http://learn.shayhowe.com/html-css/) [read]\n* [CSS 布局](http://learnlayout.com/) [read]\n* [Web 前端开发入门](http://www.pluralsight.com/courses/front-end-web-development-get-started) [watch][$]\n* [HTML & CSS 设计与构建网站](http://www.amazon.cn/HTML-CSS%E8%AE%BE%E8%AE%A1%E4%B8%8E%E6%9E%84%E5%BB%BA%E7%BD%91%E7%AB%99-%E8%BE%BE%E7%A7%91%E7%89%B9/dp/B00BMK4GKW/ref=sr_1_1?ie=UTF8&qid=1446191225&sr=8-1) [read][RMB]\n* [快速使用 HTML5, CSS 3 & JavaScript 进行 Web 前端开发](http://www.pluralsight.com/courses/front-end-web-app-html5-javascript-css) [watch][$]\n* [深入理解 HTML: 语义, 标准与样式](http://www.amazon.com/gp/product/1590597656/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1590597656&linkCode=as2&tag=fronenddevejo-20&linkId=VFZVICLZO6GUZQI2) [read][$]\n* [CSS 定位](http://www.pluralsight.com/courses/css-positioning-1834) [watch][$]\n* [HTML 文档流](http://www.pluralsight.com/courses/html-document-flow-1837) [watch][$]\n* [HTML5 & CSS3 介绍](https://frontendmasters.com/courses/introduction-html5-css3/) [watch][$]\n* [CSS 中的绝对居中](http://codepen.io/shshaw/full/gEiDt) [read]\n* [CSS 盒模型](https://webdesign.tutsplus.com/courses/understanding-the-css-box-model) [watch]\n* [HTML 表单结构](https://webdesign.tutsplus.com/courses/solid-html-form-structure) [watch]\n* [HTML 语义化: 如何构建 Web 页面](https://webdesign.tutsplus.com/courses/semantic-html-how-to-structure-web-pages) [watch]\n\n**进阶学习:**\n\n* [从 CSS 1 到 CSS 4 的选择器参考](http://css4-selectors.com/selectors/) [read]\n* [CSS Diner](http://flukeout.github.io/) [interact]\n* [深入理解 CSS3](https://frontendmasters.com/courses/css3-in-depth/) [watch][$]\n* [atozcss.com/](http://www.atozcss.com/) [watch]\n* [Flexbox 完全指南](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) [read]\n\n**参考/文档:**\n\n* [htmlelement.info](http://htmlelement.info/)\n* [MDN CSS reference](https://developer.mozilla.org/zh/docs/Web/CSS/Reference)\n* [MDN HTML element reference](https://developer.mozilla.org/zh/docs/Web/HTML/Element)\n* [cssvalues.com/](http://cssvalues.com/)\n* [CSS TRIGGERS...A GAME OF LAYOUT, PAINT, AND COMPOSITE](http://csstriggers.com/)\n* [HTML attributes reference](https://developer.mozilla.org/zh/docs/Web/HTML/Attributes)\n\n**术语表:**\n\n* [HTML 元素编程术语参考](https://www.codecademy.com/articles/glossary-html)\n* [CSS 属性和选择器编程术语参考](https://www.codecademy.com/articles/glossary-css)\n\n**标准/规范:**\n\n* [W3C HTML5 标准](http://www.w3.org/TR/html5/): WWW 核心语言的第五个主要版本\n* [HTML 元素在线标准](https://html.spec.whatwg.org/multipage/semantics.html#semantics)\n* [HTML 语法](https://html.spec.whatwg.org/multipage/syntax.html#syntax)\n* [W3C HTML 规范](http://www.w3.org/standards/techs/html#w3c_all)\n* [全局属性](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes)\n* [CSS 2.2 规范](https://drafts.csswg.org/css2/)\n* [CSS 3 选择器](http://www.w3.org/TR/css3-selectors/)\n* [W3C CSS 规范](http://www.w3.org/Style/CSS/current-work#roadmap)\n\n**CSS 架构设计:**\n\n* [OOCSS](http://oocss.org/) [read]\n* [SMACSS](https://smacss.com/) [read][$]\n* [SMACSS](https://frontendmasters.com/courses/smacss/) [watch][$]\n* [Atomic Design](http://atomicdesign.bradfrost.com/) [read]\n\n**编写规范:**\n\n* [CSS 通用编写规范](https://github.com/necolas/idiomatic-css) [read]\n* [开发灵活的, 持久的和可持续的 HTML 和 CSS 的标准](http://mdo.github.io/code-guide/) [read]\n* [cssguidelin.es](http://cssguidelin.es/) [read]\n* [谷歌的 HTML/CSS 编程风格指南](http://google-styleguide.googlecode.com/svn/trunk/htmlcssguide.xml#General_Formatting)\n\n**HTML/CSS 简报:**\n\n* [HTML 5 Weekly](http://html5weekly.com/)\n* [CSS Weekly](http://css-weekly.com/archives/)\n\n**译者补充:**\n\n* [CSS 3 教程](https://waylau.gitbooks.io/css3-tutorial/content/docs/Introduction.html)\n* [HTML & CSS 测试](https://sitthetest.com/tests)\n* [Pro HTML5 Programming](http://apress.jensimmons.com/v5/pro-html5-programming/ch0.html)\n* [Pro CSS3 Animation](http://apress.jensimmons.com/v5/pro-css3-animation/ch2.html)\n* [CSS Protips](https://github.com/AllThingsSmitty/css-protips)\n* [精通CSS: 高级Web标准解决方案](http://www.amazon.cn/%E7%B2%BE%E9%80%9ACSS-%E9%AB%98%E7%BA%A7Web%E6%A0%87%E5%87%86%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88-%E5%B7%B4%E5%BE%B7/dp/B003IURKAM/ref=sr_1_1?s=books&ie=UTF8&qid=1446191443&sr=1-1)\n* [高流量网站CSS开发技术](http://www.amazon.cn/%E9%AB%98%E6%B5%81%E9%87%8F%E7%BD%91%E7%AB%99CSS%E5%BC%80%E5%8F%91%E6%8A%80%E6%9C%AF-%E8%82%AF%E5%B0%BC%E8%BF%AA/dp/B00FIIM9JO/ref=sr_1_2?s=books&ie=UTF8&qid=1446191443&sr=1-2)\n* [深入理解HTML5: 语义, 标准与样式](http://www.amazon.cn/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3HTML5-%E8%AF%AD%E4%B9%89-%E6%A0%87%E5%87%86%E4%B8%8E%E6%A0%B7%E5%BC%8F-%E5%B8%83%E6%8B%89%E5%BE%B7%E7%A6%8F/dp/B00DNDR5HM/ref=sr_1_1?ie=UTF8&qid=1446191387&sr=8-1)\n* [HTML 5与CSS 3权威指南](http://www.amazon.cn/HTML-5%E4%B8%8ECSS-3%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97-%E9%99%86%E5%87%8C%E7%89%9B/dp/B00B03VVRW/ref=sr_1_4?ie=UTF8&qid=1446191598&sr=8-4)"
  },
  {
    "path": "02-fedHandlebook-master/learning/interface.md",
    "content": "###接口/API 设计\n\n**数据(类似 JSON) API:**\n\n* [Build APIs You Won't Hate](http://apisyouwonthate.com/) [$][read]\n* [JSON API](http://jsonapi.org/) [read]\n\n**JavaScript API**\n\n* [Writing JavaScript APIs](http://blog.wolksoftware.com/writing-javascript-apis) [read]\n* [Designing Better JavaScript APIs](http://www.smashingmagazine.com/2012/10/designing-javascript-apis-usability/) [read]\n\n**译者补充**\n\n* [HTTP API 设计指南](https://github.com/cocoajin/http-api-design-ZH_CN)\n* [用 JSON 构建 API 的标准指南](http://wiki.jikexueyuan.com/project/json-api/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/internet.md",
    "content": "###Internet/web\n\n>互联网使用网络协议套件(TCP / IP)链接全球数十亿的设备, 是一个从区域到全球, 由数以百万计的私人, 公共, 学术, 商业, 和政府网络组成的全球性网络系统, 并通过一系列广泛的电子, 无线, 光纤网络技术相互链接. 互联网提供了广泛的信息资源和服务, 如早期的超文本文档和应用万维网(WWW), 电子邮件, 电话和点对点文件共享网络. - wikipedia\n\n* [WHAT IS THE INTERNET? or, \"You Say Tomato, I Say TCP/IP\"](http://www.20thingsilearned.com/en-US/what-is-the-internet/1) [read]\n* [How does the Internet work](http://www.w3.org/wiki/How_does_the_Internet_work) [read]\n* [How Does the Internet Work?\"](http://www.theshulers.com/whitepapers/internet_whitepaper/) [read]\n* [How Does the Internet Work?\"](http://www.theshulers.com/whitepapers/internet_whitepaper/) [read]\n* [How does the Internet Work?](http://web.stanford.edu/class/msande91si/www-spr04/readings/week1/InternetWhitepaper.htm) [read]\n* [How the Internet Works in 5 Minutes](https://www.youtube.com/watch?v=7_LPdttKXPc) [watch]\n* [How The Web Works](https://www.eventedmind.com/classes/how-the-web-works-7f40254c) [watch][$]\n* [How the Internet Works](https://www.khanacademy.org/partner-content/code-org/internet-works) [watch]\n"
  },
  {
    "path": "02-fedHandlebook-master/learning/js.md",
    "content": "###JavaScript\n\n>JavaScript 是一种高级的, 动态的, 无类型的和解释型的编程语言, 它已经在 ECMAScript 语言规范中被标准化. 跟 HTML 和 CSS 一样, JavaScript 是 WWW 内容生成的第三种必不可少的技术; 大多数的网会使用Javascript, 并且 Javascript 被所有现在Web浏览器支持. JavaScript 基于原型和函数优先的特点, 使它成为多范型的语言, 支持面向对象的, 命令式的, 和函数式编程风格. JavaScript 能提供 API 来处理文本, 数组, 日期和正则表达式, 但不包括任何 I/O, 如网络, 存储或图形工具, 对这些的依赖取决于宿主环境中嵌入了什么. - wikipedia.org\n\n**入门学习:**\n\n* [https://www.codecademy.com/en/tracks/javascript](https://www.codecademy.com/en/tracks/javascript) [interact]\n* [JavaScript 高级程序设计](http://www.amazon.cn/JavaScript%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1-%E6%B3%BD%E5%8D%A1%E6%96%AF/dp/B007OQQVMY/ref=sr_1_1?ie=UTF8&qid=1446188503&sr=8-1) [read][RMB]\n* [JavaScript Enlightenment](http://www.javascriptenlightenment.com/) [read]\n* [JavaScript面向对象精要](http://www.amazon.cn/JavaScript%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%B2%BE%E8%A6%81-%E7%BE%8E-%E5%B0%BC%E5%8F%A4%E6%8B%89%E6%96%AF/dp/B00VDSW6X2/ref=sr_1_1?ie=UTF8&qid=1446188606&sr=8-1) [read][RMB]\n* [Speaking JavaScript](http://speakingjs.com/es5/index.html) [read]\n* [你不知道的 JavaScript](https://github.com/getify/You-Dont-Know-JS/blob/master/up%20&%20going/README.md#you-dont-know-js-up--going) [read]\n* [理解 ECMAScript 6](https://github.com/nzakas/understandinges6) [read]\n* [JavaScript 模式](http://www.amazon.cn/JavaScript%E6%A8%A1%E5%BC%8F-%E6%96%AF%E7%89%B9%E5%87%A1%E6%B4%9B%E5%A4%AB/dp/B008QTG1HS/ref=sr_1_1?ie=UTF8&qid=1446188801&sr=8-1) [read][RMB]\n* [JS.Next: ES6](https://frontendmasters.com/courses/jsnext-es6/) [watch][$]\n* [Crockford on JavaScript - Volume 1: The Early Years](https://www.youtube.com/watch?v=JxAXlJEmNMg) [watch]\n* [Crockford on JavaScript - Chapter 2: And Then There Was JavaScript](https://www.youtube.com/watch?v=RO1Wnu-xKoY) [watch]\n* [Crockford on JavaScript - Act III: Function the Ultimate](https://www.youtube.com/watch?v=ya4UHuXNygM) [watch]\n* [Crockford on JavaScript - Episode IV: The Metamorphosis of Ajax](https://www.youtube.com/watch?v=Fv9qT9joc0M) [watch]\n* [Crockford on JavaScript - Part 5: The End of All Things](https://www.youtube.com/watch?v=47Ceot8yqeI) [watch]\n* [Crockford on JavaScript - Scene 6: Loopage](https://www.youtube.com/watch?v=QgwSUtYSUqA) [watch]\n* [JavaScript 模块](http://jsmodules.io/cjs.html) [read] \n\n**进阶学习:**\n\n* [JavaScript 函数式编程](http://www.amazon.cn/JavaScript%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B-%E4%BD%9B%E6%A0%BC%E6%96%AF/dp/B01264FOY4/ref=sr_1_1?ie=UTF8&qid=1446189590&sr=8-1) [read][RMB]\n* [ECMA-262 by Dmitry Soshnikov](http://dmitrysoshnikov.com/) [read]\n* [JavaScript 进阶](https://frontendmasters.com/courses/advanced-javascript/) [watch][$]\n* [JavaScript 语言精粹](http://www.amazon.cn/JavaScript%E8%AF%AD%E8%A8%80%E7%B2%BE%E7%B2%B9-%E9%81%93%E6%A0%BC%E6%8B%89%E6%96%AF%E2%80%A2%E5%85%8B%E7%BD%97%E5%85%8B%E7%A6%8F%E5%BE%B7/dp/B0097CON2S/ref=sr_1_1?ie=UTF8&qid=1446189734&sr=8-1) [read][RMB]\n* [你不知道的 JS: 作用域 & 闭包](https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/README.md#you-dont-know-js-scope--closures) [read]\n* [你不知道的 JS: this & 原型](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes) [read]\n* [你不知道的 JS: 数据类型 & 语法](https://github.com/getify/You-Dont-Know-JS/blob/master/types%20&%20grammar/README.md#you-dont-know-js-types--grammar) [read]\n* [你不知道的 JS: 异步 & 性能](https://github.com/getify/You-Dont-Know-JS/blob/master/async%20&%20performance/README.md#you-dont-know-js-async--performance) [read]\n* [你不知道的 JS: ES6 & Beyond](https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20&%20beyond/README.md#you-dont-know-js-es6--beyond) [read]\n* [Eloquent JavaScript](http://eloquentjavascript.net/) [read]\n* [测试驱动的 JavaScript 开发](http://www.amazon.cn/%E6%B5%8B%E8%AF%95%E9%A9%B1%E5%8A%A8%E7%9A%84JavaScript%E5%BC%80%E5%8F%91-%E7%BA%A6%E7%BF%B0%E6%A3%AE/dp/B0077KA3J4/ref=sr_1_1?ie=UTF8&qid=1446190077&sr=8-1) [read][RMB]\n* [JavaScript Allonge](https://leanpub.com/javascriptallongesix) [read][$]\n* [JavaScript With Promises](http://www.amazon.com/JavaScript-Promises-Daniel-Parker/dp/1449373216/ref=pd_sim_sbs_14_5) [read][$]\n* [高性能 JavaScript](http://www.amazon.cn/%E9%AB%98%E6%80%A7%E8%83%BDJavaScript-%E5%B0%BC%E5%8F%A4%E6%8B%89%E6%96%AF-%E6%B3%BD%E5%8D%A1%E6%96%AF/dp/B013SGB2AO/ref=sr_1_1?ie=UTF8&qid=1446190545&sr=8-1) [read][$]\n* [JavaScript 正则表达式入门](http://codylindley.com/techpro/2013_05_14__javascript-regular-expression-/) [read]\n* [正则表达式使用](http://www.lynda.com/Regular-Expressions-tutorials/Using-Regular-Expressions/85870-2.html) [watch][$]\n\n**参考/文档:**\n\n* [MDN JavaScript reference](https://developer.mozilla.org/zh/docs/Web/JavaScript/Reference)\n\n**术语表/百科全书:**\n\n* [JavaScript 术语表](https://www.codecademy.com/articles/glossary-javascript)\n* [JavaScript 百科全书](http://www.crockford.com/javascript/encyclopedia/)\n\n**标准/规范:**\n\n* [ECMAScript® 2015 语言规范](http://www.ecma-international.org/ecma-262/6.0/)\n* [ECMA262 的状态, 进度和文档](https://github.com/tc39/ecma262)\n\n**编程规范:**\n\n* [Node.js 风格指南](https://github.com/felixge/node-style-guide)\n* [JavaScript 开发原则](https://github.com/rwaldron/idiomatic.js)\n* [Airbnb JavaScript 风格指南](http://airbnb.io/javascript/)\n\n**JavaScript 简报, 新闻和播客:**\n\n* [JavaScript Jabber](https://devchat.tv/js-jabber/)\n* [JavaScript Weekly](http://javascriptweekly.com/)\n* [Echo JS](http://www.echojs.com/)\n* [JavaScript Kicks](http://javascriptkicks.com/)\n* [javascript.com](https://www.javascript.com/news)\n* [FiveJS](https://fivejs.codeschool.com/)\n* [JavaScript Live](https://jslive.com/)\n\n**译者补充:**\n\n* [重新认识 JavaScript](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript)\n* [JavaScript 标准参考教程](http://javascript.ruanyifeng.com/)\n* [JavaScript 秘密花园](http://bonsaiden.github.io/JavaScript-Garden/zh/)\n* [浅谈JavaScript系列](http://my.oschina.net/os2015/blog/484017)\n* [深入理解JavaScript系列](http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html)\n* [JavaScript Promise 迷你书](http://liubin.github.io/promises-book/)\n* [学用 JavaScript 设计模式](http://www.oschina.net/translate/learning-javascript-design-patterns)\n* [ES 6 入门(中文)](http://es6.ruanyifeng.com/)\n* [ES 6 入门(英文)](https://leanpub.com/understandinges6/read)\n* [ES 6 In Depth 系列](http://www.infoq.com/cn/es6-in-depth/)\n* [ES6 Overview in 350 Bullet Points](https://ponyfoo.com/articles/es6)\n* [JS The Right Way](http://jstherightway.org/)\n* [JavaScript 新手教程](http://jaskokoyn.com/javascript-tutorial-series/)\n* [JavaScript 进阶教程](http://jaskokoyn.com/advanced-javascript-tutorial-series/)\n* [国外优秀 JavaScript 资源推荐](http://www.ido321.com/302.html)\n* [awesome-javascript1](https://github.com/wwsun/awesome-javascript) [awesome-javascript2](https://github.com/sorrycc/awesome-javascript)\n* [JavaScript 免费编程电子书索引(中文)](https://github.com/justjavac/free-programming-books-zh_CN#javascript)\n* [JavaScript：40+基本的 Web 开发工具](http://www.ido321.com/1543.html)\n* [JavaScript Puzzlers](http://javascript-puzzlers.herokuapp.com/)\n* [JavaScript Test](https://sitthetest.com/tests)\n* [Awesome JavaScript-CN](https://github.com/jobbole/awesome-javascript-cn)\n"
  },
  {
    "path": "02-fedHandlebook-master/learning/json.md",
    "content": "###JSON(JavaScript Object Notation)\n\n>JSON, 有时也称 JavaScript 对象表示, 是一种使用人类可读的文本传输由键值对组成的数据对象的开放格式. 对于异步浏览器/服务器通信(AJAJ), JSON 是主要的数据格式, 很大程度上代替了 XML(AJAX).\n\n>尽管最初是从 JavaScript 脚本语言衍生而来, 但是 JSON 是语言无关性的数据格式, 在许多编程语言中, 代码解析和生成 JSON 是很容易的.\n\n>JSON 的格式最初是由 Douglas Crockford 指定的, 但目前却被描述成两种标准: RFC 7159 和 ECMA-404. ECMA 标准只允许被合法的语法语句描述, 而 RFC 则提供了一些语义化描述和安全考虑. JSON 的官方网络媒体类型 application / JSON, 扩展名是 .json. - wikipedia.org\n\n**综合学习:**\n\n* [json.com](https://www.json.com/) [read]\n* [什么是 JSON](https://mijingo.com/lessons/what-is-json/) [watch]\n* [JSON 权威指南](http://www.amazon.com/Introduction-JavaScript-Object-Notation-Point/dp/1491929480/ref=pd_sim_sbs_14_1) [read][$]\n\n**参考/文档**\n\n* [json.org/](http://json.org/) [read]\n\n**标准/规范:**\n\n* [ECMA-404 JSON 数据交互格式](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)\n* [RFC 7159 JSON 数据交互格式](https://tools.ietf.org/html/rfc7159)\n\n**架构设计:**\n\n* [JSON API](http://jsonapi.org/)\n\n**译者补充:**\n\n* [JSON 系列文章](http://jaskokoyn.com/json-tutorial-series/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/learn-from.md",
    "content": "###前端开发者从哪里学\n\n关于前端开发, 独立学习会慢慢地变得没有意义. 前端开发的高级从业人员已经产出足够多的内容, 而你只要通过关注前端\"资讯\"(简报, 资讯 & 博客), 跟着社区学习就行."
  },
  {
    "path": "02-fedHandlebook-master/learning/module.md",
    "content": "###模块加载和依赖管理\n\n**综合学习:**\n\n* [用 Browserify 创建 JavaScript 模块](http://www.pluralsight.com/courses/creating-javascript-modules-browserify) [watch][$]\n* [Webpack 基本原理](http://www.pluralsight.com/courses/webpack-fundamentals) [watch]\n* [browserify-handbook](https://github.com/substack/browserify-handbook) [read]\n* [ES6 模块](http://developer.telerik.com/featured/choose-es6-modules-today/) [read]\n\n**参考/文档:**\n\n* [browserify](http://browserify.org/)\n* [system.js](https://github.com/systemjs/systemjs)\n* [webpack](http://webpack.github.io/)\n\n**译者补充:**\n\n* [React Webpack cookbook](https://fakefish.github.io/react-webpack-cookbook/)\n* [详解前端模块化工具-Webpack](http://www.ido321.com/1646.html)"
  },
  {
    "path": "02-fedHandlebook-master/learning/multi-things-dev.md",
    "content": "###多平台开发\n\n![multi-things-dev](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/things.jpg)\n\n一个网站或应用不仅能运行在各种台式机, 笔记本电脑, 平板和手机, 还能运行于少部分其它设备(手表, 温控器, 电冰箱等等). 你将怎么决定支持哪些平台和为支持这些平台, 怎么去开发, 这被称为多平台开发策略. 接下来, 我会列出常见的多平台开发策略:\n\n* 创建 [响应式 Web 设计](https://en.wikipedia.org/wiki/Responsive_web_design) (RWD) 网站/APP\n* 创建 [RESS](http://www.lukew.com/ff/entry.asp?1392) (基于服务端组件的响应式 Web 设计) 网站/APP\n* 创建 [自适应/渐进增强地](https://en.wikipedia.org/wiki/Adaptive_web_design) 网站/APP\n* 对每一个或每一组平台建立一套网站, Web 应用, 本地应用或混合应用\n* 尝试修改你用策略1, 策略2或策略创建的应用. 这可能和点缀与屏幕大小无关的部分 UI 一样简单, 也可以试图完全支持其他平台与整个 UI.\n\n**入门学习:**\n\n* [自适应网页设计](http://adaptivewebdesign.info/) [read][$]\n* [设计与渐进增强](https://www.filamentgroup.com/dwpe/) [read]\n* [响应式排版](https://www.pluralsight.com/courses/responsive-typography) [watch][$]\n* [响应式 Web 设计](https://frontendmasters.com/courses/responsive-web-design/) [watch][$]\n* [响应式 HTML 邮件设计](https://frontendmasters.com/courses/responsive-email/) [watch][$]\n* [Designing Multi-Device Experiences: An Ecosystem Approach to User Experiences across Devices](http://www.amazon.com/Designing-Multi-Device-Experiences-Ecosystem-Approach/dp/1449340385/ref=pd_sim_14_8) [read][$]\n* [响应式 Web 设计原理](https://www.udacity.com/courses/web-development) [watch]\n* [响应式图片](https://www.udacity.com/course/responsive-images--ud882) [watch]\n* [移动 Web 开发](https://www.udacity.com/course/mobile-web-development--cs256) [watch]\n\n**译者补充:**\n\n* [移动 Web 调试工具: weinre](https://people.apache.org/~pmuellr/weinre-docs/latest/)\n* [Responsive demos & tutorials](http://navnav.co/)\n* [打造最舒适的 Webview 调试环境](https://github.com/riskers/blog/issues/11)"
  },
  {
    "path": "02-fedHandlebook-master/learning/networks.md",
    "content": "###HTTP/网络(包括 CORS 和 WebSockets)\n\n>**HTTP**, The Hypertext Transfer Protocol, 即超文本传输协议, 是一个用于分布式, 协作和超媒体信息系统的应用协议, 是 WWW 数据通信的基础. - Wikipedia\n\n>**CORS**, Cross-origin resource sharing, 即跨域资源共享, 是一种允许网页上受限制的资源(如: 字体)可以从该资源所在域之外的另一个域被请求. - Wikipedia\n\n>**WebSockets**, WebSocket 是一种协议, 提供了在一个 TCP 连接上进行全双工通信的渠道. 在 2011 年, IETF 将 WebSocket 协议标准化为 RFC 6455, 并且 W3C 正在标准化 Web IDL 的WebSocket API. - Wikipedia\n\n**HTTP**\n\n* [HTTP: 每个 Web 开发者必须知道的协议(一)](http://code.tutsplus.com/tutorials/http-the-protocol-every-web-developer-must-know-part-1--net-31177) [read]\n* [HTTP: 每个 Web 开发者必须知道的协议(二)](http://code.tutsplus.com/tutorials/http-the-protocol-every-web-developer-must-know-part-2--net-31155) [read]\n* [HTTP 基本原理](http://www.pluralsight.com/courses/xhttp-fund) [watch][$]\n* [HTTP 浅谈](http://code.tutsplus.com/series/http-succinctly--net-33683) [read]\n* [高性能网络浏览: 每个 Web 开发人员都应该了解网络和网络性能](http://chimera.labs.oreilly.com/books/1230000000545/index.html) [read]\n\n**CORS**\n\n* [60秒内的 HTTP 状态码变化](http://webdesign.tutsplus.com/tutorials/http-status-codes-in-60-seconds--cms-24317) [watch]\n* [HTTP 访问控制 (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) [read]\n* [CORS 实战](https://www.manning.com/books/cors-in-action) [read][$]\n\n**WebSockets**\n\n* [WebSocket: 轻量级的 C/S 通信](http://www.amazon.com/WebSocket-Client-Server-Communications-Andrew-Lombardi/dp/1449369278/ref=sr_1_1) [read][$]\n* [WebSocket 协议](https://tools.ietf.org/html/rfc6455) [read]\n* [用 WebSockets 连接 Web](https://code.tutsplus.com/courses/connect-the-web-with-websockets) [watch]\n\n\n译者补充:\n\n* [HTTP/2 资料汇总](https://imququ.com/post/http2-resource.html)\n* [HTTP 权威指南](http://www.amazon.cn/gp/product/B008XFDQ14?keywords=http&qid=1445943752&ref_=sr_1_1&sr=8-1) [read][RMB]\n* [图解 HTTP](http://www.amazon.cn/gp/product/B00JTQK1L4?keywords=http&qid=1445943752&ref_=sr_1_2&sr=8-2) [read][RMB]\n* [图解 TCP/IP](http://www.amazon.cn/gp/product/B00DMS9990?keywords=http&qid=1445943752&ref_=sr_1_3&sr=8-3) [read][RMB]\n"
  },
  {
    "path": "02-fedHandlebook-master/learning/news-podcasts.md",
    "content": "###前端简报, 资讯网站 & 博客\n\n**综合的前端简报, 资讯 & 博客**\n\n* [shoptalkshow.com](http://shoptalkshow.com/)\n* [frontendfront.com](http://frontendfront.com/)\n* [webtoolsweekly.com](http://webtoolsweekly.com/)\n* [O'Reilly Web Platform Radar](http://radar.oreilly.com/web-platform)\n* [The Web Platform Podcast](http://radar.oreilly.com/web-platform)\n* [The Web Platform Podcast](http://thewebplatform.libsyn.com/)\n* [The Web Ahead](http://thewebahead.net/)\n* [The Big Web Show](http://5by5.tv/bigwebshow)\n* [Fresh Brewed Frontend](https://freshbrewed.co/frontend/)\n* [Mobile Web Weekly](http://mobilewebweekly.co/)\n* [Open Web Platform Daily Digest](http://webplatformdaily.org/)\n* [FRONT-END DEV weekly](http://frontenddevweekly.com/)\n* [Web Design Weekly](https://web-design-weekly.com/)\n* [Front-end News in 5 Minutes](https://frontendfive.codeschool.com/)\n* [TTL](http://ttlpodcast.com/)\n* [Viewsources](https://viewsourc.es/)\n* [Web Components Weekly](http://webcomponentsweekly.me/)\n\n**HTML/CSS 简报:**\n\n* [HTML 5 Weekly](http://html5weekly.com/)\n* [CSS Weekly](http://css-weekly.com/archives/)\n\n**JavaScript 简报, 资讯 & 博客:**\n\n* [Javascript Jabber](https://devchat.tv/js-jabber/)\n* [JavaScript Weekly](http://javascriptweekly.com/)\n* [Echo JS](http://www.echojs.com/)\n* [JavaScript Kicks](http://javascriptkicks.com/)\n* [javascript.com](https://www.javascript.com/news)\n* [FiveJS](https://fivejs.codeschool.com/)\n* [JavaScript Live](https://jslive.com/)\n\n**图形和动画简报 & 博客:**\n\n* [Motion and Meaning](http://motionandmeaning.io/)\n* [SVG Immersion Podcast](http://svgimmersion.com/)\n* [Web Animation Weekly](http://rachelnabors.us1.list-manage.com/subscribe?u=0a8f219cf8284562f91a26ee9&id=d60f6683d2)\n* [Responsive Images Community Group Newsletter](https://responsiveimages.org/#newsletter)\n*\n\n**译者补充:**\n\n* [奇舞团](http://www.75team.com/weekly/)\n* [FEX](http://fex.baidu.com/weekly/)\n* [开发者头条](http://toutiao.io/)\n* [码农周刊](http://weekly.manong.io/issues/)\n* [OurJS](http://ourjs.com/)\n* [编程狂人](http://www.tuicool.com/mags)\n* [一周拾遗](http://www.tuicool.com/articles/weekly)\n* [设计匠艺](http://www.tuicool.com/mags/design)"
  },
  {
    "path": "02-fedHandlebook-master/learning/node.md",
    "content": "###Node.js\n\n>Node.js 用于开发服务端 Web 应用, 是一个开源的, 跨平台的运行时环境. Node.js 应用由 JavaScript 编写, 可以在 OS X, Microsoft Windows, Linux, FreeBSD, NonStop, IBM AIX, IBM System z and IBM i 上的 Node.js 运行时环境运行. Node.js 的开发和维护有 Node.js 基金会提供支持, 这是 Linux 基金会的一个合作项目. \n\n>Node.js 提供一个事件驱动的体系架构和非阻塞的 I/O 设计来优化应用程序的吞吐量和实时web应用程序的可伸缩性, 它使用谷歌的 V8 JavaScript 引擎来执行代码, 并有大量的由 JavaScript 编写的基础模块. Node.js 包含内置的模块, 允许应用程序作为一个web服务器而不依赖类似  Apache HTTP Server, Nginx 或 IIS 的软件. - wikipedia\n\n**入门学习:**\n\n* [从事件角度介绍 Node.js](https://www.eventedmind.com/classes/introduction-to-node-js-4c0326de) [watch][$]\n* [Node 的艺术](https://github.com/maxogden/art-of-node#the-art-of-node) [read]\n* [Node.js 基础](http://teamtreehouse.com/library/nodejs-basics) [watch][$]\n* [io.js 和 Node.js 入门](http://www.pluralsight.com/courses/running-node-applications-io-js) [watch][$]\n* [全面学习 Nodes](https://learnallthenodes.com/episodes/1-what-is-nodejs) [watch]\n* [Node 初学者书籍](https://leanpub.com/nodebeginner) [read][$]\n* [Node.js 介绍](http://www.pluralsight.com/courses/node-intro) [watch][$]\n* [Node.js 实战](https://www.manning.com/books/node-js-in-practice#downloads) [read][$]\n* [Nodeschool.io](http://nodeschool.io/) [code]\n\n**译者补充:**\n\n* [Node.js 经典入门教程(中文版)](http://nodebeginner.org/index-zh-cn.html)\n* [从零开始学 Node.js 系列文章](http://blog.fens.me/series-nodejs/)\n* [Node.js 入门](https://cnodejs.org/getstart)\n* Node.js 中文文档: [1](https://davidcai1993.gitbooks.io/nodejs-api-doc-in-chinese/content/)  [2](http://wiki.jikexueyuan.com/project/nodejs/)  [3](http://www.nodeapp.cn/)\n* [Node.js 风格指南](https://github.com/wwsun/node-style-guide) \n* Express 中文文档: [1](http://www.expressjs.com.cn/) [2](http://expressjs.jser.us/)\n* [Express 指南](http://wiki.jikexueyuan.com/project/express-guide/)\n* Koa中文文档: [1](http://koa.rednode.cn/) [2](http://koa.bootcss.com/) [3](https://github.com/guo-yu/koa-guide) [4](http://koajs.cn/)\n* [NodeCloud](http://www.nodecloud.org/)\n* [Node面试题](https://github.com/jimuyouyou/node-interview-questions)\n* [Node.js 中文资料导航](https://github.com/youyudehexie/node123)\n* [Node.js 开发常用资源(awesome-nodejs)1](https://github.com/sindresorhus/awesome-nodejs) [开发资源2](https://github.com/lyfeyaj/awesome-resources#nodejs) [开发资源3](https://github.com/vndmtrx/awesome-nodejs)\n* [Node-books](https://github.com/pana/node-books)"
  },
  {
    "path": "02-fedHandlebook-master/learning/offline.md",
    "content": "###离线开发\n\n离线开发(又称离线优先)是一个领域常识和围绕设备并不总是连接到互联网或电源的开发实践的讨论. \n\n**综合学习:**\n\n* [offlinefirst.org](http://offlinefirst.org) [read]\n* [HTML5 离线 Web 应用](http://apress.jensimmons.com/v5/pro-html5-programming/ch12.html) [read]\n* [离线优先](http://www.webdirections.org/offlineworkshop/ibooksDraft.pdf) [read]\n* [创建离线应用你需要知道的一切](https://github.com/pazguille/offline-first) [read]"
  },
  {
    "path": "02-fedHandlebook-master/learning/optimizing.md",
    "content": "###网站性能优化\n\n>Web 性能优化, WPO, 或网站优化是提高用户浏览器的网站加载和显示速度的知识领域. 由于网速整体提高了, 很适合网站的管理者和维护者去考虑网站呈现给访问者所花费的时间了. - wikipedia\n\n**综合学习:**\n\n* [网站性能](https://frontendmasters.com/courses/website-performance/) [watch][$]\n* [高性能网站建设指南：前端工程师技能精髓](http://www.amazon.cn/%E9%AB%98%E6%80%A7%E8%83%BD%E7%BD%91%E7%AB%99%E5%BB%BA%E8%AE%BE%E6%8C%87%E5%8D%97-%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%8A%80%E8%83%BD%E7%B2%BE%E9%AB%93-%E5%8F%B2%E8%92%82%E5%A4%AB%C2%B7%E6%A1%91%E5%BE%B7%E6%96%AF/dp/B00XI979P4/ref=sr_1_1) [read][RMB]\n* [高性能网站建设进阶指南：Web开发者性能优化最佳实践](http://www.amazon.cn/%E9%AB%98%E6%80%A7%E8%83%BD%E7%BD%91%E7%AB%99%E5%BB%BA%E8%AE%BE%E8%BF%9B%E9%98%B6%E6%8C%87%E5%8D%97-Web%E5%BC%80%E5%8F%91%E8%80%85%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5-%E6%A1%91%E5%BE%B7%E6%96%AF%E3%80%80-%E5%8F%A3%E7%A2%91%E7%BD%91%E5%89%8D%E7%AB%AF%E5%9B%A2%E9%98%9F/dp/B0129346KK/ref=sr_1_1) [read][RMB]\n* [Web 性能实践日志](http://www.amazon.cn/Web%E6%80%A7%E8%83%BD%E5%AE%9E%E8%B7%B5%E6%97%A5%E5%BF%97-%E6%96%AF%E6%89%98%E6%89%AC/dp/B00K4RUL94/ref=sr_1_1) [read][RMB]\n* [JavaScript 性能宝石](http://javascriptrocks.com/) [read]\n* [性能日历](http://calendar.perfplanet.com/2014/) [read]\n* [页面速度见解规则](https://developers.google.com/speed/docs/insights/rules) [read]\n* [网站性能优化](https://www.udacity.com/course/website-performance-optimization--ud884) [watch]\n* [浏览器渲染优化](https://www.udacity.com/course/browser-rendering-optimization--ud860) [watch]\n* [Using WebPageTest](http://www.amazon.com/Using-WebPageTest-Rick-Viscomi/dp/1491902590/ref=sr_1_1) [read][$]\n* [Web 性能权威指南](http://www.amazon.cn/Web%E6%80%A7%E8%83%BD%E6%9D%83%E5%A8%81%E6%8C%87%E5%8D%97-%E6%A0%BC%E9%87%8C%E9%AB%98%E5%88%A9%E5%85%8B/dp/B00JMKWHFU/ref=sr_1_1) [read][RMB]\n* [perf.rocks](http://perf.rocks)\n\n**译者补充:**\n\n* [谷歌的性能优化指南](https://developers.google.com/web/fundamentals/performance/?hl=zh-cn)\n* [前端性能优化指南](https://github.com/kahn1990/web_performance_optimization)\n* [AlloyTeam: Web 性能优化专栏](http://www.alloyteam.com/2015/11/alloyteam-present-dry-event-countdown-2-days-performance-optimization-blog/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/package.md",
    "content": "###包管理器\n\n>包管理器或包管理系统是一系列软件工具的集合, 这些软件工具用和电脑操作系统一致的方式, 使应用的安装, 升级, 配置和删除软件包的过程自动化, 它通常维护一个数据库软件的依赖和版本信息, 防止软件不匹配和无法跟踪. - wikipedia\n\n**综合学习:**\n\n* [Bower 基本原理](http://www.pluralsight.com/courses/bower-fundamentals) [watch][$]\n* [包管理器: 前端开发人员入门指南](http://codylindley.com/techpro/2013_04_12__package-managers-an-introducto/) [read]\n* [NPM: 包的上传和运行](http://www.lynda.com/Developer-Web-Development-tutorials/Up-Running-NPM-Node-Package-Manager/409274-2.html) [watch][$]\n* [NPM 基础](http://teamtreehouse.com/library/npm-basics) [watch][$]\n* [NPM 书籍](ttps://leanpub.com/npm) [read]\n* [NPM & Bower: 依赖版本管理](http://developer.telerik.com/featured/mystical-magical-semver-ranges-used-npm-bower/) [read]\n\n**参考/文档:**\n\n* [Bower](http://bower.io/)\n* [jspm.io](http://jspm.io/)\n* [NPM](https://www.npmjs.com/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/react.md",
    "content": "###React\n\n>**React** - 用于构建用户界面的JAVASCRIPT库\n\n>**仅仅是UI** - 许多人使用React作为MVC架构的V层。 尽管React并没有假设过你的其余技术栈， 但它仍可以作为一个小特征轻易地在已有项目中使用\n\n>**虚拟DOM** - React为了更高超的性能而使用虚拟DOM作为其不同的实现。 它同时也可以由服务端Node.js渲染 － 而不需要过重的浏览器DOM支持\n\n>**数据流** - React实现了单向响应的数据流，从而减少了重复代码，这也是它为什么比传统数据绑定更简单。\n\n**入门教程:**\n\n* [React 入门实例教程](http://www.ruanyifeng.com/blog/2015/03/react.html)\n* [React 介绍及实践教程](http://www.ibm.com/developerworks/cn/web/1509_dongyue_react/index.html) 此文中的demo实现: [demo](https://github.com/dwqs/react_practice/tree/master/react-started)\n* [React 入门教程](https://hulufei.gitbooks.io/react-tutorial/content/webpack.html)\n* [Learning React](https://github.com/yiminghe/learning-react)\n* [SurviveJS - Table of Contents](http://survivejs.com/webpack_react/)\n\n**进阶学习:**\n\n* [深入浅出 React 系列](http://www.infoq.com/cn/articles/react-art-of-simplity)\n* [React.js 生态系统概览](http://www.inkpaper.io/blog/post/2015/10/18/navigating-the-react-ecosystem.html)\n* [详解React Flux架构工作方式](http://www.csdn.net/article/2015-08-31/2825587-react-flux)\n* [Awesome React](https://github.com/enaqx/awesome-react)\n* [AlloyTeam: React 专栏](http://www.alloyteam.com/2015/11/alloyteam-event-countdown-3-days-dry-presenting-react-technology-blog/)\n\n**手册参考:**\n\n* [React 速查手册](http://ricostacruz.com/cheatsheets/react.html)\n* [React Cheat Sheet](http://reactcheatsheet.com/)\n* [React Style Guide](https://github.com/dwqs/react-style-guide)\n\n**工具:**\n\n* [Awesome Redux](https://github.com/xgrommx/awesome-redux)\n* [Webpack 中文文档](https://wohugb.gitbooks.io/webpack/content/)\n* [webpack学习笔记](http://blog.csdn.net/zhbhun/article/details/47208885)\n* [Webpack傻瓜式指南](https://github.com/vikingmute/webpack-for-fools)\n* [React Webpack Cookbook](https://fakefish.github.io/react-webpack-cookbook/)\n* [Webpack](https://github.com/ruanyf/webpack-demos)\n* [React Toolbox](http://react-toolbox.com/)\n\n**React Native:**\n\n* [React Native Lession](https://github.com/vczero/react-native-lession)\n* [Awesome React Native](https://github.com/jondot/awesome-react-native)\n* [React Native 探索系列](http://www.infoq.com/cn/articles/react-native-overview)\n* [React Native专题](http://www.jianshu.com/p/96febc4fec45)\n* [React Native 学习指南](https://github.com/ele828/react-native-guide)\n* [React Native 中文版](http://wiki.jikexueyuan.com/project/react-native/)"
  },
  {
    "path": "02-fedHandlebook-master/learning/security.md",
    "content": "###安全\n\n* [浏览器安全手册](https://code.google.com/p/browsersec/wiki/Main) [read]\n* [HTML5 安全手册](https://html5sec.org/#javascript) [read]\n* [前端安全](https://mikewest.org/2013/09/frontend-security-frontendconf-2013) [watch]\n* [Security for Web Developers: Using JavaScript, HTML, and CSS](http://www.amazon.com/Security-Web-Developers-Using-JavaScript/dp/1491928646/ref=sr_1_11) [read][$]\n* [现代 Web 应用安全指南](http://lcamtuf.coredump.cx/tangled/) [read][$]\n* [Web 安全基础](https://github.com/vasanthk/web-security-basics) [read]"
  },
  {
    "path": "02-fedHandlebook-master/learning/self-direct-learning.md",
    "content": "###自主学习\n\n这个部分集中于个人能用来指导自己作为前端开发者的学习进度的免费和付费资源(视频训练, 书籍等等).\n\n这些资源包括免费的和付费的, 付费的资源是以美元为单位结算的.\n\n作者认为, 任何有着正确的决心和奉献精神的人都能教自己如何成为一个前端开发者, 除了一台能连接到Web的电脑和用于付费视频训练, 书籍的现金, 其它都不需要.\n\n下面是一些我通常推荐的视频学习资料(专注技术):\n\n* [Frontend Masters](https://frontendmasters.com/)\n* [pluralsight.com](http://www.pluralsight.com/)\n* [tutsplus.com](https://tutsplus.com/courses)\n* [lynda.com](http://www.lynda.com/) \n* [treehouse](https://teamtreehouse.com/)\n* [mijingo](https://mijingo.com/)\n* [codeschool.com](https://www.codeschool.com/)\n* [laracasts](https://laracasts.com/)\n* [eventedmind.com](https://www.eventedmind.com/)\n* [egghead.io](https://egghead.io/)\n* [codecademy.com](https://codecademy.com/)\n* [Khan Academy](https://www.khanacademy.org/computing/computer-programming)\n* [Tagtree](http://tagtree.tv/library)\n* [Udacity](https://www.udacity.com/courses/web-development) [careful, quality varies]\n\n**译者补充:**\n\n* [号称最全前端开发学习资源~~学下来能上天了](https://github.com/AutumnsWind/Front-end-tutorial)\n* [国外有哪些高质量js技术博客?](http://segmentfault.com/q/1010000002773179)\n* [你经常访问的技术社区或者技术博客（IT类）有哪些?](http://segmentfault.com/q/1010000000094981)\n* [国外的前端开发社区有哪些](http://segmentfault.com/q/1010000002899648)\n* [前端开发初学 书籍推荐](http://segmentfault.com/q/1010000002927558)\n* [MDN Web 技术文档](https://developer.mozilla.org/zh-CN/docs/Web)\n* [MSDN Web](https://msdn.microsoft.com/web-app-development-msdn)\n* [SegmentFault](http://segmentfault.com/)\n* [前端范](http://qianduanfan.com/)\n* [w3cplus](http://www.w3cplus.com/)\n* [w3ctech](http://www.w3ctech.com/)\n* [w3cfuns](http://www.w3cfuns.com/)\n* [w3help](http://www.w3help.org/zh-cn/kb/)\n* [jobbole](http://web.jobbole.com/)\n* [div.io](http://div.io/#/welcome)\n* [v2ex](https://www.v2ex.com/)\n* [CSDN](http://blog.csdn.net/web/newest.html)\n* [cnblogs](http://www.cnblogs.com/cate/108703/)\n* [博客园知识库](http://kb.cnblogs.com/list/1002/)\n* [前端乱炖](http://www.html-js.com/)\n* [慕课网](http://www.imooc.com/)\n* [极客学院](http://www.jikexueyuan.com/)\n* [网易云课堂](http://study.163.com/)\n* [The State of Web Type](http://stateofwebtype.com/)\n* [Frontend Dev Bookmarks](https://github.com/dypsilon/frontend-dev-bookmarks)\n"
  },
  {
    "path": "02-fedHandlebook-master/learning/seo.md",
    "content": "###SEO: 搜索引擎优化\n\n>搜索引擎优化(SEO)是在自然的搜索结果中, 影响一个网站或者网页可见性的过程. 一般来说, 越靠前出现(或在搜索结果页中权重高的网页)的网页, 和频繁出现在搜索结果列表中的网站, 就能获取更多来自搜索引擎的用户. SEO 会定位于不同类型的搜索, 包括图片搜索, 本地搜索, 视频搜索, 学术搜索, 新闻搜索和特定行业的垂直搜索引擎. - wikipedia\n\n**综合学习:**\n\n* [David Booth: SEO 基本原理](http://www.lynda.com/Analytics-tutorials/SEO-Fundamentals/187858-2.html) [watch][$]\n* [Paul Wilson: SEO 基本原理](http://www.pluralsight.com/courses/seo-fundamentals) [watch][$]\n* [SEO: Web 设计者](https://webdesign.tutsplus.com/courses/seo-for-web-designers) [watch][$]\n* [谷歌搜索引擎优化指南](http://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf) [read]\n* [SEO 优化指导](http://www.hobo-web.co.uk/seo-tutorial/) [read]"
  },
  {
    "path": "02-fedHandlebook-master/learning/static.md",
    "content": "###静态网页生成器\n\n静态网页生成器, 是使用服务器端代码编写(如: ruby, php, python, nodeJS 等...), 用静态文本数据 + 模板, 生成从服务器发送到客户端的静态 HTML 文件.\n\n**综合学习:**\n\n* [静态网页生成器](http://www.oreilly.com/web-platform/free/static-site-generators.csp) [read]"
  },
  {
    "path": "02-fedHandlebook-master/learning/test.md",
    "content": "###JS 测试\n\n>**单元测试** -  在计算机程序中, 单元测试是一种软件测试方法, 通过独立的代码单元, 一个或多个计算机程序模块的集合, 和相关联的控制数据, 使用程序和操作过程进行测试, 以确定它们是否适合使用. 直观地说, 可以将一个单元视为应用程序最小的, 可测试的一部分. - Wikipedia\n\n>**功能测试** - 功能测试是一个质量保证(QA)的过程, 也是一种基于在软件组件测试规范之下的测试案例的黑盒子测试. 功能测试会检查程序的输入和输出, 但很少去考虑内部地程序结构(跟白盒子测试不同). 功能测试通常描述了系统\"做什么\". - Wikipedia\n\n>**集成测试** - 在软件测试中, 集成测试(也称集成和测试, 缩写为 I&T)是各个软件模块结合起来, 作为一个整体进行测试的阶段, 之后便是单元测试和验证测试. 集成测试把已经通过的单元测试作为输入模块,  将它们组织成更大的聚集, 在集成测试中应用计划用于这些聚集而被定义的测试, 并提供为集成测试做好准备的集成系统作为其输出. - Wikipedia\n\n**综合学习:**\n\n* [测试驱动的 JavaScript 开发](http://www.amazon.cn/%E6%B5%8B%E8%AF%95%E9%A9%B1%E5%8A%A8%E7%9A%84JavaScript%E5%BC%80%E5%8F%91-%E7%BA%A6%E7%BF%B0%E6%A3%AE/dp/B0077KA3J4/ref=sr_1_1) [read][RMB]\n* [编写可测试的 JavaScript 代码](http://www.amazon.cn/%E7%BC%96%E5%86%99%E5%8F%AF%E6%B5%8B%E8%AF%95%E7%9A%84JavaScript%E4%BB%A3%E7%A0%81-%E7%BE%8E-Mark-Ethan-Trostler-%E6%89%98%E6%96%AF%E5%8B%92/dp/B00SNCI018/ref=sr_1_1) [read][RMB]\n* [JavaScript Testing Recipes](http://jstesting.jcoglan.com/) [read][$]\n* [前端优先: JavaScript 的测试和原型设计](http://www.pluralsight.com/courses/testing-and-prototyping-javascript-apps) [watch][$]\n* [测试驱动的 JavaScript](http://www.letscodejavascript.com/) [watch][$]"
  },
  {
    "path": "02-fedHandlebook-master/learning/version.md",
    "content": "###版本控制\n\n>软件配置管理, 版本控制的一个组成部分, 也称为校正控制或源码控制, 用于管理文档, 计算机程序, 大型网站和其它信息集合的变化. 变化通常被定义为一串数字或字母代码, 被称为 \"版本编号\", \"版本标识\",  或简称\"版本\". 举个例子, 初始的文件集合是\"版本1\", 当第一个改变文件时, 就变成了\"版本2\"等等. 每一个版本都和一个时间戳和做出改变的人联系在一起. 版本可以被比较, 恢复和跟其它文件合并. - wikipedia\n\n**入门学习:**\n\n* [codeschool.com](https://try.github.io/levels/1/challenges/1) [interact]\n* [Git 基本原理](http://www.pluralsight.com/courses/git-fundamentals) [watch][$]\n* [正确使用 Git](https://www.atlassian.com/git/) [read]\n* [Git 介绍](http://rypress.com/tutorials/git/introduction) [read]\n* [Git 权威指南](http://git-scm.com/book/en/v2) [read]\n\n**进阶学习:**\n\n* [Git 进阶](https://www.atlassian.com/git/tutorials/advanced-overview/) [read]\n* [Git 权威指南](http://git-scm.com/book/en/v2) [read]\n\n**参考/文档:**\n\n* [https://git-scm.com/doc](https://git-scm.com/doc)\n\n\n译者补充:\n\n* [Pro Git 教程](http://acoder.cc/git.html)\n* [Git 教程](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)\n* [git-scm(英)](https://git-scm.com/) [中文版](https://git-scm.com/book/zh/v2)\n* [my-git](https://github.com/xirong/my-git)"
  },
  {
    "path": "02-fedHandlebook-master/learning/web-hosting.md",
    "content": "###Web 主机\n\n>Web 主机是一种网络托管服务, 允许万维网访问个人和组织他们的网站, 由拥有服务器的企业提供空间, 或者租赁给客户使用, 并提供网络连接. Web 主机也能提供数据中心空间和连接到互联网上位于数据中心的其他服务器, 称为主机托管. - wikipedia\n\n![web-hosting](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/web-host.jpg)\n\n**通用知识**\n\n* [Web Hosting Beginner Guide](http://www.webhostingsecretrevealed.net/web-hosting-beginner-guide/) [read]\n* [Web Hosting For Dummies](http://www.dummies.com/store/product/Web-Hosting-For-Dummies.productCd-1118540573.html) [read][$]\n* [Ultimate Guide to Web Hosting](http://www.whoishostingthis.com/resources/web-hosting/) [read]  "
  },
  {
    "path": "02-fedHandlebook-master/learning.md",
    "content": "###第二部分: 学习\n\n第二部分为成为一个前端开发者提供自主学习和指导学习的资源.\n\n注意, 仅需要学习被列举出的资源, 或者一个类别的学习记录, 因为我不建议一个前端开发人员学习所有东西, 这是非常荒谬的. 选择自己行业内的专业知识, 我会尽可能让你掌握它.\n\n**译者补充:**\n\n* [前端开发笔记本](https://li-xinyang.gitbooks.io/frontend-notebook/content/)\n* [前端开发规范](http://zhibimo.com/read/Ashu/front-end-style-guide/)\n* [适用于小团队的前端规范](https://github.com/hzlzh/Front-End-Standards)\n* [无线 Web 开发浅谈](http://am-team.github.io/amg/dev-exp-doc.html#无线web开发简介)\n* [如何跟上前端开发的最新前沿](https://uptodate.frontendrescue.org/zh/)\n* [Engineering Blogs](https://github.com/kilimchoi/engineering-blogs)\n* [大前端工具集](https://github.com/nieweidong/fetool)\n* [前端收集](https://github.com/foru17/front-end-collect)\n* [Front-end Dev Bookmarks](https://github.com/dypsilon/frontend-dev-bookmarks)\n* [Github 资源收集](http://segmentfault.com/a/1190000003510001)\n* [github上值得关注的前端项目](http://segmentfault.com/a/1190000002804472)\n* [前端资源库](http://www.awesomes.cn/)\n* [前端人的俱乐部](http://f2er.club/)"
  },
  {
    "path": "02-fedHandlebook-master/practice/fd-dev-for.md",
    "content": "###前端开发做什么\n\n一个前端开发者能在下面的操作系统列(又称: OS)表中之一上手写运行在Web平台(如: 浏览器)之上的 HTML, CSS 和 JS:\n\n* Windows\n* Windows Phone\n* OSX\n* iOS\n* Android\n* Ubuntu (or Linux)\n* Chromium\n\n操作系统运行在下面中的一个或者多个设备之上:\n\n* Desktop computer\n* Laptop / Netbook computer\n* Mobile phone\n* Tablet\n* TV\n* Watch\n* Things (任何你能想到的, 汽车, 冰箱, 灯光, 温控器等)\n\n![front-end dev for what](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/fd-devs-for.jpeg)\n\n一般来说, 前端技术通过使用下列运行时场景, 能运行在前面提到的操作系统和设备之上:\n\n* 运行在 OS 上的Web浏览器(如: [Chrome, IE, Safari, Firefox](http://outdatedbrowser.com/en))\n* 运行在 OS 上并由 CLI 驱动的 [headless浏览器](https://en.wikipedia.org/wiki/Headless_browser)(如: [plantomJS](http://phantomjs.org/))\n* 一个[Web视图](http://wiki.awesomium.com/general-use/introduction-to-web-views.html)/嵌入本机程序的浏览器Tab(当做 iframe)作为运行时环境, 作为与本机 API 通信的桥梁. 典型的Web视图应用包括一个由Web技术(HTML, CSS, 和 JS)构建的 UI.(如: [Apache Cordova](https://cordova.apache.org/), [NW.js](http://nwjs.io/), [Electron](http://electron.atom.io/))\n* 一个由Web技术创建的本机程序会在运行时作为与本机 API 通信的桥梁, 被解释执行, UI 将使用本机的UI部分(如: IOS 本机控制)而不是Web技术控制([NativeScript](https://www.nativescript.org/), [React Native](https://facebook.github.io/react-native/)). "
  },
  {
    "path": "02-fedHandlebook-master/practice/front-end-interview.md",
    "content": "###前端面试\n\n你可能被问到的问题:\n\n* [前端工作面试问题](http://h5bp.github.io/Front-end-Developer-Interview-Questions/)\n* [前端开发面试问题](http://thatjsdude.com/interview/index.html)\n* [每个 JavaScript 开发者应该知道的 10 个面试问题](https://medium.com/javascript-scene/10-interview-questions-every-javascript-developer-should-know-6fa6bdf5ad95) \n* [前端测验](http://davidshariff.com/quiz/) \n* [JavaScript 测验](http://davidshariff.com/js-quiz/)\n\n你可以问的问题:\n\n* [一个开源的开发人员可以向潜在雇主提问的问题列表](https://github.com/ChiperSoft/InterviewThis)\n\n译者补充:\n\n* [前端开发面试题大收集](https://github.com/paddingme/Front-end-Web-Development-Interview-Question)\n* [前端开发面试问题及答案整理](https://github.com/hawx1993/Front-end-Interview-questions)\n* [收集的前端面试题和答案](https://github.com/qiu-deqing/FE-interview)\n* [写给前端面试者](http://www.w3cplus.com/css/write-to-front-end-developer-interview.html)\n* [Awesome Interviews](https://github.com/MaximAbramchuck/awesome-interviews)\n"
  },
  {
    "path": "02-fedHandlebook-master/practice/front-end-jobs-titles.md",
    "content": "###前端的工作职称\n\n下面是一个前端开发者在职业发展中各种职称的描述列表. 对于前端开发者最普遍的职称是 \"前端开发者\" 或者 \"前端工程师\", 可以根据任何包含 \"前端\", \"客户端\", \"web UI\", \"CSS\", \"HTML\" 和 \"JavaScript\" 的职称推断一个人对 HTML, CSS 和 JavaScript 的了解程度.\n\n****\n\n**前端开发者/工程师** (又称作 Web前端开发者/工程师, 客户端开发者/工程师, 前端软件开发者/工程师 或 UI 工程师)\n\n这是通用的职称, 用于描述一个开发者对 HTML, CSS, JavaScript 有很熟练的掌握, 并能在Web平台上应用这些技术.\n\n****\n\n**CSS/HTML开发者**\n\n这个职称用于描述一个开发者精通于 CSS 和 HTML, 但是对 JavaScript 和应用不熟悉.\n\n****\n\n**前端JavaScript(可选, 应用程序)开发人员**\n\n当职称中包含 \"JavaScript应用程序\" 时, 这就表示此开发人员是一个拥有高级编程, 软件开发和应用程序开发技能(如: 有构建前端应用程序的实践经验)的高级 JavaScript 开发者.\n\n****\n\n**前端Web设计师**\n\n当职称中包含 \"设计师\" 时, 这就表示此设计师不仅拥有前端技能(如: HTML & CSS), 还拥有专业的设计技能(视觉设计和交互设计).\n\n****\n\n**Web/前端用户界面(又称 UI)开发者/工程师**\n\n当职称中包含 \"界面\" 或者 \"UI\" 时, 这就表示此开发人员除了掌握前端技能, 还拥有交互设计技能.\n\n****\n\n**移动/平板前端开发者**\n\n当职称中包含 \"移动\" 或者 \"平板\" 时, 这就表示此开发人员在开发运行在移动或平板设备上的前端应用(或本机程序, 或运行在Web平台, 例如浏览器)很有经验.\n\n****\n\n**前端 SEO 专家**\n\n当职称中包含 \"SEO\" 时, 这就表示此开发者对一个 SEO 策略定制前端技术有着丰富的经验.\n\n****\n\n**前端可访问性专家**\n\n当职称中包含 \"可访问性\" 时, 这就表示此开发者对定制支持可访问性要求和标准的前端技术有着丰富的经验.\n\n****\n\n**前端开发运维**\n\n当职称中包含 \"开发运维\" 时, 这就表示此开发者对软件开发实践与合作, 集成, 部署, 自动化和测量有着丰富的经验.\n\n****\n\n**前端测试/QA**\n\n当职称中包含 \"测试\" 或 \"QA\" 时, 这就表示此开发者对测试和软件管理, 包括单元测试, 功能测试, 用户测试和 A/B 测试有着丰富的经验.\n\n****\n\n注意, 若你在职称中碰到 \"全栈\" 或 类似于 \"Web开发者\" 一样的职位, 这些可能是雇主用来描述这个角色负责 Web/应用程序 开发的各个方面, 即包括前端和后端(还可能包括设计). \n\n译者补充:\n\n* [谈前端工程师的职业规划](http://www.alloyteam.com/2015/04/talk-about-the-front-end-engineering-career-planning/)"
  },
  {
    "path": "02-fedHandlebook-master/practice/front-end-jobs.md",
    "content": "###前端工作版块\n\n可以列出很多寻找技术工作的方法. 下面的有限列表是和寻找一份具体的前端工作最相关的资源:\n\n* [frontenddeveloperjob.com](http://frontenddeveloperjob.com/)\n* [authenticjobs.com](https://authenticjobs.com/#category=4)\n* [weworkremotely.com](https://weworkremotely.com/)\n* [jobs.github.com](https://jobs.github.com/)\n* [careers.stackoverflow.com](http://careers.stackoverflow.com/jobs?searchTerm=front-end)\n* [angularjobs.com](http://angularjobs.com/)\n* [jobs.emberjs.com](http://jobs.emberjs.com/)\n* [jobs.jsninja.com](http://jobs.jsninja.com/)\n* [css-tricks.com/jobs](https://css-tricks.com/jobs/)\n* [glassdoor.com](http://www.glassdoor.com/Job/front-end-developer-jobs-SRCH_KO0,19.htm?jobType=all)\n\n译者补充:\n\n* [w3ctech](http://www.w3ctech.com/job)\n* [w3cfuns](http://www.w3cfuns.com/job.php)\n* [内推网](http://www.neitui.me/)\n* [拉勾网](http://www.lagou.com/)\n* [前端网](http://qianduan.cc/)\n* [CSDN](http://job.csdn.net/)\n* [竞鹿网](https://www.nextoffer.com/)\n* [100Offer](http://100offer.com/)\n* [SegmentFault](http://segmentfault.com/jobs)\n* [周伯通](http://www.jobtong.com/)\n* [内聘网](http://www.neipin.com/)\n* [博客园](http://job.cnblogs.com/)\n* [V2EX](http://www.v2ex.com/)\n* [简历模板](https://github.com/geekcompany/ResumeSample/blob/master/web.md)\n* [面试问题1](https://github.com/Enolak/Front-end-questions-to-the-interview-stage)   [面试问题2](https://github.com/qiu-deqing/FE-interview)"
  },
  {
    "path": "02-fedHandlebook-master/practice/front-end-skills.md",
    "content": "###前端开发的技术栈\n![front-end dev skills](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/front-end-skills.png)\n\n对于任何类型的前端开发人员, HTML, CSS, DOM, JavaScript, HTTP/URL 和浏览器利用是基本的技术要求.\n\n对于HTML, CSS, DOM, JavaScript, HTTP/URL 和浏览器开发之外的, 一个前端开发者还应该掌握下面技术列表中的一个或多个:\n\n* Content Management System (内容管理系统, 又称 CMS)\n* Node.js\n* Cross-browser testing (跨浏览器测试)\n* Cross-platform testing (跨平台测试)\n* Unit Testing (单元测试)\n* Cross-device testing (跨设备测试)\n* Accessibility / WAI-ARIA (无障碍访问/无障碍富Internet应用程序)\n* Search Engine Optimization (搜索引擎优化, 又称 SEO)\n* Interaction or User Interface design (交互或用户设计)\n* User Experience (用户体验)\n* Usability (可用性/易用性)\n* E-commerce Systems (电子商务系统)\n* Portal Systems (门户系统)\n* Wireframing (框架)\n* CSS layout / Grids (CSS 布局/栅格系统)\n* DOM manipulation (e.g. jQuery) (DOM 操作)\n* Mobile Web Performance (移动Web性能)\n* Load Testing (载荷测试)\n* Performance Testing (性能测试)\n* Progressive Enhancement / Graceful Degradation (渐进增强/优雅降级)\n* Version Control (e.g. GIT) (版本控制)\n* MVC / MVVM / MV* (MV* 框架)\n* Functional Programming (函数式编程)\n* Data Formats (e.g. JSON, XML) (数据格式)\n* Data API's (e.g Restful API) (数据API)\n* Web Font Embedding (Web字体嵌入)\n* Scalable Vector Graphics (可伸缩向量图形, 又称 SVG)\n* Regular Expressions (正则表达式)\n* Content Strategy (内容策略)\n* Microdata / Microformats (微数据/微格式)\n* Task Runners, Build Tools, Process Automation Tools (任务管道, 构建工具, 过程自动化工具)\n* Responsive Web Design (响应式设计)\n* Object Oriented Programming (面向对象编程)\n* Application Architecture (应用架构)\n* Modules (模块)\n* Dependency Managers (依赖关系管理)\n* Package Managers (包管理)\n* JavaScript Animation (JavaScript 动画)\n* CSS Animation (CSS 动画)\n* Charts / Graphs (图表/图形)\n* UI widgets (UI工具集)\n* Code Quality Testing (代码质量测试)\n* Code Coverage Testing (代码覆盖测试)\n* Code Complexity Analysis (代码复杂度测试)\n* Integration Testing (集成测试)\n* Command Line / CLI (命令行/命令行界面)\n* Templating Strategies (模板策略)\n* Templating Engines (模板引擎)\n* Single Page Applications (单页应用)\n* XHR Requests (aka AJAX) (XHR 请求, 又称 AJAX)\n* Web/Browser Security (Web/浏览器安全)\n* HTML Semantics (HTML 语义化)\n* Browser Developer Tools (浏览器开发者工具)\n\n\n译者补充:\n\n* [前端技能汇总](https://github.com/JacksonTian/fks)\n* [WebFrontEndStack](https://github.com/unruledboy/WebFrontEndStack)\n\n![front-end-skills1](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/front-end-skill1.jpg)\n\n![front-end-skills2](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/front-end-skill2.png)"
  },
  {
    "path": "02-fedHandlebook-master/practice/front-end-team-role.md",
    "content": "###团队中的前端\n\n在一个设计和开发 Web网站, Web应用, 或者基于Web技术的本机应用的团队, 前端开发者是典型的只有一个人. (注意: 构建一切的开发者曾经被称为\"Web网管\", 但这些罕见的和神秘的开发人员现在被称为\"全栈开发者\").\n\n一个构建专业的Web网站或软件的最小化团队也应该包含下列角色:\n\n* 视觉设计 (字体, 颜色, 字距, 视觉概念&主题)\n* UI/交互设计/信息架构师 (制定框架, 指定所有用户交互, UI功能和结构信息)\n* 前端开发者 (写能够在客户端/设备上运行的代码)\n* 后端开发者 (写能够在服务端运行的代码)\n\n这些角色是根据技能的覆盖排序的(后面的角色的技能会覆盖前面的). 一个前端开发者很擅长处理 UI/交互设计, 后端开发者也一样. 团队成员承担多个角色是很少见的.\n\n一个大的团队可能包含下列角色, 而不是如上面所展示的:\n\n* 视觉设计\n* UI/交互设计/信息架构师\n* **SEO 策略师**\n* 前端开发者\n* **开发-运维工程师**\n* 后端开发者\n* **API 开发者**\n* **数据库管理员**\n* **QA 工程师/测试人员**"
  },
  {
    "path": "02-fedHandlebook-master/practice/full-stack.md",
    "content": "###全才神话\n\n![full-stack](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/full-stack.jpg)\n\n这是个需要设计和开发一个web解决方案的角色, 不仅需要有很深厚的技术栈, 而且需要在视觉设计, UI/交互设计, 前端开发和后端开发有大量的经验. 任何可以以一个专业的水平承担这 4 个角色中的一个或多个的人(又称全才或全栈开发者)是很少的.\n\n务实一点, 你应该寻求, 或者雇佣一个在其中一个角色堪称专家的人. 那些声称在一个或多个角色上是专家的人是非常罕见的, \n\n![change-stack](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/stacks-change.jpg)"
  },
  {
    "path": "02-fedHandlebook-master/practice/making-fd.md",
    "content": "###如何成为前端开发者?\n\n![making-fd](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/made-fd.png)\n\n那么, 怎么才能成为一个前端开发者呢? 这个问题很复杂, 因为直到现在, 你也不能去一所大学获得前端工程师的学位, 并且我也很少听说\n或者遇见通过编写专业地 HTML, CSS 和 JavaScript 来获得一个无用的计算机科学学位或平面设计学位. 事实上, 现在的大部分前端\n开发者都是通过自学成为开发者和没有经过传统训练的程序员. 为什么会是这种情况呢?\n\n前端开发人员不是一个视觉设计师或一个交互设计师, 设计学校不是磨练前端技能的地方; 前端开发者也不是一个受过传统教育地计算机科\n学研究生, 传统教育并不专注于让一个人为前端开发做准备. 实际上, 在美国的高等教育系统中(例如大学), 紧跟传统教学方式可能会阻碍\n一个人置身实践, 而前端开发最需要实际经验. 在今天, 如果你想成为一个前端开发者, 你可以自学或者参加一些不被认可的项目, 课程,\n训练营和班级.\n \n前端工程师会精巧地创建用户界面依赖的骨架. 有时, 他们要足够关注交互设计, 因为他们会编写 UI 交互的底层代码. 因此, 现在的许多\n实践是前端工程师使用编程技巧达不到的, 但是, 从另一个方面来说, 和其它类型程序员转前端开发相比, 似乎有更多的设计师转前端开发者.\n当然, 由于 JavaScript 已经成熟, 更多的受过传统教育的程序员愿意将他们的知识带到前端实践中. 你可能没有意识到前端开发人员并不\n总是被认为是\"真正的\"程序员, 但是, 时代正待正在改变.\n\n正如所有人说的那样, 我相信作为前端开发人员, 职业生涯道路是一个未知的过程. 我能说的是, 要成为一名前端工程师, 就必须知道和在一\n个高层次的水平上使用 HTML, CSS 和 JavaScript, 也不会忽略交互设计或者传统编程所应该知道的技能. 实际上, 从我的经验来看, 最\n好的前端开发者通常会掌握交互设计和基于 Web 平台(例如浏览器, HTML, CSS, DOM 和 JavaScript)的编程. 不管出于什么原因, 还有\n很多关于前端开发的知识往往没被发现, 也就是说, 前端工程更像一些由自学的人组成的实践, 而不是一个直接对应有组织和认可的高等教育的教\n学重心的领域.\n\n如果我从现在开始决定成为一名前端开发人员, 我会努力按照下面所概括的过程进行学习. 学习过程中, 我会假设你是自己最好的老师.\n\n1. 粗略了解 Web 是怎么工作的, 确保你知道域名, DNS, URL, HTTP, 网络, 浏览器, 服务器/服务托管, 数据库, JSON, API, HTML, CSS\n   DOM 和 JavaScript. 了解这些的目的是确保你知道它们如何一起工作以及每部分用于做什么. 专注于高水平的前端架构概述. 从简单的网页\n   制作开始, 并简单学习一下 [本机 Web 应用(又称 SPA)](https://blog.andyet.com/2015/01/22/native-web-apps).\n\n2. 学习 HTML, CSS, 可访问性和 SEO.\n\n3. 学习 UI 设计模式的基本原理, 交互设计, 用户体验设计和可用性\n\n4. 学习编程的基本原理\n\n5. 学习 JavaScript\n\n6. 学习 JSON 和 API\n\n7. 学习 CLI/命令行\n\n8. 学习软件工程实践(如: 应用设计/架构, 模板, Git, 测试, 监控, 自动化, 代码质量, 开发方法学)\n\n9. 定制自己的工具箱\n\n10. 学习 Node.js\n\n当前端的 HTML/CSS 开发者和前端应用/JavaScript 开发者分离时, 你就快要结束这个学习过程.\n\n关于学习的一个简短建议: 在学习抽象的技术之前, 先学习实际的底层技术. 先学 DOM, 再学 JQuery; 先学 CSS, 再学 SASS; 先学 HTML, 再学 HAML;\n先学 JavaScript, 再学 coffeeScript; 先学 ES6 模板字符串, 再学 Handlebars; 先学 UI 模式, 再学 Bootstrap. 当你开始学习时, 你应该会\n害怕事情隐藏的复杂性. Abstracts in the wrong hands can give the appearance of advanced skills, while all the time hiding \nthe fact that a developer has an inferior understanding of the basics or underlying concepts.\n\n正如我之前所建议的学习过程, 这本书的剩下部分为读者指明学习资源和工具. 这也假设你不仅要学习, 而且会将你所学到的知识和工具用于实践.一些人认为只\n实践, 而其他人则建议只学习, 我建议你结合二者, 找到适合自己的方式, 但是一定要结合学习和实践! 因而不仅要阅读这本书, 而且要实践. 学习, 实践, 学习,\n实践. 重复执行是因为事情变化太快, 这就是为什么学习技术的基本原理, 而不是抽象的技术是如此重要.\n\n我在前文已经提到, 现在涌现出很多的非认证的前端编码教育/训练营, 这些成为前端开发者的途径也是由老师在课室(虚拟和实体)指导的课程, 遵循了从官方体系\n(如: 教学大纲, 测验, 小测试, 项目, 团队项目, 成绩等)学习的传统风格, 我在这本书的学习指导部分提到了更多关于这方面的东西. 简单地说, Web 上有\n一切你需要学习的东西(几乎没有成本), 然后, 如果你需要有人告诉你如何获取真正免费的东西, 并且对你的学习负责, 你可以考虑一个有组织的课程. 关于其他方面,\n我不知道其他任何职业可以通过互联网连接和对知识的强烈愿望来免费获取要学习的东西.\n\n如果你要马上开始学习, 我建议你看看下面一些关于前端开发实践的概述:\n\n* [前端指南](https://github.com/bendc/frontend-guidelines) [read]\n* [成为 Web 开发者](http://www.yellowshoe.com.au/standards) [read]\n* [Isobar 前端代码标准](http://isobar-idev.github.io/code-standards/) [read]\n* [Web 基本原理](https://developers.google.com/web/fundamentals) [read]\n* [前端课程](https://gist.github.com/stevekinney/03027e71aac341af14a2) [read]\n* [freeCodeCamp](http://freecodecamp.com/) [interact]\n* [Planing a Front-end JS Application](https://www.youtube.com/watch?v=q4zEGkjTBFA) [watch]\n* [So, You Want to be a Front-end Engineer](https://www.youtube.com/watch?v=Lsg84NtJbmI) [watch]\n* [Front End Web Development Career Kickstart](http://www.pluralsight.com/courses/front-end-web-development-career-kickstart) [watch][$]\n* [前端 Web 开发入门](http://www.pluralsight.com/courses/front-end-web-development-get-started) [watch][$]\n* [Front-End Web Development Quick Start With HTML5, CSS, and JavaScript](http://www.pluralsight.com/courses/front-end-web-app-html5-javascript-css) [watch][$]\n* [Web 开发介绍](https://frontendmasters.com/courses/web-development/) [watch][$]\n* [前端 Web 开发基本原理](https://www.udemy.com/foundations-of-front-end-development/) [watch][$]\n* [Lean Front-End Engineering](https://frontendmasters.com/courses/lean-front-end-engineering/) [watch][$]\n* [A Baseline for Front-End [JS] Developers: 2015](http://rmurphey.com/blog/2015/03/23/a-baseline-for-front-end-developers-2015/) [read]\n* [了解前端 Web 开发](https://teamtreehouse.com/tracks/front-end-web-development) [watch][$]\n* [前端开发精通](https://mijingo.com/products/bundles/front-end-dev-mastery/) [watch][$]\n* [没有学位的前端 Web 开发者](https://www.udacity.com/course/front-end-web-developer-nanodegree--nd001) [watch][$]\n\n**译者补充:**\n\n* [成为一名优秀的Web前端开发者](http://www.92fenxiang.com/140.html)\n* [What makes a good front end engineer?](http://www.92fenxiang.com/112.html)\n* [How to become a web developer](https://medium.com/@souporserious/how-to-become-a-web-developer-ba26b0d23d81)"
  },
  {
    "path": "02-fedHandlebook-master/practice/salaries.md",
    "content": "###前端薪资\n\n在美国, 前端开发者的平均薪资是 [$75K](http://www.glassdoor.com/Salaries/front-end-web-developer-salary-SRCH_KO0,23.htm)\n\n一个有经验的前端开发者可以去任何想去的地方生活(远程工作), 并且一年能赚的钱超过 $150k(访问 [angel.co](https://angel.co/jobs), 注册, 查找超过 $150k 的前端工作).\n\n![front-end-salary](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/front-end-salary.png)"
  },
  {
    "path": "02-fedHandlebook-master/practice/tech-employed-by-fd.md",
    "content": "###前端开发者常用的网络技术\n\n![web-tech-employed](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/web-tech-employed.jpg)\n\n\n前端开发者常用的网络技术如下:\n\n* Hyper Text Markup Language(超文本标记语言, 又称 HTML)\n* Cascading Style Sheets (层叠式样式表, 又称 CSS)\n* Document Object Model (文档对象模型, 又称 DOM)\n* JavaScript Programming Language (JavaScript编程语言, 又称: ECMAScript 6, ES6, JavaScript 2015)\n* Web API's (Web应用程序接口, 又称 HTML5 API 或浏览器 API)\n* Hypertext Transfer Protocol (超文本传输协议, 又称 HTTP)\n* Uniform Resource Locator's (统一资源定位符, 又称 URL)\n* JavaScript Object Notation (JavaScript对象表示, 又称 JSON)\n* Web Content Accessibility Guidelines (网页内容无障碍设计指南, 又称 WCAG) & Accessible Rich Internet Applications (富Internet应用程序的无障碍设计, 又称 ARIA)\n\n根据相关的文档和规范, 这些技术定义如下. 作为一个比较, 你可以在 [platform.html5.org](https://platform.html5.org/) 上看到所有与Web相关的规范.\n\n**Hyper Text Markup Language(超文本标记语言, 又称 HTML)**\n\n>超文本标记语言, 通常被称为 HTML, 是被用于创建网页的标准标记语言. Web浏览器能将 HTML 文件渲染成可见的或者可听到的. HTML 随着线索提示, 语义化地描述了网站的结构, 使它成为一种标记语言, 而不是编程语言. - wikipedia.org\n\n更多相关的文档/规范:\n\n* [W3C HTML5 规范](http://www.w3.org/TR/html5/) : HTML5 是WWW核心语言的主要修订\n* [HTML 元素在线标准](https://html.spec.whatwg.org/multipage/semantics.html#semantics)\n* [HTML 在线语法](https://html.spec.whatwg.org/multipage/syntax.html#syntax)\n* [所有 W3C HTML 规范](http://www.w3.org/standards/techs/html#w3c_all)\n* [HTML 元素参考](https://developer.mozilla.org/en-US/docs/Web/HTML/Element)\n* [HTML 属性参考](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes)\n* [全局属性](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes)\n\n**Cascading Style Sheets (层叠式样式表, 又称 CSS)**\n\n>层叠式样式表(CSS)是用于描述外观和格式化标记语言编写的文档的样式表语言. 尽管经常被用来改变用 HTML 和 XHTML 编写的网页和用户界面的样式, 但也可用于任何 XML 文档, 包括纯 XML, SVG 和 XUL. 跟 JavaScript 和 HTML 一样, CSS是被大多数网站用于为Web应用程序创建富有吸引力的网页, 用户界面的一种基础技术, 也为许多移动应用程序创建用户界面. - wikipedia.org\n\n更多相关的文档/规范:\n\n* [CSS 2.2规范](https://drafts.csswg.org/css2/)\n* [CSS 3选择器](http://www.w3.org/TR/css3-selectors/)\n* [所有 W3C CSS 规范](http://www.w3.org/Style/CSS/current-work#roadmap)\n* [CSS 参考](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference)\n\n**Document Object Model (文档对象模型, 又称 DOM)**\n\n>文档对象模型用于代表和对象交互的HTML, XHTML 和 XML 文档, 是一种跨平台和语言无关性的约定. 每一份文档的所有节点被组织成一种树结构, 称为 DOM 树. DOM 对象通过使用对象上的方法被处理和操作, 一个 DOM 对象的公共接口被指定为它的应用程序编程接口(API). - wikipedia.org\n\n更多相关的文档/规范:\n\n* [W3C DOM4](http://www.w3.org/TR/2014/WD-dom-20140204/)\n* [DOM 在线标准](https://dom.spec.whatwg.org/)\n* [DOM 3 事件规范](http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/)\n\n**JavaScript Programming Language (JavaScript编程语言, 又称: ECMAScript 6, ES6, JavaScript 2015)**\n\n>JavaScript 是一种高级的, 动态的, 无类型的和解释型的编程语言, 它已经在 ECMAScript 语言规范中被标准化. 跟 HTML 和 CSS 一样, JavaScript 是 WWW 内容生成的第三种必不可少的技术; 大多数的网会使用Javascript, 并且 Javascript 被所有现在Web浏览器支持. JavaScript 基于原型和函数优先的特点, 使它成为多范型的语言, 支持面向对象的, 命令式的, 和函数式编程风格. JavaScript 能提供 API 来处理文本, 数组, 日期和正则表达式, 但不包括任何 I/O, 如网络, 存储或图形工具, 对这些的依赖取决于宿主环境中嵌入了什么. - wikipedia.org\n\n更多相关的文档/规范:\n\n* [ECMAScript 2015 语言规范](http://www.ecma-international.org/ecma-262/6.0/)\n\n**Web API's (Web应用程序接口, 又称 HTML5 API)**\n\n>当使用 JavaScript 为Web程序写代码时, 有很多不错的 API 是可以利用的. 下面列举了所有在Web APP 或网站开发中可能会用到的接口. - Mozilla\n\n更多相关文档:\n\n* [Web API 接口](https://developer.mozilla.org/en-US/docs/Web/API)\n\n**Hypertext Transfer Protocol (超文本传输协议, 又称 HTTP)**\n\n>超文本传输协议是一个用于分布式, 协作和超媒体信息系统的应用协议, 是 WWW 数据通信的基础. - wikipedia.org\n\n更多相关规范:\n\n* [Hypertext Transfer Protocol -- HTTP/1.1](https://tools.ietf.org/html/rfc2616)\n* [Hypertext Transfer Protocol version 2 draft-ietf-httpbis-http2-16](https://tools.ietf.org/html/draft-ietf-httpbis-http2-16)\n\n**Uniform Resource Locator's (统一资源定位符, 又称 URL)**\n\n>一个 URL (也称Web地址)是一个资源引用, 指定了资源在计算机网络和检索机制中的位置. 与之类似的概念是 Uniform Resource Identifier(URI), 尽管许多人认为两个术语可以互换使用, 但 URL 是统一资源标识符( URI )[3] 的具体类型. 一个 URL 意味着一种访问资源量的方式, 但这并不适用于 URI.\n[4][5]URL 不仅常用于引用一个网页(http), 也可用于文件传输(ftp), 邮件(mailto), 数据库访问(JDBC) 和许多其它应用. - wikipedia.org\n\n更多相关规范:\n\n* [URL](http://www.w3.org/Addressing/URL/url-spec.txt)\n* [URL 在线标准](https://url.spec.whatwg.org/)\n\n**JavaScript Object Notation (JavaScript对象表示, 又称 JSON)**\n\n>JSON, 有时也称 JavaScript 对象表示, 是一种使用人类可读的文本传输由键值对组成的数据对象的开放格式. 对于异步浏览器/服务器通信(AJAJ), JSON 是主要的数据格式, 很大程度上代替了 XML(AJAX). 尽管最初是从 JavaScript 脚本语言衍生而来, 但是 JSON 是语言无关性的数据格式, 在许多编程语言中, 代码解析和生成 JSON 是很容易的. JSON 的格式最初是由 Douglas Crockford 指定的, 但目前却被描述成两种标准: RFC 7159 和 ECMA-404. ECMA 标准只允许被合法的语法语句描述, 而 RFC 则提供了一些语义化描述和安全考虑. JSON 的官方网络媒体类型 application / JSON, 扩展名是 .json. - wikipedia.org\n\n更多相关规范:\n\n* [JSON 介绍](http://json.org/)\n* [JSON 数据交换格式](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)\n* [JSON API](http://jsonapi.org/)\n\n**Web Content Accessibility Guidelines (网页内容无障碍设计指南, 又称 WCAG) & Accessible Rich Internet Applications (富Internet应用程序的无障碍设计, 又称 ARIA)**\n\n>无障碍设计是指产品, 设备, 服务, 或者环境是为残疾人设计的. 无障碍设计的概念意味着与一个人的辅助技术(例如, 电脑屏幕阅读器)相兼容, 确保直接访问(即独立)和\"间接访问\". - wikipedia.org\n\n* [无障碍设计网络倡议 (WAI)](http://www.w3.org/WAI/)\n* [网页内容无障碍设计指南 (WCAG) 的目前状态](http://www.w3.org/standards/techs/wcag#w3c_all)\n* [富 Internet 应用程序的无障碍设计 (WAI-ARIA) 的目前状态](http://www.w3.org/standards/techs/aria#w3c_all)\n\n**译者补充:**\n\n* [Web 端开发常用资源](https://github.com/lyfeyaj/awesome-resources#web-%E5%89%8D%E7%AB%AF)\n* [Web 前端开发资源](http://hao.jobbole.com/?catid=67)"
  },
  {
    "path": "02-fedHandlebook-master/practice.md",
    "content": "###第一部分：前端开发实践\n\n第一部分会大致描述前端工程的实践"
  },
  {
    "path": "02-fedHandlebook-master/styles/ebook.css",
    "content": "cite{\n\tmargin-top: -30px;\n\tfont-size:10px;\n\ttext-align: center;\n\tcolor: #666;\n}\n"
  },
  {
    "path": "02-fedHandlebook-master/styles/website.css",
    "content": "cite{\n\tmargin-top: -30px;\n\tfont-size:10px;\n\ttext-align: center;\n\tcolor: #666;\n}\n"
  },
  {
    "path": "02-fedHandlebook-master/tools/animation.md",
    "content": "###动画工具\n\n* [Velocity.js](http://julian.com/research/velocity/)\n* [snabbt.js](http://daniel-lundin.github.io/snabbt.js/)\n* [TweenJS](https://github.com/CreateJS/TweenJS)\n* [Dynamics.js](https://github.com/michaelvillar/dynamics.js)\n* [GreenSock-JS](https://github.com/greensock/GreenSock-JS)\n\n**Polyfills/shims:**\n\n* [web-animations-js](https://github.com/web-animations/web-animations-js)"
  },
  {
    "path": "02-fedHandlebook-master/tools/app.md",
    "content": "###APP(桌面, 移动, 平板等) 工具\n\n**前端 App 框架:**\n\n* [AngularJS](https://angularjs.org/) & [Batarang](https://github.com/angular/angularjs-batarang)\n* [Backbone](http://backbonejs.org/) & [Marionette](http://marionettejs.com/)\n* [React](http://facebook.github.io/react/) & [React-router](https://github.com/rackt/react-router) & [Flux](http://facebook.github.io/flux/) & [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)\n* [Vue.js](http://vuejs.org/) & [vue-loader](https://github.com/vuejs/vue-loader) & [vue-router](https://github.com/vuejs/vue-router)\n* [Ember](http://emberjs.com/) & [Ember Inspector](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi?hl=en)\n* [Aurelia](http://aurelia.io/)\n* [Polymer](https://www.polymer-project.org/1.0/) & [Iron Elements](https://elements.polymer-project.org/browse?package=iron-elements) & [Paper Elements](https://elements.polymer-project.org/browse?package=paper-elements)\n\n**全栈 JS App 平台:**\n\n* [Meteor](https://www.meteor.com/)\n* [Hood.ie](http://hood.ie/intro/)\n* [MEAN](http://meanjs.org/)\n\n**移动 Web UI/网站/App 框架:**\n\n这些解决方案可以被用到任何地方, 包括 Web 视图(Web 平台和浏览器引擎等) APP.\n\n* [Ratchet](http://goratchet.com/getting-started/)\n* [Kendo UI Mobile](http://demos.telerik.com/kendo-ui/m/index)\n* [Mobile Angular UI](http://mobileangularui.com/)\n* [Framework7](http://www.idangero.us/framework7)\n\n**本机混合移动 webview 框架:**\n\n典型解决方案是使用 [Cordova](https://cordova.apache.org/), [crosswalk](https://crosswalk-project.org/), 或者自定义 Webview 作为本机 API 的桥梁.\n\n* [ionic](http://ionicframework.com/)\n* [onsen.io](http://onsen.io/)\n\n**本机混合移动开发 webview 环境/平台/工具:**\n\n典型解决方案是使用 [Cordova](https://cordova.apache.org/), [crosswalk](https://crosswalk-project.org/), 或者自定义 Webview 作为本机 API 的桥梁.\n\n* [AppBuilder](http://www.telerik.com/appbuilder) [$]\n* [Monaca](https://monaca.io/) [$]\n* [Adobe PhoneGap](http://phonegap.com/) [$]\n* [kony](http://www.kony.com/products/mobility-platform) [$]\n* [ionic hub](http://ionic.io/) [free to $]\n* [Taco](http://taco.tools/)\n* [manifoldJS](http://manifoldjs.com/)\n* [cacoon](https://cocoon.io) [free to $]\n\n**本机桌面 webview 应用框架:**\n\n* [NW.js](https://github.com/nwjs/nw.js)\n* [Electron](http://electron.atom.io/)\n\n**本机移动应用框架 (又称 JavaScript 本机应用)**\n\n解决方案不使用浏览器引擎或 Webview, 而是利用 JS 引擎作为运行环境去编译 JavaScript, 并能调用本机的 API. UI 则使用本机的 UI 组件进行构造.\n\n* [NativeScript](https://www.nativescript.org/)\n* [React Native](https://facebook.github.io/react-native/)\n* [tabris.js](https://tabrisjs.com/) [free to $]\n* [trigger.io](https://trigger.io/how-it-works/) [$]\n\n**参考:**\n\n* [todomvc.com](http://todomvc.com/)\n\n**App seeds/starters/boilerplates:**\n\n* [React Starter Kit](http://www.reactstarterkit.com/)\n* [Ember starter-kit](https://github.com/emberjs/starter-kit)\n* [NG^-starter](https://github.com/angular-class/NG6-starter)\n* [Angular 2 Webpack Starter](http://angularclass.com/angular2-webpack-starter/)\n* [hjs-webpack](https://github.com/henrikjoreteg/hjs-webpack#developing-on-multiple-devices-at-once)"
  },
  {
    "path": "02-fedHandlebook-master/tools/bass.md",
    "content": "###前端开发者的后端服务工具(又称 BASS: Back-end as a service)\n\n**数据/后端服务管理:**\n\n* [Firebase](https://www.firebase.com/index.html) [free to $]\n* [Parse](https://www.parse.com/) [free to $]\n* [kinvey](http://www.kinvey.com/) [free to $]\n* [Back&](https://www.backand.com/) [free to $]\n* [Pusher](https://pusher.com/)\n\n**用户服务管理:**\n\n* [UserApp](https://www.userapp.io/) [free to $]\n* [hull](http://www.hull.io/) [$]\n* [auth0](https://auth0.com) [$]"
  },
  {
    "path": "02-fedHandlebook-master/tools/browser.md",
    "content": "###浏览工具\n\n**JS 浏览工具:**\n\n* [URI.js](http://medialize.github.io/URI.js/)\n* [platform.js](https://github.com/bestiejs/platform.js)\n* [history.js](https://github.com/browserstate/history.js)\n* [html2canvas](https://github.com/niklasvh/html2canvas)\n\n**参考工具(查看浏览器是否支持某特性)**\n\n* [caniusee.com](http://caniuse.com/)\n* [HTML5 Please](http://html5please.com/)\n* [HTML5 test](https://html5test.com/)\n* [Browserscope](http://www.browserscope.org/)\n* [webbrowsercompatibility.com](http://www.webbrowsercompatibility.com)\n* [iwanttouse.com/](http://www.iwanttouse.com/)\n* [Platform status](https://dev.modern.ie/platform/status/)\n* [Browser support for broken/missing images](http://codepen.io/bartveneman/full/qzCte/)\n* [Big JS-Compatibility-Table](http://compatibility.shwups-cms.ch/en/home)\n* [jscc.info](http://jscc.info/)\n* [What Web Can Do Today](https://whatwebcando.today/)\n\n**浏览器开发/调试工具:**\n\n* [Opera Dragonfly](http://www.opera.com/dragonfly/)\n* [Safari Web Inspector](https://developer.apple.com/safari/tools/)\n* [Firefox Developer Tools](https://developer.mozilla.org/en-US/docs/Tools)\n* [Chrome Developer Tools(aka DevTools)](https://developers.google.com/web/tools/?hl=en)\n  * [Per-Panel Documentation](https://developers.google.com/web/tools/chrome-devtools/#docs)\n  * [Command Line API Reference](https://developers.google.com/web/tools/javascript/command-line/command-line-reference?hl=en)\n  * [Keyboard & UI Shortcuts Reference](https://developers.google.com/web/tools/iterate/inspect-styles/shortcuts)\n  * [Settings](https://developer.chrome.com/devtools/docs/settings)\n* [IE Developer tools(aka F12)](https://dev.modern.ie/platform/documentation/f12-devtools-guide/)\n* [vorlon.js](http://vorlonjs.com/)\n\n**同步浏览工具:**\n\n* [Browsersync](http://www.browsersync.io/)\n\n**浏览器编码工具(判断用户的浏览器是否支持某特性):**\n\n* [Modernizr](https://modernizr.com/)\n* [ES Feature Tests](https://featuretests.io/)\n\n**浏览器的各种 polyfills/shims:**\n\n* [webcomponents.js](https://github.com/WebComponents/webcomponentsjs)\n* [webshim](https://afarkas.github.io/webshim/demos/)\n* [HTML5 Cross Browser Polyfills](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills)\n* [console-polyfill](https://github.com/paulmillr/console-polyfill)\n* [socket.io](http://socket.io/)\n* [sockjs](https://github.com/sockjs/sockjs-client)\n\n**浏览器承载测试/自动化:**\n\n* [browserstack](https://www.browserstack.com) [$]\n* [browserling](https://www.browserling.com/)[$]\n* [Sauce labs](https://saucelabs.com/) [$]\n* [Selenium](http://www.seleniumhq.org/)\n* [CrossBrowserTesting.com](http://crossbrowsertesting.com/)\n\n**无壳浏览器:**\n\n* [PhantomJS](http://phantomjs.org/)\n* [slimerjd](http://slimerjs.org/)\n* [TrifleJS](http://triflejs.org/)\n\n**无壳浏览器的自动化工具:**\n\n* [nightwatchjs](http://nightwatchjs.org/)\n* [casperJS](http://casperjs.org/)\n* [Nightmare](https://github.com/segmentio/nightmare)\n* [gremlins.js](https://github.com/marmelab/gremlins.js)\n\n**浏览器 hacks:**\n\n* [browserhacks.com](http://browserhacks.com/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/browserdocs.md",
    "content": "###DOC/API 浏览工具\n\n用于浏览开发者文档和 API 文档的工具.\n\n* [devdocs.io](http://devdocs.io/)\n* [Dash](https://kapeli.com/dash) [OS X, iOS][$]\n* [Velocity](https://velocity.silverlakesoftware.com/) [Windows][$]\n* [Zeal](https://zealdocs.org/) [Windows, Linux]"
  },
  {
    "path": "02-fedHandlebook-master/tools/charts.md",
    "content": "###数据可视化工具\n \n**JS 库:**\n\n* [d3](http://d3js.org/)\n* [sigmajs](http://sigmajs.org/)\n\n**部件 & 组件:</h5>\n\n* [Chart.js](http://www.chartjs.org/)\n* [C3.js](http://c3js.org/)\n* [Google Charts](https://developers.google.com/chart/interactive/docs/)\n* [chartist-jsj](https://github.com/gionkunz/chartist-js)\n* [amCharts](http://www.amcharts.com/) [$]\n* [Highcharts](http://www.highcharts.com/) [Non-commercial free to $]\n* [FusionCharts](http://www.fusioncharts.com/) [$]\n* [ZingChart](http://www.zingchart.com/) [free to $]\n* [Epoch](https://github.com/epochjs/epoch)\n\n**服务:**\n\n* [Datawrapper](https://datawrapper.de/)\n* [infogr.am](https://infogr.am) [free to $]\n* [plotly](https://plot.ly/) [free to $]\n* [ChartBlocks](http://www.chartblocks.com/) [free to $]"
  },
  {
    "path": "02-fedHandlebook-master/tools/cms.md",
    "content": "###内容管理托管/API工具\n\n**API CMS 工具:**\n\n* [prismic.io](https://prismic.io/) [free to $]\n* [contentful](https://www.contentful.com/) [$]\n* [Cosmic JS](https://cosmicjs.com/) [free to $]\n\n**Hosted CMS tools:**\n\n* [LightCMS](https://www.lightcms.com) [$]\n* [Surreal CMS](http://www.surrealcms.com/) [$]\n* [Page Lime](http://www.pagelime.com/) [$]\n* [Cushy CMS](https://www.cushycms.com) [free to $]\n\n**Static CMS tools:**\n\n* [webhook.com](http://www.webhook.com/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/code-editor.md",
    "content": "###了解代码编辑器\n\n>源代码编辑器是一个文本编辑程序, 专门为编辑计算机程序源代码的程序员而设计的, 它可能是一个独立的应用程序或内置在集成开发环境(IDE)或web浏览器中. 源代码编辑器是最基本的编程工具, ,作为程序员的基本工作就是编写和编辑源代码. - Wikipedia\n\n前端代码可以被一个简单的文本编辑应用程序(如: Notepad 或 TextEdit), 但是, 大多数前端人员使用专门为一种编程语言而设计的代码编辑器编辑.\n\n可以这么说, 代码编辑器有各种各样的类型和大小. 选择一个编辑器是主观行为。选择一个, 学习它的使用,然后继续学习 HTML, CSS 和 JavasCript DOM.\n\n但是, 我一直相信, 编辑器应该有如下特点:\n\n* 一份不错的关于如何使用编辑器的文档\n* 报告 HTML, CSS 和 JavaScript 代码的质量\n* 为 HTML, CSS 和 JavaScript 提供语法高亮\n* 为 HTML, CSS 和 JavaScript 提供代码自动完成\n* 通过插件的方式自定义编辑器架构\n* 有大量的第三方仓库/插件社区, 能够用于自定义编辑器\n* 轻量, 简单, 不耦合代码(不需要编辑代码等等)\n\n我个人推荐将下列的插件和 [Sublime Text](http://www.sublimetext.com/) 一起使用:\n\n* [Package Control](https://packagecontrol.io/packages/Package%20Control)\n* [AutoFileName](https://packagecontrol.io/packages/AutoFileName)\n* [SublimeLinter](https://packagecontrol.io/packages/SublimeLinter)\n    * [SublimeLinter-json](https://packagecontrol.io/packages/SublimeLinter-json)\n    * [SublimeLinter-jslint](https://packagecontrol.io/packages/SublimeLinter-jshint)\n    * [SublimeLinter-html-tidy](https://packagecontrol.io/packages/SublimeLinter-html-tidy)\n* [Side​Bar​Enhancements](https://packagecontrol.io/packages/SideBarEnhancements)\n* [Terminal](https://packagecontrol.io/packages/Terminal)\n* [Bracket​Highlighter](https://packagecontrol.io/packages/BracketHighlighter)\n* [Color Highlighter](https://packagecontrol.io/packages/Color%20Highlighter)\n* [CSS3](https://packagecontrol.io/packages/CSS3)\n* [HTMLAttributes](https://packagecontrol.io/packages/HTMLAttributes)\n* [StringEncode](https://packagecontrol.io/packages/StringEncode)\n* [HTML-CSS-JS Prettify](https://packagecontrol.io/packages/HTML-CSS-JS%20Prettify) \n\nSublime 的学习资源:\n\n* [Sublime Productivity](https://leanpub.com/sublime-productivity) [read][$]\n* [Sublime Text Power User Book](https://sublimetextbook.com/) [read + watch][$]\n* [Sublime Text 3 From Scratch](http://www.pluralsight.com/courses/sublime-text-3-from-scratch) [watch][$]\n* [Perfect Workflow in Sublime Text 2](https://code.tutsplus.com/courses/perfect-workflow-in-sublime-text-2) [watch][requires login, but free]\n\n**代码编辑器:**\n\n* [Atom](https://atom.io/)\n* [Brackets](http://brackets.io/)\n* [Sublime Text](http://www.sublimetext.com/) [$]\n* [WebStorm](https://www.jetbrains.com/webstorm/whatsnew/) [$]\n* [Visual Studio Code](https://code.visualstudio.com/)\n\n**在线合作的代码编辑器:**\n\n* [jsbin.com](http://jsbin.com/) [free to $]\n* [jsfiddle.net](http://jsfiddle.net/)\n* [liveweave.com](http://liveweave.com/)\n* [es6fiddle.net](http://www.es6fiddle.net/)\n* [codepen.io](http://codepen.io/) [free to $]\n* [Plunker](http://plnkr.co/)\n\n**在线代码编辑器:**\n\n* [codeanywhere](https://codeanywhere.com) [free to $]\n* [Koding](https://koding.com) [free to $]\n* [Clound9](https://c9.io) [free to $]\n"
  },
  {
    "path": "02-fedHandlebook-master/tools/coll.md",
    "content": "###合作 & 交流工具\n\n* [Slack](https://slack.com/) & [screenhero](https://screenhero.com/) [free to $]\n* [Skype](http://www.skype.com/) [free to $]\n* [Google Hangouts](https://hangouts.google.com/)\n\n**代码/Github 合作 & 交流:**\n\n* [Gitter](https://gitter.im) [free to $]\n\n**译者补充:**\n\n* [Gitup](http://gitup.co/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/css.md",
    "content": "###CSS 工具\n\n**桌面 & 移动应用 CSS 框架:**\n\n* [Semantic UI](http://semantic-ui.com/)\n* [Foundation](http://foundation.zurb.com/)\n* [Bootstrap](http://getbootstrap.com/)\n* [Metro UI](http://metroui.org.ua/)\n* [Pure.css](http://purecss.io/)\n* [Concise](http://concisecss.com/)\n* [Materialize](http://materializecss.com/)\n* [Material Design Lite(MDL)](http://www.getmdl.io/index.html)\n* [Base](http://getbase.org/)\n\n**移动应用 CSS 框架:**\n\n* [Ratchet](http://goratchet.com/)\n\n**CSS 重置:**\n\n>CSS 重置(或重置 CSS)是一个很小的, 被压缩的 CSS 规则集合, 用于重置所有 HTML 元素的样式. - [http://cssreset.com/](http://cssreset.com/)\n\n* [Eric Meyer’s “Reset CSS” 2.0](http://meyerweb.com/eric/tools/css/reset/)\n* [Normalize](https://necolas.github.io/normalize.css/)\n\n**Transpiling:**\n\n* [SASS/SCSS](http://sass-lang.com/)\n* [stylus](https://github.com/stylus/stylus)\n* [PostCSS](https://github.com/postcss/postcss) & [cssnext](http://cssnext.io/)\n* [rework](https://github.com/reworkcss/rework) & [myth](http://www.myth.io/)\n* [pleeease.io](http://pleeease.io/)\n\n**参考文档:**\n\n* [css3test.com](http://css3test.com/)\n* [css4-selectors.com](http://css4-selectors.com/)\n* [css3clickchart.com](http://css3clickchart.com)\n* [cssvalues.com](http://cssvalues.com)\n* [CSS TRIGGERS](http://csstriggers.com/)\n* [MDN CSS reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference)\n* [overapi.com CSS cheatsheet](http://overapi.com/css/)\n\n**Linting/hinting:**\n\n* [CSS Lint](http://csslint.net/)\n* [stylelint](http://stylelint.io/)\n\n**代码格式化/美化:**\n\n* [CSScomb](https://github.com/csscomb/csscomb.js)\n* [cssfmt](https://github.com/morishitter/cssfmt)\n\n**优化:**\n\n* [csso](http://css.github.io/csso/)\n* [clear-css](https://github.com/jakubpawlowicz/clean-css)\n* [cssnano](http://cssnano.co/)\n\n**CSS 在线生成工具:**\n\n* [Ultimate CSS Gradient Generator](http://www.colorzilla.com/gradient-editor/)\n* [Enjoy CSS](http://enjoycss.com/)\n* [CSS matic](http://www.cssmatic.com/)\n* [patternify.com](http://patternify.com)\n* [patternizer.com](http://patternizer.com)\n* [CSS arrow please](http://cssarrowplease.com/)\n* [flexplorer](http://bennettfeely.com/flexplorer/)\n* [Flexbox Playground](https://scotch.io/demos/visual-guide-to-css3-flexbox-flexbox-playground)\n\n**CSS 架构:**\n\n* [oocss](http://oocss.org/) [read]\n* [SMACSS](https://smacss.com/) [read][$]\n* [Atomic Design](http://atomicdesign.bradfrost.com/) [read]\n\n**编写规范:**\n\n* [idiomatic-css](https://github.com/necolas/idiomatic-css) [read]\n* [CSS code guide](http://codeguide.co/#css) [read]\n* [cssguidelin.es](http://cssguidelin.es) [read]\n* [Google HTML/CSS Style Guide](http://google-styleguide.googlecode.com/svn/trunk/htmlcssguide.xml#General_Formatting)\n\n**本月 CSS 仓库在Github的趋势:**\n\n* [https://github.com/trending?l=css&amp;since=monthly](https://github.com/trending?l=css&amp;since=monthly)"
  },
  {
    "path": "02-fedHandlebook-master/tools/data.md",
    "content": "###前端数据存储工具\n\n* [YDN-DB](http://dev.yathit.com/ydn-db/index.html)\n* [forerunner](http://forerunnerdb.com/)\n* [AlaSQL](http://alasql.org/)\n* [LokiJS](http://lokijs.org/#/)\n* [lovefiled](https://google.github.io/lovefield)\n* [Dexie.js](http://www.dexie.org/)\n* [localForage](http://mozilla.github.io/localForage/)\n* [pouchdb](http://pouchdb.com/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/deploy.md",
    "content": "###部署工具\n\n* [FTPLOY](http://ftploy.com/) [free to $]\n* [Travis CI](http://docs.travis-ci.com/) [free to $]\n* [codeship](https://codeship.com/) [free to $]\n* [Bamboo](https://www.atlassian.com/software/bamboo/) [$]\n* [Springloops](http://www.springloops.io/) [free to $]\n* [surge](https://surge.sh/)\n* [sync ninja](http://www.syncninja.com/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/diagram.md",
    "content": "###图表工具\n\n* [Cacoo](https://cacoo.com) [free to $]\n* [gliffy](https://www.gliffy.com/products/online/) [free to $]\n* [draw.io](https://www.draw.io) [free to $]"
  },
  {
    "path": "02-fedHandlebook-master/tools/dom.md",
    "content": "###DOM 工具\n\n**DOM 库/框架:**\n\n* [jQuery](http://jquery.com/)\n* [Zepto.js](http://zeptojs.com)\n* [keypress](http://dmauro.github.io/Keypress/)\n* [clipboard.js](http://zenorocha.github.io/clipboard.js/)\n* [tether.io](http://tether.io/docs/welcome/)\n\n**DOM 性能分析:**\n\n* [DOMMonster](http://mir.aculo.us/dom-monster/)\n\n**参考文档:**\n\n* [DOM Browser Support](http://www.webbrowsercompatibility.com/dom/desktop/)\n* [DOM Events Browser Support](http://www.webbrowsercompatibility.com/dom-events/desktop/)\n* [HTML Interfaces Browser Support](http://www.webbrowsercompatibility.com/html-interfaces/desktop/)\n* [Events](https://html.spec.whatwg.org/#events-2)\n* [MDN Document Object Model (DOM)](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)\n\n**DOM polyfills/shims:**\n\n* [dom-shims](https://github.com/necolas/dom-shims)\n* [Pointer Events Polyfill: a unified event system for the web platform](https://github.com/jquery/PEP)\n\n**虚拟 DOM:**\n\n* [jsdom](https://github.com/tmpvar/jsdom)\n* [virtual-dom](https://github.com/Matt-Esch/virtual-dom)"
  },
  {
    "path": "02-fedHandlebook-master/tools/error.md",
    "content": "###JavaScript 错误监控工具\n\n* [Raygun](https://raygun.io) [$]\n* [errorception](https://errorception.com/) [$]\n* [sentry](https://getsentry.com/welcome/) [free to $]\n* [{track:js}](https://trackjs.com/) [$]"
  },
  {
    "path": "02-fedHandlebook-master/tools/general-tools.md",
    "content": "###常用前端开发工具\n\n**开发工具:**\n\n* [screensiz.es](http://screensiz.es/)\n* [placehold.it](http://placehold.it/)\n* [codeKit](http://incident57.com/codekit/)\n* [prepros](https://prepros.io/)\n* [Browsersync](http://www.browsersync.io/)\n* [ish. 2.0.](https://github.com/bradfrost/ish.)\n* [Wraith](http://bbc-news.github.io/wraith/index.html)\n\n**在线代码编辑:**\n\n* [jsbin.com](http://jsbin.com/)\n* [jsfiddle.net](http://jsfiddle.net/)\n* [liveweave.com](http://liveweave.com/)\n* [es6fiddle.net](http://www.es6fiddle.net/)\n* [codepen.io](http://codepen.io/)\n* [Plunker](http://plnkr.co/)\n\n**查找工具:**\n\n* [stackshare.io](http://stackshare.io/)\n* [javascripting.com](http://www.javascripting.com/)\n* [built with](http://builtwith.com/)\n* [microjs.com](http://microjs.com/)\n* [The Tool Box](http://thetoolbox.cc/)\n* [unheap.com](http://www.unheap.com/)\n* [stylesheets.co](https://stylesheets.co/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/graphics.md",
    "content": "###图形工具\n\n**常见图形工具:**\n\n* [Two.js](http://jonobr1.github.io/two.js/#introduction)\n* [Fabric.js](http://fabricjs.com/)\n\n**画布:**\n\n* [Paper.js](http://paperjs.org/)\n* [EaselJS](https://github.com/CreateJS/EaselJS)\n\n**SVG:**\n\n* [svg.js](http://svgjs.com/)\n* [Snap.svg](http://snapsvg.io/)\n* [Raphaël](http://raphaeljs.com/)\n* [d3](http://d3js.org/)\n\n**Webgl:**\n\n* [three.js](http://threejs.org/)\n* [pixi.js](https://github.com/pixijs/pixi.js)"
  },
  {
    "path": "02-fedHandlebook-master/tools/hosting.md",
    "content": "###Web/云/静态主机托管工具\n\n* [AWS](https://aws.amazon.com/websites/) [$]\n* [Heroku](https://heroku.com) [free to $]\n* [DigitalOcean](https://digitalocean.com) [$]\n* [Modulus](https://modulus.io/) [$]\n* [DIVSHOT](https://divshot.com) [free to $]\n* [netlify](https://www.netlify.com) [free to $]\n* [surge](https://surge.sh/) [free to $]"
  },
  {
    "path": "02-fedHandlebook-master/tools/html.md",
    "content": "###HTML 工具\n\n**HTML 模板:**\n\n* [HTML5 Boilerplate](https://html5boilerplate.com/)\n* [Mobile boilerplate](https://html5boilerplate.com/mobile/)\n* [Web Starter Kit Boilerplate & Tooling for Multi-Device Development](https://developers.google.com/web/tools/starter-kit)\n* [dCodes](http://www.dcodes.net/2/docs/index.html)\n* [HTML5 Bones](http://html5bones.com/)\n* [Email-Boilerplate](https://github.com/seanpowell/Email-Boilerplate)\n* [Pears](http://pea.rs/)\n\n**HTML polyfill:**\n\n* [html5shiv](https://github.com/aFarkas/html5shiv)\n\n**Transpiling:**\n\n* [jade](http://jade-lang.com/)\n* [HAML](http://haml.info/)\n* [Markdown](http://daringfireball.net/projects/markdown/)\n\n**文档参考:**\n\n* [HTML Interfaces Browser Support](http://www.webbrowsercompatibility.com/html-interfaces/desktop/)\n* [HTML Entity Lookup](http://entity-lookup.leftlogic.com/)\n* [HTMLElement.info](http://htmlelement.info/)\n* [ELements](https://html.spec.whatwg.org/multipage/indices.html#elements-3)\n* [Elelemt Attributes](https://html.spec.whatwg.org/multipage/indices.html#attributes-3)\n* [HTML Arrows](http://htmlarrows.com/)\n\n**Linting/hinting:**\n\n* [html5-lint](https://github.com/mozilla/html5-lint)\n* [HTMLHint](http://htmlhint.com/)\n* [html-inspector](https://github.com/philipwalton/html-inspector)\n\n**HTML 优化:**\n\n* [HTML Minifier](http://kangax.github.io/html-minifier/)\n\n**HTML 在线生成工具:**\n\n* [tablesgenerator.com](http://www.tablesgenerator.com)\n\n**编写规范:**\n\n* [Principles of writing consistent, idiomatic HTML](https://github.com/necolas/idiomatic-html)\n* [HTML code guide](http://codeguide.co/#html)\n\n**Workflow:**\n\n* [Emmet](http://emmet.io/)\n\n**本月 HTML 仓库在Github的趋势:**\n\n* [https://github.com/trending?l=html&amp;since=monthly](https://github.com/trending?l=html&amp;since=monthly)"
  },
  {
    "path": "02-fedHandlebook-master/tools/http.md",
    "content": "###HTTP/网络工具\n\n* [Charles](http://www.charlesproxy.com/) [$]\n* [Fiddler](http://www.telerik.com/fiddler)\n* [Postman](https://www.getpostman.com/)\n* [Chrome DevTools Network Panel](https://developers.google.com/web/tools/chrome-devtools/profile/network-performance/resource-loading)"
  },
  {
    "path": "02-fedHandlebook-master/tools/js.md",
    "content": "###JavaScript 工具\n\n**JS 库:**\n\n* [lodash](http://lodash.com)\n* [underscore.js](http://underscorejs.org)\n* [Moment.js](http://momentjs.com/)\n* [string.js](http://stringjs.com/)\n* [Numeral.js](http://numeraljs.com/)\n* [accounting.js](http://openexchangerates.github.io/accounting.js/)\n* [xregexp.com](http://xregexp.com/)\n* [Math.js](http://mathjs.org/)\n* [wait](https://github.com/elving/wait)\n* [async](https://github.com/caolan/async)\n* [format.js](http://formatjs.io/)\n* [Chance](http://chancejs.com/)\n\n**编译转换 (ESX to ESX):**\n\n* [Babel](https://babeljs.io/)\n\n**JavaScript 兼容性检查:**\n\n* [jscc.info](http://jscc.info/)\n\n**代码检查:**\n\n* [jshint](http://jshint.com/)\n* [eshint](http://eslint.org/)\n* [JSlint](http://www.jslint.com/)\n  * [jslinterrors.com](http://jslinterrors.com/)\n\n**单元测试:**\n\n* [Mocha](http://mochajs.org/)\n* [QUnit](http://qunitjs.com/)\n* [Jasmine](http://jasmine.github.io/)\n  * [Jest](http://facebook.github.io/jest/) \n\n**单元测试的断言库:**\n\n* [should.js](http://shouldjs.github.io/)\n* [Chai](http://chaijs.com/)\n* [expect.js](https://github.com/Automattic/expect.js)\n\n**单元测试监控, 存根和模拟:**\n\n* [sinon.js](http://sinonjs.org/)\n\n**编码规范检查:**\n\n* [JSCS](http://jscs.info/)\n\n**代码格式化/美化:**\n\n* [jsfmt](http://rdio.github.io/jsfmt/)\n* [esformatter](https://github.com/millermedeiros/esformatter#esformatterformatstr-optsstring)\n* [js-beautify](http://jsbeautifier.org/)\n\n**性能测试:**\n\n* [jsperf](http://jsperf.com/)\n* [benchmark.js](http://benchmarkjs.com/)\n\n**可视化, 静态分析, 复杂性, 覆盖工具:**\n\n* [jscomplexity.org](http://jscomplexity.org/)\n* [istanbul](https://github.com/gotwarlost/istanbul)\n* [Blanket.js](http://blanketjs.org/)\n* [Coveralls](https://coveralls.io/) [$]\n* [Plato](https://github.com/es-analysis/plato)\n* [escomplex](https://github.com/jared-stilwell/escomplex)\n* [Esprima](http://esprima.org/)\n\n**优化:**\n\n* [UglifyJS 2](https://github.com/mishoo/UglifyJS2)\n\n**混淆:**\n\n* [Javascript 混淆器](http://www.javascriptobfuscator.com/)\n* [JScrambler](https://jscrambler.com/) [$]\n\n**在线代码编辑器:**\n\n* [jsbin.com](http://jsbin.com/)\n* [jsfiddle.net](http://jsfiddle.net/)\n* [es6fiddle.net](http://www.es6fiddle.net/)\n* [plnkr.co](http://plnkr.co/)\n\n**在线正则表达式编辑器/可视化工具:**\n\n* [regex101](https://regex101.com/)\n* [regexper](http://regexper.com/)\n* [debuggex](https://www.debuggex.com)\n* [RegExr](http://regexr.com/)\n\n**编码规范:**\n\n* [Node.js 规范指南](https://github.com/felixge/node-style-guide)\n* [JavaScript 编码原则](https://github.com/rwaldron/idiomatic.js)\n* [JavaScript 规范指南](http://airbnb.io/javascript/)\n\n**本月 JS 仓库在 Github 的趋势:**\n\n* [https://github.com/trending?l=javascript&since=monthly](https://github.com/trending?l=javascript&since=monthly)\n\n**NPM 上被依赖最多的包:**\n\n* [https://www.npmjs.com/browse/depended](https://www.npmjs.com/browse/depended)\n"
  },
  {
    "path": "02-fedHandlebook-master/tools/json.md",
    "content": "###JSON 工具\n\n**JSON 在线编辑器:**\n\n* [JSONmate](http://jsonmate.com/)\n\n**JSON 查询工具:**\n\n* [DefiantJS](http://www.defiantjs.com/)\n* [ObjectPath](http://objectpath.org/)\n* [JOSN Mask](https://github.com/nemtsov/json-mask)\n\n**生成模拟 JSON 工具:**\n\n* [JSON Generator](http://www.json-generator.com/)\n* [Mockaroo](https://www.mockaroo.com/)\n\n**JSON API 在线模拟工具:**\n\n* [Mocky](http://www.mocky.io/)\n* [FillText.com](http://www.filltext.com)\n* [JSONPlaceholder](http://jsonplaceholder.typicode.com/)\n* [mackable.io](https://www.mockable.io/)\n\n**JSON API 本地模拟工具:</h5>\n\n* [json-server](https://github.com/typicode/json-server)\n\n**JSON 规范/模式:**\n\n* [json-schema.org](http://json-schema.org/) & [jsonschema.net](http://jsonschema.net)\n* [jsonapi](http://jsonapi.org/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/loader.md",
    "content": "###模块/包加载工具\n\n* [SystemJS](https://github.com/systemjs/systemjs)\n* [webpack](https://webpack.github.io/)\n* [Broeserify](http://browserify.org/)\n* [rollup.js](http://rollupjs.org/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/monitor.md",
    "content": "###网站/APP 监控工具\n\n**Uptime:**\n\n* [pingdom](https://www.pingdom.com/) [free to $]\n* [Uptime Robot](https://uptimerobot.com/)\n* [Uptrends](https://www.uptrends.com/) [$]\n\n**General:**\n\n* [New Relic](http://newrelic.com/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/offline.md",
    "content": "###离线工具\n\n* [upup](https://www.talater.com/upup/)\n* [offline.js](http://github.hubspot.com/offline/docs/welcome/)\n* [pouchdb](http://pouchdb.com/)\n* [hood.ie](http://hood.ie/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/perf.md",
    "content": "###性能工具\n\n**Reporting:**\n\n* [WEIGHTOF.IT](http://weightof.it/category/application-frameworks)\n* [Web Page Test](http://www.webpagetest.org/)\n* [GTmetrix](https://gtmetrix.com/)\n* [Speed Curve](https://speedcurve.com/) [$]\n* [Chrome Devtools Timeline](https://developers.google.com/web/tools/profile-performance/evaluate-performance/timeline-tool?hl=en)\n* [sitespeed.io](https://www.sitespeed.io)\n\n**JS tools:**\n\n* [ImageOptim-CLI](http://jamiemason.github.io/ImageOptim-CLI/)\n* [imagemin](https://github.com/imagemin/imagemin)\n\n**Budgeting:**\n\n* [performancebudget.io](http://www.performancebudget.io)"
  },
  {
    "path": "02-fedHandlebook-master/tools/project.md",
    "content": "###项目管理 & 代码托管\n\n* [Github](https://github.com/) [free to $]\n* [Codebase](https://www.codebasehq.com/) [$]\n* [Bitbucket](https://bitbucket.org) [free to $]\n* [Unfuddle](https://unfuddle.com/) [$]\n* [Assembla](https://www.assembla.com) [free to $]"
  },
  {
    "path": "02-fedHandlebook-master/tools/proto.md",
    "content": "###原型和框架工具\n\n**创建原型和框架:**\n\n* [Balsamiq Mockups](https://balsamiq.com) [$]\n* [Justinmind](http://www.justinmind.com) [$]\n* [UXPin](http://www.uxpin.com/) [free to $]\n\n**合作/展示:**\n\n* [InVision](http://www.invisionapp.com/) [free to $]\n* [myBalsamiq](https://www.mybalsamiq.com/) [$]\n* [conceptboard](https://conceptboard.com/) [free to $]"
  },
  {
    "path": "02-fedHandlebook-master/tools/repo.md",
    "content": "###模块/包仓库工具\n\n* [NPM](https://www.npmjs.com/)\n* [Bower](http://bower.io/)\n* [jspm.io](http://jspm.io/)\n* [spmjs](http://spmjs.io)"
  },
  {
    "path": "02-fedHandlebook-master/tools/scaffolding.md",
    "content": "###脚手架工具\n\n脚手架是指为整个应用生成一个初始化的模板, 而不是[生成访问数据库的代码](https://en.wikipedia.org/wiki/Scaffold_%28programming%29).\n\n* [Yeoman](http://yeoman.io/)\n* [Slush](http://slushjs.github.io/#/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/security.md",
    "content": "###安全工具\n\n**Coding tool:**\n\n* [DOMPurity](https://github.com/cure53/DOMPurify)\n* [XSS](http://jsxss.com/en/index.html)\n\n**References:**\n\n* [HTML5 Security Cheatsheet](https://html5sec.org/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/seo.md",
    "content": "###SEO 工具\n\n* [Google Webmasters Search Console](https://www.google.com/webmasters/)\n* [Varvy SEO tool](https://varvy.com/tools/)\n* [Keyword Tool](http://keywordtool.io/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/static.md",
    "content": "###静态网页生成器工具\n\n**JS 网页生成器:**\n\n* [Metalsmith](http://www.metalsmith.io/)\n* [harp](http://harpjs.com/)\n\n**JS 博客网站生成器:**\n\n* [hubpress.io](http://hubpress.io)\n* [Hexo.io](http://hexo.io)\n\n**网站生成器列表:**\n\n* [staticsitegenerators.net](https://staticsitegenerators.net)\n* [www.staticgen.com](https://www.staticgen.com)"
  },
  {
    "path": "02-fedHandlebook-master/tools/svg.md",
    "content": "###SVG 工具\n\n**优化:**\n\n* [SVGOMG](https://jakearchibald.github.io/svgomg/)\n* [Peter Collingridge's SVG Optimiser](http://petercollingridge.appspot.com/svg-optimiser)\n* [SVGO](https://github.com/svg/svgo)\n* [SVGO-GUI](https://github.com/svg/svgo-gui)\n* [SVG Cleaner](https://launchpad.net/svg-cleaner)\n* [Scour SVG Scrubber](http://www.codedread.com/scour/)\n* [Clean Multiple Gradient Stops](http://codepen.io/jakealbaugh/pen/OVrQXY)\n\n**SVG 编辑器:**\n\n* [Illustrator](http://www.adobe.com/products/illustrator.html)\n* [Sketch](https://www.sketchapp.com/)\n* [Inkscape](https://inkscape.org/en/)\n* [DrawSVG](http://www.drawsvg.org/)\n\n**创建雪碧图:**\n\n* [Icomoon](https://icomoon.io/)\n* [Fontastic](http://fontastic.me/)\n* [Grunticon](http://www.grunticon.com/)\n\n**Bug 追踪:**\n\n* [SVG Weirdness](https://github.com/emilbjorklund/svg-weirdness)\n* [SVG Edit](https://code.google.com/p/svg-edit/wiki/BrowserBugs)"
  },
  {
    "path": "02-fedHandlebook-master/tools/task.md",
    "content": "###任务管理(又称 构建)工具\n\n**任务管理/构建 工具:**\n\n* [Gulp](http://gulpjs.com/)\n* [Grunt](http://gruntjs.com/)\n\n**Tasking/build and more tools:**\n\n* [Brunch](http://brunch.io/)\n* [Mimosa](http://mimosa.io/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/templates.md",
    "content": "###模板工具\n\n**Just Templating:**\n\n* [Mustache.js](https://github.com/janl/mustache.js)\n* [Handlebars](http://handlebarsjs.com/)\n    * [htmlbars](https://github.com/tildeio/htmlbars)\n* [Nunjuncks](http://mozilla.github.io/nunjucks/)\n* [Transparency](http://leonidas.github.io/transparency/)\n* [doT.js](http://olado.github.io/doT/)\n* [Hogan.js](http://twitter.github.io/hogan.js/)\n\n**Templating and reactive data binding:**\n\n* [Rivets.js](http://rivetsjs.com)\n* [paperclip.js](http://paperclipjs.com)\n* [riot](http://riotjs.com/)\n* [vue.js](http://vuejs.org)\n* [ractive.js](http://www.ractivejs.org)\n* [react.js](https://facebook.github.io/react/index.html)\n* [RxJS](https://github.com/Reactive-Extensions/RxJS)\n* [knockout](http://knockoutjs.com/index.html)\n* [jquerymy.js](http://jquerymy.com/)\n\n**Templating to Virtual DOM:**\n\n* [JSX](https://facebook.github.io/jsx/)\n* [t7](http://t7js.com/)\n\n**译者补充:**\n\n* [Handlebars 入门](http://www.ido321.com/1629.html)\n* [Handlebars 系列文章](http://jaskokoyn.com/handlebars-js-tutorial-series/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/test.md",
    "content": "###测试框架工具\n\n* [Karma](http://karma-runner.github.io/0.8/index.html)\n* [Intern](https://theintern.github.io/)\n* [NightWatch.js](http://nightwatchjs.org/)"
  },
  {
    "path": "02-fedHandlebook-master/tools/ui.md",
    "content": "###UI 部件 & 组件工具\n\n**桌面 & 移动:**\n\n* [Kendo UI](http://www.telerik.com/kendo-ui) [free to $]\n* [Webix](http://webix.com/) [$]\n* [Semantic UI](http://semantic-ui.com/)\n* [Metro UI](http://metroui.org.ua/)\n* [Bootstrap](http://getbootstrap.com/components/)\n* [Materialize](http://materializecss.com/)\n* [Material UI](http://material-ui.com/)\n* [Polymer Paper Elements](https://elements.polymer-project.org/browse?package=paper-elements)\n\n**桌面 (NW.js 和 Electron):**\n\n* [photonkit](http://photonkit.com/)\n* [React UI Components for OS X El Capitan and Windows 10](http://gabrielbull.github.io/react-desktop/)\n\n**专注移动:**\n\n* [Ratchet](http://goratchet.com/)\n* [Kendo UI Mobile](http://demos.telerik.com/kendo-ui/m/index)\n* [Mobile Angular UI](http://mobileangularui.com/)\n* [Framework7](http://www.idangero.us/framework7)"
  },
  {
    "path": "02-fedHandlebook-master/tools.md",
    "content": "###第三部分\n\n第三部分会简单地讨论一些前端开发工具的使用.\n\n为确保你理解一套工具所属的类别, 建议在此之前先研究工具本身.\n\n注意, 仅仅是一个工具列表, 或一个类别的工具记录, 但这并不等于我断言, 前端开发人员应该学习它并使用它. 选择自己的工具箱, 我只是提供常见的工具箱选项.\n\n**译者补充:**\n\n* [Web 前端开发资源汇总](https://github.com/lyfeyaj/awesome-resources#web-%E5%89%8D%E7%AB%AF)"
  },
  {
    "path": "02-fedHandlebook-master/what-is-a-fd.md",
    "content": "###什么是前端开发者?\n一个前端开发者, 要会使用Web技术(如：HTML,CSS,DOM和JavaScript)设计和开发网站应用. 网站应用,    或运行于 [Web平台](https://en.wikipedia.org/wiki/Open_Web_Platform) 之上, 或用于编译非Web平台环境的输入(如：[NativeScript](https://www.nativescript.org/)).\n\n\n![what-is-front-end-dev](https://raw.githubusercontent.com/dwqs/fedHandlebook/master/images/what-is-front-end-dev.png)\n\n<cite>图片来源：https://www.upwork.com/hiring/development/front-end-developer/</cite>\n\n一般而言, 一个人可以通过学习 HTML,CSS,JavaScript进入前端开发领域, 这些代码运行在 [Web浏览器](https://en.wikipedia.org/wiki/Web_browser), [无壳为浏览器](https://en.wikipedia.org/wiki/Headless_browser), Web视图之中, 或用于编译本地运行环境的输入. 后文将详细介绍这四个运行场景.\n\nWeb浏览器是用于检索, 呈现和遍历万维网(WWW)信息的软件. 一般而言, 浏览器可以运行在台式机, 笔记本电脑, 平板电脑或手机. 但是近来, 几乎在任何事物上都能够发现浏览器(如: 冰箱上, 汽车里等).\n\n最普遍的Web浏览器如下:\n\n* [Chrome](http://www.google.com/chrome/)\n* [Internet Explorer](http://dev.modern.ie/)\n* [Firefox](https://www.mozilla.org/firefox/)\n* [Safari](http://www.apple.com/safari/)\n\n无壳浏览器是指没有图形用户界面的Web浏览器, 可以通过命令行接口控制达到网页自动化的目的(如: 功能测试, 单元测试等). 把无壳浏览器当做可以从命令行运行的浏览器, 它依然可以检索和遍历网页.\n\n最普遍的无壳浏览器如下:\n\n* [PhantomJS](http://phantomjs.org/)\n* [slimerjs](http://slimerjs.org/)\n* [trifleJS](http://triflejs.org/)\n\n[Webviews](http://developer.telerik.com/featured/what-is-a-webview/) 被本地 OS 用来运行网页. 把Web视图当做Web浏览器中的iframe或者单个的Tab, 其嵌入于运行在设备上的本地应用程序中(如：[iOS](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebView_Class/), [android](http://developer.android.com/reference/android/webkit/WebView.html), [windows](https://msdn.microsoft.com/library/windows/apps/windows.ui.xaml.controls.webview.aspx)).\n\nWeb视图开发最普遍的解决方案如下:\n\n* [Cordova](https://cordova.apache.org/) (用于本地手机/平板应用)\n* [NW.js](https://github.com/nwjs/nw.js) (即 Node-Webkit, 用于桌面应用)\n* [Electron](http://electron.atom.io/) (用于桌面应用) \n\n最后, 前端开发者从 Web 浏览器开发环境中学到的东西也可以用于不受浏览器引擎驱动的环境下. 目前, 脱离 Web 引擎，使用 Web 技术(如: CSS 和 JavaScript)去创建真正的本地应用的开发环境正在出现.\n\n此类环境的示例如下:\n\n* [NativeScript](https://www.nativescript.org/)\n* [React Native](https://facebook.github.io/react-native/)\n\n\n**译者补充:**\n\n* [达到什么样的标准才能是大公司要的前端](http://qianduanfan.com/index.php/topic/show/217)\n* [写给初学前端工程师的一封信](http://www.w3ctech.com/topic/983)\n* [前端路上的旅行](http://www.w3cplus.com/front-end-trip-on-road.html)\n* [React Native专题](http://www.jianshu.com/p/96febc4fec45)"
  },
  {
    "path": "03-FEND_Note-master/AUTHORS",
    "content": "Li Xinyang <lixinyang1026@gmail.com>\nLi Xinyang <lixinyang1026@Gmail.com>\nrwang23 <des.renfei.wang@gmail.com>\nhcy003 <chenyu19921103@gmail.com>\nFred.W. <robert.wei.176@gmail.com>\ntinglin92 <tinglin1992@gmail.com>\nTinglin <tinglin1992@gmail.com>\nSylvia Zhang <rszhang89@gmail.com>\nleikn <leikn@users.noreply.github.com>\nThe Gitter Badger <badger@gitter.im>\nOsub <814566123@qq.com>\nChenyu <chenyu19921103@gmail.com>\nnifanle <nifanle7@163.com>\n"
  },
  {
    "path": "03-FEND_Note-master/Booklist.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [书单](#%E4%B9%A6%E5%8D%95)\n  - [HTML](#html)\n  - [CSS](#css)\n  - [JavaScript](#javascript)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n# 书单\n\n## HTML\n\nN/A\n\n## CSS\n\n- CSS Mastery: Advanced Web Standard Solutions\n\n## JavaScript\n\n- Professional JavaScript for Web Developers\n- DOM Scripting: Web Design with JavaScript and the Document Object Model\n- AdvancED DOM Scripting: Dynamic Web Design Techniques\n- JavaScript: The Definitive Guide\n\n## Version Control\n\n- [Git 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html)\n- [Git Pro](https://git-scm.com/book/en/v2)\n"
  },
  {
    "path": "03-FEND_Note-master/README.md",
    "content": "# 前端开发笔记本\n\n[![Join the chat at https://gitter.im/li-xinyang/FEND_Note](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/li-xinyang/FEND_Note?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n点击[这里](https://www.gitbook.com/read/book/li-xinyang/frontend-notebook)开始在 GitBook 阅读！\n\n点击[这里](http://wiki.jikexueyuan.com/project/fend_note/)开始在极客学院 Wiki 阅读！（中国大陆访问速度较快）\n\n前端开发笔记本的 GitHub 项目地址在[这里](https://github.com/li-xinyang/FEND_Note)。如果你觉得这个项目不错，请点击 **Star** 一下，您的支持是我最大的动力。\n\n<!-- Place this tag where you want the button to render. -->\n\n<a class=\"github-button\" href=\"https://github.com/li-xinyang/FEND_Note\" data-style=\"mega\" data-count-href=\"/li-xinyang/FEND_Note/stargazers\" data-count-api=\"/repos/li-xinyang/FEND_Note#stargazers_count\" data-count-aria-label=\"# stargazers on GitHub\" aria-label=\"Star li-xinyang/FEND_Note on GitHub\">Star</a>\n\n&nbsp;&nbsp;<a class=\"github-button\" href=\"https://github.com/li-xinyang/FEND_Note\" data-style=\"mega\" data-count-href=\"/li-xinyang/FEND_Note/watchers\" data-count-api=\"/repos/li-xinyang/FEND_Note#subscribers_count\" data-count-aria-label=\"# watchers on GitHub\" aria-label=\"Watch li-xinyang/FEND_Note on GitHub\">Watch</a>\n\n&nbsp;&nbsp;<a class=\"github-button\" href=\"https://github.com/li-xinyang/FEND_Note/fork\" data-style=\"mega\" data-count-href=\"/li-xinyang/FEND_Note/network\" data-count-api=\"/repos/li-xinyang/FEND_Note#forks_count\" data-count-aria-label=\"# forks on GitHub\" aria-label=\"Fork li-xinyang/FEND_Note on GitHub\">Fork</a>\n\n&nbsp;&nbsp;<a class=\"github-button\" href=\"https://github.com/li-xinyang/FEND_Note/archive/master.zip\" data-style=\"mega\" aria-label=\"Download li-xinyang/FEND_Note on GitHub\">Download</a>\n\n![笔记路径规划](img/C/career-path.jpg)\n\n《前端笔记本》涵盖了 Web 前端开发所需的全部基本知识以及所对应的学习路径。它并不能当做一本完整的学习材料来进行前端的学习，因为在有限的篇幅中无法深入的展开每一个单独的知识点。它更适合作为一个学习清单或者是查询手册，结合其他在各个方面更专业的图书或者官方文档来进行同步学习。在学习过程中为了能达到最佳的学习效果，也可将每个技术点实现并进行适当的拓展。\n\n### 写作进程\n\n*第一版草稿* 完成时间 1507252244\n\n| 章节   | 名称              | 进程                                |\n| :--- | :-------------- | :-------------------------------- |\n| 第一章  | 页面制作            | ![](http://progressed.io/bar/100) |\n| 第二章  | JavaScript 程序设计 | ![](http://progressed.io/bar/100) |\n| 第三章  | DOM 编程          | ![](http://progressed.io/bar/100) |\n| 第四章  | 页面构架            | ![](http://progressed.io/bar/100) |\n| 第五章  | 前端产品构架          | ![](http://progressed.io/bar/100) |\n\n### 成就\n\n**1508311803** - 100 Stars: [@dszls](https://github.com/dszls), thank you!\n\n**1511071358** - 200 Stars: [@cschenchen](https://github.com/cschenchen)\n\n**1511222144** - 300 Stars: [@lujun9972](https://github.com/lujun9972)\n\n**1512102333** - 400 Stars: [@Niefee](https://github.com/Niefee)\n\n**1601231619** - 500 Stars: [@wangdsh](https://github.com/wangdsh)\n\n**1603261510** - 600 Stars: [@lty2226262](https://github.com/lty2226262)\n\n**1605170450** - 700 Stars: [@eqzcy](https://github.com/eqzcy)\n\n**1608010000** - 800 Stars: [@BeOker](https://github.com/BeOker)\n\n### 相关链接\n\n- [NEC](http://nec.netease.com/) {N: nice, E: easy, C: css;}\n\n### 声明\n\n前端笔记本大纲及内容由[网易云课堂前端专业](http://mooc.study.163.com/smartSpec/detail/12001.htm_)改编\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\"><img alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc-sa/4.0/80x15.png\" /></a><br />This work by <a xmlns:cc=\"http://creativecommons.org/ns#\" href=\"li-xinyang.com\" property=\"cc:attributionName\" rel=\"cc:attributionURL\">Li Xinyang</a> is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/4.0/\">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.\n\n<!-- Place this tag right after the last button or just before your close body tag. -->\n\n<script async defer id=\"github-bjs\" src=\"https://buttons.github.io/buttons.js\"></script>\n"
  },
  {
    "path": "03-FEND_Note-master/SUMMARY.md",
    "content": "# Summary\n\n- [页面制作](chapter1/00_intro.md)\n  - [Photoshop](chapter1/01_photoshop.md)\n    - [工具、面板、视图](chapter1/01_01_tool_panel_view.md)\n    - [测量及取色](chapter1/01_02_measurement_and_color.md)\n    - [切图](chapter1/01_03_slice.md)\n    - [图片保存](chapter1/01_04_save_image.md)\n    - [图片优化与合并](chapter1/01_05_image_optimisation.md)\n  - [开发及调试工具](chapter1/02_dev_tools.md)\n    - [Sublime 编辑器](chapter1/02_01_sublime.md)\n    - [Atom 编辑器](chapter1/02_02_atom.md)\n  - [HTML](chapter1/03_html.md)\n    - [HTML 简介](chapter1/03_01_html_intro.md)\n    - [HTML 语法](chapter1/03_02_html_sytax.md)\n    - [HTML 标签](chapter1/03_05_html_tags.md)\n    - [实体字符](chapter1/03_03_html_ascii_encoding.md)\n    - [浏览器兼容](chapter1/03_04_cross_browser.md)\n  - [CSS](chapter1/04_css_intro.md)\n    - [语法](chapter1/04_01_css_sytax.md)\n    - [选择器](chapter1/04_02_selector.md)\n    - [文本](chapter1/04_03_text.md)\n    - [盒模型](chapter1/04_04_box_model.md)\n    - [背景](chapter1/04_05_background.md)\n    - [布局](chapter1/04_06_layout.md)\n    - [变形](chapter1/04_07_transform.md)\n    - [动画](chapter1/04_08_animation.md)\n    - [常见布局样例](chapter1/04_09_layout_demo.md)\n- [JavaScript 程序设计](chapter2/00_intro.md)\n  - [JavaScript 介绍](chapter2/01_javascript_intro.md)\n  - [调试器](chapter2/02_dev_tools.md)\n  - [基础语法](chapter2/03_basic_syntax.md)\n  - [类型系统](chapter2/04_data_type.md)\n  - [类型判断](chapter2/11_js_type_determin.md)\n  - [内置对象](chapter2/05_internal_object.md)\n  - [变量作用域](chapter2/06_scope.md)\n  - [表达式与运算符号](chapter2/07_statement_and_operator.md)\n  - [语句](chapter2/08_statement.md)\n  - [闭包](chapter2/09_closure.md)\n  - [面向对象](chapter2/10_object.md)\n  - [正则表达式](chapter2/12_reg_exp.md)\n- [DOM 编程](chapter3/00_intro.md)\n  - [文档树（DOM Tree）](chapter3/01_dom_tree.md)\n  - [节点操作](chapter3/02_node_manipulation.md)\n  - [操作属性](chapter3/03_attribute.md)\n  - [样式操作](chapter3/04_style_manipulation.md)\n  - [事件](chapter3/05_events.md)\n  - [多媒体（视频与音频）](chapter3/08_multimedia.md)\n  - [Canvas](chapter3/07_canvas.md)\n  - [BOM](chapter3/10_bom.md)\n  - [数据通信](chapter3/09_network.md)\n  - [数据存储](chapter3/11_storage.md)\n  - [动画](chapter3/06_animation.md)\n  - [表单操作](chapter3/12_form_manipulation.md)\n  - [列表操作](chapter3/13_list_manipulation.md)\n- [页面架构](chapter4/00_intro.md)\n  - [CSS Reset](chapter4/01_CSS_Reset.md)\n  - [布局解决方案](chapter4/02_layout.md)\n  - [响应式布局](chapter4/03_responsive.md)\n  - [页面优化](chapter4/04_page_optimisation.md)\n  - [规范与模块化](chapter4/05_modulation.md)\n- [产品前端架构](chapter5/00_intro.md)\n  - [协作流程](chapter5/01_collaboration.md)\n  - [接口设计](chapter5/02_design_api.md)\n  - [版本控制](chapter5/03_version_control.md)\n  - [技术选型](chapter5/04_tech_selection.md)\n  - [开发实践](chapter5/05_development.md)\n- [附录 A：书单](Booklist.md)\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/CSS/Animation.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Animation</title>\n    <style type=\"text/css\">\n    body {\n        margin: 50px;\n        text-align: center;\n        position: relative;\n        margin: ;\n        100px 0;\n    }\n\n    .row {\n        position: relative;\n        margin: 10px;\n        height: 155px;\n        background: rgba(39, 139, 210, .1);\n        border: 3px dashed rgba(39, 139, 210, 1);\n    }\n    .ball {\n      width: 150px;\n      height:150px;\n      border: 3px solid black;\n      background: rgba(139, 158, 67, 1);\n      border-radius: 50%;\n    }\n    </style>\n</head>\n\n<body>\n    <h1>动画 animation</h1>\n    <div class=\"row\">\n      <div class=\"ball\" id=\"ball1\"></div>\n    </div>\n    <style type=\"text/css\">\n    #ball1 {\n      animation: change-color 5s infinite;\n      animation-name: change-color, change-position;\n      position: relative;\n      animation-direction: alternate;\n    }\n\n    @keyframes change-color {\n      0% {background: red;}\n      100% {background: yellow;}\n    }\n    @keyframes change-position {\n      0% {left: 0;}\n      100% {left: calc(100% - 150px);}\n    }\n    </style>\n</body>\n\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/CSS/AnimationPractice.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Animation Practice</title>\n    <style type=\"text/css\">\n    body {\n        margin: 30px;\n        text-align: center;\n        font-family: monospace;\n    }\n\n    .container {\n        line-height: 300px;\n        position: relative;\n        width: 1px;\n        top: 50%;\n        left: 50%;\n        margin-top: 200px;\n        font-size: 3rem;\n        perspective: 2000px;\n        perspective-origin: 0 150px;\n        transform-style: preserve-3d;\n    }\n\n    .side {\n        transition-duration: 3s;\n        height: 300px;\n        width: 300px;\n        border: 5px solid rgba(0, 0, 0, .3);\n        position: absolute;\n        left: -150px;\n        top: 50%;\n    }\n    </style>\n</head>\n\n<body>\n    <h1>3D 正方体组合旋转</h1>\n    <div class=\"container\">\n        <div class=\"back side\">back</div>\n        <div class=\"front side\">front</div>\n        <div class=\"side right\">right</div>\n        <div class=\"side left\">left</div>\n        <div class=\"side bottom\">botto </div>\n        <div class=\"side top\">top </div>\n    </div>\n    <style type=\"text/css\">\n    .top {\n        animation: placeTop 1s linear both;\n        transition-property: background-color;\n    }\n\n    .bottom {\n        animation: placeBottom 1s 1s linear both;\n        transition-property: background-color;\n    }\n\n    .left {\n        animation: placeLeft 1s 2s linear both;\n        transition-property: background-color;\n    }\n\n    .right {\n        animation: placeRight 1s 3s linear both;\n        transition-property: background-color;\n    }\n\n    .back {\n        animation: placeBack 1s 4s linear both;\n        transition-property: background-color;\n    }\n\n    .front {\n        animation: placeFront 1s 5s linear both;\n        transition-property: background-color;\n    }\n\n    .container {\n        animation: cube 3s 6s linear infinite both;\n    }\n\n    .container:hover .top {\n      background-color: red;\n    }\n    .container:hover .bottom {\n      background-color: green;\n    }\n    .container:hover .left {\n      background-color: blue;\n    }\n    .container:hover .right {\n      background-color: yellow;\n    }\n    .container:hover .back {\n      background-color: gray;\n    }\n    .container:hover .front {\n      background-color: orange;\n    }\n\n    @keyframes placeTop {\n        100% {\n            transform: translateY(-150px) rotateX(90deg);\n        }\n    }\n\n    @keyframes placeBottom {\n        100% {\n            transform: translateY(150px) rotateX(90deg);\n        }\n    }\n\n    @keyframes placeLeft {\n        100% {\n            transform: translateX(-150px) rotateY(90deg);\n        }\n    }\n\n    @keyframes placeRight {\n        100% {\n            transform: translateX(150px) rotateY(90deg);\n        }\n    }\n\n    @keyframes placeBack {\n        100% {\n            transform: translateZ(-150px) rotateY(180deg);\n        }\n    }\n\n    @keyframes placeFront {\n        100% {\n            transform: translateZ(150px);\n        }\n    }\n\n    @-webkit-keyframes cube {\n        0% {\n            perspective: 2000px;\n        }\n        100% {\n            perspective: 0px;\n            transform: rotate3d(0.5, 0.5, 0.5, 360deg);\n        }\n    }\n    </style>\n</body>\n\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/CSS/Transform2D.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Transform 2D</title>\n    <style type=\"text/css\">\n    body {\n        margin: 50px;\n        text-align: center;\n        position: relative;\n        margin: ;\n        100px 0;\n    }\n\n    .container {\n        position: relative;\n        margin: 100px 0;\n        display: inline-block;\n    }\n\n    .box {\n        width: 150px;\n        height: 150px;\n        border: 3px solid black;\n        background-color: rgba(138, 161, 64, .5);\n    }\n\n    .box-origin {\n        position: absolute;\n        top: 0;\n        left: 0;\n    }\n    </style>\n</head>\n\n<body>\n    <h1>Transform 2D</h1>\n    <h3>可忽略所有<code>:after</code>的样式</h3>\n    <h2>transform (translate & rotate)</h2>\n    <div class=\"container\">\n        <div id=\"box1\" class=\"box\"></div>\n        <div id=\"box1-clone\" class=\"box box-origin\"></div>\n        <p>translate(50%) -> rotate(45deg)</p>\n    </div>\n    <br>\n    <style type=\"text/css\">\n    #box1 {\n        transform: translate(50%) rotate(45deg);\n    }\n\n    #box1:after {\n        background: RED;\n        width: 15px;\n        height: 15px;\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        content: \"\";\n        border-radius: 50%;\n        transform: translate(-50%, -50%);\n    }\n    </style>\n    <div class=\"container\">\n        <div id=\"box2\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>rotate(45deg) -> translate(50%)</p>\n    </div>\n    <br>\n    <style type=\"text/css\">\n    #box2 {\n        transform: rotate(45deg) translate(50%);\n    }\n\n    #box2:after {\n        background: RED;\n        width: 15px;\n        height: 15px;\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        content: \"\";\n        border-radius: 50%;\n        transform: translate(-50%, -50%);\n    }\n    </style>\n    <h2>translate-origin</h2>\n    <div class=\"container\">\n        <div id=\"box3\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>transform-origin: 100% 100%</p>\n    </div>\n    <br>\n    <style type=\"text/css\">\n    #box3 {\n        transform-origin: 100% 100%;\n        transform: rotate(45deg);\n    }\n\n    #box3:after {\n        background: RED;\n        width: 15px;\n        height: 15px;\n        position: absolute;\n        left: 100%;\n        top: 100%;\n        content: \"\";\n        border-radius: 50%;\n        transform: translate(-50%, -50%);\n    }\n    </style>\n    <h3>scale</h3>\n    <div class=\"container\">\n        <div id=\"box4\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>scale(0.5)</p>\n    </div>\n    <br>\n    <style type=\"text/css\">\n    #box4 {\n        transform: scale(0.5);\n    }\n\n    #box4:after {\n        background: RED;\n        width: 15px;\n        height: 15px;\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        content: \"\";\n        border-radius: 50%;\n        transform: translate(-50%, -50%);\n    }\n    </style>\n    <div class=\"container\">\n        <div id=\"box5\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p id=\"box-scale\">rotate(45deg) scale(1.5, 2)</p>\n    </div>\n    <br>\n    <style type=\"text/css\">\n    #box5 {\n        transform: rotate(45deg) scale(1.5, 2);\n    }\n\n    #box-scale:before {\n        background: RED;\n        width: 15px;\n        height: 15px;\n        position: absolute;\n        left: 75px;\n        top: 75px;\n        content: \"\";\n        border-radius: 50%;\n        transform: translate(-50%, -50%);\n    }\n    </style>\n\n    <h3>skew</h3>\n    <div class=\"container\">\n      <div id=\"box6\" class=\"box\"></div>\n      <div class=\"box box-origin\"></div>\n      <p>skew(-45deg, 45deg)</p>\n    </div>\n    <br>\n    <style type=\"text/css\">\n    #box6 {\n      transform: skew(-45deg, 45deg);\n    }\n    #box6:after {\n      background: RED;\n      width: 15px;\n      height: 15px;\n      position: absolute;\n      left: 50%;\n      top: 50%;\n      content: \"\";\n      border-radius: 50%;\n      transform: translate(-50%, -50%);\n    }\n    </style>\n</body>\n\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/CSS/Transform3D.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Transfomr 3D</title>\n    <style type=\"text/css\">\n    body {\n        margin: 50px;\n        text-align: center;\n        position: relative;\n        margin: 100px 0;\n    }\n\n    .container {\n        position: relative;\n        margin: 100px 10px;\n        display: inline-block;\n        perspective: 500px;\n    }\n\n    .box {\n        width: 150px;\n        height: 150px;\n        border: 3px solid black;\n        background-color: rgba(138, 161, 64, .5);\n    }\n\n    .box-origin {\n        position: absolute;\n        top: 0;\n        left: 0;\n        z-index: -999;\n    }\n    </style>\n</head>\n\n<body>\n    <h1>Transform 3D</h1>\n    <h3>可以忽略所有<code>:after</code>的样式</h3>\n    <h2>rotate</h2>\n    <div class=\"container\">\n        <div id=\"box1\" class=\"box\">\n            <div id=\"line\"></div>\n        </div>\n        <div class=\"box box-origin\"></div>\n    </div>\n    <style type=\"text/css\">\n    #box1 {\n        transform: rotateY(60deg) rotateX(0deg);\n    }\n\n    #line {\n        position: absolute;\n        width: 2px;\n        height: 150px;\n        background-color: RED;\n        left: 73px;\n    }\n    </style>\n    <h2>perspective-origin</h2>\n    <div class=\"container\" id=\"container-1\">\n        <div id=\"box2\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>top</p>\n    </div>\n    <div class=\"container\" id=\"container-2\">\n        <div id=\"box3\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>50% 50%</p>\n    </div>\n    <div class=\"container\" id=\"container-3\">\n        <div id=\"box4\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>bottom</p>\n    </div>\n    <style type=\"text/css\">\n    #box2,\n    #box3,\n    #box4 {\n        transform: rotateY(45deg);\n    }\n\n    #container-1 {\n        perspective-origin: 0 0;\n    }\n\n    #container-2 {\n        perspective-origin: 50% 50%;\n    }\n\n    #container-3 {\n        perspective-origin: 100% 100%;\n    }\n    </style>\n    <h2>translate3d(x, y, z)</h2>\n    <div class=\"container\">\n        <div id=\"box-5\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>(10px, 10px, 200px)</p>\n    </div>\n    <div class=\"container\">\n        <div id=\"box-6\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>(0, 0, -100px)</p>\n    </div>\n    <div class=\"container\">\n        <div id=\"box-7\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>(0, 0, 0)</p>\n    </div>\n    <style type=\"text/css\">\n    #box-5 {\n        transform: translateZ(100px) translateY(10px) translateX(10px);\n    }\n\n    #box-6 {\n        transform: translate3d(0, 0, -100px);\n    }\n\n    #box-7 {\n        transform: translate3d(0, 0, 0);\n    }\n    </style>\n    <h2>scale3d</h2>\n    <h3>改变轴的比例</h3>\n    <div class=\"container\">\n        <div id=\"box-8\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>scale3d(1.2, 1.2, 1)</p>\n    </div>\n    <style>\n    #box-8 {\n        transform: scale3d(1.2, 1.2, 1);\n    }\n    </style>\n    <h2>rotate3d</h2>\n    <div class=\"container\">\n        <div id=\"box-9\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>(0, 0, 1, 45deg)</p>\n    </div>\n    <div class=\"container\">\n        <div id=\"box-10\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>(1, 1, 1, 45deg)</p>\n    </div>\n    <div class=\"container\">\n        <div id=\"box-11\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>(-1, -1, -1, 45deg)</p>\n    </div>\n    <style type=\"text/css\">\n    #box-9 {\n        transform: rotate3d(0, 0, 1, 45deg);\n    }\n\n    #box-10 {\n        transform: rotate3d(1, 1, 1, 45deg);\n    }\n\n    #box-11 {\n        transform: rotate3d(-1, -1, -1, 45deg);\n    }\n    </style>\n    <h2>transform-style</h2>\n    <div class=\"container\">\n      <div id=\"box-12\" class=\"box\">\n        <div id=\"box-13\" class=\"box\"></div>\n      </div>\n      <div class=\"box box-origin\"></div>\n      <p>preserve-3d</p>\n    </div>\n    <style type=\"text/css\">\n    #box-12 {\n      transform: rotateX(45deg);\n      transform-style: preserve-3d;\n    }\n    #box-13 {\n      transform: rotateY(45deg);\n    }\n    </style>\n    <div class=\"container\">\n      <div id=\"box-14\" class=\"box\">\n        <div id=\"box-15\" class=\"box\"></div>\n      </div>\n      <div class=\"box box-origin\"></div>\n      <p>flat</p>\n    </div>\n    <style type=\"text/css\">\n    #box-14 {\n      transform: rotateX(45deg);\n      transform-style: flat;\n    }\n    #box-15 {\n      transform: rotateY(45deg);\n    }\n    </style>\n    <h2>backface-visibility</h2>\n    <div class=\"container\">\n      <div id=\"box-16\" class=\"box\">\n        <p>B</p>\n      </div>\n      <div class=\"box box-origin\"></div>\n      <p>visible</p>\n    </div>\n    <div class=\"container\">\n      <div id=\"box-17\" class=\"box\">\n        <p>B</p>\n      </div>\n      <div class=\"box box-origin\"></div>\n      <p>hidden</p>\n    </div>\n    <style type=\"text/css\">\n    #box-16 {\n      background-color: rgba(138, 161, 64, 1);\n      transform: rotateY(100deg);\n      backface-visibility: visible;\n    }\n    #box-16 p {\n      color: black;\n      font-size: 3rem;\n    }\n    #box-17 {\n      background-color: rgba(138, 161, 64, 1);\n      transform: rotateY(100deg);\n      backface-visibility: hidden;\n    }\n    #box-17 p {\n      color: black;\n      font-size: 3rem;\n    }\n    </style>\n</body>\n\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/CSS/Transition.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Transition</title>\n    <style type=\"text/css\">\n    body {\n        margin: 50px;\n        text-align: center;\n        position: relative;\n        margin: ;\n        100px 0;\n    }\n\n    .container {\n        position: relative;\n        margin: 100px 10px;\n        display: inline-block;\n        perspective: 500px;\n    }\n\n    .box {\n        width: 150px;\n        height: 150px;\n        border: 3px solid black;\n        background-color: rgba(138, 161, 64, .5);\n    }\n\n    .box-origin {\n        position: absolute;\n        top: 0;\n        left: 0;\n        z-index: -999;\n    }\n    </style>\n</head>\n\n<body>\n    <h1> 动画 - Transition </h1>\n    <h2>transition</h2>\n    <div class=\"container\">\n        <div id=\"box1\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>无过度</p>\n    </div>\n    <div class=\"container\">\n        <div id=\"box2\" class=\"box\"></div>\n        <div class=\"box box-origin\"></div>\n        <p>有过度</p>\n    </div>\n    <style>\n    #box1:hover {\n        transform: rotate(45deg);\n    }\n\n    #box2:hover {\n        transition-delay: .3s;\n        transform: rotate(45deg);\n        transition: 1s;\n    }\n    </style>\n    <h2>transition-property</h2>\n    <div class=\"row\">\n        <div class=\"box hover-demo\" id=\"box3\">\n            <p>none</p>\n        </div>\n    </div>\n    <style type=\"text/css\">\n    .row {\n        position: relative;\n        margin: 10px;\n        height: 155px;\n        background: rgba(187, 198, 145, 0.5);\n        border: 3px dashed rgba(135, 162, 64, 1);\n    }\n\n    #box3 {\n        border-radius: 50%;\n        position: absolute;\n        top: 0;\n        left: 0;\n        font-size: 3rem;\n    }\n\n    #box3:hover {\n        transition-delay: .3s;\n        transition: 2s;\n        transition-property: none;\n        left: calc(100% - 150px);\n        color: white;\n        top: 0;\n    }\n    </style>\n    <div class=\"row\">\n        <div class=\"box hover-demo\" id=\"box4\">\n            <p>all</p>\n        </div>\n    </div>\n    <style type=\"text/css\">\n    #box4 {\n        border-radius: 50%;\n        position: absolute;\n        top: 0;\n        left: 0;\n        font-size: 3rem;\n    }\n\n    #box4:hover {\n        transition-delay: .3s;\n        transition: 2s;\n        transition-property: all;\n        color: white;\n        left: calc(100% - 150px);\n        top: 0;\n    }\n    </style>\n    <div class=\"row\">\n        <div class=\"box hover-demo\" id=\"box5\">\n            <p>left</p>\n        </div>\n    </div>\n    <style type=\"text/css\">\n    #box5 {\n        border-radius: 50%;\n        transition-property: all;\n        position: absolute;\n        top: 0;\n        left: 0;\n        font-size: 3rem;\n    }\n\n    #box5:hover {\n        transition-delay: .3s;\n        transition: 2s;\n        transition-property: left;\n        color: white;\n        left: calc(100% - 150px);\n        top: 0;\n    }\n    </style>\n    <div class=\"row\">\n        <div class=\"box hover-demo\" id=\"box6\">\n            <p>color</p>\n        </div>\n    </div>\n    <style type=\"text/css\">\n    #box6 {\n        border-radius: 50%;\n        transition-property: all;\n        position: absolute;\n        top: 0;\n        left: 0;\n        font-size: 3rem;\n    }\n\n    #box6:hover {\n        transition-delay: .3s;\n        transition: 2s;\n        transition-property: color;\n        color: white;\n        left: calc(100% - 150px);\n        top: 0;\n    }\n    </style>\n    <h2>多个动画，多个时间</h2>\n    <div class=\"row\">\n        <div class=\"box hover-demo\" id=\"box7\">\n            <p>multipe</p>\n        </div>\n    </div>\n    <style type=\"text/css\">\n    #box7 {\n        border-radius: 50%;\n        position: absolute;\n        top: 0;\n        left: 0;\n        font-size: 3rem;\n    }\n\n    #box7:hover {\n        transition-delay: .3s;\n        transition-property: left, color, border-radius;\n        transition-duration: 1s, 3s, 8s;\n        color: white;\n        border-radius: 0;\n        left: calc(100% - 150px);\n        top: 0;\n    }\n    </style>\n</body>\n\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/Layout/00_center_horizontal.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>水平居中</title>\n  </head>\n  <body>\n\n    <style media=\"screen\">\n      .box {\n        width: 100px;\n        height: 100px;\n        background: #859A00;\n      }\n    </style>\n\n    <!-- Sample 00 -->\n    <h1>inline-block + text-align</h1>\n    <div class=\"demo0-parent\">\n      <div class=\"demo0-child box\"></div>\n    </div>\n    <style media=\"screen\">\n      .demo0-child {\n        display: inline-block;\n      }\n      .demo0-parent {\n        text-align: center;\n      }\n    </style>\n\n    <!-- Sample 01 -->\n    <h1>table + margin</h1>\n    <div class=\"demo1-parent\">\n      <div class=\"demo1-child box\"></div>\n    </div>\n    <style media=\"screen\">\n      .demo1-child {\n        display: table;\n        margin: 0 auto;\n      }\n    </style>\n\n    <!-- Sample 02 -->\n    <h1>absolute + transform</h1>\n    <div class=\"demo2-parent\">\n      <div class=\"demo2-child box\"></div>\n    </div>\n\n    <style media=\"screen\">\n      .demo2-parent {\n        position: relative;\n        height: 100px;\n      }\n      .demo2-child {\n        position: absolute;\n        left: 50%;\n        transform: translateX(-50%);\n      }\n    </style>\n\n    <!-- Sample03 -->\n    <h1>flex + justify-content</h1>\n    <div class=\"demo3-parent\">\n      <div class=\"demo3-child box\"></div>\n    </div>\n    <style media=\"screen\">\n      .demo3-parent {\n        display: flex;\n        justify-content: center;\n      }\n    </style>\n\n  </body>\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/Layout/01_center_vertical.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta charset=\"utf-8\">\n  <title>垂直居中</title>\n</head>\n\n<body>\n\n  <style media=\"screen\">\n    .box {\n      width: 100px;\n      height: 100px;\n      background: #859A00;\n    }\n  </style>\n\n  <div class=\"demo0-wrap\">\n    <div class=\"demo0-parent\">\n      <div class=\"demo0-child box\"></div>\n    </div>\n  </div>\n\n  <style media=\"screen\">\n    .demo0-wrap {\n      height: 100vh;\n      display: table;\n    }\n    .demo0-parent {\n      display: table-cell;\n      vertical-align: middle;\n    }\n    .demo0-child {\n      display: table-cell;\n      vertical-align: middle;\n    }\n  </style>\n</body>\n\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/SampleCode/Layout/02multiple_column.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>多列布局 - 一列定宽</title>\n  </head>\n  <body>\n    <div class=\"demo0-parent\">\n      <div class=\"demo0-left\">\n      </div>\n      <div class=\"demo0-right\">\n      </div>\n    </div>\n    \n  </body>\n</html>\n"
  },
  {
    "path": "03-FEND_Note-master/TOC.md",
    "content": "# Summary\n\n- [页面制作](chapter1/00_intro.md)\n  - [Photoshop](chapter1/01_photoshop.md)\n    - [工具、面板、视图](chapter1/01_01_tool_panel_view.md)\n    - [测量及取色](chapter1/01_02_measurement_and_color.md)\n    - [切图](chapter1/01_03_slice.md)\n    - [图片保存](chapter1/01_04_save_image.md)\n    - [图片优化与合并](chapter1/01_05_image_optimisation.md)\n  - [开发及调试工具](chapter1/02_dev_tools.md)\n    - [Sublime 编辑器](chapter1/02_01_sublime.md)\n    - [Atom 编辑器](chapter1/02_02_atom.md)\n  - [HTML](chapter1/03_html.md)\n    - [HTML 简介](chapter1/03_01_html_intro.md)\n    - [HTML 语法](chapter1/03_02_html_sytax.md)\n    - [HTML 标签](chapter1/03_05_html_tags.md)\n    - [实体字符](chapter1/03_03_html_ascii_encoding.md)\n    - [浏览器兼容](chapter1/03_04_cross_browser.md)\n  - [CSS](chapter1/04_css_intro.md)\n    - [语法](chapter1/04_01_css_sytax.md)\n    - [选择器](chapter1/04_02_selector.md)\n    - [文本](chapter1/04_03_text.md)\n    - [盒模型](chapter1/04_04_box_model.md)\n    - [背景](chapter1/04_05_background.md)\n    - [布局](chapter1/04_06_layout.md)\n    - [变形](chapter1/04_07_transform.md)\n    - [动画](chapter1/04_08_animation.md)\n    - [常见布局样例](chapter1/04_09_layout_demo.md)\n- [JavaScript 程序设计](chapter2/00_intro.md)\n  - [JavaScript 介绍](chapter2/01_javascript_intro.md)\n  - [调试器](chapter2/02_dev_tools.md)\n  - [基础语法](chapter2/03_basic_syntax.md)\n  - [类型系统](chapter2/04_data_type.md)\n  - [类型判断](chapter2/11_js_type_determin.md)\n  - [内置对象](chapter2/05_internal_object.md)\n  - [变量作用域](chapter2/06_scope.md)\n  - [表达式与运算符号](chapter2/07_statement_and_operator.md)\n  - [语句](chapter2/08_statement.md)\n  - [闭包](chapter2/09_closure.md)\n  - [面向对象](chapter2/10_object.md)\n  - [正则表达式](chapter2/12_reg_exp.md)\n- [DOM 编程](chapter3/00_intro.md)\n  - [文档树（DOM Tree）](chapter3/01_dom_tree.md)\n  - [节点操作](chapter3/02_node_manipulation.md)\n  - [操作属性](chapter3/03_attribute.md)\n  - [样式操作](chapter3/04_style_manipulation.md)\n  - [事件](chapter3/05_events.md)\n  - [多媒体（视频与音频）](chapter3/08_multimedia.md)\n  - [Canvas](chapter3/07_canvas.md)\n  - [BOM](chapter3/10_bom.md)\n  - [数据通信](chapter3/09_network.md)\n  - [数据存储](chapter3/11_storage.md)\n  - [动画](chapter3/06_animation.md)\n  - [表单操作](chapter3/12_form_manipulation.md)\n  - [列表操作](chapter3/13_list_manipulation.md)\n- [页面架构](chapter4/00_intro.md)\n  - [CSS Reset](chapter4/01_CSS_Reset.md)\n  - [布局解决方案](chapter4/02_layout.md)\n  - [响应式布局](chapter4/03_responsive.md)\n  - [页面优化](chapter4/04_page_optimisation.md)\n  - [规范与模块化](chapter4/05_modulation.md)\n- [产品前端架构](chapter5/00_intro.md)\n  - [协作流程](chapter5/01_collaboration.md)\n  - [接口设计](chapter5/02_design_api.md)\n  - [版本控制](chapter5/03_version_control.md)\n  - [技术选型](chapter5/04_tech_selection.md)\n  - [开发实践](chapter5/05_development.md)\n- [附录 A：书单](Booklist.md)\n"
  },
  {
    "path": "03-FEND_Note-master/book.json",
    "content": "{\n  \"gitbook\": \">=2.0.0\",\n  \"title\":\"Frontend Notebook\",\n  \"language\":\"zh-cn\",\n  \"description\":\"互联网前端开发过程全记录。从基础开始，从现在开始。\"\n}"
  },
  {
    "path": "03-FEND_Note-master/chapter1/00_intro.md",
    "content": "## 前端工程师概述\n\n[TOC]\n\n**网页发展史**\n\nWeb 1.0 -> Web 2.0（基于 Ajax） -> Web 3.0 （基于 HTML5）\n\n**网站开发协作流程**\n\n![](../img/D/development-flow.png)\n\n**前端职责**\n\n视觉稿（配色图标距离空间） + 交互稿（用户逻辑） = UI（用户界面）\n\n视觉稿 -> 页面制作\n\n交互稿 -> 页面逻辑开发\n\n**所需技能**\n\n- DOM (操作 HTML 及 CSS 的接口)\n- JavaScript (定义页面互动)\n- CSS (定义页面样式)\n- HTML (定义页面结果)\n- Photoshop (取图)"
  },
  {
    "path": "03-FEND_Note-master/chapter1/01_01_tool_panel_view.md",
    "content": "### 工具, 面板, 视图\n\n[TOC]\n\n在全局设置下将单位修改为像素，因其在 CSS 中运用最广 (**Preference** -> **Units & Rulers** -> **Units**) 。设置工作区布局为切图及图片编辑做准备（所需窗口为信息窗口，图层窗口以及历史记录窗口）。\n\n![](../img/P/photoshop-mainWindow.png)\n\n打开『信息窗口』、『图层窗口』、『历史纪录窗口』、『工具面板』、『选项』面板，可以通过 Window -> Workspace -> New WorkSpaces 保存工作区，以便下次打开。\n\n**切图常用工具**\n\n| 工具名    |           示意图            | 注释                                     |\n| ------ | :----------------------: | -------------------------------------- |\n| 移动工具   | ![](../img/H/hwa_03.png) |                                        |\n| 矩形选框工具 | ![](../img/H/hwa_01.png) | 需将自动选择调至选择图层                           |\n| 魔棒工具   | ![](../img/H/hwa_05.png) | （容差 Tolerance 越小选择的范围就越小）消除锯齿可以让选择区域光滑 |\n| 剪裁工具   | ![](../img/H/hwa_06.png) |                                        |\n| 切片工具   | ![](../img/H/hwa_07.png) | 在裁剪工具分支下                               |\n| 缩放工具   | ![](../img/H/hwa_34.png) | `Ctrl+加号`与`Ctrl+减号` 或者 `alt+鼠标滑轮`      |\n| 取色器    | ![](../img/H/hwa_31.png) |                                        |\n\n图层（单层元素）与组（类似于文件夹）的区别。\n\n**辅助视图**，在视图菜单下启动\n\n- 对齐，会启动靠近吸附功能\n- 标尺，<kbd>Command</kbd> + <kbd>R</kbd>\n- 参考线，<kbd>Command</kbd> + <kbd>;</kbd>\n\n![](../img/P/photoshop-menu.png)\n\nNOTE: 所有工具及快捷键如下。\n\n![](../img/T/ToolsPanelOverview.png)\n\n### 常用快捷键\n\n**放大缩小画布**\n\n- 放大到100%大小：<kbd>Ctrl</kbd>+<kbd>数字1</kbd>\n- 放大：<kbd>ctrl</kbd> + 加号\n- 缩小：<kbd>ctrl</kbd> + 减号\n- <kbd>alt</kbd> + 滚轮\n\n**合并图层**\n\n- 合并图层：<kbd>ctrl</kbd>+<kbd>E</kbd>\n- 合并可见图层：<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>E</kbd>"
  },
  {
    "path": "03-FEND_Note-master/chapter1/01_02_measurement_and_color.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [测量及取色](#%E6%B5%8B%E9%87%8F%E5%8F%8A%E5%8F%96%E8%89%B2)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 测量及取色\n\n所有能接受数字的属性都需要测量并尽可能百分百的还原设计稿。\n\n#### 测量\n\n- 宽度，高度 (width, height)\n- 内外边距 (padding, margin)\n- 边框 (border)\n- 定位 (position)\n- 文字大小 (font-size)\n- 行高 (line-height)，其为第一行的底端到第二行的底端。\n- 背景位置 (background-position)\n\nNOTE: 测量时尽可能放大画布以减少误差。量取文字是为了减少误差尽量选取尺寸大的文字进行测量。\n\n![](../img/P/photoshop-measure&colorSelection.png)\n\n**选框工具的多用途**，增（Shift）减（Alt）以及交叉选择（Shift + Alt）。左右（或上下）使用分离选框选择可以得到整两个分离边框的距离总值。\n\n![](../img/T/rect-selection-tool.gif)\n\n#### 取色\n\n所有能接受颜色的属性都需要取色。\n\n- 边框色\n- 背景色\n- 文字色\n\nNOTE：使用魔棒工具可以迅速识别背景色是否没*线性*渐变的方法。Mac OS X 推荐使用 **Sip** 可在 Mac App Store 免费下载。\nNOTE+：可以使用魔棒工具来判断颜色是否为渐变。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/01_03_slice.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [切图](#%E5%88%87%E5%9B%BE)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 切图\n\n- **内容性图片** 指的是图片在页面是作为内容存在，如页面中的海报。\n- **修饰性图片** 指的是图片在页面中起修饰作用，如页面中的背景和图标。\n\n修饰性图标和内容性图片需要（在 HTML 的 `<img>` 之中，只需站位不需切图）切出。切出的内容性图片应保存为 `*.jpg` 格式，而修饰性图片因保存为 `png24`（IE6 不支持半透明，Alpha 透明） 或 `png8` 它们均支持全透明。\n\n**隐藏文字**，方法一，直接在图层中隐藏文字图层。方法二（两种，分别应对于纯色和有背景需要隐藏文本的情况）如下图所示，使用自由变换。\n\n![](../img/B/btn-remove-text.gif)\n\n**PNG24**切图方法\n- 移动工具选中所需图层（<kbd>Ctrl</kbd> 多选）\n- 右键合并图层（<kbd>Ctrl</kbd> + <kbd>E</kbd>）\n- 复制到新图层\n\n**PNG8**带背景切图方法\n- 合并可见图层（<kbd>Shift</kbd> + <kbd>Ctrl</kbd> + <kbd>E</kbd>）\n- 矩形选框选择内容\n- 魔棒工具去除多余部分（<kbd>Alt</kbd> + 选取）\n\n**可平铺**背景的切图方法\n- 用矩形选择一个区域\n- 复制至新图层\n\nNOTE: X 轴平铺需要占满图片的宽，Y 轴平铺需要占满图片的高。\n\n**切片**工具（大图化小的方法，将一大图分为多小图）\n- 拉参考线\n- 选择切片工具\n- 点击 “基于参考线的切片” 按钮\n- 选择切片选择工具\n- 保存于新图层\n\n#### 如何开始切图\n\n##### 第一步：去掉所有文字，只留背景\n\n打开视觉稿后，用上面说过的方法去掉所有的文字，只留背景和图片（记得备份一下PSD文件）。\n\n![](../img/P/photoshop-without-image.png)\n\n##### 第二步：保存图片\n\n将去掉文字的图片保存起来。一般情况下内容性图片保存为jpg格式，图标类型的保存为png格式。\n\n![](../img/P/photoshop-cut-image.png)\n\n##### 第三步：构思页面的具体实现\n\n划分页面的结构，具体的实现方式。\n\n##### 第四步：一边编写HTML代码，一边测量、取色\n\n根据构思号的页面结构，开始编写HTML代码，并且开始进行测量和取色。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/01_04_save_image.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [图片保存](#%E5%9B%BE%E7%89%87%E4%BF%9D%E5%AD%98)\n  - [保存格式的选择](#%E4%BF%9D%E5%AD%98%E6%A0%BC%E5%BC%8F%E7%9A%84%E9%80%89%E6%8B%A9)\n- [图片修改与维护](#%E5%9B%BE%E7%89%87%E4%BF%AE%E6%94%B9%E4%B8%8E%E7%BB%B4%E6%8A%A4)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 图片保存\n\n将需要的内容保存在独立的文件里便于之后的导出。（存储于 Web 所用格式 <kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>Ctrl</kbd> + <kbd>S</kbd>）\n\n如需保存**独立图层**则要把需要的图层拖到新建的透明背景的图层，或在图层上右键复制（Duplicate）图层选择地址为新文件即可。\n\n**图片与背景合并**的切图方法如下\n\n![](../img/S/save-image.gif)\n\n#### 保存格式的选择\n\n保存类型一：色彩丰富切无透明要求时保存为 `JPG` 格式并选用时候的品质（通常使用品质 80 ）。\n\n保存类型二：图片色彩不丰富，不伦透明与否一律保存为 `PNG8` 格式（256颜色，需特殊设置如下图，需设置`杂边：无`  `无仿色`）。\n\n![](../img/P/photoshop-saveFormat.png)\n\n保存类型三：图片有半透明（Alpha 透明）的要求，保存为 `PNG24` 格式（不对图片进行压缩）。\n\n保存类型四：保留 PSD 源文件，以备不时之需。\n\n##### 如何保存\n\n一般使用『存储于 Web 所用格式』菜单（Alt + Shift + Ctrl + S）保存\n\n### 图片修改与维护\n\n维护与修改之一：**更改画布**大小以便增加新素材。\n\n![](../img/R/resize-canvas.gif)\n\n维护与修改之二：移动图标分两种，独立图层（移动工具拖动），于非独立图层（选取工具选中分离后移动工具拖动）。\n\n![](../img/M/move-layer.gif)\n\n维护与修改之三：**裁剪画布**的方法有两种，(1)用选取工具选取后图片裁取，(2)直接用裁剪工具裁剪画布。\n\n![](../img/C/crop-canvas.gif)\n\n**注意事项**：为了可维护性的考虑因适当的留出适当的空白区域以便修改所用和提高容错性。`PNG8`需更改图片颜色模式为 RGB 颜色（默认为索引颜色模式，颜色信息会被丢失）。\n\n![](../img/P/png8-color-mode.gif)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/01_05_image_optimisation.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [图片优化与合并](#%E5%9B%BE%E7%89%87%E4%BC%98%E5%8C%96%E4%B8%8E%E5%90%88%E5%B9%B6)\n  - [图片的兼容](#%E5%9B%BE%E7%89%87%E7%9A%84%E5%85%BC%E5%AE%B9)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 图片优化与合并\n\n在 HTML 中使用背景图片的方法如下：\n\n```html\n<button type=\"button\" class=\"btn-default\">Click Me</button>\n\n<style type=\"text/css\" media=\"screen\">\n  .btn-default {\n  background: url(image/btn.png) no-repeat 0 0;\n}\n.btn-default-alt {\nbackground: url(image/sprite.png) no-repeat 0 -50px;\n}\n</style>\n```\n\n图片的**合并**就如同上面提到的切图后保存的过程。拼好的图称之为 **Sprite** 它能减少网络请求次数提高速度。图片压缩工具分为无损（ImageOptim 等工具，也可结合 Grunt 自动化构建工具一同使用）与有损压缩工具（TinyPng）。\n\n#### 图片合并\n\n图片合并建议方案：\n\n- 同个模块的图片合并\n- 大小相近的图片合并\n- 色彩相近的图片合并\n- 以上3种合并混合\n\n合并的图片可以以横向或纵向的排列，分类可将同属于一个模块（功能模块），大小相近（充分利用画布空间），颜色相近（减少文件大小）。\n\n#### 图片的兼容\n\nIE6 不支持 PNG24 半透明所以需要保存两份（sprite.png - png24 和 sprite-ie.png - 8）。在使用 CSS3 是让高级浏览器使用 CSS3 低级浏览器则使用切图。优雅降级指的是让低级浏览器不显示高级浏览器中的界面细节。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/01_photoshop.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Photoshop](#photoshop)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Photoshop\n\n**切图** 从设计稿中切除网页的素材并在代码中引入图片 (复杂的图片或者解决兼容问题)\n\n```html\n// 设计稿 (*.psd) -> 产出物 (*png, *.jpg)\n\n<img src=\"../img/avatar.jpg\" alt=\"desc\">\n\n<style type=\"text/css\" media=\"screen\">\n  background-image: url(../../img/sprite.png);\n  background-position: 0 0;\n</style>\n```"
  },
  {
    "path": "03-FEND_Note-master/chapter1/02_01_sublime.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Sublime 编辑器](#sublime-%E7%BC%96%E8%BE%91%E5%99%A8)\n  - [介绍](#%E4%BB%8B%E7%BB%8D)\n  - [安装](#%E5%AE%89%E8%A3%85)\n    - [Windows/OS X](#windowsos-x)\n    - [Ubuntu](#ubuntu)\n  - [推荐插件](#%E6%8E%A8%E8%8D%90%E6%8F%92%E4%BB%B6)\n    - [1. Package Control](#1-package-control)\n    - [2.Emmet](#2emmet)\n    - [3.JQuery](#3jquery)\n    - [4.FileHeader](#4fileheader)\n    - [5.Pretty Json](#5pretty-json)\n    - [6.CSS Format](#6css-format)\n    - [7.ConvertToUTF8](#7converttoutf8)\n  - [用户自定义代码](#%E7%94%A8%E6%88%B7%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BB%A3%E7%A0%81)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### Sublime 编辑器\n\n#### 介绍\n\nSublime Text是一款性感的编辑器，具有优雅，快速，插件多等优势，不失为前端开发者的轻量高效编辑器。\n\n#### 安装\n\n##### Windows/OS X\n\n官方[站点](http://www.sublimetext.com/)下载安装即可。\n\n##### Ubuntu\n\n可参见 [Ubuntu 下使用 Sublime Text 并解决中文输入问题](http://www.zntec.cn/archives/ubuntu-sublime-text-fcitx.html)，用apt-get安装，解决任务栏，中文输入等多个问题。\n\n##### Sublime 快捷键\n<kbd>command/control</kbd> + <kbd>P</kbd> 进入查找命令（Goto Anything）,此时有三种选择：\n\n* `:` 输入行数找到对应行 （<kbd>control</kbd> + <kbd>G</kbd>）\n* `@` 找到特定函数 （<kbd>command/control</kbd> + <kbd>R</kbd>）\n* `#` 找到对应变量与块\n\n#### 推荐插件\n\n##### 1. Package Control\n\n以后的插件安装基本都靠他了，安装方法可以去[Package Control](https://packagecontrol.io/installation)查看，注意Sublime Text的版本问题。\n\n##### 2.Emmet\n\n前端神器，相信搞前端的没有不用的\n\n**下面插件在Edit 或者 Tools 里面看到插件功能：**\n\n##### 3.JQuery\n\n写JQuery怎么能不用他来增强你的提示？\n\n##### 4.FileHeader\n\n自动创建文件开头模板，并且会根据最后的保存时间修改更新时间\n\n##### 5.Pretty Json\n\n写json不格式话怎么行？\n\n##### 6.CSS Format\n\ncss格式化\n\n##### 7.ConvertToUTF8\n\nGBK编码兼容\n\n#### 用户自定义代码\n\nPreferences - Settings - User 里面加入，全部的设置均为 `JSON` 文本。\n\n```\n\"translate_tabs_to_spaces\": true,\n\"tab_size\": 2,\n```\n把Tab对齐转化为空格对齐，tab_size 控制转化比例。\n\n```\n\"trim_trailing_white_space_on_save\": true,\n```\n\n自动移除行尾多余空格。\n\n```\n\"ensure_newline_at_eof_on_save\": true,\n```\n\n自动在文件末尾加入一个空行，git 用户相信知道是干嘛的。\n\n```\n\"save_on_focus_lost\": true,\n```\n\n 窗口失去焦后立即保存文件。\n\n ```\n \"bold_folder_labels\": true,\n ```\n\n侧栏文件夹加粗。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/02_02_atom.md",
    "content": "### Atom 文本编辑器\n\n本文即为在 **Atom** 下编写完成，在写作过程中让我对这个崭新的 1.0 版本文本编辑器\n有了更多的了解。\n在阅读本文时注意快捷键于后面英文单词的对应可帮助记忆，在使用中忘记的快捷键以可以通过使用\n**查询面板**（后面会提到）进行查询。\n如果你在使用过程中发现了异常和错误可以到 **Atom** 所在的\nGitHub 仓库提交问题报告。同一款编辑器一同成长，愿力量与你同在！\n下面的快捷键均为 **Mac OS X** 默认设置。如你用的是 Windows 或者是 Linux，可能需要尝试将\n所有提到的 <kbd>cmd</kbd> 改为 <kbd>ctrl</kbd>。\n\n#### 基础中的基础\n\n开始之前先把下面这条快捷键记住。<kbd>cmd</kbd>+<kbd>shift</kbd>+<kbd>P</kbd>\n它会打开类似 Alfred 的快捷功能选择窗口，\n如果你从来没有听过 Alfred（此为 Mac OS X 特有应用） 那你应该赶紧去所搜引擎中找找了。\n\n**保存时间**\n\n|快捷键|描述|\n|-----|----|\n|`cmd-shift-S`|可以另存为 \"Save As\"|\n|`cmd-alt-S`|可以保存全部的 \"Save All\".|\n\n**打开文件与目录**\n\n如果在命令行环境中可以使用下面的方法一次打开多个目录。\n\n```bash\n# 打开目录\natom ./hopes ./dreams\n\n# 获得帮助\natom -h\n```\n\n|快捷键|描述|\n|-----|----|\n|`cmd-O`|打开文件|\n|`cmd-shift-O`|添加目录至当前编辑器窗口|\n\n`cmd-P` 可以打开 Fuzzy Finder 进行模糊搜索，默认可所搜区域为项目内所有文件。\n下面的命令可以对模糊所搜做一些限制，`cmd-B` 只所搜已打开的文件（存在与 Buffer 中的文件）。\n`cmd-shift-B`\n\n1.0 版本中在编辑器中添加的新文件无法使用 Fuzzy Finder（模糊寻找） 找到，重启后则可以解决。\n\n**边栏（树目录）**\n\n|快捷键|描述|\n|-----|----|\n|`cmd-\\`|显示或隐藏边栏|\n|`ctrl-0`|聚焦边栏，聚焦后可以操作树目录中的文件|\n\n在聚焦后可以通过 `a` 来增加（add），`m` 来移动（move），`d` 来复制（duplicate）或者\n`delete` 来删除（此处为键盘删除键）。\n这里的操作并没有自动路径补全功能，之后可能需要插件支持。\n\n#### 开始使用\n\n**Atom** 中几乎所有的功能都是以插件的形式存在的。所有如何安装插件则就是我们第一件要做的事。\n除了图形界面安装的方法外，随 **Atom** 还安装了插件管理器叫做 `apm` 。通过它也可以直接安装\n和更新插件。简单说主题也是插件，所以安装主题与安装插件的步骤类似。\n\n*下面的操作均需要联网*\n\n```\n# 安装插件\napm install <package_name>\n\n# 安装指定版本的插件\napm install <package_name>@<package_version>\n\n# 查询插件\napm search <package_name>\n\n# 查询插件详情\napm view <package_name>\n```\n\n##### 移动光标\n\n**Atom** 的移动快方法同 **Emacs** 一致。在熟悉使用 **Atom** 后也很容易的转移至\n**Emacs** 的环境下熟练工作。\n\n单个字符的移动，效果于方向键一致。\n\n|快捷键|描述|\n|-----|----|\n|`ctrl-P`|上移（Previous）|\n|`ctrl-N`|下移（Next）|\n|`ctrl-B`|后移（Back）|\n|`ctrl-F`|前移（Forward）|\n\n在单个字符移动基础上，可以延展至更大范围的移动。例如，单词，整行。\n\n|快捷键|描述|\n|-----|----|\n|`alt-B`|向后以词为单位移动（英文），中文则以英文标点为间隔|\n|`alt-F`|向前以词为单位移动（英文），中文则以英文标点为间隔|\n|`ctrl-E`|移动至行末（End）|\n|`ctrl-A`|移动至此行首字符（Ahead)|\n|`ctrl-A`（敲击两次）|移动至此行行首（包括空格）|\n|`cmd-up`|移动至文件最顶|\n|`cmd-down`|移动至文件最低|\n\n`ctrl-G` 加数字可移动至**目标行**，使用 `row:column` 可以定位行数和列数，\n使用这个方法在查找错误时变得十分方便。\n\n`cmd-R` 可以**在当前文件中**（Buffer）按照符号来搜索，符号关键字指的是函数名（代码中）\n或标题（文档中）。\n\n<!-- TODO: Add Generate ctags and Fuzzy Finder for entire project -->\n<!-- TODO: Add the usage of `ctrl-shift-R` for project width search -->\n<!-- https://atom.io/docs/v1.0.0/using-atom-moving-in-atom#navigating-by-symbols -->\n\n##### 选择\n\n选择是在移动的基础上加入 `shift` 既可完成。特别的几种选择方法如下。\n\n|快捷键|描述|\n|-----|----|\n|`cmd-L`|选取整行|\n|`ctrl-shift-W`|选取当前单词（英文），中文则为整行|\n\n##### 编辑与删除\n\n**Atom** 如同其他的常用的文本编辑器一样可以直接编辑文字，并不存在特殊的模式。但了解下面的\n编辑技巧可以让你使用 **Atom** 更得心应手。\n\n**编辑操作**\n\n|快捷键|描述|\n|-----|----|\n|`ctrl-T`|交换光标两边的字符（Transpose）|\n|`ctrl-J`|将下一行同当前行合并（Join）|\n|`ctrl-cmd-up`|向上冒泡当前行|\n|`ctrl-cmd-down`|向下冒泡当前行|\n|`cmd-shift-D`|复制当前行（Duplicate）|\n|`cmd-K, cmd-U`|转换选中字符至全大写|\n|`cmd-K, cmd-L`|转换选中字符至全小|\n\n<!-- TODO: re-flow selected paragraph to hard-wrap at given line length -->\n<!-- TODO: cmd-alt-Q -->\n\n**删除操作**\n\n|快捷键|描述|\n|-----|----|\n|`ctrl-shift-K`|删除当前（Cut）|\n|`cmd-delete`|删除此行光标后全部字符|\n|`cmd-backspace`|删除至当前行首|\n|`ctrl-K`|切帖至行末（Cut）|\n|`alt-H`|删除前一个字符|\n|`alt-D`|删除后一个字符|\n\n**多个光标及选择**\n\n同 **Sublime Text** 相同，**Atom** 也同样有多光标的实现。\n按住<kbd>cmd</kbd>可以在文本中使用进行区域性选择。\n\n|快捷键|描述|\n|-----|----|\n|`cmd-click`|在点击处增加新光标|\n|`cmd-shift-L`|将选择区域转换为多光标|\n|`ctrl-shift-up`|在上一行增加新光标|\n|`ctrl-shift-down`|在下一行增加新光标|\n|`cmd-D`|选择下一个于当前被选字符相同的字符并添加新光标|\n|`cmd-ctrl-G`|选择全部于当前选中字符相同的字符并添加光标|\n\n##### 括号\n\n编程中最常打交道和需要跳出的莫属于括号和引号了。**Atom** 对于括号有很好的处理办法，\n各种括号在光标内移动都会被自动高亮（引号和 HTML 中的标签也会被高亮和自动补全）。\n选中内容后使用括号可以自动将选中内容包含在括号或引号内。\n\n|快捷键|描述|\n|-----|----|\n|`ctrl-M`|跳至最近的一个括号的起始位置|\n|`ctrl-cmd-M`|选中括号内的所有内容|\n|`alt-cmd-.`|关闭最近的一个 XML/HTML 标签|\n\n##### 搜索与替换\n\n|快捷键|描述|\n|-----|----|\n|`cmd-F`|当前文本中搜索|\n|`cmd-shift-F`|搜索整个项目|\n|`cmd-G`|找到下一个匹配的搜索结果|\n|`cmd-G-shift`|找到上一个匹配的搜索结果|\n\n在项目搜索中可以使用 wildcard 和指定目标的搜索路径。\n\n##### 代码片段（Snippets）\n\n代码片段让你在写代码时有飞一般的感觉，代码片段会将预先设置好的代码片段替换在当前文本中，\n并且设置焦点并用 <kbd>tab</kbd> 聚焦下一个焦点，\n或 <kbd>shift</kbd> + <kbd>tab</kbd> 聚焦上一个焦点。\n\n所有的代码片都存储在下面的目录中 `~/.atom/snippets.cson`，\n你可以通过 Open Your Snippets Menu 打开此文件。\n\n|快捷键|描述|\n|-----|----|\n|`alt-shift-S`|显示当前文件类型下的全部代码片段|\n\n当然制作代码片也有一个代码片，它就是 `snip` 。\n\n###### 制作代码片段\n\n下面是一个简单的代码片样例。\n\n```javascript\n'.source.js':\n  'console.log':\n    'prefix': 'log'\n    'body': 'console.log(${1: \"crash\"});$2'\n```\n\n- `.source.js` 为代码片可用的文件类型范围\n- `console.log` 为代码片内容描述\n- `prefix` 为代码片调用字符\n- `body` 代码片主体内容\n- `${1:'crash'}` 用于定义焦点，顺序及其默认值\n\n多行代码代码片\n\n```javascript\n'.source.js':\n  'if, else if, else':\n    'prefix': 'ieie'\n    'body': \"\"\"\n      if (${1:true}) {\n        $2\n      } else if (${3:false}) {\n        $4\n      } else {\n        $5\n      }\n    \"\"\"\n```\n\n<!-- TODO: 解决实现代码片中存在的问题 -->\n\n##### 代码折叠\n\n可以点击代码行号边的箭头折叠当前层级的代码。\n\n|快捷键|描述|\n|-----|----|\n|`alt-cmd-[`|折叠当前层级|\n|`alt-cmd-]`|展开当前层级|\n|`alt-cmd-shift-{`|折叠全部层级|\n|`alt-cmd-shift-}`|展开全部层级|\n|`cmd-K, cmd-N`（层级数）|根据层级级别折叠|\n\n##### 多窗口模式\n\n任意一个窗口都可以无需的四面分割，分割的部分则依然使用标签来表示。\n\n|快捷键|描述|\n|-----|----|\n|`cmd-k arrow`|根据方向指定分割窗口|\n|`cmd-K, cmd-arrow`|聚焦指定方向的窗口|\n\n<!-- TODO: 分离窗口快捷键无效 -->\n\n##### 解码（Encoding）\n\n**Atom** 支持多种解码格式（包括中文 GBK 的支持），也可自动识别解码方式\n（不能识别时则默认为 UTF-8）。当然你也可以使用这种方法将多种文本在多种解码格式直接转换。\n\n|快捷键|描述|\n|-----|----|\n|`ctrl-shift-U`|切换解码方式|\n\n##### 书签\n\n在 **Atom** 添加书签就如同你看书的时添加书签一样，它使你在书写代码时可以自如的跳转到你需要的\n位置。\n\n|快捷键|描述|\n|-----|----|\n|`F2-cmd`|可以在当前行切换标记书签|\n|`F2`|跳转至下一个书签|\n|`F2-shift`|跳转至上一个书签|\n|`F2-ctrl`|查看全部的书签|\n|`F2-cmd-shift`|清除全部标签|\n\n##### 扩展插件\n\n下面列出了笔者在日常 Web 开发中所易用的插件，这些插件满足了超过百分之九十笔者的开发需求。下面的这些插件均可以在官方插件管理器中进行下载和安装。\n\n```javascript\n[\n\t{\n\t\t\"name\": \"advanced-new-file\",\n\t\t\"version\": \"0.4.3\"\n\t},\n\t{\n\t\t\"name\": \"advanced-open-file\",\n\t\t\"version\": \"0.8.2\"\n\t},\n\t{\n\t\t\"name\": \"atom-beautify\",\n\t\t\"version\": \"0.28.8\"\n\t},\n\t{\n\t\t\"name\": \"AtomicChar\",\n\t\t\"version\": \"0.3.8\"\n\t},\n\t{\n\t\t\"name\": \"autocomplete-paths\",\n\t\t\"version\": \"1.0.2\"\n\t},\n\t{\n\t\t\"name\": \"docblockr\",\n\t\t\"version\": \"0.7.3\"\n\t},\n\t{\n\t\t\"name\": \"ex-mode\",\n\t\t\"version\": \"0.7.0\"\n\t},\n\t{\n\t\t\"name\": \"file-icons\",\n\t\t\"version\": \"1.6.2\"\n\t},\n\t{\n\t\t\"name\": \"language-jade\",\n\t\t\"version\": \"0.6.2\"\n\t},\n\t{\n\t\t\"name\": \"linter\",\n\t\t\"version\": \"1.3.0\"\n\t},\n\t{\n\t\t\"name\": \"linter-jshint\",\n\t\t\"version\": \"1.1.4\"\n\t},\n\t{\n\t\t\"name\": \"markdown-toc\",\n\t\t\"version\": \"0.3.0\"\n\t},\n\t{\n\t\t\"name\": \"merge-conflicts\",\n\t\t\"version\": \"1.3.5\"\n\t},\n\t{\n\t\t\"name\": \"minimap\",\n\t\t\"version\": \"4.12.2\"\n\t},\n\t{\n\t\t\"name\": \"minimap-linter\",\n\t\t\"version\": \"1.0.0\"\n\t},\n\t{\n\t\t\"name\": \"open-in-browser\",\n\t\t\"version\": \"0.4.6\"\n\t},\n\t{\n\t\t\"name\": \"pigments\",\n\t\t\"version\": \"0.9.3\"\n\t},\n\t{\n\t\t\"name\": \"sort-lines\",\n\t\t\"version\": \"0.11.0\"\n\t},\n\t{\n\t\t\"name\": \"sync-settings\",\n\t\t\"version\": \"0.6.0\"\n\t},\n\t{\n\t\t\"name\": \"tab-switcher\",\n\t\t\"version\": \"1.2.1\"\n\t},\n\t{\n\t\t\"name\": \"theme-switcher\",\n\t\t\"version\": \"1.1.0\"\n\t},\n\t{\n\t\t\"name\": \"vim-mode\",\n\t\t\"version\": \"0.57.0\"\n\t},\n\t{\n\t\t\"name\": \"atom-dark-syntax\",\n\t\t\"version\": \"0.27.0\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"atom-dark-ui\",\n\t\t\"version\": \"0.49.0\",\n\t\t\"theme\": \"ui\"\n\t},\n\t{\n\t\t\"name\": \"atom-light-syntax\",\n\t\t\"version\": \"0.28.0\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"atom-light-ui\",\n\t\t\"version\": \"0.41.0\",\n\t\t\"theme\": \"ui\"\n\t},\n\t{\n\t\t\"name\": \"base16-tomorrow-dark-theme\",\n\t\t\"version\": \"0.26.0\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"base16-tomorrow-light-theme\",\n\t\t\"version\": \"0.9.0\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"one-dark-ui\",\n\t\t\"version\": \"1.0.2\",\n\t\t\"theme\": \"ui\"\n\t},\n\t{\n\t\t\"name\": \"one-dark-syntax\",\n\t\t\"version\": \"1.1.0\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"one-light-syntax\",\n\t\t\"version\": \"1.1.0\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"one-light-ui\",\n\t\t\"version\": \"1.0.2\",\n\t\t\"theme\": \"ui\"\n\t},\n\t{\n\t\t\"name\": \"solarized-dark-syntax\",\n\t\t\"version\": \"0.38.1\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"solarized-light-syntax\",\n\t\t\"version\": \"0.22.1\",\n\t\t\"theme\": \"syntax\"\n\t},\n\t{\n\t\t\"name\": \"about\",\n\t\t\"version\": \"1.0.1\"\n\t},\n\t{\n\t\t\"name\": \"archive-view\",\n\t\t\"version\": \"0.58.0\"\n\t},\n\t{\n\t\t\"name\": \"autocomplete-atom-api\",\n\t\t\"version\": \"0.9.2\"\n\t},\n\t{\n\t\t\"name\": \"autocomplete-css\",\n\t\t\"version\": \"0.9.0\"\n\t},\n\t{\n\t\t\"name\": \"autocomplete-html\",\n\t\t\"version\": \"0.7.2\"\n\t},\n\t{\n\t\t\"name\": \"autocomplete-plus\",\n\t\t\"version\": \"2.19.0\"\n\t},\n\t{\n\t\t\"name\": \"autocomplete-snippets\",\n\t\t\"version\": \"1.7.1\"\n\t},\n\t{\n\t\t\"name\": \"autoflow\",\n\t\t\"version\": \"0.25.0\"\n\t},\n\t{\n\t\t\"name\": \"autosave\",\n\t\t\"version\": \"0.22.0\"\n\t},\n\t{\n\t\t\"name\": \"background-tips\",\n\t\t\"version\": \"0.25.0\"\n\t},\n\t{\n\t\t\"name\": \"bookmarks\",\n\t\t\"version\": \"0.35.0\"\n\t},\n\t{\n\t\t\"name\": \"bracket-matcher\",\n\t\t\"version\": \"0.76.0\"\n\t},\n\t{\n\t\t\"name\": \"command-palette\",\n\t\t\"version\": \"0.36.0\"\n\t},\n\t{\n\t\t\"name\": \"deprecation-cop\",\n\t\t\"version\": \"0.53.1\"\n\t},\n\t{\n\t\t\"name\": \"dev-live-reload\",\n\t\t\"version\": \"0.46.0\"\n\t},\n\t{\n\t\t\"name\": \"encoding-selector\",\n\t\t\"version\": \"0.21.0\"\n\t},\n\t{\n\t\t\"name\": \"exception-reporting\",\n\t\t\"version\": \"0.36.0\"\n\t},\n\t{\n\t\t\"name\": \"find-and-replace\",\n\t\t\"version\": \"0.175.0\"\n\t},\n\t{\n\t\t\"name\": \"fuzzy-finder\",\n\t\t\"version\": \"0.87.0\"\n\t},\n\t{\n\t\t\"name\": \"git-diff\",\n\t\t\"version\": \"0.55.0\"\n\t},\n\t{\n\t\t\"name\": \"go-to-line\",\n\t\t\"version\": \"0.30.0\"\n\t},\n\t{\n\t\t\"name\": \"grammar-selector\",\n\t\t\"version\": \"0.47.0\"\n\t},\n\t{\n\t\t\"name\": \"image-view\",\n\t\t\"version\": \"0.54.0\"\n\t},\n\t{\n\t\t\"name\": \"incompatible-packages\",\n\t\t\"version\": \"0.24.1\"\n\t},\n\t{\n\t\t\"name\": \"keybinding-resolver\",\n\t\t\"version\": \"0.33.0\"\n\t},\n\t{\n\t\t\"name\": \"link\",\n\t\t\"version\": \"0.30.0\"\n\t},\n\t{\n\t\t\"name\": \"markdown-preview\",\n\t\t\"version\": \"0.150.0\"\n\t},\n\t{\n\t\t\"name\": \"metrics\",\n\t\t\"version\": \"0.51.0\"\n\t},\n\t{\n\t\t\"name\": \"notifications\",\n\t\t\"version\": \"0.57.0\"\n\t},\n\t{\n\t\t\"name\": \"open-on-github\",\n\t\t\"version\": \"0.37.0\"\n\t},\n\t{\n\t\t\"name\": \"package-generator\",\n\t\t\"version\": \"0.40.0\"\n\t},\n\t{\n\t\t\"name\": \"release-notes\",\n\t\t\"version\": \"0.53.0\"\n\t},\n\t{\n\t\t\"name\": \"settings-view\",\n\t\t\"version\": \"0.211.2\"\n\t},\n\t{\n\t\t\"name\": \"snippets\",\n\t\t\"version\": \"0.95.0\"\n\t},\n\t{\n\t\t\"name\": \"spell-check\",\n\t\t\"version\": \"0.59.0\"\n\t},\n\t{\n\t\t\"name\": \"status-bar\",\n\t\t\"version\": \"0.75.1\"\n\t},\n\t{\n\t\t\"name\": \"styleguide\",\n\t\t\"version\": \"0.44.0\"\n\t},\n\t{\n\t\t\"name\": \"symbols-view\",\n\t\t\"version\": \"0.100.0\"\n\t},\n\t{\n\t\t\"name\": \"tabs\",\n\t\t\"version\": \"0.82.0\"\n\t},\n\t{\n\t\t\"name\": \"timecop\",\n\t\t\"version\": \"0.31.0\"\n\t},\n\t{\n\t\t\"name\": \"tree-view\",\n\t\t\"version\": \"0.180.0\"\n\t},\n\t{\n\t\t\"name\": \"update-package-dependencies\",\n\t\t\"version\": \"0.10.0\"\n\t},\n\t{\n\t\t\"name\": \"whitespace\",\n\t\t\"version\": \"0.30.0\"\n\t},\n\t{\n\t\t\"name\": \"wrap-guide\",\n\t\t\"version\": \"0.35.0\"\n\t},\n\t{\n\t\t\"name\": \"language-c\",\n\t\t\"version\": \"0.45.0\"\n\t},\n\t{\n\t\t\"name\": \"language-clojure\",\n\t\t\"version\": \"0.16.0\"\n\t},\n\t{\n\t\t\"name\": \"language-coffee-script\",\n\t\t\"version\": \"0.41.0\"\n\t},\n\t{\n\t\t\"name\": \"language-csharp\",\n\t\t\"version\": \"0.6.0\"\n\t},\n\t{\n\t\t\"name\": \"language-css\",\n\t\t\"version\": \"0.32.1\"\n\t},\n\t{\n\t\t\"name\": \"language-gfm\",\n\t\t\"version\": \"0.80.0\"\n\t},\n\t{\n\t\t\"name\": \"language-git\",\n\t\t\"version\": \"0.10.0\"\n\t},\n\t{\n\t\t\"name\": \"language-go\",\n\t\t\"version\": \"0.31.0\"\n\t},\n\t{\n\t\t\"name\": \"language-html\",\n\t\t\"version\": \"0.40.0\"\n\t},\n\t{\n\t\t\"name\": \"language-hyperlink\",\n\t\t\"version\": \"0.14.0\"\n\t},\n\t{\n\t\t\"name\": \"language-java\",\n\t\t\"version\": \"0.15.0\"\n\t},\n\t{\n\t\t\"name\": \"language-javascript\",\n\t\t\"version\": \"0.85.0\"\n\t},\n\t{\n\t\t\"name\": \"language-json\",\n\t\t\"version\": \"0.15.0\"\n\t},\n\t{\n\t\t\"name\": \"language-less\",\n\t\t\"version\": \"0.28.1\"\n\t},\n\t{\n\t\t\"name\": \"language-make\",\n\t\t\"version\": \"0.14.0\"\n\t},\n\t{\n\t\t\"name\": \"language-mustache\",\n\t\t\"version\": \"0.12.0\"\n\t},\n\t{\n\t\t\"name\": \"language-objective-c\",\n\t\t\"version\": \"0.15.0\"\n\t},\n\t{\n\t\t\"name\": \"language-perl\",\n\t\t\"version\": \"0.28.0\"\n\t},\n\t{\n\t\t\"name\": \"language-php\",\n\t\t\"version\": \"0.27.0\"\n\t},\n\t{\n\t\t\"name\": \"language-property-list\",\n\t\t\"version\": \"0.8.0\"\n\t},\n\t{\n\t\t\"name\": \"language-python\",\n\t\t\"version\": \"0.38.0\"\n\t},\n\t{\n\t\t\"name\": \"language-ruby\",\n\t\t\"version\": \"0.57.0\"\n\t},\n\t{\n\t\t\"name\": \"language-ruby-on-rails\",\n\t\t\"version\": \"0.22.0\"\n\t},\n\t{\n\t\t\"name\": \"language-sass\",\n\t\t\"version\": \"0.40.0\"\n\t},\n\t{\n\t\t\"name\": \"language-shellscript\",\n\t\t\"version\": \"0.15.0\"\n\t},\n\t{\n\t\t\"name\": \"language-source\",\n\t\t\"version\": \"0.9.0\"\n\t},\n\t{\n\t\t\"name\": \"language-sql\",\n\t\t\"version\": \"0.17.0\"\n\t},\n\t{\n\t\t\"name\": \"language-text\",\n\t\t\"version\": \"0.7.0\"\n\t},\n\t{\n\t\t\"name\": \"language-todo\",\n\t\t\"version\": \"0.25.0\"\n\t},\n\t{\n\t\t\"name\": \"language-toml\",\n\t\t\"version\": \"0.16.0\"\n\t},\n\t{\n\t\t\"name\": \"language-xml\",\n\t\t\"version\": \"0.30.0\"\n\t},\n\t{\n\t\t\"name\": \"language-yaml\",\n\t\t\"version\": \"0.22.0\"\n\t}\n]\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/02_dev_tools.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [开发及调试工具](#%E5%BC%80%E5%8F%91%E5%8F%8A%E8%B0%83%E8%AF%95%E5%B7%A5%E5%85%B7)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 开发及调试工具\n\n- 文本编辑器或 IDE (集成开发环境)\n- Google Chrome, Firefox Firebug, Safari Developer Tool\n\nNOTE: [Google Chrome DevTools Doc](https://developer.chrome.com/devtools)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/03_01_html_intro.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [HTML 简介](#html-%E7%AE%80%E4%BB%8B)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### HTML 简介\n\n![](../img/H/html-overview.png)\n\n注意事项：\n\n- `<!DOCTYPE html>` 必须首行定格\n- `<title>` 为文档标题\n- `<meta charset=\"utf-8\">` 文档解码格式\n- `<meta name=\"keywords\" content=\"...\">` 和 `<meta name=\"description\" content=\"...\">` 提供给搜索引擎使用\n- `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">` 移动端浏览器的宽高与缩放\n- `<link>` 标签可以引入 favicon 和样式表 CSS 文件"
  },
  {
    "path": "03-FEND_Note-master/chapter1/03_02_html_sytax.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [HTML 语法](#html-%E8%AF%AD%E6%B3%95)\n  - [全局属性](#%E5%85%A8%E5%B1%80%E5%B1%9E%E6%80%A7)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### HTML 语法\n\n![](../img/H/html-syntax.png)\n\n**书写规范**：\n\n- 小写标签和属性\n- 属性值双引号\n- 代码因嵌套缩进\n\n#### 全局属性\n\n- id, `<div id='unique-element'></div>`，页面中唯一\n- class，`<button class='btn'>Click Me</button>`，页面中可重复出现\n- style，尽量避免\n- title，对于元素的描述类似于 Tooltip 的效果。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/03_03_html_ascii_encoding.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [实体字符](#%E5%AE%9E%E4%BD%93%E5%AD%97%E7%AC%A6)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 实体字符\n\n实体字符（ASCII Encoding Reference）是用来在代码中以实体代替与HTML语法相同的字符，避免浏览解析错误。它的两种表示方式，第一种为 `&` 外加实体字符名称，例如 `&nbsp;`，第二种为 `&` 加实体字符序号，例如 `&#160;`。\n\n<table>\n    <caption>常用HTML字符实体（建议使用实体）：</caption>\n    <thead>\n        <tr>\n            <th>字符</th>\n            <th>名称</th>\n            <th>实体名</th>\n            <th>实体数</th>\n        </tr>\n    </thead>\n    <tbody>\n        <tr>\n            <td>&quot;</td>\n            <td>双引号</td>\n            <td>&amp;quot;</td>\n            <td>&amp;#34;</td>\n        </tr>\n        <tr>\n            <td>&amp;</td>\n            <td>&amp;符</td>\n            <td>&amp;amp;</td>\n            <td>&amp;#38;</td>\n        </tr>\n        <tr>\n            <td>&lt;</td>\n            <td>左尖括号（小于号）</td>\n            <td>&amp;lt;</td>\n            <td>&amp;#60;</td>\n        </tr>\n        <tr>\n            <td>&gt;</td>\n            <td>右尖括号（大于号）</td>\n            <td>&amp;gt;</td>\n            <td>&amp;#62;</td>\n        </tr>\n        <tr>\n            <td>&nbsp;</td>\n            <td>空格</td>\n            <td>&amp;nbsp;</td>\n            <td>&amp;#160;</td>\n        </tr>\n        <tr>\n            <td>&#12288;</td>\n            <td>中文全角空格</td>\n            <td>&amp;amp;</td>\n            <td>&amp;#12288;</td>\n        </tr>\n    </tbody>\n</table>\n\n<table>\n    <caption>常用特殊字符实体（不建议使用实体）：</caption>\n    <thead>\n        <tr>\n            <th>字符</th>\n            <th>名称</th>\n            <th>实体名</th>\n            <th>实体数</th>\n        </tr>\n    </thead>\n    <tbody>\n        <tr>\n            <td>&yen;</td>\n            <td>元</td>\n            <td>&amp;yen;</td>\n            <td>&amp;#165;</td>\n        </tr>\n        <tr>\n            <td>&brvbar;</td>\n            <td>断竖线</td>\n            <td>&amp;brvbar;</td>\n            <td>&amp;#166;</td>\n        </tr>\n        <tr>\n            <td>&copy;</td>\n            <td>版权</td>\n            <td>&amp;copy;</td>\n            <td>&amp;#169;</td>\n        </tr>\n        <tr>\n            <td>&reg;</td>\n            <td>注册商标R</td>\n            <td>&amp;reg;</td>\n            <td>&amp;#174;</td>\n        </tr>\n        <tr>\n            <td>&trade;</td>\n            <td>商标TM</td>\n            <td>&amp;trade;</td>\n            <td>&amp;#8482;</td>\n        </tr>\n        <tr>\n            <td>&middot;</td>\n            <td>间隔符</td>\n            <td>&amp;middot;</td>\n            <td>&amp;#183;</td>\n        </tr>\n        <tr>\n            <td>&laquo;</td>\n            <td>左双尖括号</td>\n            <td>&amp;laquo;</td>\n            <td>&amp;#171;</td>\n        </tr>\n        <tr>\n            <td>&raquo;</td>\n            <td>右双尖括号</td>\n            <td>&amp;raquo;</td>\n            <td>&amp;#187;</td>\n        </tr>\n        <tr>\n            <td>&deg;</td>\n            <td>度</td>\n            <td>&amp;deg;</td>\n            <td>&amp;#176;</td>\n        </tr>\n        <tr>\n            <td>&times;</td>\n            <td>乘</td>\n            <td>&amp;times;</td>\n            <td>&amp;#215;</td>\n        </tr>\n        <tr>\n            <td>&divide;</td>\n            <td>除</td>\n            <td>&amp;divide;</td>\n            <td>&amp;#247;</td>\n        </tr>\n        <tr>\n            <td>&permil;</td>\n            <td>千分比</td>\n            <td>&amp;permil;</td>\n            <td>&amp;#8240;</td>\n        </tr>\n    </tbody>\n</table>\n\nNOTE：具体所需可在使用时查询，无需记忆。"
  },
  {
    "path": "03-FEND_Note-master/chapter1/03_04_cross_browser.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [浏览器兼容](#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 浏览器兼容\n\n主流浏览器都兼容 HTML5 的新标签，对于 IE8 及以下版本不认识 HTML5的新元素，可以使用 JavaScript 创建一个没用的元素来解决，例如：\n\n```javascript\n<script>\n    document.createElement(\"header\");\n</script>\n```\n也可以使用 shiv 来解决兼容性问题，详情可参考 [HTML5 Shiv](https://github.com/afarkas/html5shiv)"
  },
  {
    "path": "03-FEND_Note-master/chapter1/03_05_html_tags.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [HTML 标签](#html-%E6%A0%87%E7%AD%BE)\n  - [文本标签](#%E6%96%87%E6%9C%AC%E6%A0%87%E7%AD%BE)\n  - [组合内容标签](#%E7%BB%84%E5%90%88%E5%86%85%E5%AE%B9%E6%A0%87%E7%AD%BE)\n  - [嵌入](#%E5%B5%8C%E5%85%A5)\n  - [资源标签](#%E8%B5%84%E6%BA%90%E6%A0%87%E7%AD%BE)\n    - [图标签](#%E5%9B%BE%E6%A0%87%E7%AD%BE)\n    - [热点区域标签](#%E7%83%AD%E7%82%B9%E5%8C%BA%E5%9F%9F%E6%A0%87%E7%AD%BE)\n  - [表格](#%E8%A1%A8%E6%A0%BC)\n  - [表单](#%E8%A1%A8%E5%8D%95)\n  - [语义化](#%E8%AF%AD%E4%B9%89%E5%8C%96)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### HTML 标签\n\n**[HTML5 标签集合](http://www.html5star.com/manual/html5label-meaning)**\n\n![](../img/H/html-elements.jpg)\n\n#### 文档章节\n\n`<body>` 页面内容\n`<header>` 文档头部\n`<nav>` 导航\n`<aside>` 侧边栏\n`<article>` 定义外部内容（如外部引用的文章）\n`<section>` 一个独立的块\n`<footer>` 尾部\n\n**页面通常结构**\n\n![Web Structure](../img/S/structure.gif)\n\n\n#### 文本标签\n\n```html\n<!-- 默认超链接  -->\n<a href=\"http://sample-link.com\" title=\"Sample Link\">Sample</a>\n<!-- 当前窗口显示 -->\n<a href=\"http://sample-link.com\" title=\"Sample Link\" target=\"_self\">Sample</a>\n<!-- 新窗口显示 -->\n<a href=\"http://sample-link.com\" title=\"Sample Link\" target=\"_blank\">Sample</a>\n<!-- iframe 中打开链接 -->\n<a href=\"http://sample-link.com\" title=\"Sample Link\" target=\"iframe-name\">Sample</a>\n<iframe name=\"iframe-name\" frameborder=\"0\"></iframe>\n\n<!-- 页面中的锚点 -->\n<a href=\"#achor\">Achor Point</a>\n<section id=\"achor\">Achor Content</section>\n\n<!-- 邮箱及电话需系统支持 -->\n<a href=\"mailto:sample-address@me.com\" title=\"Email\">Contact Us</a>\n<!-- 多个邮箱地址 -->\n<a href=\"mailto:sample-address@me.com, sample-address0@me.com\" title=\"Email\">Contact Us</a>\n<!-- 添加抄送，主题和内容 -->\n<a href=\"mailto:sample-address@me.com?cc=admin@me.com&subject=Help&body=sample-body-text\" title=\"Email\">Contact Us</a>\n\n<!-- 电话示例 -->\n<a href=\"tel:99999999\" title=\"Phone\">Ring Us</a>\n```\n\n#### 组合内容标签\n\n- `<div>`\n- `<p>`\n- `<ol>`\n- `<ul>`\n- `<dl>`\n- `<pre>`\n- `<blockquote>`\n\n#### 文档章节\n\n`<body>` 页面内容\n`<header>` 文档头部\n`<nav>` 导航\n`<aside>` 侧边栏\n`<article>` 定义外部内容（如外部引用的文章）\n`<section>` 一个独立的块\n`<footer>` 尾部\n\n#### 引用\n\n- `<cite>` 引用作品的名字、作者的名字等\n- `<q>` 引用一小段文字（大段文字引用用`<blockquote>`）\n- `<blockquote>` 引用大块文字\n- `<pre>` 保存格式化的内容（其空格、换行等格式不会丢失）\n\n```html\n<pre>\n  <code>\n    int main(void) {\n      printf('Hello, world!');\n      return 0;\n  }\n</code>\n</pre>\n```\n\n#### 代码\n\n`<code>` 引用代码\n\n#### 格式化\n\n`<b>` 加粗\n`<i>` 斜体\n\n#### 强调\n\n`<em>` 斜体。着重于强调内容，会改变语义的强调\n`<strong>` 粗体。着重于强调内容的重要性\n\n#### 换行\n\n`<br>` 换行\n\n#### 列表\n\n**无序列表**\n\n```html\n<ul>\n  <li>标题</li>\n  <li>结论</li>\n</ul>\n```\n\n**有序列表**\n\n```html\n<ol>\n  <li>第一</li>\n  <li>第二</li>\n</ol>\n```\n\n**自定义列表**\n\n```html\n<dl>\n  <dt>作者</dt>\n  <dd>爱因斯坦</dd>\n  <dt>作品</dt>\n  <dd>《相对论》</dd>\n  <dd>《时间与空间》</dd>\n</dl>\n```\n\n一个`<dt>`可以对应多个`<dd>`\n\nNOTE: `<dl>` 为自定义列表，其中包含一个或多个 `<dt>` 及 一个或多个 `<dd>`，并且`dt` 与 `dl`列表会有缩进的效果。`<pre>` 会保留换行和空格，通常与 `<code>` 一同使用。\n\n```html\n<pre>\n  <code>\n    int main(void) {\n      printf('Hello, world!');\n      return 0;\n    }\n  </code>\n</pre>\n```\n\n`<blockquote>` 拥有 `cite` 属性，它包含引用文本的出处，示例如下所示：\n\n```html\n<blockquote cite=\"http://example.com/facts\">\n  <p>Sample Quote...</p>\n</blockquote>\n```\n\n#### 嵌入\n\n```html\n<iframe src=\"\"></iframe> 页面操作可以不影响到iframe的内容\n\n<!--object embed通常用来嵌入外部资源 -->\n<object type=\"application/x-shockwave-player\">\n  <param name=\"movie\" value=\"book.pdf\">\n</object>\n\n<!--视频 track可以引入字幕 autoplay可以使视频加载后自动播放，loop可以使其循环播放 -->\n<video autoplay loop controls=\"controls\" poster=\"poster.jpg\">\n  <source src=\"movie.mp4\" type=\"video/mp4\">\n  <source src=\"movie.webm\" type=\"video/webm\">\n  <source src=\"movie.ogg\" type=\"video/ogg\">\n  <track kind=\"subtitles\" src=\"video.vtt\" srclang=\"cn\" label=\"cn\">\n</video>\n```\n\n#### 资源标签\n\n##### 图标签\n`canvas` 基于像素，性能要求比较高，可用于实时数据展示。`svg` 为矢量图形图像。\n\n##### 热点区域标签\n\n`img`中套用`map`以及`area`可以实现点击某部分图片触发一个链接，点击另一部分触发另一个链接\n\n```html\n<img src=\"mama.jpg\" width=100 height=100 usemap=\"#map\" />\n<map name=\"map\">\n    <area shap=\"rect\" coords=\"0,0,50,50\" href=\"\" alt=\"\">\n    <area shap=\"circle\" coords=\"75,75,25\" href=\"\" alt=\"\">\n</map>\n```\n\n#### 表格\n\n**表格代码示例**\n\n```html\n<table>\n  <caption>table title and/or explanatory text</caption>\n  <thead>\n    <tr>\n      <th>header</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td>data</td>\n    </tr>\n  </tbody>\n</table>\n```\n\n使用 `colspan=val` 进行跨列，使用 `rowspan=val` 进行跨行。\n\n#### 表单\n\n```html\n<form action=\"WebCreation_submit\" method=\"get\" accept-charset=\"utf-8\">\n  <fieldset>\n    <legend>title or explanatory caption</legend>\n    <!-- 第一种添加标签的方法 -->\n    <label><input type=\"text/submit/hidden/button/etc\" name=\"\" value=\"\"></label>\n    <!-- 第二种添加标签的方法 -->\n    <label for=\"input-id\">Sample Label</label>\n    <input type=\"text\" id=\"input-id\">\n  </fieldset>\n  <fieldset>\n    <legend>title or explanatory caption</legend>\n    <!-- 只读文本框 -->\n    <input type=\"text\" readonly>\n    <!-- 隐藏文本框，可提交影藏数据 -->\n    <input type=\"text\" name=\"hidden-info\" value=\"hiden-info-value\" hidden>\n  </fieldset>\n  <button type=\"submit\">Submit</button>\n  <button type=\"reset\">Reset</button>\n</form>\n```\n\n使用`fieldset`可用于对表单进行分区\n\n表单中的其他控件类型：\n- `textarea` （文本框）\n- `select` 与 `option` （下拉菜单可多选）\n\n<table>\n  <caption>input 类型支持值列表</caption>\n  <tbody>\n  <tr>\n    <th style=\"width:22%\">Value</th>\n    <th>Description</th>\n  </tr>\n  <tr>\n    <td>button</td>\n    <td>Defines a clickable button (mostly used with a JavaScript to activate a script)</td>\n  </tr>\n  <tr>\n    <td>checkbox</td>\n    <td>Defines a checkbox</td>\n  </tr>\n  <tr>\n  <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">color</td>\n    <td>Defines a color picker</td>\n  </tr>\n  <tr>\n  <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">date</td>\n    <td>Defines a date control (year, month and day (no time))</td>\n  </tr>\n  <tr>\n  <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">datetime</td>\n    <td>The input type datetime has been removed from the HTML standard. Use datetime-local instead.</td>\n    </tr>\n    <tr>\n    <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">datetime-local</td>\n      <td>Defines a date and time control (year, month, day, hour, minute, second, and fraction of a second (no time zone)</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">email</td>\n        <td>Defines a field for an e-mail address</td>\n      </tr>\n      <tr>\n        <td>file</td>\n        <td>Defines a file-select field and a \"Browse...\" button (for file uploads)</td>\n      </tr>\n      <tr>\n        <td>hidden</td>\n        <td>Defines a hidden input field</td>\n      </tr>\n      <tr>\n        <td>image</td>\n        <td>Defines an image as the submit button</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">month</td>\n        <td>Defines a month and year control (no time zone)</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">number</td>\n        <td>Defines a field for entering a number</td>\n      </tr>\n      <tr>\n        <td>password</td>\n        <td>Defines a password field (characters are masked)</td>\n      </tr>\n      <tr>\n        <td>radio</td>\n        <td>Defines a radio button</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">range</td>\n        <td>Defines a control for entering a number whose exact value is not important (like a slider control)</td>\n      </tr>\n      <tr>\n        <td>reset</td>\n        <td>Defines a reset button (resets all form values to default values)</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">search</td>\n        <td>Defines a text field for entering a search string</td>\n      </tr>\n      <tr>\n        <td>submit</td>\n        <td>Defines a submit button</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">tel</td>\n        <td>Defines a field for entering a telephone number</td>\n      </tr>\n      <tr>\n        <td>text</td>\n        <td>Default. Defines a single-line text field (default width is 20 characters)</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">time</td>\n        <td>Defines a control for entering a time (no time zone)</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">url</td>\n        <td>Defines a field for entering a URL</td>\n      </tr>\n      <tr>\n      <td class=\"html5badge\"><img src=\"../img/H/html5_badge20.png\">week</td>\n        <td>Defines a week and year control (no time zone)</td>\n      </tr>\n    </tbody>\n</table>\n\n#### 语义化\n\n语义化（Semantic Tag）是指用合适的标签标识适当的内容，它可以起到搜索引擎优化（Search Engine Optimization），提高可访问性（例如盲人使用的屏幕阅读器），与此同时还可以提高代码的可读性。简而言之也就是**在正确的地方使用正确的标签**\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/03_html.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [HTML](#html)\n  - [HTML 历史](#html-%E5%8E%86%E5%8F%B2)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## HTML\n\n### HTML 历史\n\nHTML (Hyper Text Markup Language)，用于标记页面中的内容。\n\n![](../img/H/html-history.png)"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_01_css_sytax.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [语法](#%E8%AF%AD%E6%B3%95)\n  - [浏览器私有属性](#%E6%B5%8F%E8%A7%88%E5%99%A8%E7%A7%81%E6%9C%89%E5%B1%9E%E6%80%A7)\n  - [属性值语法](#%E5%B1%9E%E6%80%A7%E5%80%BC%E8%AF%AD%E6%B3%95)\n    - [基本元素](#%E5%9F%BA%E6%9C%AC%E5%85%83%E7%B4%A0)\n    - [组合符号](#%E7%BB%84%E5%90%88%E7%AC%A6%E5%8F%B7)\n    - [数量符号](#%E6%95%B0%E9%87%8F%E7%AC%A6%E5%8F%B7)\n  - [@规则语法](#@%E8%A7%84%E5%88%99%E8%AF%AD%E6%B3%95)\n    - [@规则](#@%E8%A7%84%E5%88%99)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 语法\n\n```css\n/* 选择器 */\n.m-userlist {\n  /* 属性声明 */\n  margin: 0 0 30px;\n  /* 属性名:属性值; */\n}\n.m-userlist .list {\n  position: relative;\n  height: 100px;\n  overflow: hidden;\n}\n```\n\n#### 浏览器私有属性\n\n- Google Chrome, Safari (`-webkit`)\n- Firefox (`-moz-`)\n- IE (`-ms-`)\n- Opera (`-o-`)\n\n```css\n.pic {\n  -webkit-transform: rotate(-3deg);\n  -ms-transform: rotate(-3deg);\n  transform: rotate(-3deg);\n}\n```\n\nNOTE: 使用 [http://pleeease.io/play/](http://pleeease.io/play/) ，CSS 预处理器（Sass，Less，Stylus）或编辑器插件可自动添加浏览器厂商的私有属性前缀。\n\n#### 属性值语法\n\n```css\nmargin: [ <length> | <percentage> | auto ]{1,4}\n/* 基本元素：<length>, <percentage>, auto*/\n/* 组合符号：[], | */\n/* 数量符号：{1,4} */\n```\n\n##### 基本元素\n\n**关键字**\n- auto\n- solid\n- bold\n- ...\n\n**类型**\n- 基本类型\n    - `<length>`\n    - `<percentage>`\n    - `<color>`\n    - ...\n- 其他类型\n    - <'padding-width'>\n    - <'color-stop'>\n- 符号\n    - `/`\n    - ','\n- inherit, initial\n\n##### 组合符号\n\n- `<'font-size'> <'font-family'>` （` ` 两项必存，顺序毕遵）\n    - 合法：`12px arial`\n    - 不合法：`2em`\n    - 不合法：`arial 14px`\n- `<length>&&<color>` (`&&` 两项必存，顺序无碍)\n    - 合法：green 2px\n    - 合法：1em orange\n    - 不合法：blue\n- `underline || overline || line-through || blink` (`||` 至少选一，顺序无碍)\n    - 合法：underline\n    - 合法：overline underline\n- `<color> | transparent`（`|` 只可选一，不可共存）\n    - 合法：orange\n    - 合法：transparent\n    - 不合法：orange transparent\n- `bold [thin || <length>]`（`[]` 分组之用，视为整体）\n    - 合法：bold thin\n    - 合法：bold 2em\n\n##### 数量符号\n\n- `<length>`（无则表示仅可出现一次）\n    - 合法：1px\n    - 合法：10em\n    - 不合法：1px 2px\n- `<color-stop>[, <color-stop>]+` (`+` 可出现一次或多次)\n    - 合法：#fff, red\n    - 合法：blue, green 50%, gray\n    - 不合法：red\n- `inset?&&<color>` (`?` 表示可选)\n    - 合法：inset orange\n    - 合法：red\n- `<length>{2,4}` (`{2,4}` 可出现次数和最少最多出现次数)\n    - 合法：1px 2px\n    - 合法：1px 2px 3px\n    - 不合法: 1px\n    - 不合法：1px 2px 3px 4px 5px\n- `<time>[, <time>]*`（`*` 出现 0 次或多次）\n    - 合法：1s\n    - 合法：1s,4ms\n- `<time>#`（`#` 出现一次或者多次，用`,`分隔）\n    - 合法：2s, 4s\n    - 不合法：1s 2s\n\n**CSS 规则示例**\n\n![](../img/C/css-value-rule.png)\n\n#### @规则语法\n\n```\n@import \"subs.css\";\n@charset \"utf-8\";\n@media print {\n  /* property: value */\n}\n@keyframes fadein {\n  /* property: value */\n}\n```\n\n- `@标示符 内容;`\n- `@标示符 内容{}`\n\n##### @规则\n\n**常用的规则**\n- `@media` （用于响应式布局）\n- `@keyframes` （CSS 动画的中间步骤）\n- `@font-face` （引入外部字体）\n\n**其他规则**（不常用）\n- `@import`\n- `@charset`\n- `@namespace`\n- `@page`\n- `@supports`\n- `@document`\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_02_selector.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [选择器](#%E9%80%89%E6%8B%A9%E5%99%A8)\n  - [简单选择器](#%E7%AE%80%E5%8D%95%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [标签选择器](#%E6%A0%87%E7%AD%BE%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [类选择器](#%E7%B1%BB%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [id 选择器](#id-%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [通配符选择器](#%E9%80%9A%E9%85%8D%E7%AC%A6%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [属性选择器](#%E5%B1%9E%E6%80%A7%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [伪类选择器](#%E4%BC%AA%E7%B1%BB%E9%80%89%E6%8B%A9%E5%99%A8)\n  - [其他选择器](#%E5%85%B6%E4%BB%96%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [伪元素选择器](#%E4%BC%AA%E5%85%83%E7%B4%A0%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [组合选择器](#%E7%BB%84%E5%90%88%E9%80%89%E6%8B%A9%E5%99%A8)\n    - [选择器分组](#%E9%80%89%E6%8B%A9%E5%99%A8%E5%88%86%E7%BB%84)\n  - [继承、优先、层级](#%E7%BB%A7%E6%89%BF%E3%80%81%E4%BC%98%E5%85%88%E3%80%81%E5%B1%82%E7%BA%A7)\n    - [继承](#%E7%BB%A7%E6%89%BF)\n    - [优先](#%E4%BC%98%E5%85%88)\n      - [改变优先级](#%E6%94%B9%E5%8F%98%E4%BC%98%E5%85%88%E7%BA%A7)\n    - [层叠](#%E5%B1%82%E5%8F%A0)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 选择器\n\n<p data-height=\"268\" data-theme-id=\"15197\" data-slug-hash=\"mJmwdK\" data-default-tab=\"result\" data-user=\"li-xinyang\" class='codepen'>See the Pen <a href='http://codepen.io/li-xinyang/pen/mJmwdK/'>FEND_Selectors</a> by Li Xinyang (<a href='http://codepen.io/li-xinyang'>@li-xinyang</a>) on <a href='http://codepen.io'>CodePen</a>.</p>\n<script async src=\"//assets.codepen.io/assets/embed/ei.js\"></script>\n\n选择器可被看做表达式，通过它可以选择相应的元素并应用不同的样式。\n\n- 简单选择器\n- 元素选择器\n- 组合选择器\n\n#### 简单选择器\n\n简单选择器可组合使用。\n\n##### 标签选择器\n\n```html\n<div>\n  <p>Sample Paragraph</p>\n  <p>Sample Paragraph</p>\n  <p>Sample Paragraph</p>\n</div>\n\n<style type=\"text/css\">\n  p {\n    color: blue;\n  }\n</style>\n```\n\n##### 类选择器\n\n`.className` 以 `.` 开头，名称可包含字母，数字，`-`，`_`，但必须以字母开头。它区分大小写并可出现多次。\n\n```html\n<div>\n  <p>Sample Paragraph</p>\n  <p class=\"special bold\">Sample Paragraph</p>\n  <p>Sample Paragraph</p>\n</div>\n\n<style type=\"text/css\">\n  p {\n    color: blue\n  }\n  .special {\n    color: orange;\n  }\n  .bold {\n    font-weight: bold;\n  }\n</style>\n```\n\n##### id 选择器\n\n`#idName` 以 `#` 开头且只可出现**一次**，其命名要求于 `.className` 相同。\n\n```html\n<div>\n  <p id=\"special\">Sample Paragraph</p>\n</div>\n\n<style type=\"text/css\">\n  #special {\n    color: red;\n  }\n</style>\n```\n\n##### 通配符选择器\n\n```html\n<div>\n  <p>Sample Paragraph</p>\n  <p>Sample Paragraph</p>\n</div>\n\n<style type=\"text/css\">\n  * {\n    color: blue;\n  }\n</style>\n```\n\n##### 属性选择器\n\n`[attr]` 或 `[attr=val]` 来选择相应的元素。`#nav{...}` 既等同于 `[id=nav]{...}`。IE7+\n\n`[attr~=val]` 可选用与选择包含 `val` 属性值的元素，像`class=\"title sports\"` 与 `class=\"sports\"`。`.sports{...}` 既等同于 `[class~=sports]{...}` IE7+\n\n`[attr|=val]` 可以选择`val`开头及开头紧接`-`的属性值。IE7+\n\n`[attr^=val]` 可选择以`val`开头的属性值对应的元素，如果值为符号或空格则需要使用引号 `\"\"`。IE7+\n\n`[attr$=val]` 可选择以`val`结尾的属性值对应的元素。IE7+\n\n`[attr*=val]` 可选择以包含`val`属性值对应的元素。IE7+\n\n```html\n<div>\n  <form action=\"\">\n    <input type=\"text\" value=\"Xinyang\" disabled>\n    <input type=\"password\" placeholder=\"Password\">\n    <input type=\"button\" value=\"Button\">\n  </form>\n</div>\n<style type=\"text/css\">\n  [disabled] {\n    background-color: orange;\n  }\n  [type=button] {\n    color: blue;\n  }\n</style>\n```\n\n##### 伪类选择器\n\n**常用伪类选择器**：\n- `:link` IE6+\n- `:visited` IE7+\n- `:hover` IE6中仅可用于链接\n- `:active` IE6/7中仅可用于链接\n- `:enabled` IE9+\n- `:disabled` IE9+\n- `:checked` IE9+\n- `:first-child` IE8+\n- `:last-child` IE9+\n- `:nth-child(even)` 可为 `odd` `even` 或数字 IE9+\n- `:nth-last-child(n)` `n`从 0 开始计算 IE9+\n- `:only-child` 仅选择唯一的元素 IE9+\n- `:only-of-type` IE9+\n- `:first-of-type` IE9+\n- `:last-of-type` IE9+\n- `:nth-of-type(even)` IE9+\n- `:nth-last-of-type(2n)` IE9+\n\n**不常用伪类选择器**：\n- `:empty` 选中页面中无子元素的标签 IE9+\n- `:root` 选择 HTML 根标签 IE9+\n- `:not()` 参数为一般选择器 IE9+\n- `:target` 被锚点选中的目标元素 IE9+\n- `:lang()` 选中语言值为某类特殊值的元素 IE7+\n\nNOTE：`element:nth-of-type(n)` 指父元素下第 n 个 `element` 元素，`element:nth-child(n)` 指父元素下第 n 个元素且元素为 `element`，若不是，选择失败。具体细节请在使用时查找文档。\n\n```html\n<div>\n  <a href=\"http://sample-site.com\" title=\"Sample Site\">Sample Site</a>\n</div>\n<style type=\"text/css\">\n  /* 伪类属性定义有顺序要求！ */\n  a:link {\n    color: gray;\n  }\n  a:visited {\n    color:red;\n  }\n  a:hover {\n    color: green;\n    /* 鼠标悬停 */\n  }\n  a:active {\n    color: orange;\n    /* 鼠标点击 */\n  }\n</style>\n```\n\n#### 其他选择器\n\n##### 伪元素选择器\n\n注意与伪类学则器的区分。\n\n- `::first-letter` IE6+\n- `::first-line` IE6+\n- `::before{content: \"before\"}` 需与 `content` 一同使用 IE8+\n- `::after{content: \"after\"}` 需与 `content` 一同使用 IE8+\n- `::selection` 被用户选中的内容（鼠标选择高亮属性）IE9+ Firefox需用 `-moz` 前缀\n\n##### 组合选择器\n\n- 后代选择器 `.main h2 {...}`，使用` `表示 IE6+\n- 子选择器 `.main>h2 {...}`，使用`>`表示 IE7+\n- 兄弟选择器 `h2+p {...}`，使用`+`表示 IE7+\n    - `h2~p {...}`，使用`~`表示（此标签无需紧邻）IE7+\n\n##### 选择器分组\n\n```html\n<style type=\"text/css\">\n/* 下面两组样式声明效果一致 */\nh1 {color: red;}\nh2 {color: red;}\nh3 {color: red;}\n\nh1, h2, h3 {color: red;}\n</style>\n```\n\n#### 继承、优先、层级\n\n##### 继承\n\n子元素继承父元素的样式，但并不是所有属性都是默认继承的。通过文档中的 `inherited: yes` 来判断属性是否可以自动继承。\n\n![](../img/C/css-inherit-doc.png)\n\n自动继承属性：\n- color\n- font\n- text-align\n- list-style\n- ...\n\n非继承属性：\n- background\n- border\n- position\n- ...\n\n##### 优先\n\nCSS Specificity Calculator 可以在[这里](http://specificity.keegan.st/)找到。更多关于 CSS 优先级别的信息可以在[这里](https://css-tricks.com/specifics-on-css-specificity/)找到（英文）。\n\n计算方法：\n- a = 行内样式\n- b = id 选择器的数量\n- c = 类、伪类的属性选择器的数量\n- d = 标签选择器和伪元素选择器的数量\n\nNOTE：从上到下优先级一次降低，且优先级高的样式会将优先级低的样式覆盖。大致公式（并不准确）如下。\n\n```\nvalue = a * 1000 + b * 100 + c * 10 + d\n```\n\n###### 改变优先级\n\n- 改变样式声明先后顺序\n- 提升选择器优先级\n- `!important`（慎用）\n\n##### 层叠\n\n层叠为相同属性根据优先级覆盖，如优先级相同则后面会覆盖前面的属性，而不同属性则会合并。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_03_text.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [文本](#%E6%96%87%E6%9C%AC)\n  - [字体](#%E5%AD%97%E4%BD%93)\n    - [改变字号](#%E6%94%B9%E5%8F%98%E5%AD%97%E5%8F%B7)\n    - [改变字体](#%E6%94%B9%E5%8F%98%E5%AD%97%E4%BD%93)\n    - [加粗字体](#%E5%8A%A0%E7%B2%97%E5%AD%97%E4%BD%93)\n    - [倾斜字体](#%E5%80%BE%E6%96%9C%E5%AD%97%E4%BD%93)\n    - [更改行距](#%E6%9B%B4%E6%94%B9%E8%A1%8C%E8%B7%9D)\n    - [font shorthand](#font-shorthand)\n    - [改变文字颜色](#%E6%94%B9%E5%8F%98%E6%96%87%E5%AD%97%E9%A2%9C%E8%89%B2)\n  - [对齐方式](#%E5%AF%B9%E9%BD%90%E6%96%B9%E5%BC%8F)\n    - [文字居中](#%E6%96%87%E5%AD%97%E5%B1%85%E4%B8%AD)\n    - [文本垂直对齐](#%E6%96%87%E6%9C%AC%E5%9E%82%E7%9B%B4%E5%AF%B9%E9%BD%90)\n    - [文本缩进](#%E6%96%87%E6%9C%AC%E7%BC%A9%E8%BF%9B)\n  - [格式处理](#%E6%A0%BC%E5%BC%8F%E5%A4%84%E7%90%86)\n    - [保留空格格式](#%E4%BF%9D%E7%95%99%E7%A9%BA%E6%A0%BC%E6%A0%BC%E5%BC%8F)\n    - [文字换行](#%E6%96%87%E5%AD%97%E6%8D%A2%E8%A1%8C)\n  - [文本装饰](#%E6%96%87%E6%9C%AC%E8%A3%85%E9%A5%B0)\n    - [文字阴影](#%E6%96%87%E5%AD%97%E9%98%B4%E5%BD%B1)\n    - [文本装饰（下划线等）](#%E6%96%87%E6%9C%AC%E8%A3%85%E9%A5%B0%EF%BC%88%E4%B8%8B%E5%88%92%E7%BA%BF%E7%AD%89%EF%BC%89)\n  - [高级设置](#%E9%AB%98%E7%BA%A7%E8%AE%BE%E7%BD%AE)\n    - [省略字符](#%E7%9C%81%E7%95%A5%E5%AD%97%E7%AC%A6)\n    - [更换鼠标形状](#%E6%9B%B4%E6%8D%A2%E9%BC%A0%E6%A0%87%E5%BD%A2%E7%8A%B6)\n    - [强制继承](#%E5%BC%BA%E5%88%B6%E7%BB%A7%E6%89%BF)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 文本\n\n<p data-height=\"268\" data-theme-id=\"15197\" data-slug-hash=\"mJmwej\" data-default-tab=\"result\" data-user=\"li-xinyang\" class='codepen'>See the Pen <a href='http://codepen.io/li-xinyang/pen/mJmwej/'>FEND_Fonts</a> by Li Xinyang (<a href='http://codepen.io/li-xinyang'>@li-xinyang</a>) on <a href='http://codepen.io'>CodePen</a>.</p>\n<script async src=\"//assets.codepen.io/assets/embed/ei.js\"></script>\n\n#### 字体\n\n##### 改变字号\n\n`font-size: <absolute-size> | <relative-size> | <length> | <percentage> | inherit`\n\n- `<absolute-size>` 有 small large medium\n- `<relative-size>` 有 smaller larger\n\n```stylus\ndiv\n  font-size 12px\n  p#sample0\n    font-size 16px\n  p#sample1\n    font-size 2em\n  p#sample2\n    font-size 200%\n```\n\nNOTE：以上两值在开发中并不常用。`2em` 与 `200%` 都为父元素默认大小的两倍（参照物为父元素的字体大小 `12px`）。\n\n##### 改变字体\n\n`font-family: [ <family-name> | <generic-family> ]# `\n\n`<generic-family>` 可选选项，但具体使用字体由浏览器决定\n- serif\n- sans-serif\n- cursive\n- fantasy\n- monospace\n\n```css\nfont-family: arial, Verdana, sans-serif;\n```\n\nNOTE：优先使用靠前的字体\n\n##### 加粗字体\n\n`font-weight: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900`\n\n```css\nfont-weight: normal;\nfont-weight: bold;\n```\n\n##### 倾斜字体\n\n`font-style: normal | italic | oblique | inherit`\n\n`italic` 使用字体中的斜体，而 `oblique` 在没有斜体字体时强制倾斜字体。\n\n##### 更改行距\n\n`line-height: normal | <number> | <length> | <percentage>`\n\n`normal` 值为浏览器决定，在1.1至1.2之间（通常设置值为1.14左右）\n\n```css\n/* length 类型 */\nline-height: 40px;\nline-height: 3em;\n/* percentage 类型 */\nline-height: 300%;\n/* number 类型 */\nline-height: 3;\n```\n\nNOTE：当`line-height`为 `number` 类型时，子类直接继承其数值（不计算直接继承）。\n而当为 `percentage` 类型时，子类则会先计算再显示（先计算后继承）。\n\n##### 字间距（字母间距）\n\n`letter-spacing: normal | <length>`\n\n其用于设置字间距或者字母间距，此属性适用于中文或西文中的字母。\n如果需要设置西文中词与词的间距或标签直接的距离则需要使用 `word-spacing`。\n\n`word-spacing: normal | <length>`\n\n##### font shorthand\n\n`font: [ [ <‘font-style’> || <font-variant-css21> || <‘font-weight’> || <‘font-stretch’> ]? <‘font-size’> [ / <‘line-height’> ]? <‘font-family’> ] | caption | icon | menu | message-box | small-caption | status-bar`\n\n```css\nfont: 30px/2 \"Consolas\", monospace;\nfont: italic bold 20px/1.5 arial, serif;\nfont: 20px arial, serif;\n```\n\nNOTE：当其他值为空时，均被设置为默认值。\n\n##### 改变文字颜色\n\n`color: <color>`\n\n```css\nelement { color: red; }\nelement { color: #f00; }\nelement { color: #ff0000; }\nelement { color: rgb(255,0,0); }\nelement { color: rgb(100%, 0%, 0%); }\nelement { color: hsl(0, 100%, 50%); }\n\n/* 50% translucent */\nelement { color: rgba(255, 0, 0, 0.5); }\nelement { color: hsla(0, 100%, 50%, 0.5); }\n\n/* 全透明 */\nelement { color: transparent' }\nelement { color: rgba(0, 0, 0, 0); }\n```\n\n#### 对齐方式\n\n##### 文字居中\n\n`text-align: start | end | left | right | center | justify | match-parent | start end`\n\nNOTE：默认为文本左对齐。\n\n##### 文本垂直对齐\n\n`vertical-align: baseline | sub | super | text-top | text-bottom | middle | top | bottom | <percentage> | <length>`\n\nNOTE：`<percentage>`的参照物为`line-height`\n\n##### 文本缩进\n\n`text-indent: <length> | <percentage> && [ hanging || each-line ]`\n\nNOTE：缩进两个字可使用 `text-indent: 2em;`\n\n#### 格式处理\n\n##### 保留空格格式\n\n`white-space: normal | pre | nowrap | pre-wrap | pre-line`\n\n`pre` 行为同 `<pre>` 一致。\n\n<table class=\"standard-table\">\n <thead>\n  <tr>\n   <th>&nbsp;</th>\n   <th>New lines</th>\n   <th>Spaces and tabs</th>\n   <th>Text wrapping</th>\n  </tr>\n </thead>\n <tbody>\n  <tr>\n   <th><code>normal</code></th>\n   <td>Collapse</td>\n   <td>Collapse</td>\n   <td>Wrap</td>\n  </tr>\n  <tr>\n   <th><code>nowrap</code></th>\n   <td>Collapse</td>\n   <td>Collapse</td>\n   <td>No wrap</td>\n  </tr>\n  <tr>\n   <th><code>pre</code></th>\n   <td>Preserve</td>\n   <td>Preserve</td>\n   <td>No wrap</td>\n  </tr>\n  <tr>\n   <th><code>pre-wrap</code></th>\n   <td>Preserve</td>\n   <td>Preserve</td>\n   <td>Wrap</td>\n  </tr>\n  <tr>\n   <th><code>pre-line</code></th>\n   <td>Preserve</td>\n   <td>Collapse</td>\n   <td>Wrap</td>\n  </tr>\n </tbody>\n</table>\n\n##### 文字换行\n\n`word-wrap: normal | break-word`\n\nNOTE：允许长单词自动换行。\n\n`word-break: normal | break-all | keep-all`\n\nNOTE：`break-all` 单词中的任意字母间都可以换行。\n\n#### 文本装饰\n\n##### 文字阴影\n\n`text-shadow:none | <shadow-t>#` 或 `text-shadow:none | [<length>{2,3}&&<color>?]#`\n\n```css\np {\n  text-shadow: 1px 1px 1px #000,\n               3px 3px 5px blue;\n}\n```\n\n1. value = The X-coordinate X 轴偏移像素\n2. value = The Y-coordinate Y 轴偏移像素\n3. value = The blur radius  阴影模糊半径\n4. value = The color of the shadow 阴影颜色（默认为文字颜色）\n\n##### 文本装饰（下划线等）\n\n`text-decoration: <'text-decoration-line'> || <'text-decoration-style'> || <'text-decoration-color'>`\n\n```css\nh1.under {\n    text-decoration: underline;\n}\nh1.over {\n    text-decoration: overline;\n}\np.line {\n    text-decoration: line-through;\n}\np.blink {\n    text-decoration: blink;\n}\na.none {\n    text-decoration: none;\n}\np.underover {\n    text-decoration: underline overline;\n}\n```\n\n#### 高级设置\n\n##### 省略字符\n\n`text-overflow: [ clip | ellipsis | <string> ]{1,2}`\n\n```css\n/* 常用配合 */\ntext-overflow: ellipsis;\noverflow: hidden; /* 溢出截取 */\nwhite-space: nowrap; /* 禁止换行 */\n```\n\n##### 更换鼠标形状\n\n`cursor: [[<funciri>,]* [ auto | crosshair | default | pointer | move | e-resize | ne-resize | nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize| text | wait | help ]] | inherit`\n\n**常用属性**\n\n`cursor: [<uri>,]*[auto | default | none | help | pointer | zoom-in | zoom-out | move]`\n\n- `<uri>` 图片资源地址代替鼠标默认形状\n- `<default>` 默认光标\n- `<none>` 隐藏光标\n- `<pointer>` 手型光标\n- `<zoom-in>`\n- `<zoom-out>`\n- `<move>`\n\n```css\ncursor: pointer;\ncursor: url(image-name.cur), pointer;\n/* 当 uri 失效时或者则会起作用 */\n```\n\n##### 强制继承\n\n`inherit` 会强制继承父元素的属性值。\n\n```css\nfont-size: inherit;\nfont-family: inherit;\nfont-weight: inherit;\n...\nword-wrap: inherit;\nwork-break: inherit\ntext-showdow: inherit\n```\n\nNOTE：具体在使用时可查询文档\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_04_box_model.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [盒模型](#%E7%9B%92%E6%A8%A1%E5%9E%8B)\n  - [属性](#%E5%B1%9E%E6%80%A7)\n    - [width](#width)\n    - [height](#height)\n    - [padding](#padding)\n    - [margin](#margin)\n      - [margin 合并](#margin-%E5%90%88%E5%B9%B6)\n    - [border](#border)\n    - [border-radius](#border-radius)\n    - [overflow](#overflow)\n    - [box-sizing](#box-sizing)\n    - [box-shadow](#box-shadow)\n    - [outline](#outline)\n  - [TRBL](#trbl)\n  - [值缩写](#%E5%80%BC%E7%BC%A9%E5%86%99)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 盒模型\n\n盒子模型是网页布局的基石。它有**边框**、**外边距**、**内边距**、**内容**组成。\n\n**盒子 3D 模型**\n\n![](../img/B/box-model-3d.png)\n\n盒子由上到下依次分为五层，它们自上而下的顺序是。\n\n1. border 边框\n2. content + padding 内容与内边距\n3. background-image 背景图片\n4. background-color 背景颜色\n4. margin 外边距\n\n<p data-height=\"268\" data-theme-id=\"15197\" data-slug-hash=\"qdmPEE\" data-default-tab=\"result\" data-user=\"li-xinyang\" class='codepen'>See the Pen <a href='http://codepen.io/li-xinyang/pen/qdmPEE/'>FEND_003_BoxModel</a> by Li Xinyang (<a href='http://codepen.io/li-xinyang'>@li-xinyang</a>) on <a href='http://codepen.io'>CodePen</a>.</p>\n<script async src=\"//assets.codepen.io/assets/embed/ei.js\"></script>\n\n#### 属性\n\n![](../img/B/box-module.jpg)\n\n##### width\n\n**内容盒子宽**\n\n`width: <length> | <percentage> | auto | inherit`\n\nNOTE：通常情况下百分比得参照物为元素的父元素。`max-width` 与 `min-width` 可以设置最大与最小宽度。\n\n##### height\n\n**内容盒子高**\n\n`height: <length> | <percentage> | auto | inherit`\n\nNOTE：默认情况元素的高度为内容高度。`max-height` 与 `min-height` 可以设置最大与最小高度。\n\n##### padding\n\n![](../img/P/padding-sample.png)\n\n`padding: [<length> | <percentage>]{1,4} | inherit`\n\n##### margin\n\n![](../img/M/margin-sample.png)\n\n`margin: [<length> | <percentage> | auto]{1,4} | inherit`\n\nNOTE：`margin` 默认值为 `auto`\n\nTrick：\n\n```\n/* 可用于水平居中 */\nmargin: 0 auto;\n```\n\n###### margin 合并\n\n![](../img/M/margin-merge.png)\n\n毗邻元素外间距（margin）会合并，既取相对较大的值。父元素与第一个和最后一个子元素的外间距也可合并。\n\n##### border\n\n![](../img/B/border-sample.png)\n\n```\nborder: [<br-width> || <br-style> || <color>] | inherit\nborder-width: [<length> | thin | medium | thick]{1,4} | inherit\nborder-style: [solid | dashed | dotted | ...]{1,4} |inherit\nborder-colro: [<color> | transparent]{1,4} | inherit\n```\n\nNOTE：`border-color` 默认为元素字体颜色。\n\n##### border-radius\n\n![](../img/B/border-radius-sample1.png)\n\n```\n/* 水平半径/垂直半径 */\nborder-radius: [ <length> | <percentage> ]{1,4} [ / [ <length> | <percentage> ]{1,4} ]?\n```\n\nNOTE：四个角的分解属性由左上角顺时针附值。\n\n##### overflow\n\n![](../img/O/overflow-sample.png)\n\n`overflow: visible | hidden | scroll | auto`\n\nNOTE：默认属性为 `visible`。使用 `overflow-x` 与 `overflow-y` 单独的设置水平和垂直方向的滚动条。\n\n##### box-sizing\n\n![](../img/B/box-sizing.png)\n\n![](../img/B/box-sizing1.png)\n\n`box-sizing: content-box | border-box | inherit`\n\n- `content-box` = 内容盒子宽高 + 填充（`Padding`）+ 边框宽（`border-width`）\n- `border-box` = 内容盒子宽高\n\n##### box-shadow\n\n![](../img/B/box-shadow.png)\n\n`box-shadown: none | [inset? && [ <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? ] ]#`\n\n```html\nbox-shadow: 4px  6px   3px  0px red;\n             |    |     |    |\n          水平偏移|     |    |\n               垂直偏移 |    |\n                    模糊半径 |\n                          阴影大小\n```\n\nNOTE：水平与垂直偏移可以为负值即相反方向偏移。颜色默认为文字颜色。阴影不占据空间，仅为修饰效果。\n\n##### outline\n\n```\noutline: [ <'outline-color'> || <'outline-style'> || <'outline-width'> ]\noutline-width: <length> | thin | medium | thick | inherit\noutline-style: solid | dashed | dotted | ... | inherit\noutline-color: <color> | invert | inherit\n/* invert 与当前颜色取反色 */\n```\n\nNOTE：`outline` 与 `border` 相似但无法分别设置四个方向的属性。`outline` 并不占据空间，而 `border` 占据空间，且显示位于 `border` 以外。\n\n#### TRBL\n\n![](../img/T/TRBL.png)\n\n![](../img/B/border-radius-sample.png)\n\nTRBL (Top, Right, Bottom, Left) 即为顺时针从顶部开始。具有四个方向的属性都可以通过 `*-top` `*-right` `*-bottom` 与 `*-left` 单独对其进行设置。\n\n#### 值缩写\n\n下面的值缩写以 `padding` 为例。\n\n> 对面相等，后者省略；四面相等，只设一个。\n\n```html\n/*      四面值 */\npadding: 20px;\npadding: 20px 20px 20px 20px;\n\n/*      上下值 右左值 */\npadding: 20px   10px;\npadding: 20px 10px 20px 10px;\n\n/*       上值 右左值 下值 */\npadding: 20px 10px   30px;\npadding: 20px 10px 30px 10px;\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_05_background.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [背景](#%E8%83%8C%E6%99%AF)\n  - [background-color](#background-color)\n  - [background-image](#background-image)\n  - [background-repeat](#background-repeat)\n  - [background-attachment](#background-attachment)\n  - [background-position](#background-position)\n    - [Sprite 的使用](#sprite-%E7%9A%84%E4%BD%BF%E7%94%A8)\n  - [linear-gradient](#linear-gradient)\n  - [radial-gradient](#radial-gradient)\n  - [repeat-*-gradient](#repeat--gradient)\n  - [background-origin](#background-origin)\n  - [background-clip](#background-clip)\n  - [background-size](#background-size)\n  - [background shorthand](#background-shorthand)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 背景\n\n#### background-color\n\n```\nbackground-color: <color>\nbackground-color: #f00;\nbackground-color: rgba(255, 0, 0, 0.5);\nbackground-color: transparent; /* 默认值 */\n```\n\n#### background-image\n\n```\nbackground-image: <bg-image>[, <bg-image>]*\n/* <bg-image> = <image> | none */\nbackground-image: url(\"../image/pic.png\");\nbackground-image: url(\"../image/pic.png0\"), url(\"../image/pic1.png\");\n/* 多张背景图时，先引入的图片在上一层后引入则在下一层 */\n```\n\nNOTE：当`background-color` 与 `background-image` 共存时，背景颜色永远在最底层（于背景图片之下）。\n\n#### background-repeat\n\n`background-repeat` 需与背景图片数量一致。\n\n```\nbackground-repeat: <repeat-style>[, <repeat-style]*\n<repeat-style> = repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}\n\n/*                   X 轴     Y 轴 */\nbackground-repeat: no-repeat repeat;\n```\n\n- `space` 平铺并在水平和垂直留有空隙，空隙的大小为图片均匀分布后完整覆盖显示区域的宽高\n- `round` 不留空隙平铺且覆盖显示区域，图标会被缩放以达到覆盖效果（缩放不一定等比）\n\n#### background-attachment\n\n当页面内容超过显示区域时，使用 `local` 使背景图片同页面内容一同滚动。\n\n```\nbackground-attachment: <attachment>[, <attachment>]*\n<attachment> = scroll | fixed | local\n```\n\n#### background-position\n\n```\nbackground-position: <position>[, <position>]*\n<position> = [left|center|right|top|bottom|<percentage>|<length>]|[left|center|right|top|bottom|<percentage>|<length>] [left|center|right|top|bottom|<percentage>|<length>] | [center |[left|right][<percentage>|<length>]?]&&[center |[left|right][<percentage>|<length>]?]\n\n/* 默认位置为 */\nbackground-position: 0 0;\n\n/* percentage 是容器与图片的百分比重合之处*/\nbackground-position: 20% 50%;\n\n/* 等同效果 */\nbackground-position: 50% 50%;\nbackground-position: center center;\n\nbackground-position: 0 0;\nbackground-position: left top;\n\nbackground-position: 100% 100%;\nbackground-position: right bottom;\n\n/* 四个值时方向只为参照物 */\nbackground-position: right 10px top 20px;\n```\n\n![](../img/B/background-position.jpg)\n\n##### Sprite 的使用\n\n```html\nbackground-image: url(sprite.png)\nbackground-repeat: no-repeat;\nbackground-positon: 0 -100px\n```\n\n使用位置为负值将图片偏移使需要的图片位置上移并显示正确的图案。\n\n#### linear-gradient\n\n```\nlinear-gradient()\n[[<angle> | to <side-or-corner],]? <color-step>[, <color-stop>]+\n<side-or-corner> = [left | right] || [top | bottom]\n<color-stop> = <color> [<percentage> | <length>]?\n\nbackground-image: linear-gradient(red, blue);\nbackground-image: linear-gradient(to top, red, blue);\nbackground-image: linear-gradient(to right bottom, red, blue);\nbackground-image: linear-gradient(0deg, red, blue);\nbackground-image: linear-gradient(45deg, red, blue);\nbackground-image: linear-gradient(red, green, blue);\nbackground-image: linear-gradient(red, green 20%, blue);\n```\n\n![](../img/L/linear-gradient.jpg)\n\n#### radial-gradient\n\n```\nradial-gradient(   [ circle || <length> ] [ at <position> ]? , | [ ellipse || [<length> | <percentage> ]{2}] [ at <position> ]? , | [ [ circle | ellipse ] || <extent-keyword> ] [ at <position> ]? , | at <position> , <color-stop> [ , <color-stop> ]+ )\n\n<extent-keyword> = closest-corner | closest-side | farthest-corner | farthest-side\n<color-stop> = <color> [ <percentage> | <length> ]?\n\nbackground-image: radial-gradient(cloest-side, red, blue);\nbackground-image: radial-gradient(circle, red, blue);\nbackground-image: radial-gradient(circle 100px, red, blue);\nbackground-image: radial-gradient(red, blue);\nbackground-image: radial-gradient(100px 50px, red, blue);\nbackground-image: radial-gradient(100px 50px at 0 0, red, blue);\nbackground-image: radial-gradient(red, green 20%, blue);\n```\n\n![](../img/R/radial-gradient.jpg)\n\n#### repeat-*-gradient\n\n```\nbackground-image: repeating-linear-gradient(red, blue 20px, red 40px);\nbackground-image: repeating-radial-gradient(red, blue 20px, red 40px);\n```\n\n![](../img/R/repeating-gradient.jpg)\n\n#### background-origin\n\n**案例模型**\n\n![](../img/B/background-box-model.png)\n\n决定背景 (0,0) 坐标与 100% 坐标的区域。默认值为 `padding-box`。\n\n```\n<box>[, <box>]*\n<box> = border-box | padding-box | content-box\n\nbackground-image: url(red.png);\nbackground-repeat: no-repeat;\n\nbackground-origin: padding-box;\nbackground-origin: border-box;\nbackground-origin: content-box;\n```\n\n![](../img/B/background-origin.jpg)\n\n#### background-clip\n\n裁剪背景，默认值为`border-box`。\n\n```\n<box>[, <box>]*\n<box> = border-box | padding-box | content-box\n\nbackground-image: url(red.png);\nbackground-repeat: no-repeat;\n\nbackground-clip: border-box;\nbackground-clip: padding-box;\nbackground-clip: content-box;\n```\n\n![](../img/B/background-clip.jpg)\n\n#### background-size\n\n```\n<bg-size>[, <bg-size>]*\n<bg-size> = [<length> | <percentage> | auto] {1, 2} | cover | contain\n\nbackground-image: url(red.png);\nbackground-repeat: no-repeat;\nbackground-position: 50% 50%;\n\nbackground-size: auto;\nbackground-size: 20px 20px;\n/* % 参照物为容器*/\nbackground-size: 50% 50%;\n/* 尽可能小，但宽度与高度不小过容器（充满容器） */\nbackground-size: cover;\n/* 尽可能大，但宽度与高度不超过容器（最大完全显示）*/\nbackground-size: contain;\n```\n\n![](../img/B/background-size.jpg)\n\n#### background shorthand\n\n```\n[<bg-layer,]* <final-bg-layer>\n<bg-layer> = <bg-image> || <position> [/ <bg-size>]? || <repeat-style> || <attachment> || <box> || <box>\n\n/* 两个 <box> 第一个为 background-origin */\n/* 两个 <box> 第二个为 background-clip */\n/* 只出现一个 <box> 则即是 background-origin 也是 background-clip */\n\n<final-bg-layer> = <bg-layer> || <'background-color'>\n\nbackground: url(red.png) 0 0/20px 20px no-repeat, url(blue.png) 50% 50%/contain no-repeat content-box green;\n```\n\n![](../img/B/background-shorthand.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_06_layout.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [布局](#%E5%B8%83%E5%B1%80)\n  - [display](#display)\n    - [display:block](#displayblock)\n    - [display:inline](#displayinline)\n    - [display:inline-block](#displayinline-block)\n    - [display:none](#displaynone)\n  - [position](#position)\n    - [position:relative](#positionrelative)\n    - [position:absolute](#positionabsolute)\n    - [position:fixed](#positionfixed)\n    - [top/right/bottom/left](#toprightbottomleft)\n    - [z-index](#z-index)\n      - [z-index 栈](#z-index-%E6%A0%88)\n  - [float](#float)\n    - [clear](#clear)\n  - [flex](#flex)\n    - [flex 方向](#flex-%E6%96%B9%E5%90%91)\n      - [flex-direction](#flex-direction)\n      - [flex-wrap](#flex-wrap)\n      - [flex-flow](#flex-flow)\n      - [order](#order)\n    - [flex 弹性](#flex-%E5%BC%B9%E6%80%A7)\n      - [flex-basis](#flex-basis)\n      - [flex-grow](#flex-grow)\n      - [flex-shrink](#flex-shrink)\n      - [flex](#flex-1)\n    - [flex 对齐](#flex-%E5%AF%B9%E9%BD%90)\n      - [justify-content](#justify-content)\n      - [align-items](#align-items)\n      - [align-self](#align-self)\n      - [align-content](#align-content)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 布局\n\n学习布局前须知道 CSS 中的定位机制。\n\n- 标准文档流（Normal Flow）\n- 浮动（Float）\n- 绝对定位（Absolute Positioning)\n\n**标准文档流**，从上到下，从左到右的输出文档内容。它由*块级*（block）元素和*行级*元素组成，且它们都是盒子模型。\n\n下面为 Firefox 布局可视化 **Gecko Reflow Visualisation**，布局是指浏览器将元素以正确的大小摆放在正确的位置上。\n\n![](../img/G/gecko-reflow-visualisation.gif)\n\n#### display\n\n设置元素的显示方式\n\n|display|默认宽度|可设置宽高|起始位置|\n|-------|--------|----------|--------|\n|block|父元素宽度|是|换行|\n|inline|内容宽度|否|同行|\n|inline-block|内容宽度|是|同行|\n\n##### display:block\n\n- 默认宽高为父元素宽高\n- 可设置宽高\n- 换行显示\n- 默认为block的元素：`<div>`, `<p>`, `<h1>` ~ `<h6>`, `<ul>`, `<form>`\n\n##### display:inline\n\n- 默认宽度为内容宽度\n- 不可设置宽高\n- 同行显示（元素内部可换行）\n- 默认为inline的元素：`<span>`, `<a>`, `<label>`, `<cite>`, `<em>`\n\n##### display:inline-block\n\n- 默认宽度为内容宽度\n- 可设置宽高\n- 同行显示\n- 整块换行\n- 默认为inline-block的元素：`<input>`, `<textarea>`, `<select>`, `<button>`\n\n##### display:none\n\n- 设置元素不显示\n\n`display:none` 与 `visibility:hidden` 的区别为 `display:none` 不显示且不占位，但 `visibility:hidden` 不显示但占位。\n\n#### position\n\n`position` 用于设置定位的方式与`top` `right` `bottom` `left` `z-index` 则用于设置参照物位置（必须配合定位一同使用）。\n\n**三种定位形式**\n\n- 静态定位（static）\n- 相对定位（relative）\n- 绝对定位（absolute、fixed）\n\n```\nposition: static | relative | absolute | fixed\n/* 默认值为 static */\n```\n\n##### position:relative\n\n- 相对定位的元素仍在文档流之中，并按照文档流中的顺序进行排列。\n- 参照物为元素本身的位置。\n\nNOTE：最常用的目的为改变元素层级和设置为绝对定位的参照物。\n\n![](../img/P/position-relative.png)\n\n##### position:absolute\n\n建立以包含块为基准的定位，其随即拥有偏移属性和 `z-index` 属性。\n\n- 默认宽度为内容宽度\n- 脱离文档流\n- 参照物为第一个定位祖先或根元素（`<html>` 元素）\n\n![](../img/P/position-absolute.png)\n\n##### position:fixed\n\n- 默认宽度为内容宽度\n- 脱离文档流\n- 参照物为视窗\n\nNOTE：宽高的100%的参照依然为视窗（例：网页遮罩效果）\n\n![](../img/P/position-fixed.png)\n\n##### top/right/bottom/left\n\n![](../img/L/layout-position.png)\n\n其用于设置元素边缘与参照物边缘的距离，且设置的值可为负值。在同时设置相对方向时，元素将被拉伸。\n\n##### z-index\n\n其用于设置 Z 轴上得排序，默认值为 0 但可设置为负值。（如不做设置，则按照文档流的顺序排列。后面的元素将置于前面的元素之上）\n\n![](../img/L/layouy-position-zindex.png)\n\n###### z-index 栈\n\n父类容器的 `z-index` 优于子类 `z-index` 如图\n\n![](../img/L/layout-position-zindex-stack.jpg)\n\n#### float\n\nCSS 中规定的定位机制，其可实现块级元素同行显示并存在于文档流之中。浮动仅仅影响文档流中下一个紧邻的元素。\n\n```\nfloat: left | right | none | inherit\n```\n\n- 默认宽度为内容宽度\n- 脱离文档流（会被父元素边界阻挡与`position`脱离文档流的方式不同）\n- 指的方向一直移动\n\n![](../img/F/float-right.png)\n\n**float 元素在同一文档流中**，当同时进行 `float` 时它们会按照文档流中的顺序排列。(当所有父元素中的所有元素脱离文档流之后，父元素将失去原有默认的内容高度)\n\n![](../img/F/float-right-all.jpg)\n\n注意：**float 元素是半脱离文档流的**，对元素是脱离文档流，但对于内容则是在文档流之中的（既元素重叠但内容不重叠）。\n\n![](../img/F/float-half-off.png)\n\n##### clear\n\n```\nclear: both | left | right | none | inherit\n```\n\n- 应用于后续元素\n- 应用于块级元素（block）\n\n**使用方法**：\n\n优先级自上而下\n\n1. clearfix 于父元素\n1. 浮动后续空白元素 `.emptyDiv {clear: both}`\n1. 为受到影响的元素设置 `width: 100% overflow: hidden` 也可\n1. 块级元素可以使用 `<br>` 不建议使用，影响 HTML 结构\n\n```\n/* clearfix */\n.clearfix:after {\n   content: \".\"; /* Older browser do not support empty content */\n   visibility: hidden;\n   display: block;\n   height: 0;\n   clear: both;\n}\n.clearfix {zoom: 1;} /* 针对 IE 不支持 :after */\n```\n\n#### flex\n\n![](../img/F/flex-container-and-item.jpg)\n\n弹性布局可用于多行自适应，多列自适应，间距自适应和任意对齐。\n\n**创建 flex container**\n\n```\ndisplay: flex\n/* 弹性容器内的均为弹性元素*/\n```\n\n**flex item**\n\n只有弹性容器在文档流中的子元素才属于弹性元素。\n\n```\n<div style=\"display: flex;\">\n  <div>Block Element</div>\n  <!-- flex item: YES-->\n  <span>Inline Element</span>\n  <!-- flex item: YES-->\n  <div style=\"position:absolute;\">Absolute Block Element</div>\n  <!-- flex item: YES-->\n</div>\n```\n\n##### flex 方向\n\n###### flex-direction\n\n```\n<!-- 默认值为 row -->\nflex-direction: row | row-reverse | column | column-reverse\n```\n\n![](../img/F/flex-direciton.png)\n\n###### flex-wrap\n\n```\n<!-- 默认值为 nowrap -->\nflex-wrap: nowrap | wrap | wrap-reverse\n```\n\n![](../img/F/flex-wrap.png)\n\n###### flex-flow\n\n`flex-flow` 为 `flex-wrap` 与 `flex-direction` 的简写，建议使用此属性（避免同时使用两个属性来修改）。\n\n```\nflex-flow: <'flex-direction'> || <'flex-wrap'>\n```\n\n![](../img/F/flex-flow.png)\n\n###### order\n\n`order` 的值为相对的（同被设置和未被设置的值相比较），当均为设置时默认值为 0 则按照文档流中的顺序排列。\n\n```\norder: <integer>\n<!-- 默认为 0 -->\n```\n\n![](../img/F/flex-order0.png)\n![](../img/F/flex-order1.png)\n\n##### flex 弹性\n\n###### flex-basis\n\n其用于设置 `flex-item` 的初始宽高（并作为弹性的基础）。如果 `flex-direction` 是以 `row` 排列则设置**宽**，如以 `column` 排列则设置**高**。\n\n```\nflex-basis: main-size | <width>\n```\n\n###### flex-grow\n\n伸展因子，其为弹性布局中最重要的元素之一，`flex-grow` 设置元素可用空余空间的比例。`flex-container` 先安装宽度（`flex-basis`）进行布局，如果有空余空间就按照 `flex-grow` 中的比例进行分配。\n\n**Width/Height = flex-basis + flex-grow/sum(flow-grow) * remain**\n\n```\nflex-grow: <number>\ninitial: 0\n<!-- 默认值为 0 -->\n```\n\n![](../img/F/flex-grow0.png)\n![](../img/F/flex-grow1.png)\n![](../img/F/flex-grow2.png)\n\n###### flex-shrink\n\n收缩因子，用于分配超出的负空间如何从可用空间中进行缩减。\n\n```\nflex-shrink: <number>\ninitial: 1\n<!-- 默认值为 1 -->\n```\n\n**Width/Height = flex-basis + flow-shrink/sum(flow-shrink) * remain**\n\nremain 为负值，既超出的区域。\n\n![](../img/F/flex-shrink.png)\n\n###### flex\n\n其为 `flex-grow` `flex-shrink` `flex-basis` 的值缩写。\n\n```\nflex: <'flex-grow'> || <'flex-shrink'> || <'flex-basis'>\ninitial: 0 1 main-size\n```\n\n##### flex 对齐\n\n###### justify-content\n\n其用于设置主轴（main-axis）上的对其方式。弹性元素根据主轴（横向和纵向均可）定位所以不可使用 `left` 与 `right` 因为位置为相对的。（行为相似的属性有 `text-align`）\n\n```\njustify-content: flex-start | flex-end | center | space-between | space-around\n<!-- 默认值为 flex-start -->\n```\n\n![](../img/F/flex-justify-content.png)\n\n###### align-items\n\n其用于设置副轴（cross-axis）上的对其方式。（行为相似的属性有 `vertical-align`）\n\n```\nalign-items: flex-start | flex-end | center | baseline | stretch\n<!-- 默认值为 stretch -->\n```\n\n![](../img/F/flex-align-items.png)\n\n###### align-self\n\n其用于设置单个 `flex-item` 在 cross-axis 方向上的对其方式。\n\n```\nalign-self: auto | flex-start | flex-end | center | baseline | stretch\n<!-- 默认值为 auto -->\n```\n\n![](../img/F/flex-align-self.png)\n\n###### align-content\n\n其用于设置 cross-axis 方向上的对其方式。\n\n```\nalign-content:flex-start | flex-end | center | space-between | space-around | stretch\n<!-- 默认为 stretch -->\n```\n\n![](../img/F/flex-align-content.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_07_transform.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [变形](#%E5%8F%98%E5%BD%A2)\n  - [2D 变形](#2d-%E5%8F%98%E5%BD%A2)\n    - [transform](#transform)\n      - [rotate()](#rotate)\n      - [transform-origin](#transform-origin)\n      - [translate()](#translate)\n      - [scale()](#scale)\n      - [skew()](#skew)\n  - [3D 变形](#3d-%E5%8F%98%E5%BD%A2)\n    - [rotateY()](#rotatey)\n    - [perspective](#perspective)\n    - [perspective-origin](#perspective-origin)\n    - [translate3d()](#translate3d)\n    - [scale3d()](#scale3d)\n    - [rotate3d()](#rotate3d)\n    - [transform-style](#transform-style)\n    - [backface-visibility](#backface-visibility)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n### 变形\n\n#### 2D 变形\n\n[2D 变形示例代码](../SampleCode/CSS/Transform2D.html)\n\n##### transform\n\n`transform` 中可以写一个或多个方法。\n\n```\ntransform: none | <transform-function>+\ntransform: none\n<!-- 默认值为 none -->\ntransform: <transform-function>+\n\ntransform: translate(50%) rotate(45deg);\ntransform: rotate(45deg) transform(50%)\n<!-- 变形函数顺序普通结果不同，原因是坐标位置发生了改变 -->\n```\n\n![](../img/T/transform-transform-function.png)\n\n###### rotate()\n\n```\nrotate(<angle>)\n\nrotate(45deg);\n<!-- 右边旋转，顺时针 -->\nrotate(-60deg);\n<!-- 左边旋转，逆时针 -->\n```\n\n![](../img/T/transform-rotate.png)\n\n###### transform-origin\n\n其用于设置原点的位置（默认位置为元素中心）第一值为 X 方向，第二值为 Y 方向， 第三值为 Z 方向。（当值空出未写的情况下默认为 50%）\n\n```\ntransform-origin: [ <percentage> | <length> | left | center | right | top | bottom] | [ [ <percentage> | <length> | left | center | right ] && [ <percentage> | <length> | top | center | bottom ] ] <length>?\n\n<!-- 默认值为 50% 50% -->\n\ntransform-origin: 50% 50%;\ntransform-origin: 0 0;\ntransform-origin: right 50px 20px;\ntransform-origin: top right 20px;\n```\n\n![](../img/T/transform-origin.png)\n\n###### translate()\n\n移动方法，参数分别代表 X 与 Y 轴的移动（偏移值均可为负值）。\n\n```\ntranslate(<translation-value>[, <translation-value>]?)\n\n<!-- 也可单独设置 X 与 Y 轴的偏移 -->\ntranslationX(<translation-value>)\ntranslationY(<translation-value>)\n\ntransform: translate(50px);\ntransform: translate(50px, 20%);\n<!-- Y 轴偏移为偏移对象的高度，X 轴为宽度 -->\ntransform: translate(-50px);\ntransform: translate(20%);\n```\n\n![](../img/T/transform-traslate.png)\n\n###### scale()\n\n缩放方法，参数分别代表 X 与 Y 轴的缩放（缩放值均可为小数）。当第二值忽略时，默认设置为等同第一值。\n\n```\nscale(<number> [, <number>]?)\n\nscaleX(<number>)\nscaleY(<number>)\n\n<!-- 整体放大 1.2 倍 -->\ntransform: scale(1.2);\n<!-- 高度拉伸 -->\ntransform: scale(1, 1.2);\n<!-- 宽度拉伸 -->\ntransform: scaleX(1.2);\n<!-- 高度拉伸 -->\ntransform: scaleY(1.2);\n```\n\n![](../img/T/transform-scale.png)\n\n###### skew()\n\n其为倾斜的方法。第一值为 Y 轴往 X 方向倾斜（逆时针），第二值为 X 轴往 Y 方向倾斜（顺时针）。（倾斜值可为负值）\n\n```\nskew(<angle>[, <angle>]?)\n\nskewX(<angle>)\nskewY(<angle>)\n\ntransform: skew(30deg);\ntransform: skew(30deg, 30deg);\ntransform: skewX(30deg);\ntransform: skewY(30deg);\n```\n\n![](../img/T/transform-skew.png)\n\n#### 3D 变形\n\n[3D 变形示例代码](../SampleCode/CSS/Transform3D.html)\n\n##### rotateY()\n\n3D 空间旋转。\n\n```\ntransform: rotateY(<angle>)\n```\n\n##### perspective\n\n![](../img/P/perspective-3d.PNG)\n\n其用于设置图片 Y 轴旋转后的透视效果。`<length>` 可以理解为人眼与元素之间的距离，越紧则效果越明显。\n\n```\nperspective: none | <length>\n\nperspective: none;\nperspective: 2000px;\nperspective: 500px;\n```\n\n![](../img/T/transform-perspective.png)\n\n##### perspective-origin\n\n其为设定透视的角度（透视位置均可设定为负值）。\n\n```\nperspective-origin: [ <percentage> | <length> | left | center | right | top | bottom] | [ [ <percentage> | <length> | left | center | right ] && [ <percentage> | <length> | top | center | bottom ] ]\n\nperspective-origin: 50% 50%\n<!-- 默认值为 50% 50% 正中间的位置进行透视-->\nperspective-origin: left bottom;\nperspective-origin: 50% -800px;\nperspective-origin: right;\n```\n\n![](../img/T/transform-perspective-origin.png)\n\n##### translate3d()\n\n```\ntranslate3d(<translate-value>, <translate-value>, <length>)\n\ntranslateX(<translate-value>)\ntranslateY(<translate-value>)\ntranslateZ(<length>)\n\ntransform: translate3d(10px, 20%, 50px);\n<!-- %的参照物为自身元素 -->\ntransform: translateX(10px);\ntransform: translateY(20%);\ntransform: translateZ(-100px);\n```\n\n![](../img/T/transform-translate3d.png)\n\n##### scale3d()\n\n```\nscale3d(<number>, <number>, <number>)\n\nscaleX(<number>)\nscaleY(<number>)\nscaleZ(<number>)\n\ntransform: scale3d(1.2, 1.2, 1);\ntransform: scale3d(1, 1.2, 1);\ntransform: scale3d(1.2, 1, 1);\ntransform: scaleZ(5);\n<!-- Z 轴的缩放扩大并不影响盒子大小 -->\n```\n\n![](../img/T/transform-scale3d.png)\n\n##### rotate3d()\n\n取 X Y Z 三轴上的一点并于坐标原点连线，以连线为轴进行旋转（逆时针）。\n\n```\nrotate3d(<number>, <number>, <number>, <angle>)\n\nrotateX(<angle>)\nrotateY(<angle>)\nrotateZ(<angle>)\n\ntransform: rotate3d(1, 0, 0, 45deg);\n<!-- 上面等同于 X 轴旋转 -->\ntransform: rotate3d(0, 1, 0, 45deg);\n<!-- 上面等同于 Y 轴旋转 -->\ntransform: rotate3d(0, 0, 1, 45deg);\n<!-- 上面等同于 2D 旋转 -->\ntransform: rotate3d(1, 1, 1, 45deg);\n```\n\n![](../img/T/transform-rotate3d.png)\n\n##### transform-style\n\n其用于设置保留内部的 3D 空间，原因是一个元素进行`transform`之后内部默认为`flat`。\n\n```\ntransform-style: flat | perserve-3d\n\n<!-- 默认为 flat -->\n\ntransform-style: flat;\ntransform-style: preserve-3d;\n```\n\n![](../img/T/transform-transform-style.png)\n\n##### backface-visibility\n\n其用于设置背面不可见。\n\n```\nbackface-visibility: visible | hidden\n\nbackface-visibility: visible;\nbackface-visibility: hidden;\n```\n\n![](../img/T/transform-backface-visibility.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_08_animation.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [动画](#%E5%8A%A8%E7%94%BB)\n  - [transition](#transition)\n    - [transition-property](#transition-property)\n    - [transition-duration](#transition-duration)\n    - [transition-delay](#transition-delay)\n    - [transition-timing-function](#transition-timing-function)\n  - [animation](#animation)\n    - [animation-name](#animation-name)\n    - [animation-duration](#animation-duration)\n    - [animation-timing-function](#animation-timing-function)\n    - [animation-iteration-count](#animation-iteration-count)\n    - [animation-direction](#animation-direction)\n    - [animation-play-state](#animation-play-state)\n    - [animation-delay](#animation-delay)\n    - [animation-fill-mode](#animation-fill-mode)\n    - [@keyframes](#@keyframes)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n\n### 动画\n\n[动画示例代码](../SampleCode/CSS/Animation.html)\n\n#### transition\n\n[过度动画](../SampleCode/CSS/Transition.html)\n\n其为众多 `<single-transition>` 的值缩写。（当两个时间同时出现是，第一个时间为动画长度，第二个时间为动画延时）\n\n```\ntransition: <single-transition> [',' <single-transition>]*\n\n<single-transition> = [none | <single-transition-property>] || <time> || <single-transition-timing-function> || <time>\n\n\ntransition: none;\ntransition: left 2s ease 1s, color 2s;\ntransition: 2s;\n```\n\n##### transition-property\n\n```\ntransition-property: none | <single-traisition-property> [ ',' <single-transition-property>]*\n\n<single-transition-property> = all | <IDENT>\n\ntransition-property: none;\n<!-- 默认值为 none -->\ntransition-property: all;\ntransition-property: left;\ntransition-property: left, color;\n```\n\n##### transition-duration\n\n```\ntransition-duration: <time>[, <time>]*\n\ntransition-duration: 0s;\ntransition-duration: 1s;\ntransition-duration: 1s, 2s, 3s;\n```\n\n##### transition-delay\n\n```\ntransition-delay: <time>[,<time>]*\n\ntransition-delay: 0s;\ntransition-delay: 1s;\ntransition-delay: 1s, 2s, 3s;\n```\n\n##### transition-timing-function\n\n```\ntransition-timing-function: <single-transition-timing-function>[',' <single-transition-timing-function>]*\n\n<!-- 默认函数为 ease -->\n<single-transition-timing-function> = ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier(<number>,<number>,<number>,<number>) | step-start | step-end | steps(<integer>)[, [start | end]]?)\n\n<!-- 对于 cubic-bezier 的曲线，前两个值为 P1 的坐标，后两值为 P2 的坐标 -->\n\ntransition-timing-function: ease;\ntransition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);\ntransition-timing-function: linear;\ntransition-timing-function: cubic-bezier(0, 0, 1, 1);\n```\n\n![](../img/T/transition-timing-function.png)\n\n#### animation\n\n```\nanimation: <single-animation> [',' <single-animation>]*\n\n<single-animation> = <single-animation-name> || <time> || <single-animation-timing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || single-animation-play-state>\n\nanimation: none;\nanimation: abc 2s ease 0s 1 normal none running;\nanimation: abc 2s;\nanimation: abc 1s 2s both, abcd 2s both;\n<!-- 调用多个动画 -->\n```\n\n动画可自动运行，但`transition`需要触发。\n\n##### animation-name\n\n`animation-name` 的名字可自由定义。\n\n```\nanimation-name: <single-animation-name>#\n\n<single-animation-name> = none | <IDENT>\n\nanimation-name: none;\nanimation-name: abc;\nanimation-name: abc, abcd;\n```\n\n##### animation-duration\n\n与 `transition-duration` 属性值类似。\n\n```\nanimation-duration: <time>[, <time>]*\n\nanimation-duration: 0s;\nanimation-duration: 1s;\nanimation-duration: 1s, 2s, 3s;\n```\n\n##### animation-timing-function\n\n其与之前的 `transition-timing-function` 完全一模一样。\n\n```\nanimation-timing-function: <timing-function>#\n\n<single-timing-function> = <single-transition-timing-function>\n\nanimation-timing-function: ease;\nanimation-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);\nanimation-timing-function: linear;\nanimation-timing-function: cubic-bezier(0, 0, 1, 1);\nanimation-timing-function: ease, linear;\n```\n\n##### animation-iteration-count\n\n其用于动画执行的次数（其默认值为 1）。\n\n```\nanimation-iteration-count: <single-animation-iteration-count>#\n\n<single-animation-iteration-count> = infinite | <number>\n\nanimation-iteration-count: 1;\nanimation-iteration-count: infinite;\nanimation-iteration-count: 1, 2, infinite;\n```\n\n##### animation-direction\n\n其用于定义动画的运动方向。\n\n```\nanimation-direction:<single-animation-direction>#\n\n<single-animation-direction> = normal | reverse | alternate | alternate-revers\n\nanimation-direction: reverse\n<!-- 动画相反帧的播放 -->\nanimation-direction: alternate\n<!-- 往返执行动画 -->\nanimation-direction: alternate-revers\n<!-- 相反的往返动画 -->\n```\n\n##### animation-play-state\n\n其用于设定动画的播放状态。\n\n```\nanimation-play-state: <single-animation-play-state>#\n\n<single-animation-play-state> = running | paused\n\nanimation-play-state: running;\nanimation-play-state: pasued;\nanimation-play-state: running, paused;\n```\n\n##### animation-delay\n\n其用于设置动画的延时，同 `transition-delay` 值相同。\n\n```\nanimation-delay: <time>[, <time>]*\nanim\nanimation-delay: 0s;\nanimation-delay: 1s;\nanimation-delay: 1s, 2s, 3s;\n```\n\n##### animation-fill-mode\n\n其用于设置动画开始时，是否保持第一帧的动画和动画在结束时时候保持最后的状态。\n\n```\nanimation-fill-mode: <single-animation-fill-mode>[',' <single-animation-fill-mode>]*\n\n<single-animation-fill-mode> = none | backwards | forwards | both\n\nanimation-fill-mode: none;\n<!-- 不做设置 -->\nanimation-fill-mode: backwards;\n<!-- 动画开始时出现在第一帧的状态 -->\nanimation-fill-mode: forwards;\n<!-- 动画结束时保留动画结束时的状态 -->\nanimation-fill-mode: both;\n<!-- 开始和结束时都应保留关键帧定义的状态（通常设定） -->\nanimation-fill-mode: forwards, backwards;\n```\n\n##### @keyframes\n\n其用于定义关键帧。\n\n```\n<!-- 写法一 -->\n@keyframes abc {\n  from {opacity: 1; height: 100px;}\n  to {opacity: 0.5; height: 200px;}\n}\n\n<!-- 写法二 -->\n@keyframes abcd {\n  0% {opacity: 1; height: 100px;}\n  100% {opacity: 0.5; height: 200px}\n}\n\n@keyframes flash {\n  0%, 50%, 100% {opacity: 1;}\n  25%, 75% {opacity: 0;}\n}\n\n<!-- 例子 -->\nanimation: abc 0.5s both;\nanimation: flash 0.5s both;\nanimaiton: abc 0.5s both, flash 0.5s both;\n```\n\n![](../img/A/animation-sample.gif)"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_09_layout_demo.md",
    "content": "### 常见布局样例\n\n#### 自动居中一列布局\n\n所需知识：\n\n- 标准文档流\n- 块级元素\n- margin 外边距属性\n\n```html\n<style type=\"text/css\" media=\"screen\">\n  article {\n    width: 800px;\n    margin: 0 auto;\n  }\n</style>\n\n<body>\n  <article>\n    <h1>Title</h1>\n    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A natus repellendus, modi culpa, dolor ducimus debitis, facere dolorum cum aspernatur, soluta molestias est illo vel iusto esse ex ullam amet!</p>\n  </article>\n</body>\n```\n\nNOTE：设置 auto 会根据浏览器宽度自动设置外边距尺寸。在设置浮动或绝对定位则会使自动居中失效，因为其会脱离文档流。\n\n`(浏览器宽度 - 外包含层的宽度)/ 2 = 外边距`。\n\n#### 横向两列布局\n\n此方法也同时可以实现横向多列布局（原理与两列布局相同）。\n\n所需知识：\n\n- float 属性，使纵向排列的块级元素，横向排列\n- margin 属性，设置列之间的间距\n\n```html\n<style type=\"text/css\" media=\"screen\">\n  .clearfix:after {\n     content: \".\"; /* Older browser do not support empty content */\n     visibility: hidden;\n     display: block;\n     height: 0;\n     clear: both;\n  }\n  .clearfix {zoom: 1;} /* 针对 IE 不支持 :after */\n  body {\n    width: 930px;\n    margin: 0 auto; /* 横向居中 */\n  }\n  article {\n    width: 800px;\n    float: left;\n    margin-right: 10px;\n  }\n  aside {\n    width: 120px;\n    float: right;\n  }\n</style>\n<body class=\"clearfix\">\n  <article>\n    <h1>Title</h1>\n    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Explicabo, quam, fugit. Accusamus voluptates nesciunt in, autem ipsa assumenda a iusto, reiciendis earum repudiandae, nulla natus blanditiis, aliquam asperiores commodi qui.</p>\n  </article>\n  <aside>\n    <h3>Aside Title</h3>\n    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita, molestiae!</p>\n  </aside>\n</body>\n```\n\n#### 绝对定位的横向两列布局\n\n应用场合较少，常用与一列定宽，另一列自适应。\n\n需要知识：\n\n- relative positon 父元素相对定位\n- absolute 自适应宽度元素绝对定位\n\n注意：固定宽度列的高度需大于自适应的列（原因是绝对定位会脱离文档流，不能撑开父元素）。\n\n```html\n<style type=\"text/css\" media=\"screen\">\n  body {\n    position: relative;\n    width: 100%;\n  }\n\n  article {\n    position: absolute;\n    top: 0;\n    right: 0;\n    width: 800px;\n  }\n  aside {\n    position: absolute;\n    top: 0;\n    right:800px;\n    left: 0;\n  }\n</style>\n\n<body>\n  <article>\n    <h1>Title</h1>\n    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error obcaecati sint minima totam fuga, tempora, id quia soluta officia iure eligendi sequi non dicta, doloribus accusamus odit fugiat quam quibusdam.</p>\n  </article>\n  <aside>\n    <h3>Aside Title</h3>\n    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque, doloremque.</p>\n  </aside>\n</body>\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter1/04_css_intro.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [CSS](#css)\n  - [简介](#%E7%AE%80%E4%BB%8B)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## CSS\n\n### 简介\n\nCSS (Cascading Stylesheet) 它用于设置页面的表现。CSS3 并不是一个完整的独立版本而是将不同的功能拆分成独立模块（例如，选择器模块，盒模型模块），这有利于不同功能的及时更新与发布也利于浏览器厂商的实习。\n\n![](../img/C/css3-history.png)\n\n**CSS 引入方法**\n```html\n// 外部样式表\n<head>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n</head>\n\n// 内部样式表\n<head>\n  <style type=\"text/css\">\n    p {\n      margin: 10px;\n    }\n  </style>\n</head>\n\n// 内嵌样式(可在动态效果中同 JavaScript 一同使用)\n<p style=\"color: red\">Sample Text</p>\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/00_intro.md",
    "content": "# JavaScript 程序设计\n\nJavascript 程序设计以 ECMAScript 5.1 为标准，从基本语法到原理深入,理解和编写Javascript程序。核心内容有语言简介、调试器、类型系统、内置对象、基本语法、变量作用域、闭包、面向对象编程等。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/01_javascript_intro.md",
    "content": "## JavaScript 介绍\n\n前端开发三要素，`HTML`（描述网页内容），`CSS`（描述样式），`JavaScript`（控制网页行为）。JavaScript 为解释型编程语（程序不需要编译，程序在运行时才翻译成机器语言，每执 行一次都要翻译一次)，运行环境也很广泛（浏览器或操作系统中 NodeJS）。\n\nJavaScript 又分为两部分，ECMAScript 和 DOM。其中 JavaScript 的基本的语言属性（例如，变量，作用域等）都在 ECMAScript 中有详细的定义好比汉子在字典中的定义。DOM 中则定义如何修改文档结构（HTML 或 XML 等）。\n\n**JavaScript**的引入方法如下：\n\n```javascript\n<!DOCTYPE html>\n<html>\n<head>\n  <title>Demo Page</title>\n</head>\n<body>\n  <!-- 以上代码忽略 -->\n\n  <!-- 为性能优化需将 javascript 代码放置在 body 标签的最末端 -->\n  <!-- 外联文件 -->\n  <script src=\"/javascripts/application.js\" type=\"text/javascript\" charset=\"utf-8\" async defer></script>\n  <!-- 内嵌代码 -->\n  <script>\n    document.write('>>> Hello, world!');\n  </script>\n</body>\n</html>\n```\n\n![](../img/J/javascript-history.png)\n\n![](../img/J/javascript-env.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/02_dev_tools.md",
    "content": "## 调试器\n\n调试工具都内置于主流浏览器中（Firefox 中需独立下载 Firebug）。更多关于 Google Chrome DevTools 的信息可以在[这里](https://developer.chrome.com/devtools)找到。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/03_basic_syntax.md",
    "content": "## 基本语法\n\n### 变量标示符\n\n**变量**的命名\n\n```javascript\nvar _name = null;\nvar $name = null;\nvar name0 = null;\n```\n\n### 关键字与保留字\n\nJavaScript 在语言定义中保留的字段，这些字段在语言使用中存在特殊意义或功能，在程序编写的过程中不可以当做变量或函数名称使用。无需记忆，报错修改即可。\n\n关键字与保留字可以在 [Mozilla 开发者站点](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar)找到。\n\n### 字符敏感\n\n字符串的大小写是有所区分的，不同字符指代不同的变量。\n\n### 严格模式\n\n**增益**\n\n- 消除语法中不合理与不安全的问题，保证代码正常运行\n- 提高编译效率，增加运行速度\n\n**使用方法**\n\n```javascript\n<!-- 全局使用 严格 模式 -->\n\"use strict\";\n(function(){\n  console.log('>>> Hello, world!');\n})()\n\n<!-- 或者在函数内部声明使用 严格 模式 -->\n(function(){\n  \"use strict\";\n  console.log('>>> Hello, world!');\n})()\n```\n\n严格模式与标准模式的区别：\n\n- 严格模式下隐式声明或定义变量被静止\n- 严格模式下对象重名的属性在严格模式下被静止\n- 严格模式下 `arguments.callee()` 被禁用\n- 严格模式下 `with()` 语句\n- 更多限制\n\n### 注释\n\n```javascript\n/*\n  多行注释，不可嵌套\n */\n\n// 单行注释\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/04_data_type.md",
    "content": "## 类型系统\n\njavascript 类型系统可以分为标准类型和对象类型，进一步标准类型又可以分为原始类型和引用类型，而对象类型又可以分为内置对象类型、普通对象类型、自定义对象类型。\n\n![](../img/J/javascript-variable-type.jpg)\n\n### 标准类型\n\n标准类型共包括了**6**个分别是：\n\n**原始类型（值类型）**：\n\n- Undefined `undefined`\n- Null `null`\n- Boolean `true`\n- String `'hello'`\n- Number `123`\n\n**引用类型（对象类型）**：\n- Object\n\n```javascript\nvar obj = {};\n<!-- 原始类型变量的包装类型如下 -->\nvar bool = new Boolean(true);\nvar str = new String(\"hello\");\nvar num = new Number(1);\nvar obj0 = new Object();\n```\n\n原始类型和引用类型的区别：\n\n原始类型储存在栈（Stack）中储存变量的值，而引用类型在栈中保存的是所引用内容储存在堆（Heap）中的值。类似于指针的概念，引用类型并非储存变量真实数值而是地址，所以对已引用类型的复制其实只是复制了相同的地址而非实际的变量值。\n\n**Undefined** 值：undefined 出现场景：\n\n- 以声明为赋值的变量 `var obj;`\n- 获取对象不存在的属性 `var obj = {x: 0}; obj.y;`\n- 无返回值函数的执行结果 `function f(){}; var obj = f();`\n- 函数参数没有传入 `function f(i){console.log(i)}; f();`\n- `void(expression)`\n\n**Null** 值：null 出现场景：\n\n- 获取不存在的对象 `document.getElementById('not-exist-element')`\n\n**Boolean** 值：true, false 出现场景：\n\n- 条件语句导致的系统执行的隐式类型转换 `if(隐式转换){}`\n- 字面量或变量定义 `var bool = true;`\n\n**String** 值：字符串 出现场景：\n\n- `var str = 'Hello, world!';`\n\n**Number** 值：整型直接量，八进制直接量（0-），十六进制直接量（0x-)，浮点型直接量 出现场景：\n\n- `1026`\n- `3.14`\n- `1.2e5`\n- `0x10`\n\n**Object** 值：属性集合 出现场景：\n\n- `var obj = {name: 'Xinyang'};`\n\n### 变量转换表\n\n|Value|Boolean|Number|String|\n|-----|-------|------|------|\n|undefined|false|NaN|\"undefined\"|\n|null|false|0|\"null\"|\n|true|true|1|\"true\"|\n|false|false|0|\"false\"|\n|''|false|0|''|\n|'123'|true|123|'123'|\n|'1a'|true|NaN|'1a'|\n|0|false|0|\"0\"|\n|1|true|1|\"1\"|\n|Infinity|true|Infinity|\"Infinity\"|\n|NaN|false|NaN|'NaN'|\n|{}|true|NaN|\"[object Object]\"|\n\n### 类型识别\n\n- `typeof`\n- `Object.prototype.toString`\n- `constructor`\n- `instanceof`\n\n**typeof**：\n- 可以是标准类型（Null 除外）\n- 不可识别具体的对象类型（Function 除外）\n\n**Object.prototype.toString**：\n- 可是识别标准类型及内置对象类型（例如，Object, Date, Array）\n- 不能识别自定义对象类型\n\n**constructor**：\n- 可以识别标准类型（Undefined/Null 除外）\n- 可识别内置对象类型\n- 可识别自定义对象类型\n\n```javascript\nfunction getConstructiorName(obj) {\n  return obj && obj.constructor && obj.constructor.toString().match(/function\\s*([^(]*)/)[1];\n}\ngetConstructiorName([]) === \"Array\"; // true\n```\n\n**instanceof**：\n- 不可判别原始类型\n- 可判别内置对象类型\n- 可判别自定义对象类型\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/05_internal_object.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [内置对象](#%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1)\n  - [标准内置对象](#%E6%A0%87%E5%87%86%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1)\n  - [Object](#object)\n    - [Object.create](#objectcreate)\n    - [Object.prototype.toString](#objectprototypetostring)\n    - [Object.prototype.hasOwnProperty](#objectprototypehasownproperty)\n  - [Boolean](#boolean)\n  - [String](#string)\n    - [String.prototype.indexOf](#stringprototypeindexof)\n    - [String.prototype.replace](#stringprototypereplace)\n    - [String.prototype.split](#stringprototypesplit)\n  - [Number](#number)\n    - [Number.prototype.toFixed](#numberprototypetofixed)\n  - [Array](#array)\n    - [Array.prototype.splice](#arrayprototypesplice)\n    - [Array.prototype.forEach](#arrayprototypeforeach)\n  - [Function](#function)\n    - [自定义对象构造器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E6%9E%84%E9%80%A0%E5%99%A8)\n    - [Function.prototype.apply](#functionprototypeapply)\n    - [Function.prototype.bind](#functionprototypebind)\n    - [子类构造器](#%E5%AD%90%E7%B1%BB%E6%9E%84%E9%80%A0%E5%99%A8)\n    - [函数调用](#%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8)\n    - [函数参数](#%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0)\n      - [arguments](#arguments)\n      - [值专递](#%E5%80%BC%E4%B8%93%E9%80%92)\n      - [函数重载](#%E5%87%BD%E6%95%B0%E9%87%8D%E8%BD%BD)\n  - [RegExp](#regexp)\n    - [RegExp.prototype.test](#regexpprototypetest)\n  - [Date](#date)\n  - [标准内置对象](#%E6%A0%87%E5%87%86%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1-1)\n    - [Math](#math)\n      - [Math.floor](#mathfloor)\n      - [Math.random](#mathrandom)\n    - [JSON](#json)\n      - [JSON.stringify](#jsonstringify)\n      - [JSON.parse](#jsonparse)\n    - [全局对象](#%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1)\n      - [NaA](#naa)\n      - [parseInt](#parseint)\n      - [eval](#eval)\n      - [encodedURIComponent](#encodeduricomponent)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 内置对象\n\n通常情况下只有对象才存在方法，但 JavaScript 不同它具有12种内置对象。内置对象又分为两类，普通对象（属性和方法）与构造器对象（可用于实例化普通对象，它还包含原型对象属性和方法，及实例对象属性和方法）。\n\n**JavaScript 对象原型链的简要说明**\n\n```javascript\nfunction Point(x, y) {\n  this.x = x;\n  this.y = y;\n}\nPoint.prototype.move = function(x, y) {\n  this.x += x;\n  this.y += y;\n}\nvar p = new Point(1, 1);\np.move(2,2);\n```\n\n`__proto__` 称之为原型链，有如下特点：\n\n1. `__proto__` 为对象内部的隐藏属性\n1. `__proto__` 为实例化该对象的构造器的 `prototype` 对象的引用，因此可以直接方法 `prototype` 的所有属性和方法\n1. 除了 `Object` 每个对象都有一个 `__proto__` 属性且逐级增长形成一个链，原型链顶端是一个 `Object` 对象。\n1. 在调用属性或方法时，引擎会查找自身的属性如果没有则会继续沿着原型链逐级向上查找，直到找到该方法并调用。\n1. `__proto__` 跟浏览器引擎实现相关，不同的引擎中名字和实现不尽相同(chrome、firefox中名称是 `__proto__` ，并且可以被访问到，IE中无法访问)。基于代码兼容性、可读性等方面的考虑，不建议开发者显式访问 `__proto__` 属性或通过 `__proto__`更改原型链上的属性和方法，可以通过更改构造器` prototype` 对象来更改对象的 `__proto__` 属性。\n\n**构造器对象与普通对象的区别**\n\n![](../img/O/object-with-constructor-and-regular-object.png)\n\n1. 构造器对象原型链中的 `__proto__` 是一个 `Function.prototype` 对象的引用，因此可以调用 `Function.prototype`的属性及方法\n1. 构造器对象本身有一个 `prototype` 属性，用该构造器实例化对象时该 `prototype` 会被实例对象的 `__proto__` 所引用\n1. 构造器对象本身是一个 `function` 对象，因此也会有自身属性\n\n### 标准内置对象\n\n\n**构造器对象**\n\n- Object\n- Boolean\n- String\n- Number\n- Function\n- Array\n- RegExp\n- Date\n- Error\n\n**其他对象**\n\n- Math\n- JSON\n- 全局对象\n\n内置对象，其实也叫内置构造器，它们可以通过 `new` 的方式创建一个新的实例对象。内置对象所属的类型就叫内置对象类型。其声明方式如下：\n\n```javascript\nvar i = new String(\"str\");          // String Object\nvar h = new Number(1);              // Number Object\nvar g = new Boolean(true);          // Boolean Object\nvar j = new Object({name : \"Tom\"}); // Object Object\nvar k = new Array([1, 2, 3, 4]);    // Array Object\nvar l = new Date();                 // Date Object\nvar m = new Error();\nvar n = new Function();\nvar o = new RegExp(\"\\\\d\");\n```\n\n注意：虽然标准类型中有`Boolean` `String` `Number` `Object`，内置对象类型中也有`Boolean` `String` `Number` `Object`，但它们其实是通过不同的声明方式来进行区别的。标准类型通过直接赋值，而对象类型则是通过构造器实现初始化。\n\n### Object\n\n> 构造器的原型对象在对象实例化时将会被添加到实例对象的原型链当中。\n> `__proto__` 为原型链属性，编码时不可被显像调用。但是实例化对象可以调用原型链上的方法。\n\n用 String/Number 等构造器创建的对象原型链顶端对象始终是一个Object对象，因此这些对象可以调用Object的原型对象属性和方法。所以 String/Number 等构造器是 Object 的子类。\n\n更多关于 Object 的内容可以在[这里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)找到。\n\n**构造器说明**：\n- Object 是属性和方法的集合\n- String/Number/Boolean/Array/Date/Error 构造器均为 Object 的子类并集成 Object 原型对象的属性及方法。\n\n**实例化方法**\n```\nvar obj0 = new Object({name: 'X', age: 13});\n// 常用方法\nvar obj1 = {name: 'Q', age: 14};\n```\n\n**属性及方法**\n- prototype\n- create\n- keys\n- ...\n\n**原型对象属性及其方法\n- constructor\n- toString\n- valueOf\n- hasOwnProperty\n- ...\n\n**实例对象属性及方法**\n\n无\n\n#### Object.create\n\n功能：基于原型对象创造新对象\n\n```javascript\n// Object.create(prototype[, propertiesObject])\nvar prototype = {name: 'X', age: 13};\nvar obj = Object.create(proto);\n```\n\n#### Object.prototype.toString\n\n功能：获取方法调用者的标准类型\n\n```javascript\n// objectInstance.toString()\nvar obj = {};\nobj.toString(); // Object\n```\n\n#### Object.prototype.hasOwnProperty\n\n功能：判断一个属性是否是一个对象的自身属性\n\n```javascript\n// objectInstance.hasOwnProperty(\"propertyName\")\nvar obj = Object.create({a: 1, b: 2});\nobj.c = 3;\nobj.hasOwnProperty('a'); // false\nobj.hasOwnProperty('c'); // true\n```\n\n### Boolean\n\n**构造器说明**：值为 true 与 false\n\n**属性及方法**\n- prototype\n\n**原型对象属性及其方法\n- constructor, toString, valueOf\n\n### String\n\n**构造器说明**：单双引号内的字符串\n\n**实例化方法**\n```javascript\n'Hello, world!'\nvar str0 = 'Xinyang';\nvar str1 = new String('Xinyang');\n```\n\n**属性及方法**\n- prototype\n- fromCharCode（转换 ASCII 代码为字符）\n\n**原型对象属性及其方法**\n- constructor\n- indexOf\n- replace\n- slice\n- split\n- charCodeAt\n- toLowerCase\n- ...\n\n#### String.prototype.indexOf\n\n功能：获取子字符串在字符串中的索引\n\n```javascript\n// stringObject.indexOf(searchValue, fromIndex)\nvar str = \"I am X. From China!\";\nvar index = str.indexOf('a'); // 2\nstr.indexOf('a', index + 1); // 16\nstr.indexOf('Stupid'); // -1 字符串不存在\n```\n\n#### String.prototype.replace\n\n功能：查找字符串替换成目标文字\n\n```javascript\n// stringObject.replace(regexp/substr, replacement)\nvar str = \"apple is bad\";\nstr = str.replace('bad', 'awesome');\n```\n\n#### String.prototype.split\n\n功能：按分隔符将分隔符分成字符串数组\n\n```javascript\n// stringObject.split(separator, arrayLength)\nvar str = '1 2 3 4';\nstr.split(' '); // ['1', '2', '3', '4'];\nstr.split(' ', 3); // ['1', '2', '3'];\nstr.split(/\\d+/); // [\"\", \" \", \" \", \" \", \"\"]\n```\n\n### Number\n\n**构造器说明**：整型直接量，八进制直接量（0-），十六进制直接量（0x-)，浮点型直接量\n\n**实例化方法**\n\n```javascript\n10\n1.2e5\nvar count = 0x10;\nvar pi = new Number(3.1415);\n```\n\n**属性及方法**\n- prototype\n- MAX_VALUE\n- MIN_VALUE\n- NaN\n- NEGATIVE_INFINITY\n- POSITIVE_INFINITY\n\n**原型对象属性及其方法**\n- constructor\n- toFixed\n- toExponential\n- ...\n\n#### Number.prototype.toFixed\n\n功能：四舍五入至指定小数位\n\n```javascript\n// numberObject.toFixed(num)\nvar num0 = 3.14;\nnum0.toFixed(1); // 3.1\nvar num1 = 3.35;\nnum1.toFixed(1); // 3.4\n```\n\n### Array\n\n**构造器说明**：定义数组对象\n\n**实例化方法**\n\n```javascript\nvar a0 = [1, 'abc', true, function(){}];\nvar a1 = new Array();\nvar a2 = new Array(1, 'abc', true);\n```\n\n**属性及方法**\n- prototype\n- isArray\n\n**原型对象属性及其方法**\n- constructor\n- splice\n- forEach\n- find\n- concat\n- pop\n- push\n- reverse\n- shift\n- slice\n- ...\n\n#### Array.prototype.splice\n\n功能：从数组中删除或添加元素，返回被删除的元素列表（作用域原有数组）\n\n```javascript\n// arrayObject.splice(start, deleteCount[, item1[, item2[, ...]]])\nvar arr = ['1', '2', 'a', 'b', '6'];\nvar ret = arr.splice(2, 2, '3', '4', '5'); // ['a', 'b']\narr; // ['1', '2', '3', '4', 5', '6']\n```\n\n#### Array.prototype.forEach\n\n功能：遍历元素组并调用回调函数\n\n```javascript\n// arrayObject.forEach(callback[, thisArg])\n// 回调函数\n// function callback(value, index, arrayObject) {...}\n// value - 当前值 index - 当前索引 arrayObject - 数组本身\nfunction logArray(value, index, arrayObject) {\n  console.log(value);\n  console.log(value === array[index]);\n}\n[2, 5, 6, 9].forEach(logArray);\n```\n\n### Function\n\n**构造器说明**：定义函数或新增对象构造器\n\n**实例化方法**\n\n```javascript\n// 对象实例化\nvar f0 = new Function('i', 'j', 'return (i + j)');\n// 函数关键字语句\nfunction f1(i, j){return i + j;}\n// 函数表达式\nvar f3 = function(i, j){return i + j;};\n```\n\n**属性及方法**\n- prototype\n\n**原型对象属性及其方法**\n- constructor\n- apply\n- call\n- bind\n\n**实例对象属性和方法**\n- length\n- prototype\n- arguments\n- caller\n\n#### 自定义对象构造器\n\n下面的代码声明一个 Point 增加了一个move方法，最后创建了一个 Point 的实例对象。\n\n```javascript\nfunction Point(x, y) {\n  this.x = x;\n  this.y = y;\n}\n\nPoint.prototype.move = function(x, y) {\n  this.x += x;\n  this.y += y;\n}\n\nvar p = new Point(1, 2);\n```\n\n#### Function.prototype.apply\n\n功能：通过参数指定调用者和函数参数并执行该函数\n\n```javascript\n// functionObj.apply(thisArg[, argsArray])\nfunction Point(x, y) {\n  this.x = x;\n  this.y = y;\n}\n\nPoint.prototype.move = function(x, y) {\n  this.x += x;\n  this.y += y;\n}\n\nvar p = new Point(1, 1);\nvar circle = {x: 1, y: 1, r: 1};\np.move.apply(circle, [2, 1]); // {x: 3, y: 2, r: 1}\n```\n\n#### Function.prototype.bind\n\n功能：通过参数指定函数调用者和函数参数并返回该函数的引用\n\n```javascript\n// functionObj.bind(thisArg[, arg1[, arg2[, ...]]])\nfunction Point(x, y) {\n  this.x = x;\n  this.y = y;\n}\n\nPoint.prototype.move = function(x, y) {\n  this.x += x;\n  this.y += y;\n}\n\nvar p = new Point(1, 1);\nvar circle = {x: 1, y: 1, r: 1};\nvar circleMoveRef = p.move.bind(circle, 2, 1);\nsetTimeout(circleMoveRef, 1000); // {x: 3, y: 2, r: 1}\n\n// 之间使用 circleMoveRef() 效果等同于 apply()\ncircleMoveRef();\n```\n\n#### 子类构造器\n\n```javascript\nfunction Circle(x, y, r) {\n  Point.apply(this, [x, y]);\n  this.radius = r;\n}\nCircle.prototype = Object.create(Point.prototype);\nCircle.prototype.constructor = Circle;\nCircle.prototype.area = function(){\n  return Math.PI * this.radius * this.radius;\n}\n\nvar c = new Circle(1, 2, 3);\nc.move(2, 2);\nc.area();\n```\n\n#### 函数调用\n\n- `()`\n- `apply`\n- `call`\n\n#### 函数参数\n\n- 形参个数不一定等于实参个数\n- 值专递\n- 通过参数类型检查实现函数重载\n\n##### arguments\n\narguments 的常用属性\n- length 实参个数\n- 0...arguments.length-1 实参属性名称（key）\n- callee 函数本身\n\n```javascript\nfunction max(a, b) {\n  if (max.length === arguments.length) {\n    return a>b?a:b;\n  } else {\n    var _max = arguments[0];\n    for(var i = 0; i < arguments.length; i++) {\n      if (_max < arguments[i]) {\n        _max = arguments[i];\n      }\n    }\n    return _max;\n  }\n}\n```\n\n##### 值专递\n\n函数参数的值专递是参数复制都是栈内存中的复制。\n\n![](../img/M/memory-management.jpg)\n\n```javascript\n// 原始类型\nfunction plusplus(num) {\n  return num++;\n}\nvar count = 0;\nvar result = plusplus(count); // result = 1; count = 0;\n\n// 引用类型\nfunction setName(obj) {\n  obj.name = 'obama';\n}\nvar president = {name: 'bush'};\nsetName(president); // {name: 'obama'};\n```\n\n##### 函数重载\n\n以 `Require.JS` 中的 `define()` 为例：\n\n```javascript\ndefine(function(){\n  var add = function(x, y) {\n    return x + y;\n  };\n  return {\n    add: add\n  };\n})\n\ndefine(['lib'], function(){\n  var add = function(x, y) {\n    return x + y;\n  };\n  return {\n    add: add\n  };\n})\n\ndefine('math', ['lib'], function(){\n  var add = function(x, y) {\n    return x + y;\n  };\n  return {\n    add: add\n  };\n})\n\n// define 的实现代码\n/**\n * The function that handles definitions of modules. Differs from\n * require() in that a string for the module should be the first argument,\n * and the function to execute after dependencies are loaded should\n * return a value to define the module corresponding to the first argument's\n * name.\n */\ndefine = function (name, deps, callback) {\n    var node, context;\n\n    //Allow for anonymous modules\n    if (typeof name !== 'string') {\n        //Adjust args appropriately\n        callback = deps;\n        deps = name;\n        name = null;\n    }\n\n    //This module may not have dependencies\n    if (!isArray(deps)) {\n        callback = deps;\n        deps = null;\n    }\n\n    // 省略以下代码\n    // ...\n};\n```\n\n### RegExp\n\n**构造器说明**：用于定义正则表达式，一个 RegExp 对象包含一个正则表达式和关联的标志\n\n**定义方法**\n- `/pattern/flags`\n- `new RegExp(pattern[, flags]);`\n\n**属性及方法**\n- prototype\n\n**原型对象属性及其方法**\n- constructor\n- test\n- exec\n- ...\n\n#### RegExp.prototype.test\n\n功能：使用正则表达式对字符串进行测试，并返回测试结果\n\n```javascript\n// regexObj.text(str)\nvar reg = /^abc/i;\nreg.test('Abc123'); // true\nreg.test('1Abc1234'); // false\n```\n\n### Date\n\n**构造器说明**：用于定义日期对象\n\n**定义方法**\n```javascript\nvar date0 = new Date();\nvar date1 = new Date(2014, 3, 1, 7, 1, 1, 100);\n```\n\n**属性及方法**\n- prototype\n- parse\n- now\n- ...\n\n**原型对象属性及其方法**\n- constructor\n- Date\n- getDate\n- getHours\n- setDate\n- setHours\n- ...\n\n### 标准内置对象\n\n#### Math\n\n**对象说明**：拥有属性和方法的单一对象主要用于数字计算\n\n**对象属性**：\n- E\n- PI\n- SQRT2\n- ...\n\n**对象方法**：\n- floor\n- random\n- abs\n- max\n- cos\n- ceil\n\n##### Math.floor\n\n功能：向下取整\n\n```javascript\n// Math.floor(num)\nMath.floor(0.97); // 0\nMath.floor(5.1); // 5\nMath.floor(-5.1); //6\n```\n\n相似方法：`ceil`，`round`\n\n##### Math.random\n\n功能：返回 0~1 之间的浮点数\n\n```javascript\n// Math.random()\nMath.random(); // 0.14523562323461\n```\n\n#### JSON\n\n**对象说明**：用于存储和交换文本信息\n\n**对象方法**：\n- parse\n- stringify\n\n##### JSON.stringify\n\n功能：将 JSON 对象转换为字符转\n\n```javascript\n// JSON.stringify(value[, replacer[, space]])\nvar json = {'name': 'X'};\nJSON.stringify(json); // \"{\"name\":\"X\"}\"\n```\n\n##### JSON.parse\n\n功能：将 JSON 字符转转换为对象\n\n```\n// JSON.parse(text[, reviver])\nvar jsonStr = '{\"name\":\"X\"}';\nJSON.parse(jsonStr); // {name: 'X'}\n```\n\n#### 全局对象\n\n全局对象定义了一系列的属性和方法在编程过程中可以被之间调用。\n\n属性：NaN，Infinity，undefined\n\n方法：\n- parseInt\n- parseFloat\n- isNaN\n- isFinite\n- eval\n\n处理 URI 方法：\n- encodedURIComponent\n- decodeURIComponent\n- encodedURI\n- decodeURI\n\n构造器属性：\n- Boolean\n- String\n- Number\n- Object\n- Function\n- Array\n- Date\n- Error\n- ...\n\n对象属性：\n- Math\n- JSON\n\n##### NaA\n\n非数字值：表示错误或无意义的运算结果，NaN 参与运算仍会返回 NaA，且 NaN 不等于任何值，包括它本身。可以使用 `isNaN()` 判断运算结果的类型是否为 NaN。\n\n```javascript\nisNaN(NaN); // true\nisNaN(4 - '2a'); // true;\n```\n\n##### parseInt\n\n功能：转换字符串成数字\n\n```javascript\n// parseInt(string[, radix])\n// radix - 为进制数\nparseInt('010'); // 10\nparseInt('010', 8) // 8\nparseInt('010', 16) // 16\n\nparseInt('0x1f'); // 31\nparseInt('0x1f', 16); // 31\nparseInt('1f'); // 1\nparseInt('1f', 16); // 31\n```\n\n##### eval\n\n功能：计算字符串并执行其中的 JavaScript 代码（会带来安全性和代码逻辑问题，通常不建议使用）\n\n```javascript\n// eval(string)\nvar res = '{\"error\": \"0\", \"msg\": \"OK\"};\nvar obj;\nif (!JSON) {\n  obj = eval('(' + res + ')');\n} else {\n  obj = JSON.parse(res);\n}\n```\n\n##### encodedURIComponent\n\n功能：将 URI 参数中的特殊字符，中文等作为 URI 的一部分进行编码\n\n```javascript\nvar uri = \"http://w3schools.com/my test.asp?name=ståle&car=saab\";\nvar res = encodeURIComponent(uri);\n\n// 结果\n// http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab\n```"
  },
  {
    "path": "03-FEND_Note-master/chapter2/06_scope.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [变量作用域](#%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F)\n  - [作用域介绍](#%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%BB%8B%E7%BB%8D)\n    - [静态作用域](#%E9%9D%99%E6%80%81%E4%BD%9C%E7%94%A8%E5%9F%9F)\n    - [动态作用域](#%E5%8A%A8%E6%80%81%E4%BD%9C%E7%94%A8%E5%9F%9F)\n  - [JavaScript 变量作用域](#javascript-%E5%8F%98%E9%87%8F%E4%BD%9C%E7%94%A8%E5%9F%9F)\n    - [词法环境](#%E8%AF%8D%E6%B3%95%E7%8E%AF%E5%A2%83)\n      - [组成](#%E7%BB%84%E6%88%90)\n      - [创建](#%E5%88%9B%E5%BB%BA)\n      - [结构](#%E7%BB%93%E6%9E%84)\n    - [关于词法环境的问题](#%E5%85%B3%E4%BA%8E%E8%AF%8D%E6%B3%95%E7%8E%AF%E5%A2%83%E7%9A%84%E9%97%AE%E9%A2%98)\n    - [with 语句](#with-%E8%AF%AD%E5%8F%A5)\n    - [try-catch 句法](#try-catch-%E5%8F%A5%E6%B3%95)\n    - [带名称的函数表达式](#%E5%B8%A6%E5%90%8D%E7%A7%B0%E7%9A%84%E5%87%BD%E6%95%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 变量作用域\n\n变量的作用域值的是变量的生命周期和作用范围（全局与局部作用域的区别）。\n\n### 作用域介绍\n\n#### 静态作用域\n\n静态作用域有称为词法作用域，即指其在编译的阶段就可以决定变量的引用。**静态作用域**只更变量定义的位置有关与代码执行的顺序无关。\n\n```javascript\nvar x = 0;\nfunction foo() {\n  alert(x);\n}\n\nfunction bar() {\n  var x = 20;\n  foo();\n}\n\nfoo();\n```\n\n![](../img/S/scope-lexical-scope.png)\n\n#### 动态作用域\n\n动态作用域的变量引用只可在程序运行时刻决定（其通常通过动态栈来进行管理）。\n\n```javascript\nvar x = 0;\nfunction foo() {\n  alert(x);\n}\n\nfunction bar() {\n  var x = 20;\n  foo();\n}\n\nfoo();\n```\n\n![](../img/S/scope-dynamic-scope.gif)\n\n### JavaScript 变量作用域\n\nJavaScript （1）使用静态作用域，（2）其没有块级作用域（只有函数作用域，就是只有 function 用于可以定义作用域），（3）在 ES5 之作使用词法环境来管理作用域。\n\n#### 词法环境\n\n##### 组成\n\n词法环境用来描述静态作用域的数据结构。它由`环节记录`和`外部词法环境的引用`组成。\n\n- 环境记录（record）（指形参，变量，函数等）\n- 外部词法环境的引用（outer）\n\n##### 创建\n\n在一段代码执行之前，先初始化词法环境。会被初始化的有：\n\n- 形参\n- 函数定义（创建函数对象，会保存当前作用域。见下图）\n- 变量定义（所有初始化值均为 `undefined`）\n\n![](../img/S/scope-function-init.png)\n\n##### 结构\n\n```javascript\nvar x = 10;\nfunction foo(y) {\n  var z = 30;\n  function bar(q) {\n    return x + y + z + q;\n  }\n  return bar;\n}\nvar bar = foo(20);\nbar(40);\n```\n\n**全局词法作用域（初始化状态）**\n\n![](../img/S/scope-global-init.png)\n\n**函数词法作用域**\n\n![](../img/S/scope-structure.jpg)\n\n#### 关于词法环境的问题\n\n**命名冲突**\n\n形参，函数定义，变量名称命名冲突。其中的优先级的排序如下：\n\n```\n函数定义 > 形参 > 变量\n```\n\n**`arguments` 的使用**\n\n 为函数中定义好的变量。\n\n**函数表达式与函数定义的区别**\n\n- 函数表达式是在执行时才创建函数对象。\n- 函数定义为在代码执行之前就进行创建的。\n\n#### with 语句\n\n`with` 会创造一个临时作用域。\n\n```javascript\nvar foo = 'abc';\nwith({\n  foo: 'bar';\n}) {\n  function f() {\n    alert(foo);\n  };\n  (function() {\n    alert(foo);\n  })();\n  f();\n}\n```\n\n#### try-catch 句法\n\n```\ntry {\n  var e = 10;\n  throw new Error();\n} catch (e) {\n  function f() {\n    alert(e);\n  }\n  (function() {\n    alert(e);\n  })();\n  f();\n}\n```\n\n#### 带名称的函数表达式\n\n当一个函数表达式有了名称之后，JavaScript 会创建一个新的词法环境。并在这个词法环境中用有一个属性 A 指向这个函数，同时这个属性 A 指向的函数是不可被修改的。\n\n**下面例子为不常规的写法**\n\n```\n(function A(){\n  A = 1;\n  alert(A);\n})();\n```\n\n![](../img/S/scope-function-with-name.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/07_statement_and_operator.md",
    "content": "## 表达式与运算符\n\n### 表达式\n\n表达式为 JavaScript 的短语可执行并生成值。\n\n```javascript\n1.7 // 字面量\n\"1.7\"\nvar a = 1;\nvar b = '2';\nvar c = (1.7 + a) * '3' - b\n```\n\n### 运算符\n\n- 算数运算符 （`+` `-` `*` `/` `%`）\n- 关系运算符 （`>` `<` `==` `!=` `>=` `<=` `===` `!==`)\n- 逻辑运算符 （`!` `&&` `||`）\n- 位运算符   （`&` `|` `^` `~` `<<` `>>`）\n- 负值运算符 （`=`）\n- 条件运算符 （`?:`）\n- 逗号运算符 （`,`）\n- 对象运算符 （`new` `delete` `.` `[]` `instanceof`）\n\n#### === 全等符号\n\n全等运算符用于盘对左右两边的对象或值是否类型相同且值相等。\n\n**伪代码拆解**\n\n```javascript\nfunction totalEqual(a, b) {\n  if (a 和 b 类型相同) {\n    if (a 和 b 是引用类型) {\n      if (a 和 b 是同一引用)\n        return true;\n      else\n        return false;\n    } else { // 值类型\n      if (a 和 b 值相等)\n        return true;\n      else\n        return false;\n    }\n  } else {\n    return false;\n  }\n}\n```\n\n**例子**\n\n```javascript\nvar a = \"123\";\nvar b = \"123\";\nvar c = \"4\";\nvar aObj = new String(\"123\");\nvar bObj = new String(\"123\");\nvar cObj = aObj;\n\na === aObj      // false\naObj === bObj   // false\naObj === cObj   // true\na === b         // true\na === c         // false\n```\n\n#### ==\n\n`==` 用于判断操作符两边的对象或值是否相等。\n\n**伪代码拆解**\n\n```javascript\nfunction equal(a, b) {\n  if (a 和 b 类型相同) {\n    return a === b;\n  } else { // 类型不同\n    return Number(a) === Number(b); // 优先转换数值类型\n  }\n}\n```\n\n**例子**\n\n```javascript\n\"99\" == 99; // true\nnew String(\"99\") == 99; // true\ntrue == 1; // true\nfalse == 0; // true\n'\\n\\n\\n' == // true\n```\n\n##### 例外规则\n\n- `null == undefined` 结果为真 `true`\n- 在有 `null`/`undefined` 参与的 `==` 运算是不进行隐式转换。\n\n```javascript\n0 == null; // false\nnull == false; // false\n\"undefined\" == undefined; // false\n```\n\n#### ! 取反\n\n`!x` 用于表达 x 表达式的运行结果转换成布尔值（Boolean）之后取反的结果。`!!x` 则表示取 x 表达式的运行结果的布尔值。\n\n```javascript\nvar obj = {};\nvar a = !obj // false;\nvar a = !!obj // true;\n```\n\n#### && 逻辑与\n\n`x && y` 如果 x 表达式的运行交过转换成 Boolean 值为 false 则不运行表达式 y 而直接返回 x 表达式的运行结果。**相反**，如果 x 表达式的运行交过转换成 Boolean 值为 true 则运行表达式 y 并返回 y 表达式的运行结果。\n\n**伪代码拆解**\n\n```javascript\nvar ret = null;\nif (!!(ret = x)) {\n  return y;\n} else {\n  return ret;\n}\n```\n\n**例子**\n\n```javascript\nvar a = 0 && (function(){return 1 + 1;})(); // 0\nvar b = 1 && (function(){return 1 + 1;})(); // 2\n```\n\n#### || 逻辑或\n\n`x || y` 如果 x 表达式的运行结果转换为 Boolean 值为 true，则不运行 表达式 y 而直接返回表达式 x 的运算结果。（与 `&&` 方式相反）\n\n**伪代码拆解**\n\n```javascript\nvar ret = null;\nif (!!(ret = x)) {\n  return ret;\n} else {\n  return y;\n}\n```\n\n**例子**\n\n```javascript\nvar a = 0 || (function(){return 1 + 1;})(); // 2\nvar b = 1 || (function(){return 1 + 1;})(); // 1\n```\n\n### 元算符优先级（Operator Precedence）\n\n- `+` `-` `*` `/` 高于 `&&`\n- `*` `/` 高于 `+` `-`\n- `&&` 高于 `?:`\n- `()` 内优先级高于之外\n\nNOTE：和数学上的算术优先级类似，同级从**左到右**计算。如有疑问加上 `()` 既可解决优先级问题。\n\n<table class=\"fullwidth-table\">\n <tbody>\n  <tr>\n   <th>Precedence</th>\n   <th>Operator type</th>\n   <th>Associativity</th>\n   <th>Individual operators</th>\n  </tr>\n  <tr>\n   <td>19</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Grouping\">Grouping</a></td>\n   <td>n/a</td>\n   <td><code>( … )</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"3\">18</td>\n   <td><a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation\">Member Access</a></td>\n   <td>left-to-right</td>\n   <td><code>… . …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation\">Computed Member Access</a></td>\n   <td>left-to-right</td>\n   <td><code>… [ … ]</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/JavaScript/Reference/Operators/Special/new\" title=\"JavaScript/Reference/Operators/Special_Operators/new_Operator\">new</a> (with argument list)</td>\n   <td>n/a</td>\n   <td><code>new … ( … )</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"2\">17</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Guide/Functions\" title=\"JavaScript/Reference/Operators/Special_Operators/function_call\">Function Call</a></td>\n   <td>left-to-right</td>\n   <td><code>… (&nbsp;<var>…&nbsp;</var>)</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/new\" title=\"JavaScript/Reference/Operators/Special_Operators/new_Operator\">new</a>&nbsp;(without argument list)</td>\n   <td>right-to-left</td>\n   <td><code>new …</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"2\">16</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Postfix Increment</a></td>\n   <td>n/a</td>\n   <td><code>… ++</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Postfix Decrement</a></td>\n   <td>n/a</td>\n   <td><code>… --</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"9\">15</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_NOT\" title=\"JavaScript/Reference/Operators/Logical_Operators\">Logical NOT</a></td>\n   <td>right-to-left</td>\n   <td><code>! …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_NOT\" title=\"JavaScript/Reference/Operators/Bitwise_Operators\">Bitwise NOT</a></td>\n   <td>right-to-left</td>\n   <td><code>~ …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Unary Plus</a></td>\n   <td>right-to-left</td>\n   <td><code>+ …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_negation\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Unary Negation</a></td>\n   <td>right-to-left</td>\n   <td><code>- …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Increment\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Prefix Increment</a></td>\n   <td>right-to-left</td>\n   <td><code>++ …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Decrement\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Prefix Decrement</a></td>\n   <td>right-to-left</td>\n   <td><code>-- …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/typeof\" title=\"JavaScript/Reference/Operators/Special_Operators/typeof_Operator\">typeof</a></td>\n   <td>right-to-left</td>\n   <td><code>typeof …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/void\" title=\"JavaScript/Reference/Operators/Special_Operators/void_Operator\">void</a></td>\n   <td>right-to-left</td>\n   <td><code>void …</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/delete\" title=\"JavaScript/Reference/Operators/Special_Operators/delete_Operator\">delete</a></td>\n   <td>right-to-left</td>\n   <td><code>delete …</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"3\">14</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Multiplication\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Multiplication</a></td>\n   <td>left-to-right</td>\n   <td><code>… *&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Division\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Division</a></td>\n   <td>left-to-right</td>\n   <td><code>… /&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Remainder\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Remainder</a></td>\n   <td>left-to-right</td>\n   <td><code>… %&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"2\">13</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Addition\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Addition</a></td>\n   <td>left-to-right</td>\n   <td><code>… +&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Subtraction\" title=\"JavaScript/Reference/Operators/Arithmetic_Operators\">Subtraction</a></td>\n   <td>left-to-right</td>\n   <td><code>… -&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"3\">12</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators\" title=\"JavaScript/Reference/Operators/Bitwise_Operators\">Bitwise Left Shift</a></td>\n   <td>left-to-right</td>\n   <td><code>… &lt;&lt;&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators\" title=\"JavaScript/Reference/Operators/Bitwise_Operators\">Bitwise Right Shift</a></td>\n   <td>left-to-right</td>\n   <td><code>… &gt;&gt;&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators\" title=\"JavaScript/Reference/Operators/Bitwise_Operators\">Bitwise Unsigned Right Shift</a></td>\n   <td>left-to-right</td>\n   <td><code>… &gt;&gt;&gt;&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"6\">11</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Less_than_operator\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Less Than</a></td>\n   <td>left-to-right</td>\n   <td><code>… &lt;&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Less_than__or_equal_operator\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Less Than Or Equal</a></td>\n   <td>left-to-right</td>\n   <td><code>… &lt;=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_operator\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Greater Than</a></td>\n   <td>left-to-right</td>\n   <td><code>… &gt;&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_or_equal_operator\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Greater Than Or Equal</a></td>\n   <td>left-to-right</td>\n   <td><code>… &gt;=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/in\" title=\"JavaScript/Reference/Operators/Special_Operators/in_Operator\">in</a></td>\n   <td>left-to-right</td>\n   <td><code>… in&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/instanceof\" title=\"JavaScript/Reference/Operators/Special_Operators/instanceof_Operator\">instanceof</a></td>\n   <td>left-to-right</td>\n   <td><code>… instanceof&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"4\">10</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Equality\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Equality</a></td>\n   <td>left-to-right</td>\n   <td><code>… ==&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Inequality\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Inequality</a></td>\n   <td>left-to-right</td>\n   <td><code>… !=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Identity\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Strict Equality</a></td>\n   <td>left-to-right</td>\n   <td><code>… ===&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Nonidentity\" title=\"JavaScript/Reference/Operators/Comparison_Operators\">Strict Inequality</a></td>\n   <td>left-to-right</td>\n   <td><code>… !==&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>9</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_AND\" title=\"JavaScript/Reference/Operators/Bitwise_Operators\">Bitwise AND</a></td>\n   <td>left-to-right</td>\n   <td><code>… &amp;&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>8</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_XOR\" title=\"JavaScript/Reference/Operators/Bitwise_Operators\">Bitwise XOR</a></td>\n   <td>left-to-right</td>\n   <td><code>… ^&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>7</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_OR\" title=\"JavaScript/Reference/Operators/Bitwise_Operators\">Bitwise OR</a></td>\n   <td>left-to-right</td>\n   <td><code>… |&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>6</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_AND\" title=\"JavaScript/Reference/Operators/Logical_Operators\">Logical AND</a></td>\n   <td>left-to-right</td>\n   <td><code>… &amp;&amp;&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>5</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_OR\" title=\"JavaScript/Reference/Operators/Logical_Operators\">Logical OR</a></td>\n   <td>left-to-right</td>\n   <td><code>… ||&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>4</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator\" title=\"JavaScript/Reference/Operators/Special_Operators/Conditional_Operator\">Conditional</a></td>\n   <td>right-to-left</td>\n   <td><code>… ? … : …</code></td>\n  </tr>\n  <tr>\n   <td rowspan=\"12\">3</td>\n   <td rowspan=\"12\"><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators\" title=\"JavaScript/Reference/Operators/Assignment_Operators\">Assignment</a></td>\n   <td rowspan=\"12\">right-to-left</td>\n   <td><code>… =&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… +=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… -=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… *=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… /=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… %=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… &lt;&lt;=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… &gt;&gt;=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… &gt;&gt;&gt;=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… &amp;=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… ^=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td><code>… |=&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>2</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/yield\" title=\"JavaScript/Reference/Operators/yield\">yield</a></td>\n   <td>right-to-left</td>\n   <td><code>yield&nbsp;…</code></td>\n  </tr>\n  <tr>\n   <td>1</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator\" title=\"JavaScript/Reference/Operators/Spread_operator\">Spread</a></td>\n   <td>n/a</td>\n   <td><code>...</code>&nbsp;…</td>\n  </tr>\n  <tr>\n   <td>0</td>\n   <td><a href=\"/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator\" title=\"JavaScript/Reference/Operators/Comma_Operator\">Comma / Sequence</a></td>\n   <td>left-to-right</td>\n   <td><code>… ,&nbsp;…</code></td>\n  </tr>\n </tbody>\n</table>\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/08_statement.md",
    "content": "## 语句\n\n### 条件控制语句\n\n其中expression可以使用整型，字符串，甚至表达式\n\n```javascript\nif (expression0) {statement0}\nelse if (expression1) {statement1}\nelse {statement2}\n\n// JavaScript 中的 case 可以使用整型，字符串，甚至表达式\nswitch(persion.type) {\n  case \"teacher\":\n    statement1\n    break;\n  case \"student\":\n    statement2\n    break;\n  default:\n    statement3\n    break;\n}\n```\n\n### 循环控制语句\n\n```javascript\nwhile(expression) {statement}\n\n// 至少执行一次\ndo {statement} while(expression);\n\nfor (initialise; test_expresiion; increment) {statement}\n\n// 跳过下面代码并进入下一轮循环\ncontinue;\n\n// 退出当前循环\nbreak;\n```\n\n#### for-in\n\n用于遍历对象的**全部**属性。\n\n```javascript\nfunction Car(id, type, color) {\n  this.type = type;\n  this.color = color;\n  this.id = id;\n}\n\nvar benz = new Car('benz', 'black', 'red');\nCar.prototype.start = function(){\n    console.log(this.type + ' start');\n}\n\nfor (var key in benz) {\n  console.log(key + ':' benz[key]);\n}\n\n// 输出结果\ntype:black\ncolor:red\nid:benz\nstart:function (){\n    console.log(this.type + ' start');\n}\n\n// -----------\n\n// 如不需原型对象上的属性可以使用 hasOwnProperty\nfor (var key in benz) {\n  if (benz.hasOwnProperty(key)) {\n    console.log(key + ':' benz[key]);\n  }\n}\n\n// 输出结果\ntype:black\ncolor:red\nid:benz\n```\n\n如不需原型对象上的属性可以使用 hasOwnProperty\n\n```javascript\nfor (var key in benz) {\n  if (benz.hasOwnProperty(key)) {\n    console.log(key + ':' benz[key]);\n  }\n}\n/* 输出结果\ntype:black\ncolor:red\nid:benz */\n```\n\n### 异常处理语句\n\n```javascript\ntry{\n  // statements\n  throw new Error();\ncatch(e){\n  // statements\n}\nfinally{\n  // statements\n}\n```\n\n### with 语句\n\n`with` 语句是 JavaScript 中特有的语句形式，它主要有两个作用：\n\n其一，其用于缩短特定情况下必须书写的代码量。它可以暂时改变变量的作用域。\n\n```javascript\n// 使用 with 之前\n(function(){\n  var x = Math.cos(3 * Math.PI) + Math.sin(Math.LN10);\n  var y = Math.tan(14 * Math.E);\n})();\n\n// 使用 with\n(function(){\n  with(Math) {\n    var x = cos(3 * PI) + sin(LN10);\n    var y = tan(14 * E);\n  }\n})();\n```\n\n![](../img/W/with-scope.png)\n\n其二，改变变量的作用域，将`with`语句中的对象添加至作用域链的头部。\n\n```javascript\nframe[1].document.forms[0].name.value = \"\";\nframe[1].document.forms[0].address.value = \"\";\nframe[1].document.forms[0].email.value = \"\";\n\nwith(frame[1].document.[0]) {\n  name.value = \"\";\n  address.value = \"\"\n  email.value = \"\";\n}\n```\n\n**缺点**就是导致 JavaScript 语句的可执行性下降，所以通常情况下因尽可能的避免使用。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter2/09_closure.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [闭包](#%E9%97%AD%E5%8C%85)\n  - [闭包的应用](#%E9%97%AD%E5%8C%85%E7%9A%84%E5%BA%94%E7%94%A8)\n    - [保存变量现场](#%E4%BF%9D%E5%AD%98%E5%8F%98%E9%87%8F%E7%8E%B0%E5%9C%BA)\n    - [封装](#%E5%B0%81%E8%A3%85)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n\n## 闭包\n\n- 闭包有函数和与其相关的引用环境的组合而成\n- 闭包允许函数访问其引用环境中的变量（又称自由变量）\n- 广义上来说，所有 JavaScript 的函数都可以成为闭包，因为 JavaScript 函数在创建时保存了当前的词法环境。\n\n```\nfunction add() {\n  var i = 0;\n  return function() {\n    alert(i++);\n  }\n}\nvar f = add();\nf();\nf();\n```\n\n### 闭包的应用\n\n#### 保存变量现场\n\n```javascript\n\n// 错误方法\nvar addHandlers = function(nodes) {\n  for (var i = 0, len = nodes.length; i < len; i++) {\n    nodes[i].onclick = function(){\n      alert(i);\n    }\n  }\n}\n\n// 正确方法\nvar addHandlers = function(nodes) {\n  var helper = function(i) {\n    return function() {\n      alert(i);\n    }\n  }\n\n  var (var i = 0, len = nodes.length; i < len; i++) {\n    nodes[i].onclick = helper(i);\n  }\n}\n```\n\n#### 封装\n\n```javascript\n\n// 将 observerList 封装在 observer 中\nvar observer = (function(){\n  var observerList = [];\n  return {\n    add: function(obj) {\n      observerList.push(obj);\n    },\n    empty: function() {\n      observerList = [];\n    },\n    getCount: function() {\n      return observerList.length;\n    },\n    get: function() {\n      return observerList;\n    }\n  };\n})();\n```"
  },
  {
    "path": "03-FEND_Note-master/chapter2/10_object.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [面向对象](#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1)\n  - [程序设计方法](#%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E6%96%B9%E6%B3%95)\n    - [面向过程](#%E9%9D%A2%E5%90%91%E8%BF%87%E7%A8%8B)\n    - [面向对象](#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1-1)\n      - [概念](#%E6%A6%82%E5%BF%B5)\n      - [基本特点](#%E5%9F%BA%E6%9C%AC%E7%89%B9%E7%82%B9)\n- [JavaScript 面向对象](#javascript-%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1)\n  - [constructor](#constructor)\n    - [自定义构造器](#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%9E%84%E9%80%A0%E5%99%A8)\n      - [创建构造器的方法（3 种）](#%E5%88%9B%E5%BB%BA%E6%9E%84%E9%80%A0%E5%99%A8%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%883-%E7%A7%8D%EF%BC%89)\n  - [this](#this)\n    - [全局环境中](#%E5%85%A8%E5%B1%80%E7%8E%AF%E5%A2%83%E4%B8%AD)\n    - [构造器中](#%E6%9E%84%E9%80%A0%E5%99%A8%E4%B8%AD)\n    - [函数中](#%E5%87%BD%E6%95%B0%E4%B8%AD)\n  - [this 实例](#this-%E5%AE%9E%E4%BE%8B)\n  - [原型继承](#%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF)\n  - [原型链](#%E5%8E%9F%E5%9E%8B%E9%93%BE)\n    - [属性查找](#%E5%B1%9E%E6%80%A7%E6%9F%A5%E6%89%BE)\n    - [属性修改](#%E5%B1%9E%E6%80%A7%E4%BF%AE%E6%94%B9)\n    - [属性删除](#%E5%B1%9E%E6%80%A7%E5%88%A0%E9%99%A4)\n    - [Object.create(proto[, propertiesObject])](#objectcreateproto-propertiesobject)\n  - [面向对象的应用](#%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BA%94%E7%94%A8)\n    - [全局变量](#%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F)\n    - [封装](#%E5%B0%81%E8%A3%85)\n    - [继承](#%E7%BB%A7%E6%89%BF)\n      - [原型继承](#%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF-1)\n      - [类继承](#%E7%B1%BB%E7%BB%A7%E6%89%BF)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 面向对象\n\n### 程序设计方法\n\n程序设计描述系统如何通过程序来实现的过程，其为一种设计方法与语言实现无关。常见的设计方法有面向流程与面向对象。\n\n#### 面向过程\n\n以程序的过程为中心，采用自定而下逐步细化的方法来实现。常见的面向过程语言有 C、Fortran、Pascall。\n\n![](../img/P/procedure_programming.png)\n\n#### 面向对象\n\n将对象作为程序的基本单元，将程序分解为数据和操作的集合。常见的面向过程语言有 smalltalk（也是 Objective-C 的父亲）、Java、C++。\n\n![](../img/O/object-oriented-programming.png)\n\n##### 概念\n\n- 类（Class）、对象（Object）\n- 属性（Property）、方法（Method）\n\n##### 基本特点\n\n- 继承（Inheritance）\n- 封装（Encapsulation）\n- 多态（Polymorphism）\n\n## JavaScript 面向对象\n\n### constructor\n\n对象的构造器，也可称之为构造类型。\n\n```javascript\n// 使用 new 关键字创建\nvar o = new Object();\nvar a = new Array();\nvar d = new Date();\n    |         |\n object    constructor\n\n// 使用直接量创建\nvar o = {name: 'Xinyang'};\nvar a = [1, 2, 3];\n```\n\n#### 自定义构造器\n\n```javascript\n// constructor\nfunction Person(name, age, birthdate) {\n  this.name = name;\n  this.age = age;\n  this.birthdate = birthdate;\n  this.changeName = function(newAge) {\n    this.age = newAge;\n  }\n}\n\n// 创建对象\nvar X = new Person('Stupid', 13, new Date(2015, 01, 01));\nvar Q = new Person('Q', 12, new Date(2015, 01, 01));\n\nX.changeName('X');\n```\n\n##### 创建构造器的方法（3 种）\n\n- `function ClassName() {...}`\n- `var Class = function() {...}`\n- `var Class = new Function()`\n\nNOTE: 并不是所有函数都可以被当成构造器，例如 `var o = new Math.min()`。通常自定义的函数均可当做构造器来使用。内置对象的构造器也可被当做构造器。\n\nNOTE+：如果构造器有返还值并为对象类型，则对象将被直接返回。\n\n```javascript\nfunction Person(name, age, birthdate) {\n  this.name = name;\n  this.age = age;\n  this.birthdate = birthdate;\n  this.changeName = function(newAge) {\n    this.age = newAge;\n  }\n  // !!! 注意这里\n  return {};\n}\n\nvar X = new Person('X', 13, new Date());\nconsole.log(X.name); // undefined;\n```\n\n### this\n\n`this` 在不同环境中指代的对象不同（`this` 指代的值可在函数运行过程中发生改变）。\n\n|出现场景|所指代值|\n|--------|--------|\n|全局环境|全局对象（window 在浏览器环境中时）|\n|constructor|创建的新实例对象|\n|函数调用|函数的调用者|\n|`new Function()`|全局对象|\n|`eval()`|调用上下文中的 `this`|\n\n#### 全局环境中\n\n全局环境中 `this` 指代全局对象，既 `window` 在浏览器环境中。\n\n```javascript\n// 以下的所有 this 均指代全局对象\nvar a = 10;\nalert(this.a);\n\nthis.b = 20;\nalert(b);\n\nc = 30;\nalert(this.c);\n```\n\n#### 构造器中\n\n构造器中的 `this` 指代的是即将被创建出的对象。\n\n```javascript\n// constructor\nfunction Person(name, age, birthdate) {\n  // 下面的指代即将被创建的对象\n  this.name = name;\n  this.age = age;\n  this.birthdate = birthdate;\n  this.changeName = function(newAge) {\n    this.age = newAge;\n  }\n}\n\n// 创建对象\nvar X = new Person('Stupid', 13, new Date(2015, 01, 01));\nvar Q = new Person('Q', 12, new Date(2015, 01, 01));\n\nX.changeName('X');\n```\n\n#### 函数中\n\n函数中的 `this` 指代函数的调用者。\n\n```javascript\n// constructor\nfunction Person(name, age, birthdate) {\n  // 下面的指代即将被创建的对象\n  this.name = name;\n  this.age = age;\n  this.birthdate = birthdate;\n  this.changeName = function(newAge) {\n    this.age = newAge;\n  }\n  this.gretting = function() {\n    // !!! 下面这个 this 指代调用它的对象，既上面的\n    // 上面的 gretting 左边的 this，既为即将被创建的对象\n    console.log('Hi, I am ' + this.name)\n  }\n}\n\n// 创建对象\nvar X = new Person('Stupid', 13, new Date(2015, 01, 01));\n\nX.changeName('X');\nX.gretting();\n```\n\nNOTE: `new Function('console.log(this)')` 中的 `this` 均指代全局对象。`eval('console.log(this)` 则为调用上下文指代的 `this`。\n\n### this 实例\n\n下面的例子使用 `apply` 与 `call`。通过这两个方法来将一个对象中 `this` 指代的目标进行改变。\n\n```javascript\nfunction Point(x, y) {\n  this.x = x;\n  this.y = y;\n  this.move = function(x, y) {\n    this.x += x;\n    this.y += y;\n  }\n}\n\nvar point = new Point(0, 0);\npoint.move(1, 1);\n\nvar circle = {x: 0, y: 1, r: 1};\n\n// 改变 point 中 move 方法 this 指代的对象至 circle\npoint.move.apply(circle, [1, 1]);\n// 同样可以用类似的 call 方法，区别为参数需依次传入\npoint.move.call(circle, 1, 1);\n```\n\n![](../img/T/this-sample.jpg)\n\n### 原型继承\n\n使用原型（prototype）可以解决重复定义实例对象拥有的完全一致的属性或方法（既共享原型中的属性或方法）。\n\n```javascript\nfunction Boss() {\n  this.age = 0;\n  this.birthdate = null;\n  this.name = '';\n  this.tasks = [];\n  this.title = 'Boss';\n  this.gretting = function() {console.log('I am a Boss!');};\n}\n\nvar X = new Boss();\nvar Q = new Boss();\n\n// X 与 Q 中具有完全一致（不必唯一的属性或方法）\n// 并耗用内存的共享部分\n// this.title 与 this.gretting\n```\n\n**改造后的构造器**\n\n```javascript\nfunction Boss() {\n  this.age = 0;\n  this.birthdate = null;\n  this.name = '';\n  this.tasks = [];\n}\nBoss.prototype = {\n  title: 'Boss',\n  gretting: function(){console.log('I am a Boss!');}\n}\n\nvar X = new Boss();\nvar Q = new Boss();\n\n// X 与 Q 中具有完全一致（不必唯一的属性或方法）\n// 并耗用内存的共享部分\n// this.title 与 this.gretting\n\nvar X = new Boss();\nvar Q = new Boss();\n\n// X 与 Q 拥有相同的原型 Boss.prototype\n```\n\n### 原型链\n\n使用原型继承的方法会产生原型链。JavaScript 中对于对象的查找、修改和删除都是通过原型链来完成的。\n\n**判断属性是否为对象本身**\n\n```javascript\nobjectName.hasOwnProperty('propertyName');\n// 返回布尔值 true 或 false\n```\n\n#### 属性查找\n\n对象的属性查找会更随原型链依次查找，如果在当前环境中无法找到需要的属性则会继续向下一层原型中继续寻找。\n\n#### 属性修改\n\n在 JavaScript 中对于对象属性的修改永远只修改对象自身的属性（不论是来源于对象本身还是对象的原型）。当创建当前对象不存在属性时（即便原型拥有此属性），也会为此对象增加改属性。\n\n**修改原型上的属性**\n\n修改原型属性会印象所有被创建出的对象现有的属性和方法。\n\n```javascript\nClassName.prototype.propertyName = 'new value';\nClassName.prototype.methodName = function(){...};\n```\n\n#### 属性删除\n\n`delete objectName.propertyName` 只可删除对象自身的属性，无法删除对象的原型属性。\n\n#### Object.create(proto[, propertiesObject])\n\n其为ECMAScript 5 中提出的新建立对象的方式。在 `X` 中使用隐式的原型对象指向 `boss` 对象，并将其设为 `X` 对象的原型。\n\n```javascript\nvar boss = {\n  title: 'Boss',\n  gretting: function(){console.log('Hi, I am a Boss!');}\n};\n\nvar X = Object.create(boss);\nX.gretting(); // Hi, I am a Boss!\n```\n\n**低版本中实现 Object.create 功能**\n\n此种方式仍需使用 `ClassName.prototype` 的方式来实现。\n\n```javascript\nvar clone = (function(){\n  var F = function(){};\n  return function(proto) {\n    F.prototype = proto;\n    return new F();\n  }\n})();\n```\n\n### 面向对象的应用\n\n#### 全局变量\n\n全局变量可在程序任意位置进行访问和修改的变量。滥用全局变量会导致，命名冲突，导致程序不稳定。\n\n**全局标量的三种定义方法：**\n\n- `var gloablVal = 'value';` 。\n- `window.gloablVal = 'value';` 附加于 `window` 对象上\n- `gloablVal = 'value';` 不使用 `var` 关键字，也附加于 `windwo` 对象\n\nNOTE：`delete` 无法删除在代码最顶端定义的全局标量 `var globale`\n\n#### 封装\n\n信息隐藏可以保证程序的稳定，将内部信息进行隐藏。其他语言中可词用访问权限来实现封装的概念，像 `private`、`public`。\n\n**JavaScript 中的封装**可使用函数的方法（闭包）。\n\n```javascript\n// 模拟 private 的属性\nfunction ClassName(){\n  var _property = '';\n  this.getProperty = function(){\n    return _property;\n  };\n}\n\n// 模拟 protected 属性，使用人为约束规则\nvar pro = ClassName.prototype;\npro._protectedMethod = function(){...};\npro.publicMethod = function(){...};\n```\n\n#### 继承\n\n##### 原型继承\n\n原型继承的方式为 JavaScript 中固有的继承方式。\n\n```javascript\nvar proto = {\n  action1: function(){},\n  action2: function(){}\n}\n\nvar obj = Object.create(proto);\n```\n\n在不支持 EM5 中的实现方法：\n\n```javascript\nvar clone = (function(){\n  var F = function(){};\n  return function(proto) {\n    F.prototype = proto;\n    return new F();\n  }\n})();\n```\n\n##### 类继承\n\n使用原型链继承的方式模拟其他语言类继承的特性。\n\n```javascript\nfunction ClassA() {\n  ClassA.classMethod = function(){};\n  ClassA.prototype.api = function(){};\n\n  function ClassB() {\n    ClassA.apply(this, argument);\n  }\n  ClassB.prototype = new ClassA();\n  ClassB.prototype.constructor = ClassB;\n  ClassB.prototype.api = function(){\n    ClassA.prototype.api.apply(this, arguments);\n  }\n}\n\n// ClassA 为父类\n// ClassB 为子类\n\nvar b = new ClassB();\nb.api();\n```\n\n![](../img/C/class-inherence.jpg)"
  },
  {
    "path": "03-FEND_Note-master/chapter2/11_js_type_determin.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [类型识别](#%E7%B1%BB%E5%9E%8B%E8%AF%86%E5%88%AB)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n\n### 类型识别\n\n- `typeof`\n- `Object.prototype.toString`\n- `constructor`\n- `instanceof`\n\n**typeof**：\n- 可以是标准类型（Null 除外）\n- 不可识别具体的对象类型（Function 除外）\n\n**Object.prototype.toString**：\n- 可是识别标准类型及内置对象类型（例如，Object, Date, Array）\n- 不能识别自定义对象类型\n\n**constructor**：\n- 可以识别标准类型（Undefined/Null 除外）\n- 可识别内置对象类型\n- 可识别自定义对象类型\n\n```javascript\nfunction getConstructiorName(obj) {\n  return obj && obj.constructor && obj.constructor.toString().match(/function\\s*([^(]*)/)[1];\n}\ngetConstructiorName([]) === \"Array\"; // true\n```\n\n**instanceof**：\n- 不可判别原始类型\n- 可判别内置对象类型\n- 可判别自定义对象类型\n\nJavaScript的数据类型可以分为：标准类型和对象类型。\n\n`标准类型有`：undefined Null Boolean Date Number Object\n\n`对象类型（构造器类型）`：Boolean Date Number Object Array Date Error Function RegExp\n\n用来判断数据类型的一般有四种方式，分别是：\n\n- `typeof `\n- `Prototype.toString()`\n- `constructor`\n- `instanceof`\n\n**下面我们写一个HTML来检验一下：**\n\n```html\n<html>\n<head>\n    <title>JavaScript类型判断</title>\n    <meta charset=\"utf-8\">\n    <style type=\"text/css\">\n        .red{\n            background-color:red;\n        }\n    </style>\n</head>\n<body>\n    <script type=\"text/javascript\">\n        /* Standard Type */\n        var a;    //undefined\n        var b = document.getElementById(\"no_exist_element\"); //null\n        var c = true;    //Boolean\n        var d = 1;    //Number\n        var e = \"str\";     //String\n        var f = {name : \"Tom\"};    //Object\n\n        /* Object Type */\n        var g = new Boolean(true);    //Boolean Object\n        var h = new Number(1);    //Number Object\n        var i = new String(\"str\");    //String Object\n        var j = new Object({name : \"Tom\"}); //Object Object\n        var k = new Array([1, 2, 3, 4]);    //Array Object\n        var l = new Date();    //Date Object\n        var m = new Error();\n        var n = new Function();\n        var o = new RegExp(\"\\\\d\");\n\n        /* Self-Defined Object Type */\n        function Point(x, y) {\n          this.x = x;\n          this.y = y;\n        }\n\n        Point.prototype.move = function(x, y) {\n          this.x += x;\n          this.y += y;\n        }\n\n        var p = new Point(1, 2);\n\n        /* Use the Prototype.toString() to judge the type */\n        function type(obj){\n            return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();\n        }\n    </script>\n    <table border=\"1\" cellspacing=\"0\">\n        <tr>\n            <td></td>\n            <td>typeof</td>\n            <td>toString</td>\n            <td>constructor</td>\n            <td>instanceof</td>\n        </tr>\n        <tr>\n            <td>undefined</td>\n            <td><script type=\"text/javascript\">document.write(typeof a)</script></td>\n            <td><script type=\"text/javascript\">document.write(type(a))</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(a.constructor)</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(a instanceof \"undefined\")</script></td>\n        </tr>\n        <tr>\n            <td>Null</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof b);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(b));</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(b.constructor);</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(b instanceof \"null\");</script></td>\n        </tr>\n        <tr>\n            <td>Boolean</td>\n            <td><script type=\"text/javascript\">document.write(typeof c);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(c));</script></td>\n            <td><script type=\"text/javascript\">document.write(c.constructor);</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(c instanceof \"boolean\");</script></td>\n        </tr>\n        <tr>\n            <td>Number</td>\n            <td><script type=\"text/javascript\">document.write(typeof d);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(d));</script></td>\n            <td><script type=\"text/javascript\">document.write(d.constructor);</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(d instanceof \"number\");</script></td>\n        </tr>\n        <tr>\n            <td>String</td>\n            <td><script type=\"text/javascript\">document.write(typeof e);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(e));</script></td>\n            <td><script type=\"text/javascript\">document.write(e.constructor);</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(e instanceof \"string\");</script></td>\n        </tr>\n        <tr>\n            <td>Object</td>\n            <td><script type=\"text/javascript\">document.write(typeof f);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(f));</script></td>\n            <td><script type=\"text/javascript\">document.write(f.constructor);</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(f instanceof \"object\");</script></td>\n        </tr>\n        <tr><td colspan=\"5\">-----------------------</td></tr>\n        <tr>\n            <td>Boolean Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof g);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(g));</script></td>\n            <td><script type=\"text/javascript\">document.write(g.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(g instanceof Boolean);</script></td>\n        </tr>\n        <tr>\n            <td>Number Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof h);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(h));</script></td>\n            <td><script type=\"text/javascript\">document.write(h.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(h instanceof Number);</script></td>\n        </tr>\n        <tr>\n            <td>String Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof i);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(i));</script></td>\n            <td><script type=\"text/javascript\">document.write(i.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(i instanceof String);</script></td>\n        </tr>\n        <tr>\n            <td>Object Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof j);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(j));</script></td>\n            <td><script type=\"text/javascript\">document.write(j.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(j instanceof Object);</script></td>\n        </tr>\n        <tr>\n            <td>Array Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof k);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(k));</script></td>\n            <td><script type=\"text/javascript\">document.write(k.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(k instanceof Array);</script></td>\n        </tr>\n        <tr>\n            <td>Date Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof l);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(l));</script></td>\n            <td><script type=\"text/javascript\">document.write(l.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(l instanceof Date);</script></td>\n        </tr>\n        <tr>\n            <td>Error Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof m);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(m));</script></td>\n            <td><script type=\"text/javascript\">document.write(m.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(m instanceof Error);</script></td>\n        </tr>\n        <tr>\n            <td>Function Object</td>\n            <td><script type=\"text/javascript\">document.write(typeof n);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(n));</script></td>\n            <td><script type=\"text/javascript\">document.write(n.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(n instanceof Function);</script></td>\n        </tr>\n        <tr>\n            <td>RegExp Object</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof o);</script></td>\n            <td><script type=\"text/javascript\">document.write(type(o));</script></td>\n            <td><script type=\"text/javascript\">document.write(o.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(o instanceof RegExp);</script></td>\n        </tr>\n        <tr><td colspan=\"5\">-----------------------</td></tr>\n        <tr>\n            <td>Point Objct</td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(typeof p);</script></td>\n            <td class=\"red\"><script type=\"text/javascript\">document.write(type(p));</script></td>\n            <td><script type=\"text/javascript\">document.write(p.constructor);</script></td>\n            <td><script type=\"text/javascript\">document.write(p instanceof Point);</script></td>\n        </tr>\n    </table>\n</body>\n</html>\n```\n\n执行的结果如下：\n\n![](../img/J/javascript-type-judge.png)\n\n其中红色的单元格表示该判断方式不支持的类型。"
  },
  {
    "path": "03-FEND_Note-master/chapter2/12_reg_exp.md",
    "content": "## 正则表达式\n\n正则表达式为标书字符串规则的表达式。下面为两个例子为在 JavaScript 中的使用，\n\n- `/pattern/attrs`\n- `new RegExp(pattern, attrs)`\n\n### 锚点\n\n**锚点**用于匹配一个位置，下列为常用的锚点\n\n- `^` 起始的位置 `/^http/`\n- `$` 结尾的位置 `/\\.jpg$/`\n- `\\b` 单词边界\n\n### 字符类\n\n**字符类**用于匹配一类字符中的一个，下面为几个常用的例子，\n\n- `[abc]` 可用于匹配 `a` `b` 还有 `c`\n- `[0-9]` 可用于匹配一个数字\n- `[^0-9]` 可用于匹配一个**非**数字\n- `[a-z]` 可用于匹配一个字母\n- `.` 任意字符但换行符除外\n\n### 元字符\n\n**元字符**为具有特殊意义的字符。常见的有，\n\n- `^`, `$`, `\\b`\n- `\\d` 用于匹配数字 `[0-9]`\n- `\\D` 用于匹配 `[^\\d]`\n- `\\s` 用于匹配空白符\n- `\\S` 用于匹配非空白符 `[^\\s]`\n- `\\w` 用于匹配任意单词字符（例如程序中的变量字符） `[A-Za-z0-9_]`\n- `\\W` 用于匹配非单词字符 `[^\\W]`\n\n### 量词\n\n量词用于表现字符出现的次数。可用的连词如下，\n\n- `{m,n}` 用于表示出现 `m` 到 `n` 次之间。\n- `*` 用于表示出现 `0` 到无穷之间也就等同于 `{0,}`\n- `?` 用于表示出现 `0` 次到 `1` 次也等同于 `{0,1}`\n- `+` 用于表现出现 `1` 次以及一次以上也等同于 `{1,}`\n\n### 转移符\n\n**转义符**需要在匹配的字符是元字符的时候使用。使用 `\\` 来进行转移即可。\n\n### 多选分支\n\n**多选分支**用于表示*或*的概念。`/thi(c|n)k/` 其又等同于 `/thi[cn]k/`。其还可以用于匹配文件扩展名 `/\\.(png|jpg|jpeg|gif)$/` 。\n\n### 常用方法\n\n#### 测试：regxObj.test(str)\n\n其用于测试正则表达式与指定字符串是否匹配。\n\n```\n/123/.test(123); // true\n/123/.test(111); // false\n/123/.test('x123'); // true\n```\n\n#### 捕获\n\n其用于保存所匹配到的字符串为后续开发所用。`()` 可用于捕获，正则表达式再运行时会将其保存下来，`(?:)` 则不予保存。\n\n```\n// str.match(regexp)\nvar url = 'http://www.google.com/query?test=li-xinyang#cool';\nvar reg = /(https?:)\\/\\/([^\\/]+)(\\/[^\\?]*)?(\\?[^#]*)?(#.*)?/;\n\nvar arr = url.match(reg);\nvar protocol = arr[1];\nvar host = arr[2];\nvar pathname = arr[3];\nvar search = arr[4];\nvar hash = arr[5];\n```\n\n#### 搜索与替换\n\n`regexpObj.exec(str)` 可以提供更强大的检索，它可以提供更详尽的结果 `index` 也可以提供过程状态 `lastIndex`。\n\n`str.replace(regex/substr, replacement)` 可以使用正则表达式来对字符串进行替换。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/00_intro.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [DOM 编程艺术](#dom-%E7%BC%96%E7%A8%8B%E8%89%BA%E6%9C%AF)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n# DOM 编程艺术\n\nDOM 编程就是使用 W3C 定义的 API (Application Program Interface)\n来操作 HTML 文档\n（此处不局限于 HTML，亦可操作 XHTML、XML  等），使用户可以与进行页面交互。\n你需要了解节点、属性、样式等基本 DOM 操作，DOM 事件模型，数据存储\n(Cookie、Storage) 与数据通信 (Ajax) ，JavaScript 动画，音频、视频、Canvas\n等 HTML5 特性，表单、列表操作。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/01_dom_tree.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [文档树](#%E6%96%87%E6%A1%A3%E6%A0%91)\n    - [HTML 转换 DOM 树](#html-%E8%BD%AC%E6%8D%A2-dom-%E6%A0%91)\n    - [节点遍历](#%E8%8A%82%E7%82%B9%E9%81%8D%E5%8E%86)\n    - [节点类型](#%E8%8A%82%E7%82%B9%E7%B1%BB%E5%9E%8B)\n    - [元素遍历](#%E5%85%83%E7%B4%A0%E9%81%8D%E5%8E%86)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 文档树\n\nDocument Object Model (DOM) 为文档**对象**模型，\n它使用对象的表示方式来表示对应的文档结构及其中的内容。\n\n下面为一个样例 `p` 元素在文档中的对象所包含的所有属性。\n\n```html\n<p id=\"target\">Hello, World!</p>\n```\n\n```\np#targetaccessKey: \"\"\nalign: \"\"\nattributes: Named\nNodeMapbaseURI: \"\"\nchildElementCount: 0\nchildNodes: NodeList[1]\nchildren: HTMLCollection[0]\nclassList: DOMTokenList[0]\nclassName: \"\"\nclientHeight: 0\nclientLeft: 0\nclientTop: 0\nclientWidth: 0\ncontentEditable: \"inherit\"\ndataset: DOM\nStringMapdir: \"\"\ndraggable: false\nfirstChild: text\nfirstElementChild: null\nhidden: false\nid: \"target\"\ninnerHTML: \"Hello, World!\"\ninnerText: \"Hello, World!\"\nisContentEditable: false\nlang: \"\"\nlastChild: text\nlastElementChild: null\nlocalName: \"p\"\nnamespaceURI: \"http://www.w3.org/1999/xhtml\"\nnextElementSibling: null\nnextSibling: null\nnodeName: \"P\"\nnodeType: 1\nnodeValue: null\noffsetHeight: 0\noffsetLeft: 0\noffsetParent: null\noffsetTop: 0\noffsetWidth: 0\nonabort: null\nonautocomplete: null\nonautocompleteerror: null\nonbeforecopy: null\nonbeforecut: null\nonbeforepaste: null\nonblur: null\noncancel: null\noncanplay: null\noncanplaythrough: null\nonchange: null\nonclick: null\nonclose: null\noncontextmenu: null\noncopy: null\noncuechange: null\noncut: null\nondblclick: null\nondrag: null\nondragend: null\nondragenter: null\nondragleave: null\nondragover: null\nondragstart: null\nondrop: null\nondurationchange: null\nonemptied: null\nonended: null\nonerror: null\nonfocus: null\noninput: null\noninvalid: null\nonkeydown: null\nonkeypress: null\nonkeyup: null\nonload: null\nonloadeddata: null\nonloadedmetadata: null\nonloadstart: null\nonmousedown: null\nonmouseenter: null\nonmouseleave: null\nonmousemove: null\nonmouseout: null\nonmouseover: null\nonmouseup: null\nonmousewheel: null\nonpaste: null\nonpause: null\nonplay: null\nonplaying: null\nonprogress: null\nonratechange: null\nonreset: null\nonresize: null\nonscroll: null\nonsearch: null\nonseeked: null\nonseeking: null\nonselect: null\nonselectstart: null\nonshow: null\nonstalled: null\nonsubmit: null\nonsuspend: null\nontimeupdate: null\nontoggle: null\nonvolumechange: null\nonwaiting: null\nonwebkitfullscreenchange: null\nonwebkitfullscreenerror: null\nonwheel: null\nouterHTML: \"<p id=\"target\">Hello, World!</p>\"\nouterText: \"Hello, World!\"\nownerDocument: document\nparentElement: null\nparentNode: null\nprefix: null\npreviousElementSibling: null\npreviousSibling: null\nscrollHeight: 0\nscrollLeft: 0\nscrollTop: 0\nscrollWidth: 0\nshadowRoot: null\nspellcheck: true\nstyle: CSSStyle\nDeclarationtabIndex: -1\ntagName: \"P\"\ntextContent: \"Hello, World!\"\ntitle: \"\"\ntranslate: true\nwebkitdropzone: \"\"\n__proto__: HTMLParagraphElement\n```\n\n通过使用 DOM 提供的 API (Application Program Interface)\n可以动态的修改节点（node），也就是对 DOM 树的直接操作。\n浏览器中通过使用 JavaScript 来实现对于 DOM 树的改动。\n\n**DOM 包含**\n\n- DOM Core\n- DOM HTML\n- DOM Style\n- DOM Event\n\n### HTML 转换 DOM 树\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>My title</title>\n  </head>\n  <body>\n    <a href=\"\">My Link</a>\n    <h1>My header</h1>\n  </body>\n</html>\n```\n\n![](../img/D/dom-tree.gif)\n\n### 节点遍历\n\n在元素节点中提取自己所需的节点，并予以操作。\n\n```Javascript\n// Document.getElementsByTagName()\n// 更具标签名找到目标节点的集合，此例中为 <h1>My header</h1>\nvar node = document.getElementsByTagName('h1')[0];\n\n// Node.parentNode;\n// 获得目标节点的父节点，此例中为 body 元素\nnode.parentNode;\n\n// Node.firstChild\n// 获得目标节点的第一个子节点，此例中为 \"My header\"\nnode.firstChild;\n\n// Node.lastChild\n// 获得目标节点的最后一个子节点，此例中为 \"My header\"\nnode.lastChild;\n\n// Node.previousSibling;\n// 获得目标节点的前一个相邻节点\nnode.previousSibling;\n\n// Node.nextSibling;\n// 获得目标节点的下一个相邻节点\nnode.nextSibling;\n```\n\n### 节点类型\n\n**常用节点类型**\n\n- ELEMENT_NODE 可使用 `Document.createElement('elementName');` 创建\n- TEXT_NODE 可使用 `Document.createTextNode('Text Value');` 创建\n\n**不常用节点类型**\n\n- COMMENT_NODE\n- DOCUMENT_TYPE_NODE\n\n**不同节点对应的NodeType类型**\n\n此值可以通过 `Node.nodeType` 来获取。\n\n|节点编号|节点名称|\n|--------|--------|\n|1|Element|\n|2|Attribute|\n|3|Text|\n|4|CDATA Section|\n|5|Entity Reference|\n|6|Entity|\n|7|Processing Instrucion|\n|8|Comment|\n|9|Document|\n|10|Document Type|\n|11|Document Fragment|\n|12|Notation|\n\nNOTE：此处需要清楚`节点`和`元素`的区别。我们平常说的`元素`\n其实指的是节点中得`元素节点`，所以说`节点`包含`元素`，节点还包括文本节点、实体节点等。\n\n### 元素遍历\n\n元素节点符合 HTML DOM 树规则，所以它与 DOM 中存在的节点相似。\n\n```\n<p>\n  Hello,\n    <em>Xinyang</em>!\n  回到\n    <a href=\"http://li-xinyang.com\">\n      主页\n    </a>\n  。\n</p>\n```\n\n```\n// 在选取元素节点后\n\np.firstElementChild;       // <em>Xinyang</em>\np.lastElementChild;        // <a href=\"http://li-xinyang.com\">主页</a>\n\nem.nextElementSibling;     // <a href=\"http://li-xinyang.com\">主页</a>\nem.previousElementSibling; // \"Hello,\"\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/02_node_manipulation.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [节点操作](#%E8%8A%82%E7%82%B9%E6%93%8D%E4%BD%9C)\n    - [获取节点](#%E8%8E%B7%E5%8F%96%E8%8A%82%E7%82%B9)\n      - [接口获取节点](#%E6%8E%A5%E5%8F%A3%E8%8E%B7%E5%8F%96%E8%8A%82%E7%82%B9)\n        - [getElementById](#getelementbyid)\n        - [getElementsByTagName](#getelementsbytagname)\n        - [getElementsByClassName](#getelementsbyclassname)\n        - [querySelector / querySelectorAll](#queryselector--queryselectorall)\n    - [创建节点](#%E5%88%9B%E5%BB%BA%E8%8A%82%E7%82%B9)\n    - [修改节点](#%E4%BF%AE%E6%94%B9%E8%8A%82%E7%82%B9)\n    - [插入节点](#%E6%8F%92%E5%85%A5%E8%8A%82%E7%82%B9)\n      - [appendChild](#appendchild)\n      - [insertBefore](#insertbefore)\n    - [删除节点](#%E5%88%A0%E9%99%A4%E8%8A%82%E7%82%B9)\n    - [innerHTML](#innerhtml)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 节点操作\n\n因为 DOM 的存在，这使我们可以通过 JavaScript 来获取、创建、修改、或删除节点。\n\nNOTE：下面提供的例子中的 `element` 均为元素节点。\n\n### 获取节点\n\n**父子关系**\n\n- `element.parentNode`\n- `element.firstChild`/`element.lastChild`\n- `element.childNodes`/`element.children`\n\n**兄弟关系**\n\n- `element.previousSibling`/`element.nextSibling`\n- `element.previousElementSibling`/`element.nextElementSibling`\n\n通过节点直接的关系获取节点会导致代码维护性大大降低（节点之间的关系变化会直接影响到获取节点），而通过接口则可以有效的解决此问题。\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>ELEMENT_NODE & TEXT_NODE</title>\n</head>\n<body>\n  <ul id=\"ul\">\n    <li>First</li>\n    <li>Second</li>\n    <li>Third</li>\n    <li>Fourth</li>\n  </ul>\n  <p>Hello</p>\n  <script type=\"text/javascript\">\n    var ulNode = document.getElementsByTagName(\"ul\")[0];\n    console.log(ulNode.parentNode);             //<body></body>\n    console.log(ulNode.previousElementSibling); //null\n    console.log(ulNode.nextElementSibling);     //<p>Hello</p>\n    console.log(ulNode.firstElementChild);      //<li>First</li>\n    console.log(ulNode.lastElementChild);       //<li>Fourth</li>\n  </script>\n</body>\n</html>\n```\n\nNTOE：细心地人会发现，在节点遍历的例子中，body、ul、li、p节点之间是没有空格的，因为如果有空格，那么空格就会被当做一个TEXT节点，从而用ulNode.previousSibling获取到得就是一个空的文本节点，而不是 `<li>First</li>` 节点了。即节点遍历的几个属性会得到所有的节点类型，而元素遍历只会得到相对应的元素节点。一般情况下，用得比较多得还是元素节点的遍历属性。\n\n**实现浏览器兼容版的element.children**\n\n有一些低版本的浏览器并不支持 `element.children` 方法，但我们可以用下面的方式来实现兼容。\n\n```html\n<html lang>\n<head>\n  <meta charest=\"utf-8\">\n  <title>Compatible Children Method</title>\n</head>\n<body id=\"body\">\n  <div id=\"item\">\n    <div>123</div>\n    <p>ppp</p>\n    <h1>h1</h1>\n  </div>\n  <script type=\"text/javascript\">\n    function getElementChildren(e){\n      if(e.children){\n        return e.children;\n      }else{\n        /* compatible other browse */\n        var i, len, children = [];\n        var child = element.firstChild;\n        if(child != element.lastChild){\n          while(child != null){\n            if(child.nodeType == 1){\n              children.push(child);\n            }\n            child = child.nextSibling;\n          }\n        }else{\n          children.push(child);\n        }\n        return children;\n      }\n    }\n    /* Test method getElementChildren(e) */\n    var item = document.getElementById(\"item\");\n    var children = getElementChildren(item);\n    for(var i =0; i < children.length; i++){\n      alert(children[i]);\n    }\n  </script>\n</body>\n</html>\n```\n\nNOTE：此兼容方法为初稿，还未进行兼容性测试。\n\n#### 接口获取元素节点\n\n- `getElementById`\n- `getElementsByTagName`\n- `getElementsByClassName`\n- `querySelector`\n- `querySelectorAll`\n\n|API|只作用于 `document`|唯一返回值|live|\n|---|:-----------------:|:--------:|:--:|\n|getElementById|√|√||\n|getElementsByTagName|||√|\n|getElementsByClassName|||√|\n|querySelectorAll||||\n|querySelector||√|||\n\n##### getElementById\n\n获取文档中指定 `id` 的节点**对象**。\n\n```javascript\nvar element = document.getElementById('id');\n```\n\n##### getElementsByTagName\n\n动态的获取具有指定标签元素节点的集合（其返回值会被 DOM 的变化所影响，其值会发生变化）。此接口可直接通过元素而获取，不必直接作用于 `document` 之上。\n\n```javascript\n// 示例\nvar collection = element.getElementsByTagName('tagName');\n\n// 获取指定元素的所有节点\nvar allNodes = document.getElementsByTagName('*');\n\n// 获取所有 p 元素的节点\nvar elements = document.getElementsByTagName('p');\n// 取出第一个 p 元素\nvar p = elements[0];\n```\n\n##### getElementsByClassName\n\n获取指定元素中具有指定 `class` 的所有节点。多个 `class` 可的选择可使用空格分隔，与顺序无关。\n\n```javascript\nvar elements = element.getElementsByClassName('className');\n```\n\nNOTE：IE9 及一下版本不支持 `getElementsByClassName`\n\n**兼容方法**\n\n```javascript\nfunction getElementsByClassName(root, className) {\n  // 特性侦测\n  if (root.getElementsByClassName) {\n    // 优先使用 W3C 规范接口\n    return root.getElementsByClassName(className);\n  } else {\n    // 获取所有后代节点\n    var elements = root.getElementsByTagName('*');\n    var result = [];\n    var element = null;\n    var classNameStr = null;\n    var flag = null;\n\n    className = className.split(' ');\n\n    // 选择包含 class 的元素\n    for (var i = 0, element; element = elements[i]; i++) {\n      classNameStr = ' ' + element.getAttribute('class') + ' ';\n      flag = true;\n      for (var j = 0, name; name = className[j]; j++) {\n        if (classNameStr.indexOf(' ' + name + ' ') === -1) {\n          flag = false;\n          break;\n        }\n      }\n      if (flag) {\n        result.push(element);\n      }\n    }\n    return result;\n  }\n}\n```\n\n##### querySelector / querySelectorAll\n\n获取一个 `list` （其返回结果不会被之后 DOM 的修改所影响，获取后不会再变化）符合传入的 CSS 选择器的第一个元素或全部元素。\n\n```javascript\nvar listElementNode = element.querySelector('selector');\nvar listElementsNodes = element.querySelectorAll('selector');\n\nvar sampleSingleNode = element.querySelector('#className');\nvar sampleAllNodes = element.querySelectorAll('#className');\n```\n\nNOTE: IE9 一下不支持 `querySelector` 与 `querySelectorAll`\n\n### 创建节点\n\n创建节点 -> 设置属性 -> 插入节点\n\n```javascript\nvar element = document.createElement('tagName');\n```\n\n### 修改节点\n\n**textContent**\n\n获取或设置节点以及其后代节点的文本内容（对于节点中的所有文本内容）。\n\n```javascript\nelement.textContent; // 获取\nelement.textContent = 'New Content';\n```\n\nNOTE：不支持 IE 9 及其一下版本。\n\n**innerText** （不符合 W3C 规范）\n\n获取或设置节点以及节点后代的文本内容。其作用于 `textContent` 几乎一致。\n\n```javascript\nelement.innerText;\n```\n\nNOTE：不符合 W3C 规范，不支持 FireFox 浏览器。\n\n**FireFox 兼容方案**\n\n```javascript\nif (!('innerText' in document.body)) {\n  HTMLElement.prototype.__defineGetter__('innerText', function(){\n    return this.textContent;\n  });\n  HTMLElement.prototype.__defineSetter__('innerText', function(s) {\n    return this.textContent = s;\n  });\n}\n```\n\n### 插入节点\n\n#### appendChild\n\n在指定的元素**内**追加一个元素节点。\n\n```javascript\nvar aChild = element.appendChild(aChild);\n```\n\n#### insertBefore\n\n在指定元素的指定节点前插入指定的元素。\n\n```javascript\nvar aChild = element.insertBefore(aChild, referenceChild);\n```\n\n### 删除节点\n\n删除指定的节点的子元素节点。\n\n```javascript\nvar child = element.removeChild(child);\n```\n\n### innerHTML\n\n获取或设置指定节点之中所有的 HTML 内容。替换之前内部所有的内容并创建全新的一批节点（去除之前添加的**事件**和**样式**）。`innerHTML` 不检查内容，直接运行并替换原先的内容。\n\nNOTE：只建议在创建全新的节点时使用。不可在用户可控的情况下使用。\n\n```javascript\nvar elementsHTML = element.innerHTML;\n```\n\n**存在的问题**\n\n- 低版本 IE 存在内存泄露\n- 安全问题（用户可以在名称中运行脚本代码）\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/03_attribute.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [属性操作](#%E5%B1%9E%E6%80%A7%E6%93%8D%E4%BD%9C)\n  - [HTML 属性与 DOM 属性的对应](#html-%E5%B1%9E%E6%80%A7%E4%B8%8E-dom-%E5%B1%9E%E6%80%A7%E7%9A%84%E5%AF%B9%E5%BA%94)\n  - [属性操作方式](#%E5%B1%9E%E6%80%A7%E6%93%8D%E4%BD%9C%E6%96%B9%E5%BC%8F)\n    - [Property Accessor](#property-accessor)\n    - [getAttribute / setAttribute](#getattribute--setattribute)\n    - [dataset](#dataset)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 属性操作\n\n### HTML 属性与 DOM 属性的对应\n\n每个 HTML 属性都会对应相应的 DOM 对象属性。\n\n```html\n<div>\n  <label for=\"username\">User Name: </label>\n  <input type=\"input\" name=\"username\" id=\"username\" class=\"text\" value=\"\">\n</div>\n```\n\n```javascript\ninput.id;        // 'username'\ninput.type;      // 'text'\ninput.className; // 'text'\n\nlabel.htmlFor;   // 'username'\n```\n\n### 属性操作方式\n\n#### Property Accessor\n\n通过属性方法符得到的属性为转换过的实例对象（并非全字符串）。\n\n**特点**\n\n- X 通用行差（命名异常，使用不同的命名方式进行访问）\n- X 扩展性差\n- √ 实用对象（取出后可直接使用）\n\n**读取属性**\n\n```html\n<div>\n  <label for=\"username\">User Name: </label>\n  <input type=\"input\" name=\"username\" id=\"username\" class=\"text\" value=\"\">\n</div>\n```\n\n```javascript\ninput.className; // 'text'\ninput[id];        // 'username'\n```\n\n**写入属性**\n\n可增加新的属性或改写已有属性。\n\n```javascript\ninput.value = 'new value';\ninput[id] = 'new-id';\n```\n\n#### getAttribute / setAttribute\n\n**特点**\n\n- X 仅可获取字符串（使用时需转换）\n- √ 通用性强\n\n**读取属性**\n\n获取到的均为属性的**字符串**。\n\n```javascript\nvar attribtue = element.getAttribute('attributeName');\n```\n\n**写入属性**\n\n可增加新的属性或改写已有属性。\n\n```javascript\nelement.setAttribute('attributeName', value);\n```\n\n#### dataset\n\n自定义属性，其为 `HTMLElement` 上的属性也是 `data-*` 的属性集。主要用于在元素上保存数据。获取的均为**属性字符串**。数据通常使用 AJAX 获取并存储在节点之上。\n\n```html\n<div id='user' data-id='1234' data-username='x' data-email='mail@gmail.com'></div>\n```\n\n```javascript\ndiv.dataset.id;         // '1234'\ndiv.dataset.username;   // 'x'\ndiv.dataset.email;      // 'mail@gmail.com'\n```\n\nNOTE：`dataset` 在低版本 IE 不可使用，但可通过 `getAttribute` 与 `setAttribute` 来做兼容。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/04_style_manipulation.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [样式操作](#%E6%A0%B7%E5%BC%8F%E6%93%8D%E4%BD%9C)\n  - [CSS 对应 DOM 对象](#css-%E5%AF%B9%E5%BA%94-dom-%E5%AF%B9%E8%B1%A1)\n    - [内部样式表](#%E5%86%85%E9%83%A8%E6%A0%B7%E5%BC%8F%E8%A1%A8)\n    - [行内样式](#%E8%A1%8C%E5%86%85%E6%A0%B7%E5%BC%8F)\n  - [更新样式](#%E6%9B%B4%E6%96%B0%E6%A0%B7%E5%BC%8F)\n    - [element.style](#elementstyle)\n    - [element.style.cssText](#elementstylecsstext)\n    - [更新 class](#%E6%9B%B4%E6%96%B0-class)\n    - [统一更新多个元素样式](#%E7%BB%9F%E4%B8%80%E6%9B%B4%E6%96%B0%E5%A4%9A%E4%B8%AA%E5%85%83%E7%B4%A0%E6%A0%B7%E5%BC%8F)\n  - [获取样式](#%E8%8E%B7%E5%8F%96%E6%A0%B7%E5%BC%8F)\n    - [element.style](#elementstyle-1)\n    - [window.getComputedStyle()](#windowgetcomputedstyle)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 样式操作\n\n通过 JavaScript 动态修改页面样式。\n\n### CSS 对应 DOM 对象\n\n![](../img/C/css-dom-overview.jpg)\n\n```html\n<link rel=\"stylesheet\" type=\"text/css\" href=\"sample.css\">\n// var element = document.querySelector('link');\n// 对应于 element.sheet\n\n<style type=\"text/css\" media=\"screen\">\n  body {\n    margin: 30px\n  }\n</style>\n// var element = document.querySelector('style');\n// 对应于 element.sheet\n\n// 整个页面的全部样式（不包括行内样式）\ndocument.styleSheets\n\n<p style=\"color:red\">Text Color</p>\n// var element = document.querySelector('p');\n// 对应于 element.style\n```\n\n#### 内部样式表\n\n```html\n<style>\n  body{margin:30;}\n  p{color: #aaa; line-height:20px}\n</style>\n\n// 1.对应所有样式的列表\n// body{margin:30;}\n// p{color: #aaa; line-height:20px}\nelement.sheet.cssRules;\n\n// 2.对应相应的 CSS 选择器\n// p\nelement.sheet.cssRules[1].selectorText;\n\n// 3.对应一个样式\n// p{color: #aaa; line-height:20px}\nelement.sheet.cssRules[1]\n\n// 4.对应所有样式的键值对\n// color: #aaa; line-height:20px\nelement.sheet.cssRules[1].style;\n\n// 5.对应的属性值\n// #aaa\nelement.sheet.cssRules[1].stlye.color;\nelement.sheet.cssRules[1].lineHeight;\n```\n\n#### 行内样式\n\n其对应于 `CSSStyleDeclaration` 的对象。\n\n```html\nelement.style.color;\n// 获取行内样式的键值对\n\n```\n\n### 更新样式\n\n#### element.style\n\n```javascript\nelement.style.color = 'red';\nelement.style.background = 'black';\n```\n\n增加样式后得到的结果\n\n```html\n<div style=\"color: red; background: black;\"></div>\n```\n\n**缺点**\n\n- 每个属性的更新都需要一个命令\n- 命名异常（以驼峰命名法命名属性）\n\n#### element.style.cssText\n\n一次同时设置多个行内样式，其结果同 `element.style` 单独设置相同。\n\n```javascript\nelement.style.cssText = 'color: red; background: black';\n```\n\n增加样式后得到的结果\n\n```html\n<div style=\"color: red; background: black;\"></div>\n```\n\n**以上两种方式均将样式混合在逻辑当中。**\n\n#### 更新 class\n\n首先需要创建对应样式的 CSS 样式。\n\n```html\n.angry {\n  color: red;\n  background: black;\n}\n```\n\n然后再在 JavaScript 中，在对应的事件中给元素添加需要的类即可。\n\n```javascript\nelement.className += ' angry';\n```\n\n增加样式后得到的结果\n\n```html\n<div class=\"angry\"></div>\n```\n\n#### 统一更新多个元素样式\n\n以上方法均不适合同时更新多个样式，通过更换样式表的方式则可同时更改多个页面中的样式。将需要的大量样式也在一个**皮肤样式**表中，通过 JavaScript 来直接更换样式表来进行样式改变。（此方法也可用于批量删除样式）\n\n```html\n<link rel=\"stylesheet\" type=\"text/css\" href=\"base.css\">\n<link rel=\"stylesheet\" type=\"text/css\" href=\"style1.css\">\n```\n\n```javascript\nelement.setAttribute('href', 'style2.css');\n```\n\n### 获取样式\n\n#### element.style\n\n其对应的为元素的**行内样式表**而不是实际样式表。\n\n```html\n<input type=\"checkbox\" name=\"\" value=\"\">\n```\n\n```javascript\nelement.style.color; // \"\"\n```\nline-height: 200px\n\n#### window.getComputedStyle()\n\n将需要取出样式的目标元素传入 `window.getComputedStyle()` 函数中，即可得到对应元素的实际样式。注意的是这里获取到的样式值为**只读**属性不可修改！\n\nNOTE：获取的实际为 `CSSStyleDeclaration` 的实例对象。\nNOTE+：此方法不支持 IE9 以下版本，IE9 中需使用 `element.currentStyle` 来做兼容。\n\n```javascript\nvar style = window.getComputedStyle(element[, pseudoEle]);\n```\n\n```html\n<input type=\"checkbox\" name=\"\" value=\"\">\n```\n\n```javascript\nwindow.getComputedStyle(element).color; // 'rgb(0,0,0)'\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/05_events.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [DOM 事件](#dom-%E4%BA%8B%E4%BB%B6)\n  - [事件流](#%E4%BA%8B%E4%BB%B6%E6%B5%81)\n  - [事件注册](#%E4%BA%8B%E4%BB%B6%E6%B3%A8%E5%86%8C)\n    - [注册事件](#%E6%B3%A8%E5%86%8C%E4%BA%8B%E4%BB%B6)\n    - [取消事件](#%E5%8F%96%E6%B6%88%E4%BA%8B%E4%BB%B6)\n    - [触发事件](#%E8%A7%A6%E5%8F%91%E4%BA%8B%E4%BB%B6)\n    - [浏览器兼容型](#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E5%9E%8B)\n      - [兼容低版本代码实现](#%E5%85%BC%E5%AE%B9%E4%BD%8E%E7%89%88%E6%9C%AC%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0)\n  - [事件对象](#%E4%BA%8B%E4%BB%B6%E5%AF%B9%E8%B1%A1)\n    - [属性和方法](#%E5%B1%9E%E6%80%A7%E5%92%8C%E6%96%B9%E6%B3%95)\n      - [通用属性和方法](#%E9%80%9A%E7%94%A8%E5%B1%9E%E6%80%A7%E5%92%8C%E6%96%B9%E6%B3%95)\n        - [阻止事件传播](#%E9%98%BB%E6%AD%A2%E4%BA%8B%E4%BB%B6%E4%BC%A0%E6%92%AD)\n        - [阻止默认行为](#%E9%98%BB%E6%AD%A2%E9%BB%98%E8%AE%A4%E8%A1%8C%E4%B8%BA)\n  - [事件分类](#%E4%BA%8B%E4%BB%B6%E5%88%86%E7%B1%BB)\n    - [Event](#event)\n      - [window](#window)\n      - [image](#image)\n    - [UIEvent](#uievent)\n    - [MouseEvent](#mouseevent)\n      - [属性](#%E5%B1%9E%E6%80%A7)\n      - [MouseEvent 顺序](#mouseevent-%E9%A1%BA%E5%BA%8F)\n        - [实例：拖动元素](#%E5%AE%9E%E4%BE%8B%EF%BC%9A%E6%8B%96%E5%8A%A8%E5%85%83%E7%B4%A0)\n    - [滚轮事件（Wheel）](#%E6%BB%9A%E8%BD%AE%E4%BA%8B%E4%BB%B6%EF%BC%88wheel%EF%BC%89)\n    - [FocusEvent](#focusevent)\n    - [InputEvent](#inputevent)\n    - [KeyboardEvent](#keyboardevent)\n  - [事件代理](#%E4%BA%8B%E4%BB%B6%E4%BB%A3%E7%90%86)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## DOM 事件\n\n何为 DOM 事件，HTML DOM 使JavaScript 有能力对 HTML 事件做出反应。（例如，点击 DOM 元素，键盘被按，输入框输入内容以及页面加载完毕等）\n\n### 事件流\n\n一个 DOM 事件可以分为`捕获过程`、`触发过程`、`冒泡过程`。\nDOM 事件流为 DOM 事件的处理及执行的过程。下面以一个`<a>`元素被点击为例。\n\n![](../img/E/event_flow.jpg)\n\n1. [红虚线]Capture Phase（事件捕获过程）当 DOM 事件发生时，它会从window节点一路跑下去直到触发事件元素的父节点为止，去捕获触发事件的元素。\n2. [红绿实线]Target Phase（事件触发过程）当事件被捕获之后就开始执行事件绑定的代码\n3. [绿虚线]Bubble Phase（冒泡过程）当事件代码执行完毕后，浏览器会从触发事件元素的父节点开始一直冒泡到window元素（**即元素的祖先元素也会触发这个元素所触发的事件**）\n\n**关于捕获过程的补充**\n\n如果有一个支持三个阶段的事件，它一定在触发时遵循下面的顺序：\n\n```\nCapture -> Target -> Bubbling\n```\n\n![](../img/E/event-phases.png)\n\n使用下面的代码来举例：\n\n```JavaScript\n// 添加Capture阶段事件\ndocuemnt.addEventListener('click',function(){\n    alert('capture：'+1);\n},true);\ntableNode.addEventListener('click',function(){\n    alert('capture：'+2);\n},true);\ntdNode.addEventListener('click',function(){\n    alert('capture：'+3);\n},true);\n\n// 添加Bubbling阶段事件\ndocuemnt.addEventListener('click',function(){\n    alert('bubble：'+1);\n});\ntableNode.addEventListener('click',function(){\n    alert('bubble：'+2);\n});\ntdNode.addEventListener('click',function(){\n    alert('bubble：'+3);\n});\n```\n\n输出结果为：\n\n```\ncapture：1\ncapture：2\ncapture：3\nbubble：3\nbubble：2\nbubble：1\n```\n\n![](../img/E/event-apply.png)\n\n```javascript\n// 对document添加了三个bubbling阶段的事件\ndocument.addEventListener('click',function(){\n    alert(1);\n});\ndocument.addEventListener('click',function(){\n    alert(2);\n});\ndocument.addEventListener('click',function(){\n    alert(3);\n});\n```\n\n如上面的代码所示，其为同一节点添加了同一阶段的多个事件，那执行顺序如何呢？\n早期并没有规范定义，DOM 3 中规范已经明确规定\n同一节点同一阶段的事件应按照注册函数的顺序执行。\n\n> 在实际项目过程中，某些情况下比如若干的组件或者模块都需要监听某个节点的某个事件，但是组件或者模块的生成（即添加事件的时机）是不一定保证顺序的，所以这个情况下如果某个组件对这个节点的这个事件的优先级特别高（需要保证必须先触发这个组件里的这个事件）而这个平台又支持这个阶段事件的话可以添加 capture 阶段事件，用三阶段的顺序来保证，比如移动平台模拟手势的实现会添加 document 上 touchXXX 的 capture 阶段事件，以优先识别手势操作\n> 当然实践过程中考虑到不同浏览器对三阶段支持的情况的差异，大部分情况下都采用的是 bubbling 阶段的事件\n>\n> —— 蔡剑飞 网易前端工程师\n\nNOTE：低版本 IE 中并未实现捕获过程。也不是所有事件均存在这三个完整的过程（例如 `load` 没有冒泡事件）\n\nNOTE+：在这三个阶段中无论将**事件捕获**和**事件处理**注册到任意一个父或祖父节点上都会被触发事件。\n\n### 事件注册\n\n事件注册，取消以及触发其作用对象均为一个 DOM 元素。\n\n#### 注册事件\n\n```javascript\neventTarget.addEventListener(type, listener[,useCapture])\n```\n\n- evenTarget 表示要绑定事件的DOM元素\n- type    表示要绑定的事件，如：\"click\"\n- listener  表示要绑定的函数\n- useCapture  可选参数，表示是否捕获过程\n\nNOTE：`useCapture` 为设定是否为捕获过程，默认事件均为冒泡过程，只有 `useCapture` 为 `true` 时才会启用捕获过程。\n\n```javascript\n// 获取元素\nvar elem = document.getElemenyById('id');\n\n// 事件处理函数\nvar clickHandler = function(event) {\n  // statements\n};\n\n// 注册事件\nelem.addEventListener('click', clickHandler, false);\n\n// 第二种方式，不建议使用\nelem.onclick = clickHandler;\n// 或者来弥补只可触发一个处理函数的缺陷\nelem.onclick = function(){\n  clickHandler();\n  func();\n  // 其他处理函数\n};\n```\n\n#### 取消事件\n\n```javascript\neventTarget.removeEventListener(type, listener[,useCapture]);\n```\n\n- evenTarget 表示要绑定事件的DOM元素\n- type    表示要绑定的事件，如：\"click\"\n- listener  表示要绑定的函数\n- useCapture  可选参数，表示是否捕获过程\n\n```javascript\n// 获取元素\nvar elem = document.getElemenyById('id');\n\n// 取消事件\nelem.removeEventListener('click', clickHandler, false);\n\n// 第二种方式。不建议使用\nelem.onclick = null;\n```\n\n#### 触发事件\n\n点击元素，按下按键均会触发 DOM 事件，当然也可以以通过代码来触发事件。\n\n```javascript\neventTarget.dispatchEvent(type);\n\n// 获取元素\nvar elem = document.getElemenyById('id');\n\n// 触发事件\nelem.dispatchEvent('click');\n```\n\n#### 浏览器兼容型\n\n以上均为 **W3C**定义的标准定义，但早期浏览器 IE8 及其以下版本，均没有采用标准的实现方式。不过这些低版本浏览器也提供了对于 DOM 事件的注册、取消以及触发的实现。\n\n**事件注册与取消**，`attchEvent/detachEvent`。**事件触发**，`fireEvent(e)`，其也**不存在**捕获阶段（Capture Phase）。\n\n\n##### 兼容低版本代码实现\n\n**注册事件**\n\n```javascript\nvar addEvent = document.addEventListener ?\n  function(elem, type, listener, useCapture) {\n    elem.addEventListener(type, listener, useCapture);\n  } :\n  function(elem, type, listener, useCapture) {\n    elem.attachEvent('on' + type, listener);\n  }\n```\n\n**取消事件**\n\n```javascript\nvar addEvent = document.removeElementListener ?\n  function(elem, type, listener, useCapture) {\n    elem.removeElementListener(type, listener, useCapture);\n  } :\n  function(elem, type, listener, useCapture) {\n    elem.detachEvent('on' + type, listener);\n  }\n```\n\n### 事件对象\n\n调用事件处理函数时传入的信息对象，这个对象中含有关于这个事件的详细状态和信息，它就是事件对象 `event`。其中可能包含鼠标的位置，键盘信息等。\n\n```javascript\n// 获取元素\nvar elem = document.getElemenyById('id');\n\n// 事件处理函数\nvar clickHandler = function(event) {\n  // statements\n};\n\n// 注册事件\nelem.addEventListener('click', clickHandler, false);\n```\n\nNOTE：在低版本 IE 中事件对象是被注册在 `window` 之上而非目标对象上。使用下面的兼容代码既可解决。\n\n```javascript\nvar elem = document.getElemenyById('id');\n\n// 事件处理函数\nvar clickHandler = function(event) {\n  event = event || window.event;\n  // statements\n};\n```\n\n#### 属性和方法\n\n##### 通用属性和方法\n\n**属性**\n\n- type 事件类型\n- target(srcElement IE 低版本) 事件触发节点\n- currentTarget 处理事件的节点\n\n**方法**\n\n- stopPropagation 阻止事件冒泡传播\n- preventDefault 阻止默认行为\n- stopImmediatePropagation 阻止冒泡传播\n\n###### 阻止事件传播\n\n`event.stopPropagation()`（W3C规范方法），如果在当前节点已经处理了事件，则可以阻止事件被冒泡传播至 DOM 树最顶端即 `window` 对象。\n\n`event.stopImmediatePropagation()` 此方法同上面的方法类似，除了阻止将事件冒泡传播值最高的 DOM 元素外，还会阻止在此事件后的事件的触发。\n\n`event.cancelBubble=true` 为 IE 低版本中中对于阻止冒泡传播的实现。\n\n###### 阻止默认行为\n\n默认行为是指浏览器定义的默认行为（点击一个链接的时候，链接默认就会打开。当我们双击文字的时候，文字就会被选中），比如单击链接可以打开新窗口。\n\n`Event.preventDefault()` 为 W3C 规范方法，在 IE 中的实现方法为 `Event.returnValue=false`。\n\n### 事件分类\n\n#### Event\n\n![](../img/E/event_types.jpg)\n\n|事件类型|是否冒泡|元素|默认事件|元素例子|\n|--------|--------|----|--------|--------|\n|load|NO|Window, Document, Element|None|window, image, iframe|\n|unload|NO|Window, Document, Element|None|window|\n|error|NO|Window, Element|None|window, image|\n|select|NO|Element|None|input, textarea|\n|abort|NO|Window, Element|None|window, image|\n\n##### window\n\n- load 页面全部加载完毕\n- unload 离开本页之前的卸载\n- error 页面异常\n- abort 取消加载\n\n##### image\n\n- load 图片加载完毕\n- error 图标加载错误\n- abort 取消图标加载\n\n在目标图标不能正常载入时，载入备份替代图来提供用户体验。\n\n```javascript\n<img src=\"http://sample.com/img.png\" onerror=\"this.src='http://sample.com/default.png'\">\n```\n\n#### UIEvent\n\n|事件类型|是否冒泡|元素|默认事件|元素例子|\n|--------|--------|----|--------|--------|\n|resize|NO|Window, Element|None|window, iframe|\n|scroll|NO/YES|Document, Element|None|document, div|\n\nNOTE：`resize` 为改变浏览器或`iframe`的窗体大小时会触发事件，`scroll` 则会在滑动内容时触发，作用于 `Document` 则不会冒泡，作用于内部元素则会冒泡。\n\n#### MouseEvent\n\nDOM 事件中最常见的事件之一。\n\n|事件类型|是否冒泡|元素|默认事件|元素例子|\n|--------|--------|----|--------|--------|\n|click|YES|Element|focus/activation|div|\n|dbclick|YES|Element|focus/activation/select|div|\n|mousedown|YES|Element|drag/scroll/text selection|div|\n|mosuemove|YES|Element|None|div|\n|mouseout|YES|Element|None|div|\n|mouseover|YES|Element|None|div|\n|mouseup|YES|Element|context menu|div|\n|mouseenter|NO|Element|None|div|\n|mouseleave|NO|Element|None|div|\n\nNOTE：`mouseenter` 与 `mouseover` 的区别为前者在鼠标在子元素直接移动不会触发事件，而后者会触发。\n`mouseleave` 与 `mouseout` 同上相似。\n\n##### 属性\n\n- clientX, clientX\n- screenX, screenY\n- ctrlKey, shiftKey, altKey, metaKey 如果被按下则为真（true）\n- button(0, 1, 2) 鼠标的间位\n\n![](../img/M/mouse_move_event.jpg)\n\n##### MouseEvent 顺序\n\n鼠标的移动过程中会产生很多事件。事件的监察频率又浏览器决定。\n\n**例子：从元素 A 上方移动过**\n\nmousemove -> mouseover(A) -> mouseenter(A) -> mousemove(A) -> mouseout(A) -> mouseleave(A)\n\n**例子：点击元素**\n\nmousedown -> [mousemove] -> mouseup -> click\n\n###### 实例：拖动元素\n\n```html\n<div id=\"div0\"></div>\n<style media=\"screen\">\n  #div0 {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100px;\n    height: 100px;\n    border: 1px solid black;\n  }\n</style>\n```\n\n```javascript\nvar elem = document.getElemenyById('div0');\nvar clientX, clientY, isMoving;\nvar mouseDownHandler = function(event) {\n  event = event || window.event;\n  clientX = event.clientX;\n  clientY = event.clientY;\n  isMoving = true;\n}\n\nvar mouseMoveHandler = function(event) {\n  if (!isMoving) return;\n  event = event || window.event;\n  var newClientX = event.clientX,\n      newClientY = event.clientY;\n  var left = parseInt(elem.style.left) || 0,\n      top = parseInt(elem.style.top) || 0;\n  elem.style.left = left + (newClientX - clientX) + 'px';\n  elem.style.top = top + (newClientY - clientY) + 'px';\n  clientX = newClientX;\n  clientY = newClientY;\n}\n\nvar mouseUpHandler = function() {\n  isMoving = false;\n}\n\naddEvent(elem, 'mousedown', mouseDownHandler);\naddEvent(elem, 'mouseup', mouseUpHandler);\naddEvent(elem, 'mousemove', mouseMoveHandler);\n```\n\n#### 滚轮事件（Wheel）\n\n|事件类型|是否冒泡|元素|默认事件|元素例子|\n|--------|--------|----|--------|--------|\n|wheel|YES|Element|scroll or zoom document|div|\n\n**属性**\n\n- deltaMode 鼠标滚轮偏移量的单位\n- deltaX\n- deltaY\n- deltaZ\n\n#### FocusEvent\n\n其用于处理元素获得或失去焦点的事件。（例如输入框的可输入状态则为获得焦点，点击外部则失去焦点）\n\n|事件类型|是否冒泡|元素|默认事件|元素例子|\n|--------|--------|----|--------|--------|\n|blur|NO|Window, Element|None|window, input|\n|focus|NO|Window, Element|None|window, input|\n|focusin|NO|window, Element|None|window, input|\n|focusout|NO|window, Element|None|window, input|\n\nNOTE：`blur` 失去焦点时，`focus` 获得焦点时，`focusin` 即将获得焦点，`focusout`即将失去焦点。\n\n**属性**\n\n一个元素失去，既另一个元素获得焦点。这里的 `relatedTarget` 则为相对的那个元素。\n\n- relatedTarget\n\n#### InputEvent\n\n输入框输入内容则会触发输入事件。\n\n|事件类型|是否冒泡|元素|默认事件|元素例子|\n|--------|--------|----|--------|--------|\n|beforeInput|YES|Element|update DOM Element|input|\n|input|YES|Element|None|input|\n\nNOTE：`beforeInput` 为在按键按下后即将将输入字符显示之前生成的事件。\n\nNOTE+：IE 并没有 `InputEvent` 则需使用 `onpropertychange(IE)` 来代替。\n\n#### KeyboardEvent\n\n其用于处理键盘事件。\n\n|事件类型|是否冒泡|元素|默认事件|元素例子|\n|--------|--------|----|--------|--------|\n|keydown|YES|Element|beforeInput/input/focus/blur/activation|div, input|\n|keyup|YES|Element|None|div, input|\n\n**属性**\n\n- key 按下的键字符串\n- code\n- ctrlKey, shiftKey, altKey, metaKey\n- repeat 代表按键不松开为 true\n- keyCode\n- charCode\n- which\n\n### 事件代理\n\n事件代理是指在父节点上（可为元素最近的父节点也可为上层的其他节点）处理子元素上触发的事件，其原理是通过事件流机制而完成的。可以通过**事件对象**中获取到触发事件的对象（如下所示）。\n\n```javascript\nvar elem = document.getElemenyById('id');\nelem.addEventListener('click', function(event) {\n  var e = event || window.event;\n  var target = e.target || e.srcElement;\n  // statements\n});\n```\n\n**优点**\n\n- 需要管理的事件处理函数更少\n- 内存分配更少，更高效\n- 增加与删除子节点可以不额外处理事件\n\n**缺点**\n\n- 事件管理的逻辑变的复杂（因为冒泡机制）\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/06_animation.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [JavaScript 动画](#javascript-%E5%8A%A8%E7%94%BB)\n  - [实现方式](#%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F)\n  - [JavaScript 动画三要素](#javascript-%E5%8A%A8%E7%94%BB%E4%B8%89%E8%A6%81%E7%B4%A0)\n  - [定时器](#%E5%AE%9A%E6%97%B6%E5%99%A8)\n  - [常见动画](#%E5%B8%B8%E8%A7%81%E5%8A%A8%E7%94%BB)\n  - [动画函数](#%E5%8A%A8%E7%94%BB%E5%87%BD%E6%95%B0)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## JavaScript 动画\n\n**帧**，为动画的最小单位，一个静态的图像。**帧频**，每秒播放的帧的数量。一个动画是由很多帧组成的，因为人眼的暂留特性，当图片交替的速度大于每秒 30 帧以上既有动画的感觉。\n\n### 实现方式\n\n- gif 图像形式存储，容量大，需第三方制图工具制作。\n- flash 需要第三方制作工具，不推荐。\n- CSS3 实现动画具有局限性\n- JavaScript 可实现大部分上面几类可实现的动画效果\n\n### JavaScript 动画三要素\n\n![](../img/J/javascript-animation.jpg)\n\n### 定时器\n\n**setInterval**\n\n- `func` 为执行改变属性的操作\n- `delay` 为出发时间间隔（毫秒为单位）\n- `para1` 为执行时可传入改变属性函数的参数\n\n```javascript\nvar intervalId = setInterval(func, delay[, param1, param2, ...]);\nclearInterval(intervalId);\n```\n\nNOTE：使用 `setInterval` 可以调用一次定时器既可实现连贯的动画。使用 `clearInterval` 即可清除动画效果。\n\n**setTimeout**\n\n- `func` 为执行改变属性的操作\n- `delay` 为出发时间间隔（毫秒为单位）默认为 0\n- `para1` 为执行时可传入改变属性函数的参数\n\n```javascript\nvar timeoutId = setTimeout(func[, delay, param1, param2, ...]);\nclearTimeout(timeoutId);\n```\n\nNOTE：使用 `setTimeout` 实现动画，则需要在动画每一帧结束时再次调用定时器。但它无需清除定时器。\n\n**区别**\n\n- `setTimeout` 在延时后只执行一次，`setInterval` 则会每隔一个延时期间后会再执行。\n\n**requestAnimationFrame**\n\n类似于 `setTimeout` 但是无需设定时间间隔。此定时器为 HTML5 中的新标准，其间隔时间不由用户控制，而是由显示器的刷新频率决定。（市面上的显示器刷新频率为每秒刷新60次）\n\n**优势**\n\n- 无需设置间隔时间\n- 动画流畅度高\n\n```javascript\nvar requestId = requestAnimationFrame(func);\ncancelAnimationFrame(requestId);\n```\n\nNOTE：使用它来实现动画与 `setTimeout` 类似，需要每次每帧结束时再次调用。不可设置时间间隔（系统决定），时间间隔为16.67毫秒一帧。\n\n### 常见动画\n\n大多的复杂动画都是有下列的简单动画所组成的。\n\n- 形变，改变元素的宽高\n- 位移，改变元素相对位置\n- 旋转\n- 透明度\n- 其他...\n\n### 动画函数\n\n下面的例子为以 px 为单位的动画代码\n\n```javascript\nvar animation = function(ele, attr, from, to) {\n  var distance = Math.abs(to - from);\n  var stepLength = distance/100;\n  var sign = (to - from)/distance;\n  var offset = 0;\n  var step = function(){\n    var tmpOffset = offset + stepLength;\n    if (tmpOffset < distance) {\n      ele.style[attr] = from + tmpOffset * sign + 'px';\n      offset = tmpOffset;\n    } else {\n      ele.style[attr] = to + 'px';\n      clearInterval(intervalID);\n    }\n  }\n  ele.style[attr] = from + 'px';\n  var intervalID = setInterval(step, 10);\n}\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/07_canvas.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Canvas](#canvas)\n  - [渲染上下文对象](#%E6%B8%B2%E6%9F%93%E4%B8%8A%E4%B8%8B%E6%96%87%E5%AF%B9%E8%B1%A1)\n  - [绘图步骤](#%E7%BB%98%E5%9B%BE%E6%AD%A5%E9%AA%A4)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Canvas\n\n**Mozilla** 官方 `<canvas>` 教程在[这里](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial)。\n\n画布 `<canvas>` 的默认宽高为 300 与 150 ，但是同样可以使用 CSS 设定宽高。但因为 CSS 与 JavaScript 在渲染工程中有速度的差异，所以**不建议使用** CSS 对 `<canvas>` 的宽高做设定。\n\n```html\n<canvas id=\"canvasId\" width=\"300\" height=\"150\">\n</canvas>\n```\n\n### 渲染上下文对象\n\n下面的 `ctx` 即为渲染上下文对象。`globalCompositeOperation` 为对于 `canvas` 绘画时的渲染属性设置，具体表现如下图所示。\n\n```Javascript\nvar canvas = document.getElementById('canvasId');\nvar ctx = canvas.getContext('2d');\n\n\n// 绘画 canvas 的属性\nctx.globalCompositeOperation = 'destination-over';\n```\n\n![](../img/C/canvas-global-composite.png)\n\n### 绘图步骤\n\n![](../img/C/canvas-drawing-steps.png)\n\n一个周期就是完整的一帧的绘画过程。\n\n![](../img/C/canvas-animation.gif)\n\n```javascript\nvar sun = new Image();\nvar moon = new Image();\nvar earth = new Image();\n\nfunction init() {\n  sun.src = 'Canvas_sun.png';\n  moon.src = 'Canvas_moon.png';\n  earth.src = 'Canvas_earth.png';\n  window.requestAnimationFrame(draw);\n}\n\nfunction draw(){\n  var ctx = document.getElementById('canvas').getContext('2d');\n\n  ctx.globalCompositeOperation = 'destination-over';\n  // 清空画布内容\n  ctx.clearRect(0, 0, 300, 300);\n\n  ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';\n  ctx.strokeStyle = 'rgba(0, 153, 255, 0.4)';\n\n  // 保存画布状态\n  ctx.save();\n  ctx.translate(150, 150);\n\n  // 开始绘制图形\n\n  // 地球\n  var time = new Date();\n  ctx.rotate(((2*Math.PI)/60)* time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds());\n  ctx.translate(105, 0);\n  // 阴影\n  ctx.fillRect(0, -12, 50, 24);\n  ctx.drawImage(earth, -12, -12);\n\n  // 月亮\n  ctx.rotate(((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds());\n  ctx.translate(0, 28.5);\n  ctx.drawInmage(moon, -3.5, -3.5);\n\n  // 恢复画布状态\n  ctx.restore();\n\n  ctx.beginPath();\n  ctx.arc(150, 150, 105, 0, Math.PI*2, false);\n\n  ctx.stroke();\n\n  ctx.drawImage(sun, 0, 0, 300, 300);\n\n  window.requestAnimationFrame(draw);\n}\n\ninit();\n```"
  },
  {
    "path": "03-FEND_Note-master/chapter3/08_multimedia.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [多媒体](#%E5%A4%9A%E5%AA%92%E4%BD%93)\n  - [基本用法](#%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95)\n  - [多媒体支持类型](#%E5%A4%9A%E5%AA%92%E4%BD%93%E6%94%AF%E6%8C%81%E7%B1%BB%E5%9E%8B)\n  - [多媒体格式兼容](#%E5%A4%9A%E5%AA%92%E4%BD%93%E6%A0%BC%E5%BC%8F%E5%85%BC%E5%AE%B9)\n  - [HTML 属性](#html-%E5%B1%9E%E6%80%A7)\n  - [控制多媒体](#%E6%8E%A7%E5%88%B6%E5%A4%9A%E5%AA%92%E4%BD%93)\n  - [多媒体相关事件](#%E5%A4%9A%E5%AA%92%E4%BD%93%E7%9B%B8%E5%85%B3%E4%BA%8B%E4%BB%B6)\n  - [Web Audio API](#web-audio-api)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 多媒体\n\nHTML5 前的多媒体需要借助第三方插件，例如 Flash，但是 HTML5 将网页中的多媒体带入了新的一章。\n\n![](../img/M/mutimedia.jpg)\n\n### 基本用法\n\n```html\n// 音频\n// 指定资源类型可以帮助浏览器更快的定位解码\n<audio autobuffer autoloop loop controls>\n  <source src=\"/media/audio.mp3\" type=\"audio/mpeg\">\n  <source src=\"/media/audio.oga\">\n  <source src=\"/media/audio.wav\">\n  <object type=\"audio/x-wav\" data=\"/media/audio.wav\" width=\"290\" height=\"45\">\n    <param name=\"src\" value=\"/media/audio.wav\">\n    <param name=\"autoplay\" value=\"false\">\n    <param name=\"autoStart\" value=\"0\">\n    <p><a href=\"/media/audio.wav\">Download this audio file.</a></p>\n  </object>\n</audio>\n\n// 视频\n<video autobuffer autoloop loop controls width=320 height=240>\n  <source src=\"/media/video.oga\">\n  <source src=\"/media/video.m4v\">\n  <object type=\"video/ogg\" data=\"/media/video.oga\" width=\"320\" height=\"240\">\n  <param name=\"src\" value=\"/media/video.oga\">\n  <param name=\"autoplay\" value=\"false\">\n  <param name=\"autoStart\" value=\"0\">\n  <p><a href=\"/media/video.oga\">Download this video file.</a></p>\n  </object>\n</video>\n```\n\n### 多媒体支持类型\n\nHTML5 支持音频[列表](http://en.wikipedia.org/wiki/HTML5_Audio#Supported_audio_coding_formats)\n\nHTML5 支持视频[列表](http://en.wikipedia.org/wiki/HTML5_video#Browser_support)\n\n### 多媒体格式兼容\n\n测试音频兼容性。\n\n```javascript\nvar a = new Audio();\n// 检测媒体类型返回\n// 支持 - 'maybe' 或 'probably'\n// 不支持 - ''\na.canPlayType('audio/nav');\n```\n\n### HTML 属性\n\n视频与音频的大部分属性和方法几乎相同。\n\n|属性|是否必须|默认值|备注|\n|----|--------|------|----|\n|src|是||音频文件地址 URL|\n|controls|否|false|显示控件|\n|autoplay|否|false|音频就绪后自动播放|\n|preload|否|none|可取值为 none、metadata、auto。音频在页面加载是进行加载，并预备播放。如果使用 autoplay 则忽略该属性（该属性失效）|\n|loop|否|false|是否循环播放|\n\n### 控制多媒体\n\n**方法**\n\n- `load()` 加载资源\n- `play()` 播放\n- `pause()` 暂停播放\n\n**属性**\n\n- `playbackRate` 1为正常速度播放，大于1为快速播放最高20。\n- `currentTime` 调准播放时间，以秒为单位。\n- `volume` 取值范围0到1\n- `muted` 真假值\n\n\n- `paused` 布尔值暂停\n- `seeking` 布尔值跳转\n- `ended` 布尔值播放完成\n- `duration` 媒体时长数值\n- `initialTime` 媒体开始时间\n\n### 多媒体相关事件\n\n- `loadstart` 开始请求媒体内容\n- `loadmetadata` 媒体元数据以加载完成（时长，编码格式等）\n- `canplay` 加载一些内容但可播放\n- `play` 调用`play()`或设置 `autoplay`\n- `waiting` 缓冲数据不够，暂停播放\n- `playing` 正在进行播放\n\n**全部事件列表**\n\n事件[列表](http://www.w3.org/wiki/HTML/Elements/audio#Media_Events)\n\n### Web Audio API\n\n音频 W3C 官网定义在[这里](http://webaudio.github.io/web-audio-api/)\n\nMozilla 官方音频教程在[这](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)，以及第三方[教程 1](http://www.html5rocks.com/en/tutorials/webaudio/intro/)和[教程 2](http://webaudioapi.com/)。"
  },
  {
    "path": "03-FEND_Note-master/chapter3/09_network.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [数据通信](#%E6%95%B0%E6%8D%AE%E9%80%9A%E4%BF%A1)\n  - [HTTP](#http)\n    - [HTTP 事务](#http-%E4%BA%8B%E5%8A%A1)\n      - [HTTP 请求报文](#http-%E8%AF%B7%E6%B1%82%E6%8A%A5%E6%96%87)\n      - [HTTP 回复报文](#http-%E5%9B%9E%E5%A4%8D%E6%8A%A5%E6%96%87)\n    - [常用 HTTP 方法](#%E5%B8%B8%E7%94%A8-http-%E6%96%B9%E6%B3%95)\n    - [URL 构成](#url-%E6%9E%84%E6%88%90)\n    - [HTTP 版本](#http-%E7%89%88%E6%9C%AC)\n    - [常见 HTTP 状态码](#%E5%B8%B8%E8%A7%81-http-%E7%8A%B6%E6%80%81%E7%A0%81)\n  - [AJAX](#ajax)\n    - [AJAX 调用](#ajax-%E8%B0%83%E7%94%A8)\n      - [open](#open)\n      - [setRequestHeader](#setrequestheader)\n      - [send](#send)\n    - [请求参数序列化](#%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0%E5%BA%8F%E5%88%97%E5%8C%96)\n    - [同源策略](#%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5)\n    - [跨域资源访问](#%E8%B7%A8%E5%9F%9F%E8%B5%84%E6%BA%90%E8%AE%BF%E9%97%AE)\n      - [其他跨域技术](#%E5%85%B6%E4%BB%96%E8%B7%A8%E5%9F%9F%E6%8A%80%E6%9C%AF)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 数据通信\n\n### HTTP\n\nHTTP 为一个通信协议。HTTP 客户端发起请求并创建端口。HTTP 服务器在端口监听客户端的请求。\nHTTP 服务器在收到请求后则返回状态和所请求的内容。\n\n**网页浏览全过程** （粗浅流程）\n\n1. 域名解析\n  1. 搜索浏览器自身 DNS 缓存\n  1. 搜索操作系统自身 DNS 缓存（如上一级未找到或已失效）\n  1. 读取本地 HOST 文件 （如上一级未找到或已失效，`/etc/hosts`）\n  1. 浏览器发起 DNS 系统调用请求\n    1. ISP 服务器查找自身缓存\n    1. ISP 服务器发起迭代（逐域寻找需要的地址）请求\n1. 得到请求资源的 IP 地址\n1. 发起 HTTP “三次握手”（下面为一个超级简化版）\n  1. 建立连接，等待服务器确认\n  1. 服务器接受请求，回复客户\n  1. 客户端与服务器连接成功（TCP/IP 连接成功）\n1. 客户根据协议发送请求\n1. 服务器更具请求返回客户需求资源\n1. 客户获得资源\n\n#### HTTP 事务\n\n![](../img/H/http-process.png)\n\n##### HTTP 请求报文\n\n![](../img/H/http-request.jpg)\n\n其中包括主机地址，HTTP 协议版本号。头部由键值对组成。因为此请求为 GET 方法所以请求体为空。\n\n##### HTTP 回复报文\n\n![](../img/H/http-response.png)\n\n其中包括 HTTP 版本号，状态码及状态码描述。头部依然为键值对组成。主体则为 HTML 文件。\n\n#### 常用 HTTP 方法\n\n**常用方法**\n\n|方法|描述|是否包含主题|\n|----|----|------------|\n|GET|从服务器获取一份文档|否|\n|POST|向服务器发送需要处理的数据|是|\n|PUT|将请求的主题部分储存在服务器上|是|\n|DELETE|从服务器删除一份文档|否|\n\n**不常用方法**\n\n|方法|描述|是否包含主题|\n|----|----|------------|\n|HEAD|只从服务器获取头文档的首部|否|\n|TRACE|对可能经过代理服务器传送到服务器上的报文进行追踪|否|\n|OPTIONS|决定可以在服务器上执行的方法|否|\n\n#### URL 构成\n\n```html\nhttp://www.github.com:8080/index.html?user=li-xinyang&lang=zh-CN#home\n  |          |          |       |                  |              |\nprotocol     |          |       |                  |              |\n          hostname     port     |                  |              |\n              \\        /    pathname             search          hash\n                 host\n```\n\n**可选部分包括**：\n\n- port\n- pathname\n- search\n- hash\n\nNOTE：上面提供的 URL 地址仅为参考所用。\n\n#### HTTP 版本\n\n- HTTP/0.9 1991年 HTTP 原型，存在设计缺陷\n- HTTP/1.0 第一个广泛应用版本\n- HTTP/1.0+ 添加持久的 keep-alive 链接，虚拟主机支持，代理连接支持，成为非官方的事实版本\n- HTTP/1.1 校正结构性缺陷，明确语义，引入重要的新能优化措施，删除不好的特性（**当前使用版本**）\n\nNOTE：此文写于2015年6月。\n\n#### 常见 HTTP 状态码\n\n|状态码|描述|代码描述|\n|------|----|--------|\n|200|请求成功，一般用于 GET 和 POST 方法|OK|\n|301|资源移动。所请求资源自动到新的 URL，浏览器自动跳转至新的 URL | Moved Permanently|\n|304|未修改。所请求资源未修改，浏览器读取缓存数据|Not Modified|\n|400|请求语法错误，服务器无法解析|Bad Request|\n|404|未找到资源，可以设置个性“404页面”|Not Found|\n|500|服务器内部错误|Internal Server Error|\n\n![](../img/H/http-state-code.jpg)\n\n### AJAX\n\nAJAX（Asynchronous JavaScript and HTML）异步获取数据的概念，由 Jesse James Garrett 在2005年提出。\n\n**AJAX 请求全过程**\n\n![](../img/A/ajax-process.jpg)\n\n#### AJAX 调用\n\n三部完成 AJAX 调用\n\n1. 创建 XHR 对象\n2. 处理返回数据及错误处理\n3. 发送请求\n\n```javascript\nvar xhr = new XMLHttpRequest();\n\nxhr.onreadystatechange = function(callback) {\n  if (xhr.readyState === 4) {\n    if ((xhr.status >== 200 && xhr.status < 300) || xhr.status === 304) {\n      callback(xhr.responseText);\n    } else {\n      console.error('Request was unsuccessful: ' + xhr.status);\n    }\n  }\n}\n\nxhr.open('get', 'exmaple.json', true);\nxhr.setRequestHeader('myHeader', 'myValue');\nxhr.send(null);\n```\n\nNOTE：`xhr.onload` 只针对当 `readyState === 4` 和 `status === 200` 时的事件。\n\n##### open\n\n```javascript\nxhr.open(method, url[, async = true]);\n```\n\n- `method` 为上面说过的 HTTP 方法（例如，GET、POST）\n- `url` 为资源地址\n- `async` 默认为真，用于设置异步请求\n\n##### setRequestHeader\n\n```javascript\nxhr.setRequestHeader('myHeader', 'myValue');\n\nxhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n```\n\n用于设置头部的键值对。\n\n##### send\n\n```javascript\nxhr.send([data=null]);\n\nxhr.send()\n```\n\n数据可包含字符串或表单数控，但需要提前为 RequestHeader 做设置。\n\n#### 请求参数序列化\n\n将查询参数使用字符串，跟入资源地址中。\n\n```javascript\nxhr.open('get', 'example.json?' + 'name=value&age=value', true);\n```\n\n**对象转换字符串的函数实现**\n\n```javascript\nfunction serialize(data) {\n  if (!data) return '';\n  var pairs = [];\n  for (var name in data) {\n    if (!data.hasOwnProperty(name)) continue;\n    if (typeof data[name] === 'function') continue;\n    var value = data[name].toString();\n    name = encodeURIComponent(name);\n    value = encodeURIComponent(value);\n    pairs.push(name + '=' + value);\n  }\n  return pairs.join('&');\n}\n```\n\n**GET 请求**\n\n```javascript\nvar url = 'example.json?' + serialize(formData);\nxhr.open('get', url, true);\nxhr.send(null);\n```\n\n**POST 请求**\n\n查询参数需要作为 `send()` 的存数传入。\n\n```javascript\nxhr.open('get', 'example.json', true);\nxhr.send(serialize(formData));\n```\n\n#### 同源策略\n\n两个页面拥有相同的协议（Protocol）、端口（Port）、和主机（host）那么这两个页面就是属于同一个源（Origin）。\n\n```html\nhttp://www.github.com:8080/index.html?user=li-xinyang&lang=zh-CN#home\n  |          |          |       |                  |              |\nprotocol     |          |       |                  |              |\n          hostname     port     |                  |              |\n              \\        /    pathname             search          hash\n                 host\n|-----完全一致则同源------|\n```\n\n#### 跨域资源访问\n\n不满足同源策略的资源访问均属于跨域资源访问，W3C 定义了 [**CORS**](http://www.w3.org/TR/cors/)。现代浏览器已经实现了 CORS 的支持。\n\n**CORS 原理实现图**\n\n![](../img/C/cors.jpg)\n\n##### 其他跨域技术\n\n- Frame 代理\n- JSONP\n- Comet\n- Web Sockets\n- ...\n\n**Frame 代理**\n\n关于 Frame 代理的更多内容在[这里](https://github.com/genify/nej/blob/master/doc/AJAX.md)。\n\n![](../img/F/frame_proxy.jpg)\n\n优点：\n\n- 参照 CORS 标准\n- 支持各种请求方法 GET POST PUT DELETE\n\n缺点：\n\n- 需要在目标服务器防止代理文件（造成延时）\n- 低版本在大并发消息通信机制会产生延时\n\n**JSONP**\n\n全程为 JSON with Padding（填充式 JSON），它利用 `<script>` 可以跨域的原理。请求一段 JavaScript 代码，然后执行 JavaScript 代码来实现跨域。\n\n```javascript\nfunction handleResponse(response) {\n  alert(response.name);\n}\n\nvar script = document.createElement('script');\nscript.src = 'http://localhost:3000/json?callback=handleResponse';\ndocument.body.insertBefore(script, document.body.firstChild);\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/10_bom.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [BOM](#bom)\n  - [属性](#%E5%B1%9E%E6%80%A7)\n    - [navigator](#navigator)\n    - [location](#location)\n      - [方法](#%E6%96%B9%E6%B3%95)\n    - [history](#history)\n      - [方法](#%E6%96%B9%E6%B3%95-1)\n    - [screen](#screen)\n  - [Window 方法](#window-%E6%96%B9%E6%B3%95)\n  - [Window 事件](#window-%E4%BA%8B%E4%BB%B6)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## BOM\n\n![](../img/B/bom-intro.jpg)\n\nBOM 为浏览器窗口对象的一组 API。\n\n**BOM 结构图**\n\n![](../img/B/bom-structure.jpg)\n\n### 属性\n\n|属性名|描述|\n|------|----|\n|navigator|浏览器信息|\n|location|浏览器定位和导航|\n|history|窗口浏览器历史|\n|screen|屏幕信息|\n\n#### navigator\n\n`navigator.userAgent`\n\n- Chrome, Mozilla/5.0(Windows NT 6.1; WOW64) Apple WebKit/37.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36\n- Firefox, Mozilla/5.0(Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0\n- IE, Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; rv:11.0) like Gecko\n\n```html\nappCodeName: \"Mozilla\"appName: \"Netscape\"appVersion: \"5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36\"cookieEnabled: truedoNotTrack: \"1\"geolocation: GeolocationhardwareConcurrency: 8language: \"en-US\"languages: Array[4]maxTouchPoints: 0mimeTypes: MimeTypeArrayonLine: truepermissions: Permissionsplatform: \"MacIntel\"plugins: PluginArrayproduct: \"Gecko\"productSub: \"20030107\"serviceWorker: ServiceWorkerContaineruserAgent: \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36\"vendor: \"Google Inc.\"vendorSub: \"\"webkitPersistentStorage: DeprecatedStorageQuotawebkitTemporaryStorage: DeprecatedStorageQuota__proto__: Navigator\n```\n\nNOTE：可以通过 `userAgent` 判断浏览器。\n\n#### location\n\n代表浏览器的定位和导航。可以使用 `location` 来操作 URL 中的各个部分。最常用的有 `href` 属性，当前访问资源的完整路径。\n\n```html\nhttp://www.github.com:8080/index.html?user=li-xinyang&lang=zh-CN#home\n  |          |          |       |                  |              |\nprotocol     |          |       |                  |              |\n          hostname     port     |                  |              |\n              \\        /    pathname             search          hash\n                 host\n```\n\n##### 方法\n\n- `assign(url)` 载入新的 url，记录浏览记录\n- `replace(url)` 载入新的 url 不记录浏览记录\n- `reload()` 重新载入当前页\n\n#### history\n\n浏览器当前窗口的浏览历史。\n\n```html\nlength: 9state: null __proto__: History\n```\n\n##### 方法\n\n- `back(int)` 后退\n- `forward(int)` 前进\n- `go(int)` 正数向前，附属向后\n\n#### screen\n\n其中包含屏幕信息。其中 `avil-` 开头的属性为可用属性，其余则为显示器设备属性。\n\n### Window 方法\n\n|方法|描述|\n|----|----|\n|`alert()`, `confirm()` 返回真假, `prompt()` 返回用户输入值| 三种对话框|\n|`setTimeout()`, `setInterval()`| 计时器|\n|`open()`, `close()`| 开启窗口，关闭窗口|\n\nNOTE：对话框会阻塞线程。\n\n**打开或关闭窗口**\n\n```javascript\nvar w = window.open('subwindow.html', 'subwin', 'width=300, height=300, status=yes, resizable=yes');\n\n// 既可关闭窗口\nw.close();\n```\n\nNOTE：无需记忆，更多属性在使用时查询文档。\n\n### Window 事件\n\n|事件名|描述|\n|------|----|\n|load|文档和所有图片完成加载时|\n|unload|离开当前文档时|\n|beforeunload|和 unload 类似，但是它提供询问用户是否确认离开的机会|\n|resize|拖动改变浏览器窗口大小时|\n|scroll|拖动浏览器时|\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/11_storage.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [数据存储](#%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8)\n  - [Cookie](#cookie)\n    - [属性](#%E5%B1%9E%E6%80%A7)\n    - [作用域](#%E4%BD%9C%E7%94%A8%E5%9F%9F)\n    - [读取](#%E8%AF%BB%E5%8F%96)\n    - [设置与修改](#%E8%AE%BE%E7%BD%AE%E4%B8%8E%E4%BF%AE%E6%94%B9)\n    - [Cookie 缺陷](#cookie-%E7%BC%BA%E9%99%B7)\n  - [Storage](#storage)\n    - [对象](#%E5%AF%B9%E8%B1%A1)\n    - [API](#api)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 数据存储\n\n### Cookie\n\n浏览器中的 Cookie 是指小型文本文件，通常在 4KB 大小左右。（由键值对构成用 `;` 隔开）大部分时候是在服务器端对 Cookie 进行设置，在头文件中 `Set-Cookie` 来对 Cookie 进行设置。\n\n页面可以访问当前页的 Cookie 也可以访问父域的 Cookie。\n\n#### 属性\n\n|属性|默认值|作用|\n|----|------|----|\n|Name（必填）||名|\n|Value（必填）||值|\n|Domain|当前文档域|作用域|\n|Path|当前文档路径|作用路径|\n|Expires（时间戳）/Max-Age（毫秒数值）|浏览器会话时间|失效事件|\n|Secure|false|https 协议时生效|\n\n#### 作用域\n\n**设置作用域**\n\n![](../img/C/cookie-domain.jpg)\n\n**设置作用路径**\n\n![](../img/C/cookie-path.jpg)\n\n#### 读取\n\n下面转换 Cookie 至 JavaScript 对象的函数。\n\n```javascript\nfunction getcookie() {\n  var cookie = {};\n  var all = document.cookie;\n  if (all === '') return cookie;\n  var list = all.split('; ');\n  for (var i = 0, len = list.length; i < len; i++) {\n    var item = list[i];\n    var p = item.indexOf('=');\n    var name = item.substring(0, p);\n    name = decodeURIComponent(name);\n    var value = item.substring(p + 1);\n    value = decodeURIComponent(value);\n    cookie[name] = value;\n  }\n  return cookie;\n}\n```\n\n#### 设置与修改\n\n```javascript\ndocument.cookie = 'name=value';\n```\n\n下面为**设置** Cookie 值的封装函数。\n\n```javascript\nfunction setCookie(name, value, expires, path, domain, secure) {\n  var cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value);\n  if (expires)\n    cookie += '; expires=' + expires.toGMTString();\n  if (path)\n    cookie += '; path=' + path;\n  if (domain)\n    cookie += '; domain=' + domain;\n  if (secure)\n    cookie += '; secure=' + secure;\n  document.cookie = cookie;\n}\n```\n\n**下面为**删除** Cookie 值的函数\n\n```javascript\nfunction removeCookie(name, path, domain) {\n  document.cookie = 'name=' + name + '; path=' + path + '; domain=' + domain + '; max-age=0';\n}\n```\n\n#### Cookie 缺陷\n\n- 流量代价\n- 安全性（明文传递）\n- 大小限制\n\n### Storage\n\n因为 Cookie 弊端的存在，所以在 HTML5 中提供了 Storage 的替代方案。\n\n作用域的不同 Storage 分为 Local Storage 和 Session Storage，前者在用户不清理的情况下默认时间为永久，后者默认事件则为浏览器的会话时间（浏览器不同窗口直接不共享 Session Storage）。\n\n![](../img/S/storage-scope.png)\n\n不同浏览器对其实现的不同导致支持大小也不太，通常在 5MB 作用。\n\n#### 对象\n\n**读取**\n\n`localStorage.name`\n\n**添加或修改**\n\n`localStorage.name = 'Value';`\n\n浏览器只支持字符串在 Storage 中的存储。\n\n**删除**\n\n`delete localStorage.name`\n\n#### API\n\n使用 API 操作 Storage 可以进行向下兼容的功能，在不支持的情况下可以用 Cookie 来代替。\n\n- `localStorage.length` 获取键值对数量\n- `localStorage.getItem('name')` 获取对应值\n- `localStorage.key(i)` 对应值的索引获取\n- `localStorage.setItem('name', 'value')` 设置键值对\n- `localStorage.removeItem('name')` 删除一个值\n- `localStorage.clear()` 删除所有数据\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/12_form_manipulation.md",
    "content": "## 表单操作\n\n表单为页面的主要组成部分，其中包含许多的表单控件。用户通过控件提供数据并提交给服务器，服务器则做出相应的处理。而编写一个正常工作的表单需要三个部分：\n\n1. 构建表单\n2. 服务器处理（提供接受数据接口）\n3. 配置表单\n\n**构建表单**\n\n![](../img/F/form_sample_form.png)\n\n```HTML\n<form>\n  <p><label>姓名：<input></label></p>\n  <p><label>电话：<input type=\"tel\"></label></p>\n  <p><label>邮箱：<input type=\"email\"></label></p>\n  <fieldset>\n    <legend> 披萨大小 </legend>\n    <label><input type=\"radio\" name=\"size\"> 小 </label>\n    <label><input type=\"radio\" name=\"size\"> 中 </label>\n    <label><input type=\"radio\" name=\"size\"> 大 </label>\n  </fieldset>\n  <fieldset>\n    <legend> 披萨配料 </legend>\n    <label><input type=\"checkbox\"> 熏肉 </input></label>\n    <label><input type=\"checkbox\"> 奶酪 </input></label>\n    <label><input type=\"checkbox\"> 洋葱 </input></label>\n    <label><input type=\"checkbox\"> 蘑菇 </input></label>\n  </fieldset>\n  <p><label>配送时间：<input type=\"time\" min=\"11:00\" max=\"2100\" step=\"900\"></label></p>\n  <p><button>提交订单</button></p>\n</form>\n```\n\n**服务器处理**\n\n提供接口地址（例如，`https://pizza.example.com/order`，数据格式(`application/x-www-form-urlencoded`)，还是接受的参数信息(custname、custtel、custemail、size、topping、delivery)。\n\n数据命名需在表单控件中注明。\n\n**配置表单**\n\n![](../img/F/form_data_receive.png)\n\n```HTML\n<form action=\"https://pizza.example.com/order\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">\n  <p><label>姓名：<input name=\"custname\"></label></p>\n  <p><label>电话：<input type=\"tel\" name=\"custtel\"></label></p>\n  <p><label>邮箱：<input type=\"email\" name=\"custemail\"></label></p>\n  <fieldset>\n    <legend> 披萨大小 </legend>\n    <label><input type=\"radio\" name=\"size\" value=\"small\"> 小 </label>\n    <label><input type=\"radio\" name=\"size\" value=\"medium\"> 中 </label>\n    <label><input type=\"radio\" name=\"size\" value=\"large\"> 大 </label>\n  </fieldset>\n  <fieldset>\n    <legend> 披萨配料 </legend>\n    <label><input type=\"checkbox\"> 熏肉 </input></label>\n    <label><input type=\"checkbox\"> 奶酪 </input></label>\n    <label><input type=\"checkbox\"> 洋葱 </input></label>\n    <label><input type=\"checkbox\"> 蘑菇 </input></label>\n  </fieldset>\n  <p><label>配送时间：<input type=\"time\" min=\"11:00\" max=\"2100\" step=\"900\"></label></p>\n  <p><button>提交订单</button></p>\n</form>\n```\n\n用户所有提交的信息需在提交服务器前对其进行验证从而提高用户体验。\n\nNOTE：**表单验证** 使用 `require` 来强制用户填写相应的信息。\n\n### 内容\n\n#### 元素\n\n##### form 元素\n\n**form** 元素为构建表单中最重要的元素。\n\n```html\n<form novalidate name=\"pizza\" target=\"abc\" method=\"post\" autocomplete=\"off\" accept-charset=\"utf-8\" action=\"http://pizza.example.com/order\" enctype=\"application/x-www-form-urlencoded\">\n```\n\n其对应的信息则可以视为\n\n| 字段          | 值                                |\n| ------------- | --------------------------------- |\n| noValidate    | true                              |\n| target        | abc                               |\n| method        | post                              |\n| acceptCharset | utf-8                             |\n| action        | http://pizza.example.com/order    |\n| enctype       | application/x-www-form-urlencoded |\n| name          | pizza                             |\n| autocomplete  | off                               |\n\nNOTE：前六项为表单提交相关的信息。\n\n###### 属性\n\n- `name` 属性：可以用于获取表单节点元素。\n\n```javascript\nvar pizzaForm = document.forms.pizza;\n```\n\n- `autocomplete` 属性：有两个值 `on` 与 `off`，在设置为 `on` 时，可以自动对输入框进行补全（之前提交过的输入值，下图左）。\n\n![](../img/F/form-auto-complete.png)\n\nNOTE：在已经设置 `autocomplete=\"off\"` 时依然出现提示框，大多数情况为浏览器设置的自动补全（可以强制关闭，需要时请搜索对应的解决方案）。\n\n- `elements` 属性：为一个**动态节点集合**（更具 DOM 的变化进行变化），其用于归结该表单的子孙表单控件（除图标按钮外 `<input type=\"image>\"`）:\n\n  - button\n  - fieldset\n  - input\n  - keygen\n  - object\n  - output\n  - select\n  - textarea\n\n此外还有归属于该表单的空间（依旧图片按键除外）代码如下所示。\n\n```html\n<form id=\"a\">\n</form>\n<label><input name=\"null\" form=\"a\"></label>\n```\n\n- `length` 属性：等价于 `elements.length` 来用于描述表单内节点集合的个数。\n\n###### 选取表单空间元素\n\n```html\n<form name=\"test\">\n  <input name=\"a\">\n  <input name=\"b\">\n</form>\n```\n\n选取 `name=\"a\"` 的控件可以使用下面的方法：\n\n```javascript\ntestForm.elements[0];\ntestForm.elements['a'];\n\n// 操作 Form 表单的属性\ntestForm[0];\ntestForm['a'];\n```\n\n- `form[name]` 通过名称作为索引时有如下特点：\n\n  - 返回 `id` 或者 `name` 为指定名称的表单空间（图标按键除外）\n  - 如果结果为空，则返回`id` 为指定名称的 `img` 元素（入下面代码所示）\n  - 如果有多个同名元素，则返回的元素为动态节点集合\n  - 一旦用指定名称取过改元素，之后则不论该元素的 `id` 或者 `name` 如何变化，只有节点存在则均可使用**原名称**来继续获取改节点。\n\n*无指定名称索引范例*\n\n```html\n<form name=\"test\">\n  <img id=\"a\" src=\"sample.png\">\n</form>\n```\n\n```javascript\ntestForm['a']; // 取得的便是 id 为 a 的图片元素\n```\n\n*更新名称，依然可以获取节点范例*\n\n```html\n<form name=\"test\">\n  <input name=\"a\">\n</form>\n```\n\n```javascript\n// 第一步\ntestForm['a'];\n// 或者\ntestForm.elements['a'];\n\n// 第二步\ntestForm['a'].name = 'b';\n```\n\n![](../img/F/form_element.png)\n\n###### form 接口\n\n`form` 元素也提供了一些接口便于对其进行操作 `reset()` `submit()` `checkValidity()`。\n\n可以重置（reset）的元素有下面的几种：\n\n- input\n- keygen\n- output\n- select\n- textarea\n\n当触发表单 `reset` 事件时可使用阻止该事件的默认行为来取消重置。而且元素重置时将不会再次触发元素上的 `change` 与 `input` 事件。\n\n![](../img/F/form-reset.png)\n\n##### label 元素\n\n```html\n<label for=\"textId\" form=\"formId\">\n```\n\n| 字段    | 值                     |\n| ------- | ---------------------- |\n| htmlFor | textId                 |\n| control | HTMLElement#textId     |\n| form    | HTMLFormElement#formId |\n\n- `htmlFor` 属性：用于关联表单控件的激活行为（可使点击 `label` 与点击表单控件的行为一致），可关联的元素有下列（`hidden` 除外）：\n\n  - button\n  - input\n  - keygen\n  - meter\n  - output\n  - progress\n  - select\n  - textarea\n\n*自定义文件提交控件样式*\n\n![](../img/F/form_file_upload.png)\n\n- `control` 属性：如果指定了 `for` 属性则指定该`for` 属性对于 `id` 的可关联元素。如果没有指定 `for` 属性则为第一个可关联的子孙元素。\n\n![](../img/F/for_label.png)\n\n**可关联的元素** （只读属性不可在程序中直接赋值修改）\n\n  - button\n  - fieldset\n  - input\n  - keygen\n  - label\n  - object\n  - output\n  - select\n  - textarea\n\n－ `form` 属性：修改关联元素所归属的表单则可以修改元素的 `form` 属性为带关联表单Id（元素中对于的`for`属性也应该做对应的修改）。//这里有一点小问题，更改form属性之后label并不能自动绑定到新表单对应的元素上\n\n```javascript\nlabel.setAttribute('form', 'newFormId');\n```\n\n##### input 元素\n\n```html\n<input type=\"text\">\n```\n\n- `type` 属性：可用于控制控件的*外观*以及*数据类型*（默认为 `text`），在不同的浏览器不同数据类型有不同的展示效果。\n\n*本地图片预览示例*\n\n所需技术点（HTMLInputElement属性）\n\n  - onchange\n  - accept\n  - multiple\n  - files\n\n```html\n<input type=\"file\" accept=\"image/*\" multiple>\n```\n\n```javascript\nfile.addEventListener(\n  'change', function(event){\n      var files = Array.prototype.slice.call(\n        event.target.files, 0\n      );\n      files.forEach(function(item){\n        files2dataurl(item,function(url){\n          var image = new Image();\n          parent.appendChild(image);\n          image.src = url;\n        });\n      });\n  }\n);\nfunction file2dataurl(file, callback) {\n\tif (!window.FileReader) {\n\t\tthrow 'Browser not support File API !';\n\t}\n\tvar reader = new FileReader();\n\treader.readAsDataURL(file);\n\treader.onload = function(event) {\n\t\tcallback(event.target.result);\n\t};\n}\n```\n\nNOTE：`accept` 所支持的格式有 `audio/*` `video/*` `image/*` 以及不带`;`的 MINE Type 类型和 `.` 开头的文件名后缀的文件。多个文件类型可以使用`,`分隔。\n\n##### select 元素\n\n![](../img/F/form_select.png)\n\n指定选项列表中选择需要的选项。\n\n主要的三个子标签 `select`、`optgroup`（用于选项分组）、`option`。\n\n- `select` 具有的属性和方法如下：\n\n  - name\n  - value\n  - multiple\n  - options（动态节点集合）\n  - selectedOptions（动态节点集合）\n  - selectedIndex\n  - add(element[, before])（无指定参照物则添加至最末端）\n  - remove([index])\n\n- `optgroup` 所具有的属性和方法：\n\n  - disabled （分组选项不可选）\n  - label（分组说明）\n\n- `option` 所具有的属性和方法：\n\n  - disabled\n  - label（描述信息）\n  - value（提交表单时的数据信息）\n  - text（用户看到的文字）\n  - index\n  - selected\n  - defaultSelected\n\n###### 选项操作\n\n**创建选项**\n\n```javascript\ndocument.createElement('option')\n// 或者\nnew Option([text[, value[, defaultSelected[, selected]]]])\n```\n\n**添加选项**\n\n```javascript\nvar option = new Option('sample');\nopt.insertAdjacentElement(option, '参照元素');\n// 或者\nselect.add(option, '参照元素')\n```\n\n**删除选项**\n\n```javascript\nopt.parentNode.removeChild(option);\n// 或者使用它的索引将其删除\nselect.remove(2);\n```\n\n###### 级联下列选择器\n\n所需知识点:\n\n- onchange\n- remove\n- add\n\n```html\n<form name=\"course\">\n  <select name=\"chapter\">\n    <option>Select0</option>\n  </select>\n  <select name=\"section\">\n    <option>Select1</option>\n  </select>\n</form>\n```\n\n```javascript\nvar chapters = {\n  {text: 1, value: 1},\n  {text: 2, value: 2}\n};\nvar sections = {\n  1: [{\n    text:1.1, value: 1.1\n  }, {\n    text:1.2, value: 1.2\n  }],\n  2:[{\n    text:2.1, value:2.1;\n  }]\n};\n\nfunction fillSelect(select, list) {\n  for(var i = select.length; i > 0; i--) {\n    select.remove(i);\n  }\n  list.forEach(function(data){\n    var option = new Option(data.text, data.value);\n    select.add(option);\n  })\n}\n\nfileSelect(chapterSelect, chapters);\nchapterSelect.addEventListener(\n  'change', function(event) {\n    var value = event.target.value,\n        list = sections[value] || [];\n    fillSelect(sectionSelect, list);\n  }\n);\n```\n\n##### textarea 元素\n\n`textarea` 具有的属性和方法如下：\n\n- name\n- value （用户输入信息）\n- select() （全选当前输入的内容）\n- selectionStart （选中的内容的起始位置，无选中时返回当前光标所在位置）\n- selectionEnd （选中内容结束位置，无选中时返回光标位置）\n- selectionDirection （选取方向 `forward` `backward`）\n- setSelectionRange(start, end[, direction]) （使用程序选中内容）\n- setRangeText(replacement[, start, end, [mode]]) （设置内容范围）\n\n###### selection\n\n表示选择区域，对于 `input` 元素同样有效。\n\n![](../img/F/form_select_start_and_end.png)\n\n`selectionDirection` 主要是用于在使用 SHIFT 键与方向键组合选取时的选取方向。设置为 `forward` 时选取移动的方向为 `selectionEnd` 设置为 `backward` 时移动方向为 `selectionStart`。\n\n*@输入提示示例*\n\n![](../img/F/form_textarea_at_symble.png)\n\n所需知识点：\n\n- oninput\n- selectionStart\n- setRangeText\n\n```javascript\ntextarea.addEventListener(\n  'input', function(event) {\n    var target = event.target,\n        cursor = target.selectionStart;\n    if(target.value.charAt(cursor-1) === '@') {\n      doShowAtList(functi=on(name){\n        var end = cursor + name.length;\n        target.setRangeText(\n          name, cursor, end, 'end'\n        );\n      });\n    }\n  }\n);\n```\n\n##### 其他元素\n\n- fieldset\n- button\n- keygen\n- output\n- progress\n- meter\n\n![](../img/F/form_supportability.jpg)\n\n#### 验证\n\n可以被验证的元素如下所示：】\n\n- button\n- input\n- select\n- textarea\n\n以下情况不可以做验证\n\n- input 元素在类型是 hidden, reset, button 时\n- button 元素在类型为 reset, button 时\n- input 与 textarea 当属性为 readonly 时\n- 当元素为 datalist 的子孙节点时\n- 当元素被禁用时 disabled 的状态\n\n##### 属性\n\n验证涉及到以下的以下属性，在每一个可以验证的元素上均可以调用对于的属性或通过接口进行操作：\n\n- willValidate （表明此元素在表单提交时是否会被验证）\n- checkValidity() （用于验证元素，返回 true 当验证通过，或者触发 invalid 事件）\n- validity （存储验证结果）\n- validationMessage （显示验证异常信息）\n- setCustomValidity(message) （自定义验证错误信息）\n\n![](../img/F/form_validity.png)\n\n*自定义异常范例*\n\n涉及到的知识点：\n\n- oninvalid\n- setCustomValidity\n\n```html\n<form action=\"./api\" method=\"post\">\n  <label>Name: <input name=\"username\" required></label>\n  <button>submit</button>\n</form>\n```\n\n```javascript\ninput.addEventListener(\n  'invalid', function(event){\n    var target = event.target;\n    if (target.validity.valueMissing) {\n      target.setCustomValidity('Name is missing');\n    }\n  }\n)\n```\n\n*禁止验证范例*\n\n使用 `form` 中 `novalidate` 属性来禁止表单提交的验证。\n\n```html\n<form action=\"./api\" method=\"post\" novalidate>\n  <label>Mobile: <input name=\"mobile\" type=\"number\"></label>\n  <button>submit</button>\n</form>\n```\n\n#### 提交\n\n##### 隐式提交\n\n在操作过程中通过控件的操作来提交表单（敲击回车来提交表单），其需要满足以下的条件：\n- 表单有非禁用的提交按键\n- 没有提交按键时，不超过一个类型为 `text` `search` `url` `email` `password` `date` `time` `number` 的 `input` 元素\n\n##### 提交过程细节\n\n提交过程分为两个阶段，第一个阶段是更具表单 enctype 指定的值构建要提交的数据，第二个阶段是使用指定的方法（method）发送数据到 `action` 指定的目标。\n\n*构建提交数据*，从可提交元素中提取数据组成指定数据结构过程（可提交元素有 `button` `input` `keygen` `object` `select` `textarea`）\n\n*编码方式*（enctype）所支持的形式：\n\n- application/x-www-form-urlencoded （默认，数据格式为 `&` 分隔的键值对）\n- multipart/form-data （IFC 2388 字节流形式，例如文件上传所使用的数据编码形式）\n- text/plain （回车换行符分隔的键值对）\n\n![](../img/F/form_submit_data_type.png)\n\n![](../img/F/form_submit_data_2.png)\n\n![](../img/F/form_submit_data_type1.png)\n\n*特殊案例一*\n\n当一个表单元素 `name=\"isindex\"` 并且 `type=\"text\"` 而且满足如下要求时：\n\n- 编码格式为 application/x-www-form-urlencoded\n- 作为表单的第一个元素\n\n则提交时只发送 value 值，不包含 name。\n\n```html\n<form action=\"./api\" method=\"post\">\n  <input name=\"isindex\">\n  <input name=\"a\">\n  <button>submit</button>\n</form>\n```\n\n![](../img/F/form_special_case.png)\n\n*特殊案例二*\n\n当 `name=\"_charset_\"` 并且类型为 `hidden` 时，而且满足如下要求时：\n\n- 没有设置 `value` 值\n\n则提交时 `value` 自动使用当前提交的字符集填充。\n\n![](../img/F/form_speicla_calse2.png)\n\n###### submit 接口\n\n`form.submit()` 可以通过调用接口`submit()`直接提交表单，在提交表单时均会触发一个 `onsubmit` 表单提交事件，在这个事件中 women 可以做下面的事件：\n\n- 提交前的数据验证\n- 阻止事件的默认行为来取消表单的提交（例如当验证失败时）\n\n```javascript\nform.addEventListener(\n  'submit', function(event) {\n    var notValid = false;\n    var elements = event.target.elements;\n\n    // 自定义验证\n\n    if (notValid) {\n      // 取消提交\n      event.preventDefault();\n    }\n  }\n)\n```\n\n*无刷新表单提交范例*\n\n常用的方式是通过 AJAX 进行实现，这里我们使用 iframe 来做中介代理实现。\n\n![](../img/F/form_ifram_submit_data.png)\n\n所需知识点：\n\n- form\n- target\n- iframe\n\n```html\n<iframe name=\"targetFrame\" class=\"f-hidden\" style=\"display:none\" id=\"result\">\n\n<form action=\"./api\" method=\"post\" target=\"targetFrame\">\n  <input name=\"isindex\">\n  <input name=\"a\">\n  <button>submit</button>\n</form>\n```\n\n```javascript\nvar frame = document.getElementById('result');\nframe.addEventListener(\n  'load', function(event) {\n    try {\n      var result = JSON.parse(\n        frame.contentWindow.document.body.textContent\n      );\n\n      // 还原登陆按钮状态\n      disabledSubmit(false);\n\n      // 识别登陆结果\n      if (result.code === 200) {\n        showMessage('j-suc', 'success');\n        form.reset();\n      }\n    } catch(ex) {\n      // 忽略操作\n    }\n  }\n)\n```\n\n### 表单应用\n\n首先需要知道服务器端登陆接口的相关信息，如下所示：\n\n|描述|数据信息|\n|----|--------|\n|请求地址|/api/login|\n|请求参数|`telephone` 手机号码; `password` 密码 MD5 加密|\n|返回结果|`code` 请求状态; `result` 请求数据结果|\n\n![](../img/F/form_app_code.png)\n\n```javascript\nvar form = document.forms.loginForm;\n\nvar message = document.getElementById('message');\n\n// 通用逻辑封装\nfunction showMessage(class, message) {\n  if(!class) {\n    message.innerHTML = \"\";\n    message.classList.remove('j-suc');\n    message.classList.remove('j-err');\n  } else {\n    message.innerHTML = message;\n    message.classList.add(class);\n  }\n}\n\nfunction invalidInput (node, message) {\n  showMessage('j-err', message);\n  node.classList.add('j-err');\n  node.focus();\n}\n\nfunction clearInvalid(node){\n  showMessage();\n  node.classList.remove('j-err');\n}\n\nfunction disabledSubmit(disabled) {\n  form.loginBtn.disabled = !!disabled;\n  var method = !disabled ? 'remove' : 'add';\n  form.loginBtn.classList[method]('j-disabled');\n}\n\n// 验证手机号码（系统自带方法）\nform.telephone.addEventListener(\n  'invalid', function(event) {\n    event.preventDefault();\n    invalidInput(form.telephone, 'invalid mobile number');\n  }\n);\n\n// 验证密码\nform.addEventListener(\n  'submit', function(event) {\n    var input = form.password;\n    var password = input.value;\n    errorMessage = '';\n    if (password.length < 6) {\n      errorMessage = 'password less than 6 char';\n    } else if (!/\\d./test(password) || !/[a-z]/i.test(password)) {\n      errorMessage = 'password must contains number and letter'\n    }\n\n    if (!!errorMessage) {\n      event.preventDefault();\n      invalidInput(input, errorMessage);\n      return;\n    }\n    // 提交表单代码\n    // ...\n  }\n);\n\n// 提交表单\nform.addEventListener(\n  'submit', function(event){\n    input.value = md5(password);\n    disabledSubmit(true);\n  }\n);\n\n// 状态恢复\nform.addEventListener(\n  'focus', function(event) {\n    // 错误还原\n    clearInvalid(event.target);\n    // 还原登陆按钮状态\n    disabledSubmit(false);\n  }\n)\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter3/13_list_manipulation.md",
    "content": "## 列表操作\n\n![](../img/L/list_format.png)\n\n列表的常用形式有图片形式与信息形式的，常见的有如下的操作：\n\n- 显示列表\n- 选择列表项\n- 新增列表项\n- 删除列表项\n- 更新列表项\n\n### 范例代码\n\n**数据结构**\n\n![](../img/L/list_data_structure.png)\n\n```javascript\n[\n  {\n    \"id\": 22341234,\n    \"name\": \"Good Song\",\n    \"album\": {\n      \"id\": 213512,\n      \"name\": \"Good Album\"\n    },\n    \"artist\":{\n      \"id\": 1234512,\n      \"name\": \"Evil Artist\"\n    }\n  }\n]\n```\n\n**显示列表**\n\n*列表容器*\n\n![](../img/L/list_container.png)\n\n*列表模板* 分离数据和视图\n\n![](../img/L/list_template.png)\n\n**绘制列表**\n\n*准备数据并整合模板与数据*\n\n![](../img/L/list_render.png)\n\n*通过 AJAX 获取数据*\n\n![](../img/L/list_ajax_get_data.png)\n\n*列表单选操作*\n\n![](../img/L/list_single_selection.png)\n\n*列表多选操作（Control 与 Shift 操作）*\n\n```javascript\nparent.addEventListener(\n  'mouseup', function(event) {\n    var target = getTarget(event),\n        selected = isSelected(target);\n    // right click\n    if (event.button == 2&&selected) {\n      return;\n    }\n    // with control click\n    if (event.ctrlKey) {\n      !selected?appendToSelection(target):removeFromSelection(target);\n    }\n    // with shift key\n    if (event.shiftKey) {\n      var list = Array.prototype.slice.call(\n        parent.getElementsByTagName('li'), 0\n      );\n      if (!last) {\n        last = getLastElection() || target;\n      }\n      selectWithRangeFromTo(list, last, target);\n    } else {\n      last = null;\n    }\n  }\n);\n```\n\n*右键菜单*\n\n`contextmenu` 事件为右键菜单弹出事件。\n\n![](../img/L/list_right_click.png)\n\n![](../img/L/list_right_click_details.png)\n\n*增加列表*\n\n![](../img/L/list_add_item.png)\n\n![](../img/L/list_add_item_using_template.png)\n\n*删除列表*\n\n![](../img/L/list_item_remove.png)\n\n*更新列表*\n\n![](../img/L/list_update.png)\n\n*更新状态*\n\n![](../img/L/list_update_state.png)\n\n### 编程方式\n\n**面向视图** 的操作方式，即为针对视图的直接编程（对 DOM 树进行直接的操作）。\n\n![](../img/L/list_view_oriented.png)\n\n![](../img/L/list_view_oriented_1.png)\n\n这样的方式代理了许多的弊端，例如无法进行完全的自动化测试以及极高的视图层和控制层耦合的紧密性。\n\n**面向数据** 的操作方式，视图则被抽象为若干的数据以及状态（后续所有的操作都会更加数据模型而操作），从而做到视图模型层完全自动化的测试。\n\n![](../img/L/list_viewmodel_1.png)\n\n![](../img/L/list_viewmodel_2.png)\n\n![](../img/L/list_viewmodel_3.png)\n\n![](../img/L/list_viewmodel_4.png)\n\n![](../img/L/list_viewmodel_5.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter4/00_intro.md",
    "content": "# 页面架构\n\n页面架构从实际需求出发，提供多种需求的多种解决方案和优缺点，\n各种页面优化方案以及如何为团队或产品制定规范等，\n帮助你完成产品的页面架构，进一步提升前端页面技术。\n\n本章包括布局解决方案、响应式、页面优化、规范与模块化等。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter4/01_CSS_Reset.md",
    "content": "## CSS Reset\n\n所有的 HTML 标签在**没有设置**样式时均被浏览器默认的样式列表所装饰\n（不同浏览器默认样式有所**不同**）。**CSS** 的样式重置就是清楚浏览器的默认样式\n，可以理解为**对于全局的样式定义**。\n对于开发者来言，如不重置每一个浏览器特定的默认样式，则会在开发造成诸多的不便。\n\n> 在前端开发过程中做加法，远远比做减法简单。将所有浏览器的默认样式统一，\n> 可以使它们有一个相同起点。\n>\n> — Li Xinyang 资深前端工程师\n\nNOTE：一份 CSS Reset 文件并不一定适用于所有场景，需要更具需求做出变通\n（需符合产品需求为主）。\n\nNOTE+：浏览器对于控件的样式和功能的特性支持也可以重置\n（例如日历，清楚输入框内容按键等）。\n\nNOTE++：Reset 文件需比页面其他样式文件的引入顺序优先（优先级需最高）。\n\n#### 样式重置前后对比\n\n**样式重置前**\n\n![](../img/C/css-reset-before.png)\n\n**样式重置后**\n\n![](../img/C/css-reset-after.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter4/02_layout.md",
    "content": "# 布局解决方案\n了解 CSS 中属性的值及其特性， 透彻分析问题和需求才可以选择和设计最适合的布局解决方案。\n\n## 居中布局\n\n### 水平居中\n![](../img/L/layout-center-horizontal.png)\n\n子元素于父元素水平居中且其（子元素与父元素）宽度均可变。\n\n#### inline-block + text-align\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .child {\n    display: inline-block;\n  }\n  .parent {\n    text-align: center;\n  }\n</style>\n```\n\n**优点**\n- 兼容性佳（甚至可以兼容 IE 6 和 IE 7）\n\n#### table + margin\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .child {\n    display: table;\n    margin: 0 auto;\n  }\n</style>\n```\n\nNOTE: `display: table` 在表现上类似 `block` 元素，但是宽度为内容宽。\n\n**优点**\n- 无需设置父元素样式 （支持 IE 8 及其以上版本）\n\nNOTE：兼容 IE 8 一下版本需要调整为 `<table>` 的结果\n\n#### absolute + transform\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    position: relative;\n  }\n  .child {\n    position: absolute;\n    left: 50%;\n    transform: translateX(-50%);\n  }\n</style>\n```\n\n**优点**\n- 绝对定位脱离文档流，不会对后续元素的布局造成影响。\n\n**缺点**\n- `transform` 为 CSS3 属性，有兼容性问题\n\n#### flex + justify-content\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    display: flex;\n    justify-content: center;\n  }\n\n  /* 或者下面的方法，可以达到一样的效果 */\n\n  .parent {\n    display: flex;\n  }\n  .child {\n    margin: 0 auto;\n  }\n</style>\n```\n\n**优点**\n- 只需设置父节点属性，无需设置子元素\n\n**缺点**\n- 有兼容性问题\n\n### 垂直居中\n![](../img/L/layout-center-vertical.png)\n\n子元素于父元素垂直居中且其（子元素与父元素）高度均可变。\n\n#### table-cell + vertical-align\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    display: table-cell;\n    vertical-align: middle;\n  }\n</style>\n```\n\n**优点**\n- 兼容性好（支持 IE 8，以下版本需要调整页面结构至 `table`）\n\n#### absolute + transform\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    position: relative;\n  }\n  .child {\n    position: absolute;\n    top: 50%;\n    transform: translateY(-50%);\n  }\n</style>\n```\n\n**优点**\n- 绝对定位脱离文档流，不会对后续元素的布局造成影响。但如果绝对定位元素是唯一的元素则父元素也会失去高度。\n\n**缺点**\n- `transform` 为 CSS3 属性，有兼容性问题\n\n#### flex + align-items\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    display: flex;\n    align-items: center;\n  }\n</style>\n```\n\n**优点**\n- 只需设置父节点属性，无需设置子元素\n\n**缺点**\n- 有兼容性问题\n\n### 水平与垂直居中\n\n![](../img/L/layout-center-center.png)\n\n子元素于父元素**垂直及水平**居中且其（子元素与父元素）高度宽度均可变。\n\n#### inline-block + text-align + table-cell + vertical-align\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    text-align: center;\n    display: table-cell;\n    vertical-align: middle;\n  }\n  .child {\n    display: inline-block;\n  }\n</style>\n```\n\n**优点**\n- 兼容性好\n\n#### absolute + transform\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    position: relative;\n  }\n  .child {\n    position: absolute;\n    left: 50%;\n    top: 50%;\n    transform: translate(-50%, -50%);\n  }\n</style>\n```\n\n**优点**\n- 绝对定位脱离文档流，不会对后续元素的布局造成影响。\n\n**缺点**\n- `transform` 为 CSS3 属性，有兼容性问题\n\n#### flex + justify-content + align-items\n\n```html\n<div class=\"parent\">\n  <div class=\"child\">Demo</div>\n</div>\n\n<style>\n  .parent {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n  }\n</style>\n```\n\n**优点**\n- 只需设置父节点属性，无需设置子元素\n\n**缺点**\n- 有兼容性问题\n\n## 多列布局\n多列布局在网页中非常常见（例如两列布局），多列布局可以是两列定宽，一列自适应， 或者多列不定宽一列自适应还有等分布局等。\n\n### 一列定宽，一列自适应\n\n![](../img/L/layout-multicolumn-0.jpg)\n\n#### float + margin\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .left {\n    float: left;\n    width: 100px;\n  }\n  .right {\n    margin-left: 100px\n    /*间距可再加入 margin-left */\n  }\n</style>\n```\n\nNOTE：IE 6 中会有3像素的 BUG，解决方法可以在 `.left`\n加入 `margin-left:-3px`。\n\n#### float + margin + (fix) 改造版\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right-fix\">\n    <div class=\"right\">\n      <p>right</p>\n      <p>right</p>\n    </div>\n  </div>\n</div>\n\n<style>\n  .left {\n    float: left;\n    width: 100px;\n  }\n  .right-fix {\n    float: right;\n    width: 100%;\n    margin-left: -100px;\n  }\n  .right {\n    margin-left: 100px\n    /*间距可再加入 margin-left */\n  }\n</style>\n```\n\nNOTE：此方法不会存在 IE 6 中3像素的 BUG，但 `.left` 不可选择，\n需要设置 `.left {position: relative}` 来提高层级。\n此方法可以适用于多版本浏览器（包括 IE6）。缺点是多余的 HTML 文本结构。\n\n#### float + overflow\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .left {\n    float: left;\n    width: 100px;\n  }\n  .right {\n    overflow: hidden;\n  }\n</style>\n```\n\n设置 `overflow: hidden` 会触发\nBFC 模式（Block Formatting Context）块级格式化文本。\nBFC 中的内容**与外界的元素是隔离的**。\n\n**优点**\n\n- 样式简单\n\n**缺点**\n\n- 不支持 IE 6\n\n#### table\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .parent {\n    display: table;\n    width: 100%;\n    table-layout: fixed;\n  }\n  .left {\n    display: table-cell;\n    width: 100px;\n  }\n  .right {\n    display: table-cell;\n    /*宽度为剩余宽度*/\n  }\n</style>\n```\n\n`table` 的显示特性为每列的单元格宽度合**一定**等与表格宽度。\n`table-layout: fixed;` 可加速渲染，也是设定布局优先。\n\nNOTE：`table-cell` 中不可以设置 `margin` 但是可以通过 `padding` 来设置间距。\n\n#### flex\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .parent {\n    display: flex;\n  }\n  .left {\n    width: 100px;\n    margin-left: 20px;\n  }\n  .right {\n    flex: 1;\n    /*等价于*/\n    /*flex: 1 1 0;*/\n  }\n</style>\n```\n\nNOTE：`flex-item` 默认为内容宽度。\n\n**缺点**\n\n- 低版本浏览器兼容问题\n- 性能问题，只适合小范围布局。\n\n### 两列定宽，一列自适应\n\n![](../img/L/layout-multicolumn-1.png)\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"center\">\n    <p>center<p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .left, .center {\n    float: left;\n    width: 100px;\n    margin-right: 20px;\n  }\n  .right {\n    overflow: hidden;\n    /*等价于*/\n    /*flex: 1 1 0;*/\n  }\n</style>\n```\n\n多列定宽的实现可以更具单列定宽的例子进行修改与实现。\n\n\n### 一列不定宽加一列自适应\n\n![](../img/L/layout-multicolumn-2.png)\n\n不定宽的宽度为内容决定，下面为可以实现此效果的方法：\n\n- `float` + `overflow`，此方法在 IE6 中有兼容性问题\n- `table`，此方法在 IE6 中有兼容性问题\n- `flex`，此方法在 IE9及其以下版本中有兼容性问题\n\n### 多列不定宽加一列自适应\n\n![](../img/L/layout-multicolumn-1.png)\n\n其解决方案同*一列不定宽加一列自适应*相仿。\n\n### 多列等分布局\n\n![](../img/L/layout-multicolumn-4.png)\n\n每一列的宽度和间距均相等，下面为多列等分布局的布局特定。\n\n![](../img/L/layout-multicolumn-5.png)\n\n父容器宽度为 C，`C = W * N + G * N - G` => `C + G = (W + G) * N`。\n\n![](../img/L/layout-multicolumn-6.png)\n\n#### float\n\n![](../img/L/layout-multicolumn-7.png)\n\n```html\n<div class=\"parent\">\n  <div class=\"column\">\n    <p>1</p>\n  </div>\n  <div class=\"column\">\n    <p>2</p>\n  </div>\n  <div class=\"column\">\n    <p>3</p>\n  </div>\n  <div class=\"column\">\n    <p>4</p>\n  </div>\n</div>\n<style media=\"screen\">\n  .parent {\n    margin-left: -20px;\n  }\n  .column {\n    float: left;\n    width: 25%;\n    padding-left: 20px;\n    box-sizing: border-box;\n  }\n</style>\n```\n\nNOTE：此方法可以完美兼容 IE8 以上版本。\nNOTE+：此方法结构和样式具有耦合性。\n\n#### table\n\n```html\n<div class='parent-fix'>\n  <div class=\"parent\">\n    <div class=\"column\">\n      <p>1</p>\n    </div>\n    <div class=\"column\">\n      <p>2</p>\n    </div>\n    <div class=\"column\">\n      <p>3</p>\n    </div>\n    <div class=\"column\">\n      <p>4</p>\n    </div>\n  </div>\n</div>\n\n<style media=\"screen\">\n  .parent-fix {\n    margin-left: -20px;\n  }\n  .parent {\n    display: table;\n    width: 100%;\n    /*可以布局优先，也可以单元格宽度平分在没有设置的情况下*/\n    table-layout: fixed;\n  }\n  .column {\n    display: table-cell;\n    padding-left: 20px;\n  }\n</style>\n```\n\nNOTE：缺点是多了文本结果\n\n#### flex\n\n```html\n<div class=\"parent\">\n  <div class=\"column\">\n    <p>1</p>\n  </div>\n  <div class=\"column\">\n    <p>2</p>\n  </div>\n  <div class=\"column\">\n    <p>3</p>\n  </div>\n  <div class=\"column\">\n    <p>4</p>\n  </div>\n</div>\n\n\n<style media=\"screen\">\n  .parent {\n    display: flex;\n  }\n  .column {\n    /*等价于 flex: 1 1 0;*/\n    flex: 1;\n  }\n  .column+.column {\n    margin-left: 20px;\n  }\n</style>\n```\n\nNOTE：`flex` 的特性为分配剩余空间。\nNOTE+：兼容性有问题。\n\n###\n\n![](../img/L/layout-multicolumn-8.png)\n\n#### table\n\n`table` 的特性为每列等宽，每行等高可以用于解决此需求。\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .parent {\n    display: table;\n    width: 100%;\n    table-layout: fixed;\n  }\n  .left {\n    display: table-cell;\n    width: 100px;\n  }\n  .right {\n    display: table-cell;\n    /*宽度为剩余宽度*/\n  }\n</style>\n```\n\n#### flex\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .parent {\n    display: flex;\n  }\n  .left {\n    width: 100px;\n    margin-left: 20px;\n  }\n  .right {\n    flex: 1;\n    /*等价于*/\n    /*flex: 1 1 0;*/\n  }\n</style>\n```\n\nNOTE：flex 默认的 `align-items` 的值为 `stretch`。\n\n#### float\n\n```html\n<div class=\"parent\">\n  <div class=\"left\">\n    <p>left</p>\n  </div>\n  <div class=\"right\">\n    <p>right</p>\n    <p>right</p>\n  </div>\n</div>\n\n<style>\n  .parent {\n    overflow: hidden;\n  }\n  .left,\n  .right {\n    padding-bottom: 9999px;\n    margin-bottom: -9999px;\n  }\n  .left {\n    float: left;\n    width: 100px;\n    margin-right: 20px;\n  }\n  .right {\n    overflow: hidden;\n  }\n</style>\n```\n\nNOTE：此方法为伪等高（只有背景显示高度相等），左右真实的高度其实不相等。\nNOTE+：此方法兼容性较好。\n\n## 全屏布局\n\n![](../img/L/layout-full-screen.png)\n\n例如管理系统，监控与统计平台均广泛的使用全屏布局。\n\n### 定宽需求\n\n![](../img/L/layout-full-0.jpg)\n\n**实现方案**\n\n- Position 常规方案\n- Flex CSS3 新实现\n\n#### Position\n\n```html\n<div class=\"parent\">\n  <div class=\"top\"></div>\n  <div class=\"left\"></div>\n  <div class=\"right\">\n    /*辅助结构用于滚动*/\n    <div class=\"inner\"></div>\n  </div>\n  <div class=\"bottom\"></div>\n</div>\n<style>\n  html,\n  body,\n  .parent {\n    height: 100%;\n    /*用于隐藏滚动条*/\n    overflo: hidden;\n  }\n  .top {\n    /*相对于 body 定位*/\n    position: absolute;\n    top: 0;\n    left: 0;\n    right: 0;\n    height: 100px;\n  }\n  .left {\n    position: absolute;\n    left: 0;\n    top: 100px;\n    bottom: 50px;\n    width: 200px;\n  }\n  .right {\n    position: absolute;\n    left: 200px;\n    right: 0;\n    top: 100px;\n    bottom: 50px;\n    overflow: auto;\n  }\n  .right .inner {\n    /*此样式为演示所有*/\n    min-height: 1000px;\n  }\n  .bottom {\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    height: 50px;\n  }\n</style>\n```\n\n##### Position 兼容\n\n此方法不支持 IE6 可以使用下面的方法解决兼容问题。\n\n```html\n<div class=\"g-hd\"></div>\n<div class=\"g-sd\"></div>\n<div class=\"g-mn\"></div>\n<div class=\"g-ft\"></div>\n<style>\n  html,\n  body {\n    width: 100%;\n    height: 100%;\n    overflow: hidden;\n    margin: 0;\n  }\n\n  html {\n    _height: auto;\n    _padding: 100px 0 50px;\n  }\n\n  .g-hd,\n  .g-sd,\n  .g-mn,\n  .g-ft {\n    position: absolute;\n    left: 0;\n  }\n\n  .g-hd,\n  .g-ft {\n    width: 100%;\n  }\n\n  .g-sd,\n  .g-mn {\n    top: 100px;\n    bottom: 50px;\n    _height: 100%;\n    overflow: auto;\n  }\n\n  .g-hd {\n    top: 0;\n    height: 100px;\n  }\n\n  .g-sd {\n    width: 300px;\n  }\n\n  .g-mn {\n    _position: relative;\n    left: 300px;\n    right: 0;\n    _top: 0;\n    _left: 0;\n    _margin-left: 300px;\n  }\n\n  .g-ft {\n    bottom: 0;\n    height: 50px;\n  }\n</style>\n```\n\n\n#### Flex\n\n```html\n<div class=\"parent\">\n  <div class=\"top\"></div>\n  <div class=\"middle\">\n    <div class=\"left\"></div>\n    <div class=\"right\">\n      <div class=\"inner\"></div>\n    </div>\n  </div>\n  <div class=\"bottom\"></div>\n</div>\n<style media=\"screen\">\n  html,\n  body,\n  parent {\n    height: 100%;\n    overflow: hidden;\n  }\n\n  .parent {\n    display: flex;\n    flex-direction: column;\n  }\n\n  .top {\n    height: 100px;\n  }\n\n  .bottom {\n    height: 50px;\n  }\n\n  .middle {\n    // 居中自适应\n    flex: 1;\n    display: flex;\n    /*flex-direction: row 为默认值*/\n  }\n\n  .left {\n    width: 200px;\n  }\n\n  .right {\n    flex: 1;\n    overflow: auto;\n  }\n  .right .inner {\n    min-height: 1000px;\n  }\n</style>\n```\n\n##### Flex 兼容性\n\nCSS3 中的新概念所有 IE9 及其也行版本都不兼容。\n\n### 百分比宽度需求\n\n![](../img/L/layout-full-percentage.jpg)\n\n只需把定宽高（`px` 为单位的值）的实现改成百分比（%）既可。\n\n### 内容自适应\n\n![](../img/L/layout-content-response.jpg)\n\n只有右侧栏占据剩余位置，其余空间均需根据内容改变。\n所以 Postion 的定位方法不适合实现此方案。下面列出了两种布局方案：\n\n- Flex\n- Grid，W3C 草案并不稳定，浏览器支持也并不理想\n\n#### Flex\n\n只有不为宽高做出限制，既可对其中的内容做出自适应的布局。\n\n```html\n<div class=\"parent\">\n  <div class=\"top\"></div>\n  <div class=\"middle\">\n    <div class=\"left\"></div>\n    <div class=\"right\">\n      <div class=\"inner\"></div>\n    </div>\n  </div>\n  <div class=\"bottom\"></div>\n</div>\n\n<style media=\"screen\">\n  html,\n  body,\n  parent {\n    height: 100%;\n    overflow: hidden;\n  }\n\n  .parent {\n    display: flex;\n    flex-direction: column;\n  }\n\n  .middle {\n    // 居中自适应\n    flex: 1;\n    display: flex;\n    /*flex-direction: row 为默认值*/\n  }\n\n  .right {\n    flex: 1;\n    overflow: auto;\n  }\n  .right .inner {\n    min-height: 1000px;\n  }\n</style>\n```\n\n### 方案比较\n\n|方案|兼容性|性能|自适应|\n|---|-----|----|-----|\n|Position|好|好|部分自适应|\n|Flex|较差|差|可自适应|\n|Grid|差|较好|可自适应|\n"
  },
  {
    "path": "03-FEND_Note-master/chapter4/03_responsive.md",
    "content": "## 响应式布局\n\n多屏的环境让我们不得不考虑网络内容在各个尺寸中的表现，\n均可正常访问和极佳的用户体验。\n\n响应式布局可以更具屏幕尺子的大小对内容和布局做出适当的调成，\n从而提供更好的用户感受。也是因为响应式布局的出现，\n开发者也无需对不同尺寸设备而特殊定制不同的页面，\n这大大降低了开发成本和缩短了开发时间。\n\n\n这样的方法也同样存在着缺点。\n缺点是同样的资源被加载，但因为展示平台所限并不能全部显示。\n\n**View Port**\n\n![](../img/R/responsive_viewport.jpg)\n\n```html\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n```\n\n**针对不同尺寸的屏幕进行开发，因少使用定宽而使用自适应单位。**\n\n![](../img/R/responsive_design0.jpg)\n\n**需求会更具具体设备而产生变化。**（例如布局方式发生了变化）\n\n```html\n@media screen and (max-width: 320px) {\n  /* 视窗宽度小于等于 320px */\n}\n@media screen and (min-width: 320px) {\n  /* 视窗宽度大于等于 320px */\n}\n@media screen and (min-width: 320px) and (max-width: 1000px){\n  /* 视窗宽度大于等于 320px 且小于等于 1000px */\n}\n```\n"
  },
  {
    "path": "03-FEND_Note-master/chapter4/04_page_optimisation.md",
    "content": "## 页面优化\n\n页面优化可以提升页面的访问速度从而提高用户体验，优化的页面可以更好的提升 SEO 的效果同时也可以提高代码的可读性和维护性。\n\n从下面的几个方面可以进行页面的优化：\n\n- 减少请求数\n  - 图片合并\n  - CSS 文件合并\n  - 减少内联样式\n  - 避免在 CSS 中使用 import\n- 减少文件大小\n  - 选择适合的图片格式\n  - 图片压缩\n  - CSS 值缩写（Shorthand Property)\n  - 文件压缩\n- 页面性能\n  - 调整文件加载顺序\n  - 减少标签数量\n  - 调整选择器长度\n  - 尽量使用 CSS 制作显示表现\n- 增强代码可读性与可维护性\n  - 规范化\n  - 语义化\n  - 模块化\n\n**减少请求**\n\n请求数与网页加载时长有直接的关系。所以对于图标可以使用 Sprite 来减少小图标的请求数，对于文本则可以通过合并缩小。（避免使用 import 引入 CSS 文件，并且请求是同步请求）\n\n**减少文件大小**\n\n页面上最大的流量产生与多媒体（视频或图片）所以为了减少文件大小，开发者需要使用合适的媒体格式并对文件进行压缩。\n\n**页面性能**\n\n页面文件的加载顺序自上而下，样式则需要放置于最顶部，脚本则放置于底部（因为 JavaScript 的加载会阻塞页面的绘制）。\n\n减少标签的数量也可以起到提升性能的作用，缩短 CSS 选择器的层级来提高性能。减少使用消耗性能的样式属性例如下面的这些：\n\n- expression `.class{width: expression(this.width > 100?'100px':'auto')}`\n- filter `.class{filter:alpha(opacity=50)}`\n- border-radius\n- box-shadow\n- gradients\n\n页面中所使用的图片尺子应该与现实尺寸相符否则在图标下载后需要重绘导致性能下降。\n\n能使用样式（使用 CSS 的类名）实现的交互就不使用脚本（需要重绘导致多次页面渲染）来实现。\n\n**可读性与可维护性**\n\n开发之前需要明确规范，尤其是对人协作时。使用 HTML5 语义化的标签来制作页面，同样也适用于样式选择器的 ID 与类名。在使用开发中的奇技淫巧的适合需要深思是否需要使用。模块化的制作页面和样式，提高可复用性并减少文件大小。\n\n注释注释注释，在代码中添加注释，利人利己。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter4/05_modulation.md",
    "content": "## 页面模块化\n\n### 规范\n\n在具体谈论规范的之前，可以下去查看下各大网络公司的前端开发规范（Developemnt Style Guide）例如谷歌，Facebook 或者 Dropbox。从而更好的理解开发规范在实际应用中和多人协作中的重要性。\n\n不同开发者在开发过程中使用不同的代码风格会直接的提升在之后的开发和维护的成本和难度，对前端开发来说更是尤为突出。这时使用代码规范来约束开发者的编码风格就可以大体解决这些问题。规范的制订应从下面的几个方面来开始考虑：\n\n- 文件规范\n- 注释规范\n- 命名规范\n- 书写规范\n- 其他规范\n\n**文件规范**\n\n文件规范又可以从三个方面入手，分类，引入，以及文本本身的内容。\n\n- 分类（分类可分为*通用类*和*业务类*。通用类有第三方的库，团队开发的通用模块或者通用样式。业务类则有不同业务所对应的特定模块。）\n\n- 引入\n  - CSS （引入文件则需尽少的使用行内样式）\n  - JavaScript （文件名的约束，以及编码设置通常使用 `utf-9`）\n\n**注释规范**\n\n注释可使用块状，单行注释和行内注释，需要统一缩进等细节要求。\n\n**命名规范**\n\n例如 CSS 选择器的命名规范\n\n- 分类命名 （例如 `g-header` 来给布局类的样式设置命名空间来防止*样式污染*，`m-header` 来制定模块类的样式）\n- 命名格式 （大小写的规定，建议使用小写并使用 `-` 分隔，也许控制选择器的长度避免过长的样式选择器名称但不可失去选择器语义）\n- 语义化命名 （以内容的语义来给选择器命名）\n\n**书写规范**\n\n这里使用 CSS 的书写规范来做示例，可以参考下面的约束：\n\n- 单行与多行（单行与多行的 CSS 书写格式，使用多行！）\n- 空格与分号（使用空格进行缩进并保留最后一个属性的分号）\n- 书写顺序（更具显示的重要性来安排可参照下表）\n- Hack 方式（三思而后行）\n- 值格式（例如颜色值的格式以及引用中是否使用引号）\n\n![](../img/M/module_page_style_order.png)\n\n**其他规范**\n\n这里包括有 HTML 以及图片的规范：\n\n- HTML\n  - 文档声明\n  - 闭合\n  - 属性\n  - 层级\n  - 注释\n  - 大小写\n- 图片\n  - 文件名称（语言以及长度的规范）\n  - 保留源文件\n  - 图片合并\n\n### 模块化\n\n模块化是一系列相关的结果组成的整体，这部分具备独立存在的意义不单纯只是表现。\n\n在开发模块化是需要注意的一些步骤（以 CSS 模块化为例）：\n\n- 为模块分类命名（`m-module-name`）\n- 以一个主选择器作为开头（模块跟节点）\n- 使用以主选择器开头的后代选择器（模块子节点）\n\n![](../img/M/module_css_class_extend.jpg)\n\n![](../img/M/module-css-name-module.jpg)\n\n模块化可以利于多人开发，便于扩展，当然也可以提高代码的可读性与可维护性。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter5/00_intro.md",
    "content": "# 产品前端架构\n\n专注于引导前端工程师去主导团队高效协作，去引领团队规范化、工程化构建复杂系统的实践过程。\n\n本章节的核心内容包括多角色低耦合的协作流程、协作规范、\n多角度分析选择适合具体项目的技术解决方案、工程化的版本管理、系统构建案例分析。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter5/01_collaboration.md",
    "content": "## 协作流程\n\n### Web 系统\n\n![](../img/W/websevice.png)\n\nWeb 系统部署在服务器上为提出不同需求的外部客户端服务。\n\n**MVC** (Model, View, Controller) 它们分别代表**数据层**，**视图层**，\n和**控制层**。\n\n![](../img/M/MVC.png)\n\n- 数据层，封装数据管理操作（例如数据的 CRUD ）\n- 视图层，展示数据模型提供人机交互\n- 控制层，处理用户请求，委托数据层，选择视图层进行展示\n\nNOTE：CRUD 代表 Create、Read、Update、Delete。\n\n\n下面以用户请求页面为例：\n\n![](../img/M/MVC_Process.png)\n\n1. 客户端发送请求，服务器**控制层**接受到请求\n1. 请求**数据层**获取数据，返回**控制层**\n1. **控制层**根据数据选择合适的**视图层**进行展示\n1. **视图层**生成页面代码，返回**控制层**\n1. **控制层**返回客户端进行展示\n\n#### 技术栈全览\n\n![](../img/M/mvc-before.png)\n\n- Photoshop，获取图片资源\n- CSS 与 HTML，制作页面\n- JavaScript 前端交互逻辑\n- Template 结构与内容分离整合\n- Java/PHP/Node 后端逻辑\n\n**弊端**\n\n- 后期维护性差（相同内容，不同形成存在）\n- 专业化程度低\n- 需求响应速度慢\n\n**前端工程师新责任**\n\n![](../img/M/mvc-after.png)\n\n随着视图层也会存在业务逻辑的需求，前端工程师也会参与到业务逻辑的实现中去。\n这样使前端工程师可以在后期转换成**全栈工程师**（Fullstack Developer)。\n\n### 角色定义\n\n完成一个 Web 系统需要至少以下三种角色：\n\n- 视觉工程师，视觉稿到交互原型的转化\n- 前端工程师，实现系统前端交互逻辑\n- 后端工程师，系统后端业务逻辑\n\n#### 前端工程师\n\n![](../img/F/frontend-developer.png)\n\n前端部分又可再细分为**页面工程师**和前端工程师**。前者更注重和视觉工程师的协作，\n后者则更多的与后端工程师进行协作。\n\n**页面工程师**\n\n- 精通切图技术 （Photoshop，Sketch）\n- 精通页面制作 （CSS，HTML）\n- 熟悉前端开发技术 （JavaScript，Template）\n- 了解后端开发技术 （Java，Node）\n\n**前端工程师**\n\n- 精通页面制作 （CSS，HTML）\n- 精通前端开发技术 （JavaScript，Template）\n- 熟悉切图技术 （Photoshop，Sketch）\n- 熟悉后端开发技术 （Java，Node）\n\n##### 项目工时分配比\n\n![](../img/T/tasks-assign.png)\n\n- 页面制作：3天\n- 前端逻辑：7天\n- 后端逻辑：10天\n\nNOTE：多角色开发会比单人工程增加工作沟通成本。\n\n### 协作流程\n\n#### 开发过程\n\n![](../img/C/collaboration-process.png)\n\n按照流程规范可以明确角色和其对应的职责，这样可以大大减少角色间的沟通成本。\n\n- 页面入口规范，定义系统对外可访问入口和配置信息\n- 同步数据规范，定义系统对模板文件的预填信息\n- 异步接口规范，定义前后端接口信息\n\n#### 维护过程\n\n![](../img/C/collaboration-mataince.png)\n\nNOTE：红色路径为不需要改变规范的前提下，响应需求变更。\n\n### 职责说明\n\n下面将总结各个角色职责具体任务：\n\n**页面工程师**\n\n- 切图、图片优化\n- 页面制作、优化页面效果与结构（适合业务逻辑开发）\n- 完成简单的前端业务逻辑开发\n\n**前端工程师**\n\n- 主导制定前后端分离规范\n- 主导前端联调对接测试\n- 系统前端设计架构、满足一定的非功能性需求\n- 完成系统前端的业务逻辑实现、优化实现逻辑\n\n**后端工程师**\n\n- 协助定制前后端分离规范\n- 协作前后端联调对接测试\n- 完成后端系统框架及业务逻辑实现\n\n角色与人之间不一定需要一一对应，前端工程师和页面工程师可能是一人。\n全栈工程师则有能力包揽一切。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter5/02_design_api.md",
    "content": "## 接口设计\n\n![](../img/A/api_design_overview.png)\n\n用户使用 Web 客户端访问 Web 系统，系统在收到请求后执行操作\n（收集数据模型，选择数据经行组装），将结果返回给客户。\n\n其中包括的元素和关系如下图所示：\n\n![](../img/A/api_elements.png)\n\n- Template，分离数据模型的页面结构，根据不同的数据模型展现不同的信息\n- URL，页面访问地址、页面标示\n- API，用于载入异步请求的接口\n- Model，数据模型，页面模板组装模型和异步请求返回的数据模型\n\n**约定**\n\n![](../img/A/api_rule.png)\n\n1. URL 与页面模板间的映射，和异步载入内容对应的接口\n1. 视图模板和数据模型的对应（数据模型的格式和类型）\n1. 异步接口输入输出信息的约定\n\n![](../img/A/api_rule_detail.png)\n\n1. 页面入口规范，定义系统对外可访问入口和配置信息（URL、模板、接口）\n1. 同步数据规范，定义系统对模板文件的预填信息（模板、数据模型）\n1. 异步接口规范，定义前后端接口信息（接口、数据模型）\n\n### 接口规范\n\n每个规范也会对应若干规定若干规则约定来指导前后端工程师的具体实施。\n\n#### 页面入口规范\n\n![](../img/A/api_page_entry.png)\n\n- 基本信息\n- 输入参数\n- 模板列表\n- 接口列表（异步载入数据接口）\n\n**页面入口规范（范例）**\n\n|条目|详情|\n|----|----|\n|访问地址|`/dj/{id}`|\n|页面描述|节目详情及推荐信息|\n|输入参数|名称：ID；类型：Number；描述：节目标示|\n|异常跳转|异常：500；跳转地址：`/500/`|\n|模板列表|默认：`/template/dj/dj.ftl`|\n||过期：`/template/dj/over.ftl`|\n||未找到：`/template/dj/404.ftl`|\n|接口列表|歌曲列表：`/api/dj/tracks/{id}/`|\n||相关节目：`/api/dj/rec/{id}/`|\n||收藏节目：`/api/dj/fav/{id}/`|\n||评论节目：`/api/comments/{id}`|\n\n- 页面基本信息，描述页面的主要功能\n- 输入参数为访问地址时支持的参数说明\n- 异常跳转，为系统全局异常处理\n- 模板列表，列举当前页面的相关模板，包括异常（如下图）\n- 页面需要的所有异步接口列表\n\n![](../img/T/template_normal_error.jpg)\n\n#### 同步数据规范\n\n![](../img/A/api_data_sync.png)\n\n- 基本信息\n- 预填数据\n- 注入接口\n\n**同步数据规范（范例）**\n\n|条目|详情|\n|----|----|\n|模板文件|`/templates/dj/dj.ftl`|\n|模板描述|节目详情及推荐信息模板文件|\n|预填信息|`{\"名称\":\"user\", \"类型\":\"User\",\"描述\":\"登陆用户信息\"}`|\n||`{\"名称\":\"dj\", \"类型\":\"Program\",\"描述\":\"节目信息\"}`|\n||`{\"名称\":\"other\", \"类型\":\"String\",\"描述\":\"其他信息\"}`|\n|注入接口|jd.parser|\n||`{\"输入\":[[\"String\", \"节目信息\"], [\"Boolean\", \"是否格式化\"]]}`|\n||`{\"输出\":[\"Program\", \"节目对象\"]}`|\n||dj.api|\n||dj.api2|\n\n- 模板的基本信息\n- 预填数据包括全局和页面数据及其类型\n- 注入的接口说明（输入输出信息），没有可以不填写\n\n#### 异步接口数据规范\n\n![](../img/A/api_async.png)\n\n- 基本信息\n- 输入信息\n- 输出信息\n\n**异步接口规范（范例）**\n\n|条目|详情|\n|----|----|\n|请求方式|`GET` `POST`|\n|接口地址|`api/dj/tracks/{id}/`|\n|接口描述|获取指定节目的歌曲列表|\n|输入数据|`{\"名称\":\"id\", \"类型\":\"Number\",\"描述\":\"节目标示\"}`|\n||`{\"名称\":\"offset\", \"类型\":\"Number\",\"描述\":\"节目起始位置\"}`|\n||`{\"名称\":\"limit\", \"类型\":\"Number\",\"描述\":\"列表数量\"}`|\n|输出结果|`{\"名称\":\" code\", \"类型\":\"Number\",\"描述\":\"请求结果标示\"}`|\n||`{\"名称\":\"message\", \"类型\":\"String\",\"描述\":\"请求异常信息\"}`|\n||`{\"名称\":\"result\", \"类型\":\"Array\",\"描述\":\"歌曲列表\"}`|\n\n- 接口基本信息，地址不带查询参数\n- 输入数据，REST，查询数据（必须包含名称类型及描述）\n- 输出结果，通用部分及结果集（复杂的信息需展开说明）\n\n### 规范的应用\n\n通过**模拟数据**的形成，将前端本地开发与后端独立出来，\n这样前端工程师就可以独立的进行本地的开发工作。\n\n![](../img/A/api-rule-apply.jpg)\n\n使用页面入口规范制定项目结构（配置信息，目录结构和模板结构），\n此过程可以使用自动化工具自动完成。\n\n![](../img/A/api-rule-apply-1.jpg)\n\n根据同步数据规范可生成模拟数据的配置文件。（此部分通用可以使用自动化工具来完成）\n\n![](../img/A/api-apply-2.jpg)\n\n根据异步接口规范生成模拟异步数据。\n\n### 本地开发\n\n![](../img/L/local-development.jpg)\n\n前端开发环境包含两个部分，**本地模拟服务器**和**本地代理**。\n\n1. 客户端发送的请求，会被本地模拟服务器拦截并返回相应的模拟数据\n1. 客户端发送的异步请求，会被本地代理拦截并返回对应的模拟数据\n\n**Local Server**\n\n![](../img/L/local-server-working.jpg)\n\n根据请求规则进行匹配，然后生成（整合模板和模拟数据）所请求的页面\n\n**Local Proxy**\n\n![](../img/L/local-proxy-working.jpg)\n\n拦截异步请求后，根据请求的匹配规则返回所请求的数据（例如 JSON 或 XML）。\n\n#### 联调\n\n![](../img/L/local-and-remote.png)\n\n前后端联调需要去除本地环境，在实际开发中只需要对配置文件进行调整既可\n（控制哪些请求需要被本地服务器或代理拦截，哪些需要使用远程服务器）。\n"
  },
  {
    "path": "03-FEND_Note-master/chapter5/03_version_control.md",
    "content": "## 版本控制\n\n版本管理涉及团队协作，产品质量，和产品上线。使用版本控制工具可使我们自由的做的一些几点：\n\n- 回退到任意版本\n- 查看历史版本\n- 对比两个版本差异\n\n\n### 版本控制系统\n\n版本控制系统（Version Control System）是一种记录若干文件修订记录的系统，它可以帮助开发者查阅或回档至某个历史版本。\n\n- 手动版本控制\n- LVCS 本地\n- CVCS 集中式（例如 SVN）\n- DVCS 分布式（例如 Git）\n\n**手动版本控制**\n\n![](../img/V/vc-manual.png)\n\n无法有效找到需要版本和差异，污染工作目录结构。\n\n**Local VCS 本地式**\n\n![](../img/V/vc-vcs.png)\n\n于是出现了本地版本控制系统 RCS（Reversion Control System），其利用本地版本数据库存储不断出现的文件版本。\n它可以迅速找出需求的版本和维持工作目录结构。其缺点是不支持协同开发，这也让开发者不将其选做通用的版本控制工具来使用。\n\n**CVCS 集中式**\n\n![](../img/V/vc-svn.png)\n\n利用中央服务器来管理文件版本，但每一次操作都需要网络请求，且具有致命的单点故障。\n（既中央服务器故障可导致，无法协同工作或数据丢失）\n\n**DVCS 分布式**\n\n![](../img/V/vc-git.png)\n\n分布式指的是每一份本地仓库都是一个完整的项目历史拷贝，即使一份仓库丢失或者损坏也可以从其他的仓库中获取此项目的完整历史记录。\n也因为在添加新版本不需要网络，这可以使操作流程。\n\n### 分支模型\n\n如果多人并行在一条线上开发会导致开发困难并且难以定位错误位置。\n\n![](../img/V/vc-git-branch.png)\n\n分支，就是从目标仓库获得一份项目拷贝，每条分支都具有和原仓库功能一样的开发线。\n\n分支模型（Branching Model）或称之为工作流（Workflow），它是一个围绕项目\n**开发**、**部署**、**测试**等工作流的分支操作（创建及合并等）的规范集合。\n\n#### 产品级开发分支模型\n\n**常驻分支**\n\n- development，从 master 创建\n- production（master），默认分支可用于发布的代码\n\n**活动分支**\n\n- feature，从 development，创建其为特性分支\n- hotfix，从 master 创建，用于修复 Bug\n- release，从 development 创建\n\n![](../img/V/vc-production.png)\n\n#### 环境\n\n![](../img/V/vs-environment.jpg)\n\n- 开发环境，使用测试开发配置（数据库，缓存，元数据配置）\n  - 使用提交到下一个 release 的特性分支\n- 测试环境，使用测试配置（测试数据库）\n  - 使用 release/development\n- 预发布环境，小范围发布使用线上数据库模拟真实环境\n  - 使用 release\n- 生产环境，线上配置\n  - 使用 master\n\n### Git\n\nGit 是一个免费开源的分布式版本控制系统，它也一个基于内容寻址的存储系统。\nGit 是由 Linux 的创造者 Linus Torvalds。\n\n**优势**\n\n- 速度快，不依赖网络\n- 完全分布式\n- 轻量级分支操作\n- Git 为行业标准版本控制供给\n- 活跃和成熟的社区\n\n**安装**\n\n**Mac OS X** 下使用 `brew install git` 下载更新既可。\n\n**Linux Ubuntu** 下可使用 `apt-get install git` 既可。\n\n### Git 介绍\n\n#### Git 命令\n\n常用 Git 命令，当在命令行中键入 `git` 可以便可以在帮助信息中看到。\n\n![](../img/G/git_command.png)\n\n**获取帮助**\n\n`git help <command>` `git <command> -h` `git <command> --help` 还有\n`man git-<command>` 均可查询某个命令的帮助文档。\n\n**基本操作**\n\n配置 Git 使用 `git config` 此为创建 Git 仓库前必须完成的配置。\n\n```bash\ngit config --global user.name \"Li Xinyang\"\ngit config --global user.email \"lixinyang1026@gmail.com\"\n```\n\n- --local 默认 具有最高优先级 只影响本仓库 `.git/config`\n- --global 中级优先级 影响到所有当前用户的仓库 `~/.gitconfig`\n- --system 最低优先级 影响到全系统的仓库 `/etc/gitconfig`\n\n**初始化仓库**\n\n![](../img/G/git-init.png)\n\n初始化仓库，使用 `git status` 可以查询当前仓库的状态。\n如在*未初始化*仓库时查询状态会报出错误信息。\n\n```bash\ngit init [path]\ngit init [path] --bare\n```\n\n在初始化仓库后会出现一个隐藏的目录 `.git`\n其中包括了所有的当前仓库的版本信息和本地设置文件(`.git/config`)。\n\n![](../img/G/git-after-init.png)\n\n**查询状态**\n\n`git status` 此命令可以帮助开发者在下面三对关系中找出文件状态的变化。\n\n- 未跟踪   <--> 跟踪\n- 工作目录 <--> 暂存区\n- 暂存区   <--> 最新提交\n\n![](../img/G/git-status-kind.jpg)\n\nGit 中存在两种状态**内容状态**和**文件状态**。\n仓库中的文件均可以在状态和区域之间进行转换。\n\n![](../img/G/git-first-file.png)\n\n**添加文件到暂存区（同时跟踪文件）**\n\n`git add [file]`\n\n![](../img/G/git-add-file.png)\n\n上图所示，我们将 `README.md` 文件从工作区提交至暂存区，\n并将文件状态从未跟踪改变成已跟踪。\n\n![](../img/G/git-first-step.jpg)\n\nNOTE：批量增加当前目录下全部文件 `git add .`\n\n![](../img/G/git-add-multiple.png)\n\n**忽略文件**\n\n`.gitignore` 可以在添加至仓库时忽略匹配的文件，但仅作用于*未跟踪*的文件。\n\n![](../img/G/git-sample-gitignore.png)\n\nNOTE：GitHub 为各个类型项目和操作系统提供了忽略文件模板，\n可以在[这里](https://github.com/github/gitignore)找到。\n\n**暂存区删除文件**\n\n使用 `git rm` 可以做到从暂存区删除文件，下面提供几种常用的使用方法：\n\n- `git rm --cached` 仅存暂存区删除\n- `git rm` 才暂存区和工作区目录中删除\n- `git rm $(git ls-files --deleted)` 删除所有被跟踪但在工作区已经被删除的文件\n\nNOTE：`git-ls-files`\n- Show information about files in the index and the working tree\n\n**工作区与暂存区**\n\n不同的区域中可以存在文件的独立版本，如下图所示工作区和暂存区的文件为两个不同的版本。\n（之前上个例子中所创建的 `DummyFile` 文件已被删除）\n\n![](../img/G/git-file-multiple-version.png)\n\n**暂存区**\n\n我们可以把暂存区比作一个每类物品只能放置一次的购物车此外还具有下面的特质：\n\n- 货架和购物车可同时出现同种物品\n- 货架上的物品可以替换掉购物车的物品\n- 可以删除物品\n- 提交购物车完成购买并生成购买记录\n\n其中\n\n- 物品：文件\n- 货架：工作目录\n- 购物车：暂存区\n- 购买：提交内容\n\n**提交版本记录**\n\n![](../img/G/git-commit.png)\n\n`git commit` 可以根据暂存区的内容创建一个提交目录。\n\n![](../img/G/git-first-commit.png)\n\nNOTE：直接提交工作区的内容`git commit -a -m 'message'`，工作中不建议这样操作。\n\n**查询提交历史记录**\n\n`git log` 可以用来显示提交是记录信息。\n\n![](../img/G/git-log.png)\n\n其中包括：\n\n- 提交编号 SHA-1 编码的 HASH 标示符\n- git-config 配置的提交者信息\n- 提交日期\n- 提交描述信息\n\n工作中可使用下面简单的配置进行版本查询\n\n```bash\ngit log --oneline\n\n# 较长的命令可以使用 alias 的方法简化\ngit log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit\n```\n\n**Git 中 alias 命令设置**\n\n配置 Git 中别名的方法 `git config alias.shortname <fullcommand>`。\n\n```bash\ngit config --global alias.lg \"log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit\"\n\ngit lg\n```\n\nNOTE：如果你使用 Mac OS X 可以尝试使用 [Oh My Zsh](http://ohmyz.sh)\n其中已经预先设置好了非常多常用别名。\n\n**显示版本差异**\n\n![](../img/G/git-diff-terminal.png)\n\n`git diff` 用于显示版本差异，下面是几个常用的方法：\n\n- `git diff` 显示工作目录与暂存区的差异\n- `git diff -cached [<reference>]` 暂存区与某次提交的差异（默认为 HEAD）\n- `git diff <reference>` 工作目录和某次提交间的差异\n- `git diff <reference> <reference>` 查询两次提交直接的差别\n\n![](../img/G/git-diff-overview.png)\n\n**撤销工作区的修改**\n\n![](../img/G/git-checkout-file.jpg)\n\n`git checkout -- <file>...` 可用于撤销工作区的修改\n（此方法会丢弃工作区修改且**不可恢复**），下面是一些常用方法：\n\n- `git checkout -- <file>` 将文件从暂存区复制到工作目录\n\n![](../img/G/git-checkout-file-terminal.png)\n\nNOTE：使用 `--` 是为了避免路径和引用（或提交 ID）同名发生的冲突。\n\n**撤销暂存区内容**\n\n![](../img/G/git-reset-head.jpg)\n\n使用 `git reset HEAD <file>...` 可用于撤销暂存区的修改，下面是一些常用操作：\n\n- `git reset HEAD <file>` 将文件内容存上次提交复制到暂存区。\n\n![](../img/G/git-reset-head-terminal.png)\n\n**撤销全部修改**\n\n![](../img/G/git-reset-everything.png)\n\n`git checkout HEAD -- <file>` 可以直接将内容从上次的提交复制到工作区。\n\n![](../img/G/git-reset-everything-terminal.png)\n\n**命令总结**\n\n![](../img/G/git-command-overview.jpg)\n\n#### 分支操作\n\n**git branch**\n\n使用 `git branch` 可以对仓库分支进行增删查改的操作，下面列举了一下常用的操作方式：\n\n- `git branch <branchname>`，创建指定分支\n- `git branch -d <branchname>`，删除指定分支\n- `git branch -v`，显示所有分支信息\n\n> 一份分支的引用只是一个文本文件，里面只有一个 SHA 编码。它保存于 `.get/refs/heads/master` 中。\n>\n> —— 郑海波 网易工程师\n\n```bash\ngit branch next\n```\n\n![](../img/G/git-brnach-next.png)\n\n```bash\ngit commit -m 'message'\n```\n\n![](../img/G/git-commit-after-next.png)\n\n**切换至目标分支**\n\n`git checkout` 它可以本枝上根据通过移动 HEAD（指向当前的提交） 检测出版本，\n也可用于切换分支。（其会把当前的工作目录和暂存区移动到提出分支的版本）\n常用命令有：\n\n- `git checkout <branchname>`，使指针指向目标分支\n- `git checkout -b <branchname>`，创建目标分支并切换分支\n- `git checkout <reference>`，可以指向任何一个版本\n\n```bash\ngit checkout next\n```\n\n![](../img/G/git-checkout-next-head.png)\n\nNOTE：所有提交是更具 HEAD 向前进的，所以前后分支后则会跟着 Next 分支进行开发。\n\n```bash\ngit commit -m 'message'\n```\n\n![](../img/G/git-next-first-commit.png)\n\n```bash\n# -- 为短名与 cd 类似\ngit checkout --\n\n# 或者使用\n# git checkout master\n```\n\n![](../img/G/git-next-back-master.png)\n\n```bash\ngit checkout -b Issue-26\n```\n\n![](../img/G/git-new-b-branch.png)\n\nNOTE：使用 `git branch -v` 可以列出全部分支，带 `*`\n表示当前所属分支（HEAD 指向分支）。\n\n```bash\ngit checkout c4006ec\n```\n\n![](../img/G/git-checkout-reference.png)\n\n当 HEAD 指针与具体的分支分离时，我们将其称之为 `detached head`。\n如果 HEAD 在分离状态则因尽量避免在此状态下进行提交，只做内容的查看。\n\n![](../img/G/git-checkout-reference-view.png)\n\n**完全回退**\n\n![](../img/G/git-reset-current.jpg)\n\n使用`git reset`可以将当前分支回退到历史中的某个版本，\n下面为常用的三种方式（三种的区别是恢复的内容时候同时会恢复的工作区或暂存区）：\n\n- `git reset --mixed <commit>` 默认方式，内容存入暂存区\n- `git reset --soft <commit>` 内容存入暂存区和工作区\n- `git reset --hard <commit>` 暂存区和工作区保留现有状态\n\n```bash\ngit reset --mixed e390b3\n```\n\n![](../img/G/git-reset-mixed.jpg)\n\n**如果上一个命令如果使用 hard**\n\n```bash\ngit reset --hard e390b3\n```\n\n![](../img/G/git-reset-hard.jpg)\n\n**如果上一个命令如果使用 hard**\n\n```bash\nget reset --soft e390b3\n```\n\n![](../img/G/git-reset-soft.jpg)\n\n此方法暂存区和工作目录不会发生任何变化仅仅只是 HEAD 指针发生了变化，\n但原有的提交已经无指针指向成为无索引的提交其就有可能被回收。\n\n**查询所有提交记录**\n\n`git reflog` 会根据仓库的提交顺序按顺序来排列，其中包括无索引的提交，\n可以在这里使用 HASH 值来进行，但是无索引的提交可能会丢失。\n\n**使用捷径**\n\n`A^` 表示 `A`上的父提交，多个 `^` 可表示以上的多个级别。\n`A~n` 则表示在 `A` 之前的第 n 次提交。\n\n![](../img/G/git-move-head.jpg)\n\n##### reset 与 checkout 区别\n\n两种方法都有两个作用范围，一个是分支操作（commit 操作），\n另一个是文件操作（file 操作）。\n\n|命令|范例|移动 HEAD/Branch |注释|\n|----|----|-----------------|----|\n|`git reset [commit]`|`git reset HEAD^ --soft`|是/是|完全回退到某个提交（之前所在的位置将失去索）|\n|`git reset [file]`|`git reset README.md`|否/否|恢复**暂存区**到某个提交状态（不移动指针）|\n|`git checkout [commit]`|`git checkout master`|是/否|移动当前指针 HEAD 到某个提交（并复制内容到工作目录）|\n|`git checkout [file]`|`git checkout -- README.md` `git checkout HEAD -- xx.log`|否/否|恢复**工作目录**到某个状态|\n\n##### stash 的作用\n\n```bash\ngit checkout next\n\n# error: Your local change to the following files whould be overwritten by checkout:\n#       README.md\n# Please, commit your changes or stash them before you can switch branches.\n# Aborting...\n```\n\n突然需要切换到其他分支，工作区和暂存区还有在当前分支没完成的任务。那么 `stash` 就使用 `.git` 中的特殊区（Stash 区）来帮你解决这个问题（因为强切回丢失当前的工作区和暂存区的内容）。\n\n![](../img/G/git-stash-overview.png)\n\n![](../img/G/git-stash-terminal.png)\n\n`stash` 可以把当前工作区和暂存区的状态以栈（Stack）的形式保存起来（每次保存都会推一个内容到 `stash` 栈中），并返回一个干净的工作空间（工作区和暂存区）。\n\nNOTE：`stash pop = stash apply + stash drop` 类似于 JavaScript 中的 `pop` 操作。\n\nNOTE+：什么是栈？可以把栈想象成一摞盘子堆（一个叠一个）。具体关于堆栈的信息可以在[这里](https://zh.wikipedia.org/zh-sg/堆栈)找到。如果还看不懂，建议完成哈佛大学在线计算机入门课程 `CS50`，可以在[这里](http://open.163.com/movie/2010/3/U/R/M6U6LS8CV_M6U6MHDUR.html)找到。\n\n##### merge\n\n![](../img/G/git-merge-overview.jpg)\n\n使用 `git merge` 可用于合并分支。下面的例子是将 `next` 分支合并到 `master` 分支中去。\n\n![](../img/G/git-merge-detail.jpg)\n\n![](../img/G/git-merge-detail-after.jpg)\n\n![](../img/G/git-merge-detail-terminal.png)\n\n###### 解决 merge 冲突\n\n当一个文件被同时修改时（更多情况为同时修改相同的一行代码时）则极有可能产生合并冲突。\n\n```bash\ngit merge next master\n# Autom-merging README.md\n# CONFLICT (content): Merge confilict in README.md\n# Automatic merge failed; fix confilict and then commit the result\n\ngit status\n# On branch master\n# You have unmerged paths.\n#   (fix confilict and run 'git commit')\n# ...\n#   both:modified: README.md\n# no changes added to commit (use \"git add\" and/or \"git commit -a\")\n```\n\n![](../img/G/git-merge-conflic-code-sample.png)\n\n在解决完合并冲突后可以使用 `git add .` 然后 `git commit -m 'resove merge confilict'` 来完成合并冲突解决并提交一个新的版本。\n\nNOTE：`git cat-file -p HEAD` 可用于显示 `git` 中某个对象的具体信息。\nNOTE+：`<<<<<<<< HEAD` 与 `=========` 之间为 HEAD 所在的内容。\n\n###### merge fast-forward\n\n也并不是所有的合并操作都会造成合并从图（merge confilic)。最简单的一种合并是 `fast-forward` 仅仅只是变化 HEAD 指向的位置（**不产生**新的合并节点）。\n\n![](../img/G/git-fast-forward0.png)\n\n如果需要生成新的合并节点可以使用 `git merge next --no-ff` 意思是合并但不使用 `fast-forward`。\n\n![](../img/G/git-fast-forward-no-ff.jpg)\n\n###### merge 不足\n\n![](../img/G/git-merge-bad.jpg)\n\n当参与的人阅读分支越多其分支结构就越复杂和难以被理解。如何实现在任何状态下的**线性提交**？\n\n如需完成线性提交可以使用 `git rebase`，其可以修剪提交历史的基线。它会将不同分支的提交在**所选节点**上进行**重演**（重演并重新创造新节点）这里 HEAD/Branch 均会发生移动。\n\n```bash\ngit rebase master\n```\n\n![](../img/G/git-rebase-0.jpg)\n\n但有时并不需要将其他分支上的全部提交节点统统进行重演。则可以使用 `git rebase --onto` 来选择需要重演的提交节点。\n\n```bash\ngit rebase --onto master 5751363\n```\n\n![](../img/G/git-rebase-onto.jpg)\n\nNOTE：上面的红色的节点，未被重建（被丢弃）。\n\n###### rebase 与 merge 区别\n\n![](../img/G/git-mergerebase.png)\n\n`rebase` 会产生线性的提交历史，`merge` 则会产生多个不同分支的合并节点。所以具体没有好坏之分，可根据使用的需求来决定。\n\n注意！不要在共有分支上使用 `rebase`（例如 `master` 分支）这会导致其他开发者在进行拉取（Pull）时，必须进行合并且合并中包含重复的提交。\n\n##### tag\n\n不论是 Branch 还是 HEAD 它们均为动态指针，如果想定义一个静止的标示则可以使用 `git tag` ，它将给发布的**提交版本**设置一个别名。在设置了标签后就可以直接使用标签名来代替它所指代的版本提交了。\n\n```bash\ngit tag v0.1 e39d9b2\n\ngit checkout v0.1\n```\n\n![](../img/G/git-tag.jpg)\n\n#### 远程操作\n\n远程操作可以将本地仓库推送至远程仓库服务器。**Git** 支持许多主流的通信协议，其中包括 `Local`、`HTTP`、`SSH`、还有`Git`。服务器只应该是作为同步之用（被动接受既可）。\n\n**初始化一个本地的远程服务器**\n\n```bash\ngit init ~/git-server --bare\n```\n\n![](../img/G/git-local-server.png)\n\n**推送**\n\n`git push` 可以将当期的全部版本提交提交推送至远程仓库，其完成了提交历史的完全不复制并同时移动复制版本的 HEAD 与 Branch。\n\n![](../img/G/git-push.png)\n\n**添加远程仓库别名**\n\n`git remote` 可用于添加远程仓库的别名。\n\n![](../img/G/git-remote.png)\n\n```bash\n# 更改仓库 url 地址\ngit remote set-url origin 'https://github.com/li-xinyang/FEND_Note.git'\n```\n\n**远程 push 冲突**\n\n可以先使用 `git fetch` + `git merge` 来解决冲突的问题。`git pull` 就等同于 `fetch` 与 `merge` 的合并。\n\n**克隆远程仓库**\n\n使用 `git clone` 可以克隆远程仓库，并将克隆地址默认设为 `origin`。\n\n![](../img/G/git-clone.png)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter5/04_tech_selection.md",
    "content": "## 技术选择\n\n### 模块化\n\nNOTE：以下讨论都是基于 JavaScript 的模块组织（每个模块均以文件形式组织），而非工程的模块化。\n\n> The secret to building large app is never build arge apps. Break your applications into small pieces. Then, assemble those testable, bite-sized pieces into your big application.\n>\n> Justin Meyer\n\n**其他语言中的模块支持**\n\n- Java - `import`\n- C#   - `using`\n- css  - `@import`\n\n但在 JavaScript 中并不存在模块组织在并不支持，于是产生了很多，模块系统。\n\n**模块的职责**\n\n- 封装实现（将复杂的内容于外界个例）\n- 暴露接口（外部可通过接口使用模块）\n- 声明依赖（提供给模块系统使用）\n\n#### 模块的使用\n\n##### 反模式（Anti-Pattern）\n\n反模式既没有使用任何设计模式。\n\nmath.js\n\n```javascript\nfunction add(a, b) {\n  return a + b;\n}\nfunction sub(a, b) {\n  return a - b;\n}\n```\n\n上面的代码有下面的几个缺点：\n\n- 无封装性\n- 接口结构不明显\n\ncalculator.js\n\n```javascript\nvar action = 'add';\nfunction compute(a, b) {\n  switch (action) {\n    case 'add': return add(a, b);\n    case 'sub': return sub(a, b);\n  }\n}\n```\n\n上面的代码也有几个缺点：\n\n- 没有依赖声明\n- 使用全局状态\n\n##### 字面量（Object Literal）\n\nmath.js\n\n```javascript\nvar math = {\n  add: function(a, b) {\n    return a + b;\n  },\n  sub: function(a, b) {\n    return a - b;\n  }\n};\n```\n\n结构性好，但没有访问控制。\n\ncalculator.js\n\n```javascript\nvar calculator = {\n  action: 'add',\n  compute: function(a, b) {\n    switch (action) {\n      case 'add': return add(a, b);\n      case 'sub': return sub(a, b);\n    }\n  }\n}\n```\n\n同样没有依赖声明\n\n#####  IIFE（Immediately-invoked Function Expresion)\n\n其为自执行函数。\n\n**版本一**\n\ncalculator.js\n\n```javascript\nvar calculator = (function(){\n  var action = 'add';\n  return {\n    compute: function(a, b) {\n      switch (action) {\n        case 'add': return add(a, b);\n        case 'sub': return sub(a, b);\n      }\n    }\n  }\n})();\n```\n\n上面的代码可以进行访问控制，但是不能进行依赖声明。\n\n**版本二**\n\ncalculator.js\n\n```javascript\nvar calculator = (function(m){\n  var action = 'add';\n  function compute(a, b) {\n    switch (action) {\n      case 'add': return m.add(a, b);\n      case 'sub': return m.sub(a, b);\n    }\n  }\n  return {\n    compute: compute;\n  }\n})(math)\n```\n\n上面的代码虽然可以显示的声明依赖，但是仍然污染了全局变量，而且必须手动进行依赖管理。\n\n#### 命名空间（Namespace）\n\n命运空间可以解决全局变量的污染的问题。\n\nmath.js\n\n```javascript\nnamespace('math', [], function(){\n  function add(a, b) { return a + b; }\n  function sub(a, b) { return a - b; }\n  return {\n    add: add,\n    sub: sub\n  }\n})\n```\n\ncalculator.js\n\n```javascript\n//                     依赖声明        依赖注入\n//                         |               |\nnamespace('calculator', ['math'], function(m){\n  var action = 'add';\n  function compute(a,b) {\n    return m[action](a, b);\n  }\n  return {\n    compute: compute;\n  }\n})\n```\n\n#### 模块管理\n\n复杂的模块管理，不能单纯的通过代码文件的排列顺序来进行管理。于是引入了模块系统，它有下面的职责：\n\n- 依赖管理（加载、分析、注入、初始化—）\n- 决定模块的写法\n\n常用的模块系统有 `Common.JS`、`AMD`、语言基本的模块化。\n\n##### CommonJS\n\nCommonJS 是一个模块规范，通常适用于非浏览器环境（NodeJS）。\n\n> A module spec for JavaScript outside the browser.\n\nmath.js\n\n```javascript\nfunction add(a, b) {\n  return a + b;\n}\nfunction sub(a, b) {\n  return a - b;\n}\nexports.add = add;\nexports.sub = sub;\n```\n\ncalculator.js\n\n```javascript\n// 依赖声明\nvar math = require('./math');\n\nfunction Calculator(container) {\n  // ...\n}\nCalculator.prototype.compute = function(){\n  this.result.textContent = math.add(...);\n}\n\n// 接口暴露\nexports.Calculator = Calculator;\n```\n\n**优点**\n\n- 依赖管理成熟可靠\n- 社区活跃且规范接受度高\n- 运行时支持且模块化定义简单\n- 文件级别的模块作用域隔离\n- 可以处理循环依赖\n\n**缺点**\n\n- 不是标准组织规范\n- 同步请求未考虑浏览器环境（可以使用 Browserify 来解决）\n\n```bash\n# browserify 为 npm 下命令行工具\n# > 为 Linux/Unix 添加至命令\nbrowserify file0.js > file1.js;\n```\n\n打包后的文件如下所示。\n\n```javascript\n(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n\n},{}]},{},[1]);\n```\n\n##### AMD（Asynchronous Module Definition）\n\n适合异步环境的依赖管理方案。\n\nmath.js\n\n```javascript\n//   依赖列表\n//      |\ndefine([], function(){\n  function add(a, b) { return a + b; }\n  function sub(a, b) { return a - b; }\n// 接口暴露\n  return {\n    add: add,\n    sub: sub\n  }\n})\n```\n\ncalculator.js\n\n```javascript\ndefine(['./math'], function(math){\n  function Calculator(container) {\n    // ...\n  }\n  Calculator.prototype.compute = function(){\n    this.result.textContent = math.add(...);\n  };\n\n  // 暴露接口\n  return {\n    Calculator: Calculator;\n  }\n})\n```\n\n**优点**\n\n- 依赖管理成熟可靠\n- 社区活跃且规范接受度高\n- 转为异步环境制作，适合浏览器\n- 支持 CommonJS 的书写方式\n- 通过插件 API 可以加载非 JavaScript 资源\n- 成熟的打包构建工具，并可结合插件一同使用\n\n**缺点**\n\n- 模块定义繁琐，需要额外嵌套\n- 酷基本的支持，需要引入额外的库\n- 无法处理循环依赖\n- 无法实现条件加载\n\n###### Simplified CommonJS Wrapping\n\n使用同样的 CommonJS 的依赖管理书写方法，之后在使用正则表达式来提取依赖列表。\n\n```javascript\ndefine(function(require, exports){\n  // 依赖声明\n  var math = require('./math');\n\n  function Calculator(container) {\n    // ...\n  }\n  Calculator.prototype.compute = function(){\n    this.result.textContent = math.add(...);\n  }\n\n  // 接口暴露\n  exports.Calculator = Calculator;\n})\n```\n\n##### Loader Plugins\n\n允许调用处理脚本外的其他资源（例如 HTML 与 CSS 文件），这样就可以形成一个完整的组件。\n\n```\n完整组件 = 结构 + 逻辑 + 样式\n```\n\n##### ECMAScript 6 Module\n\nECMAScript 6 中的模块化管理。\n\nmath.js\n\n```javascript\nfunction add(a, b) {\n  return a + b;\n}\nfunction sub(a, b) {\n  return a- b;\n}\n// export 关键字暴漏接口\nexport {add, sub}\n```\n\ncalculator.js\n\n```javascript\nimport {add} from './math';\n\n\nclass Calculator {\n  constructor(container) {}\n  compute(){\n    this.result.textContent = add(+this.left.value, +this.right.value);\n  }\n}\nexport{Calculator}\n```\n\n**优点**\n\n- 真正的规范未来标准\n- 语言基本支持\n- 适用于所有的 JavaScript 允许环境\n- 可用于处理循环依赖\n\n**缺点**\n\n- 规范未达到稳定级别\n- 暂无浏览器支持\n\n#### SystemJS\n\nSystemJS 是一个动态模块加载器，下面是它的一下特性：\n\n- 支持加载 AMD\n- 支持加载 CommonJS\n- 支持加载 ES6\n- 支持加载 Transpiler 也可支持任意类型资源\n\n#### 模块管理的对比\n\n- IIFE，没有解决核心的依赖分析和注入的问题。\n- AMD，可以直接使用，库基本的支持。\n- CommonJS，可以直接使用，在运行时的支持。\n- ES6，语言本身的支持。\n\n使用插件工具，可以将后三种模块管理系统进行相互转换。\n\n### 框架\n\nNOTE：以下讨论都是基于 JavaScript 的框架。\n\n\n#### 库（Library）与框架（Framework）的区别\n\n![](../img/T/tech_lib_and_frame.png)\n\n**库** 为针对特定问题的解答具有专业性，不控制应用的流程且被动调用。**框架** 具有*控制翻转*，决定应用的生命周期，于是便集成了大量的库。\n\n#### 解决方案\n\n常见的解决方案针对的方面：\n\n- DOM\n- Communication\n- Utility\n- Templating\n- Component\n- Routing（单页系统中尤其重要）\n- Architecture\n\n**使用外部专业解决方案的原因** 可以提高开发效率，可靠性高（浏览器兼容，测试覆盖），也配备优良的配套（文档及工具）。如果外部框架的质量可可靠性无法保证或无法满足业务学期时则不应该选择外部的框架。\n\n**实际项目中的使用**\n\n- 开发式：基于外部模块系统自由组合\n- 半开放：基于一个定制的模块系统，内部外部解决方案共存\n- 封闭式：深度定制的模块系统不引入外部模块\n\n##### DOM\n\n与其相关的有 *Selector*、*Manipulation*、*Event（DOM）*、*Animation*。\n它的主要职责则为为下面的这些：\n\n- 提供便利的 DOM 查询、操作、移动等操作\n- 提供事件绑定及事件代理支持\n- 提供浏览器特性检测及 UserAgent 侦测\n- 提供节点属性、样式、类名的操作\n- 保证目标平台的跨浏览器支持\n\n常用的 DOM 库有 **jQuery**（使用链式接口），**zepto.JS**，**MOOTOO.JS**（使用原生 DOM 对象，通过直接跨站了 DOM 原生对象）。\n\n**基础领域**\n\n|库名|大小|兼容性|优点|缺点|\n|----|----|------|----|----|\n|MOOTOO.JS|96KB|IE6+|概念清晰、无包装对象、接口设计优秀、源码清晰易懂、不局限于 DOM 与 AJAX|扩展原生对象（致命）、社区衰弱|\n|jQuery|94KB|IE6+|社区强大普及率高、包装对象、专注于 DOM|包装对象（容易混淆）|\n|zepto.JS|25KB|IE10+|小且启动快、接口与 jQuery 兼容、提供简单手势操作|无法与 jQuery 100% 对于、支持浏览器少、功能弱|\n\n**专业领域**\n\n|领域|库名|大小|描述|\n|----|----|----|----|\n|手势|Hammer.JS|12KB|常见手势封装（Tab、Hold、Transform、Swifp）并支持自定义|\n|高级动画|Velocity.JS|12KB|复杂动画序列实现，不仅局限于 DOM|\n|视频播放|Video.JS|101KB|类似原生 video 标签的使用方式，对低级浏览器使用 flash 播放器|\n|局部滚动|isscroll.JS|13KB|移动端`position:fix` + `overflow:scroll`的救星|\n\n##### Communication\n\n与其相关的有 *XMLHttpRequest*、*Form*、*JSONP*、*Socket*。\n它的主要职责则为为下面的这些：\n\n- 处理与服务器的请求与相应\n- 预处理请求数据与响应数据 Error/Success 的判断封装\n- 多类型请求，统一接口（XMLHttpRequest1/2、JSONP、iFrame）\n- 处理浏览器兼容性\n\n|库名|大小|支持|\n|----|----|----|\n|Reqwest|3.4KB|JSONP支持、稳定 IE6+支持、CORS 跨域、Promise/A 支持|\n|qwest|2.5KB|代码少、支持XMLHttpRequest2、CORS 跨域、支持高级数据类型（ArrayBuffer、Blob、FormData）|\n\n**实时性要求高的需求**\n\n|库名|支持|\n|----|----|\n|socket.io|实时性、支持二进制数据流、智能自动回退支持、支持多种后端语言（NodeJS 最为稳妥）|\n\n##### Utility（Lang）\n\n与其相关的有 *函数增强 & Shim（保证实现与规范一致）*、*Flow Control*。\n它的主要职责则为为下面的这些：\n\n- 提供 JavaScript 原生不提供的功能\n- 方法门面包装使其便于使用\n- 异步列队及流程控制\n\n|库名|大小|描述|\n|----|----|----|\n|es5-shim|53KB|提供 ES3 环境下的 ES5 支持|\n|es6-shim|38KB|\n|underscore|16.5KB|兼容 IE6+ 的扩展功能函数|\n|Lodash|50KB|其为 underscore 的高性能版本，方法多为 runtime 编译出来的|\n\n##### Templating\n\n与其相关的有 *String-based*、*DOM-based*、*Living Template*。\n\n**基于字符串**的模板\n\n![](../img/T/tech_template0.jpg)\n\n之后的数据修改展现不会进行变化，如果重新绘制（性能低）页面则会去除已有的 DOM 事件。\n\n**基于 DOM** 的模板\n\n![](../img/T/tech-template1.jpg)\n\n修改数据可以改变显示（性能更好）也会保留 DOM 中的已有事件，最终导致 DOM 树与数据模型相联系。\n\n**Living-Template**\n\n![](../img/T/tech_template0.jpg)\n\n其拼接了字符串模板和 DOM 模板的技术（类似 Knockout.JS 注释的实现），最终导致 DOM 树与数据模型相联系。\n\n| |String-based|DOM-based|Living-Template|\n|-|------------|---------|---------------|\n|好处|可以服务器端运行|||\n|解决方案|dust.JS、hogan、dot.JS|Angular.JS、Vue.JS、Knockout|Regular.JS、Ractive.JS、htmlbar|\n|初始化时间|☆☆☆|☆|☆☆|\n|动态更新|无|☆☆☆|☆☆☆|\n|DOM 无关|☆☆☆|无|☆☆|\n|语法|☆☆☆|☆|☆☆|\n|学习成本|☆|☆☆☆|☆☆|\n|SVG 支持|无|☆☆|☆☆|\n|安全性|☆|☆|☆☆☆|\n\n##### Component\n\n与其相关的有 *Modal*、*Slider*、*DatePicker*、*Tabs*、*Editor*（其为产品开发中最耗时也是最必要的一部分）。它的主要职责则为为下面的这些：\n\n- 提供基础的 CSS 支持\n- 提供常见的组件\n- 提供声明式的调用方式（类似 Bootstrap）\n\n|组件库名|版本|特定|支持|\n|--------|----|----|----|\n|Bootstrap|3.x|Mobile First 流式栅格，基于 LESS与 SASS 组织可定制 UI，提供大量组件|IE8+|\n|Foundation|5.x|Mobile First 流式栅格，基于 SASS 组织，可定制 UI，提供大量组件|IE9+|\n\nNOTE：有存在不使用 jQuery 版本的 Bootstrap 可供使用。\n\n##### Router\n\n与其相关的有 *Client Side*、*Server Side*。它的主要职责则为为下面的这些：\n\n- 监听 URL 变化，并通知注册的模块\n- 通过 JavaScript 进行主动跳转\n- 历史管理\n- 对目标浏览器的兼容性支持\n\n|路由库名|大小|特定|支持|\n|--------|----|----|----|\n|page.JS|6.2KB|类似 Express.Router 的路由规则的前端路由库|IE8+|\n|Director.JS|10KB|可以前后端使用同一套规则定义路由|IE6+|\n|Stateman|10KB|处理深层复杂路由的独立路优库|IE6+|\n|crossroad.JS|7.5KB|老牌路由库，API 功能较为繁琐|\n\n##### Architecture（解耦）\n\n与其相关的有 *MVC*、*MVVC*、*MV\\**，解耦又可以通过很多方式来实现（例如事件、分层）。它的主要职责则为为下面的这些：\n\n- 提供一种凡是帮助（强制）开发者进行模块解耦\n- 视图与模型分离\n- 容易进行单元测试\n- 容易实现应用扩展\n\n**下面以 MVVM**为例：\n\n![](../img/T/tech_mvvm.png)\n\n- Model 数据实体用于记录应用程序的数据\n- View 友好的界面其为数据定制的反映，它包含样式结构定义以及 VM 享有的声明式数据以及数据绑定\n- ViewModel 其为 View 与 Model 的粘合，它通过绑定事件与 View 交互并可以调用 Service 处理数据持久化，也可以通过数据绑定将 Model 的变动反映到 View 中\n\nNOTE：MV* 不等同于 SPA，路由是 MV* 系统的课定位状态信息来源。\nNOTE+：单页系统的普世法则为*可定位的*应用程序状态都应该统一由路由系统进入，以避免网状的信息流。\nNOTE++：库与框架选择站点[microjs](http://microjs.com/#) [javascriptOO](http://www.javascriptoo.com/) [JavaScripting](https://www.javascripting.com/)\n"
  },
  {
    "path": "03-FEND_Note-master/chapter5/05_development.md",
    "content": "## 开发实践\n\n### 系统设计\n\nNOTE：综合运用实习案例，本章使用案例为网易云音乐，\n并且主要关注前端工程师的工作职责，其他工程师的职责规范并不包含。\n\n**交互流程说明**\n\n通过交互文案来了解用户行为与异常提示。\n\n**系统分解**\n\n例如下面的独立的子系统：\n\n- 注册登录密码\n- 系统主框架\n  - 顶栏\n    - 搜索\n    - 账号\n    - 消息\n    - 设置\n  - 边栏\n    - 歌单操作\n    - 其他\n  - 底栏\n    - 播放器\n    - 播放列表\n    - 歌曲详情\n  - 内容区\n\n系统分解必须对照交互稿做到百分之百的对应，不能漏掉任何一个模块。\n后续的开发与评估都需根据此分解进行。\n\n**接口设计**\n\n分析模块交互理解需求以及交互行为。对于数据获取的形式进行适当的假设，\n并定义*数据类型*、*模板资源*、*异步接口*、以及*页面摘要*。\n\n**项目结构**\n\n根据规范说明就可以做出项目的结构定义，项目结构分两部分*后端模板*与*前端实现*。\n\n**初始代码**\n\n前端工程师需要在开发工具中添加开发规范，以及测试使用的模拟数据。\n\n### 系统实现\n\n**视觉说明**（视觉稿）中包含各个情况下用户界面的显示样式，其定义了交互稿中的所有效果。之后则需要从中提取出通用组件，其中包括：\n\n- 通用原件（Logo，提示，输入框，图标，按钮等）\n- 通用列表\n- 复合组件（留言板类）\n- 浮层弹出\n\n### 测试发布\n\n使用同步模拟数据进行 **本地测试** 测试，只需在入口页面引入既可。异步处理则可以使用第三方的代理软件既可。在本地测试完后，需要前后端的对接联调。去除模拟同步数据，直接使用后端数据既可。然而对于异步数据联调直接去除代理转向既可。\n\n在完成测试后需要打包发布上线，可使用自动化工具将工程文件打包优化（合并压缩混淆）。\n"
  },
  {
    "path": "03-FEND_Note-master/config.json",
    "content": "{\n  \"name\": \"前端开发笔记本\",\n  \"introduction\": \"前端笔记本涵盖了 Web 前端开发所需的基本知识以及学习路径。\",\n  \"path\": {\n    \"images\": \"img\"\n  }\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/KnowledgeSystem.md",
    "content": "综合类 | 地址\n--- | --- \n前端知识体系|http://www.cnblogs.com/sb19871023/p/3894452.html\n前端知识结构|https://github.com/JacksonTian/fks\nWeb前端开发大系概览|https://github.com/unruledboy/WebFrontEndStack\nWeb前端开发大系概览-中文版|http://www.cnblogs.com/unruledboy/p/WebFrontEndStack.html\nWeb Front-end Stack v2.2|https://raw.githubusercontent.com/unruledboy/WebFrontEndStack/master/Web%20Front%20End%20Stack.png\n免费的编程中文书籍索引|https://github.com/justjavac/free-programming-books-zh_CN\n前端书籍|https://github.com/dypsilon/frontend-dev-bookmarks\n前端免费书籍大全|https://github.com/vhf/free-programming-books\n前端知识体系|http://www.cnblogs.com/sb19871023/p/3894452.html\n免费的编程中文书籍索引|https://github.com/justjavac/free-programming-books-zh_CN\n智能社 - 精通JavaScript开发|http://study.163.com/course/introduction/224014.htm\n重新介绍 JavaScript（JS 教程）|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript\n麻省理工学院公开课：计算机科学及编程导论|http://v.163.com/special/opencourse/bianchengdaolun.html\nJavaScript中的this陷阱的最全收集--没有之一|http://segmentfault.com/a/1190000002640298\nJS函数式编程指南|https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch1.html\nJavaScript Promise迷你书（中文版）|http://liubin.github.io/promises-book\n腾讯移动Web前端知识库|https://github.com/AlloyTeam/Mars\nFront-End-Develop-Guide 前端开发指南|https://github.com/Front-End-Developers-Hunan/Front-End-Develop-Guide\n前端开发笔记本|https://li-xinyang.gitbooks.io/frontend-notebook/content\n大前端工具集 - 聂微东|https://github.com/nieweidong/fetool\n前端开发者手册|https://dwqs.gitbooks.io/frontenddevhandbook/content\n\n\n入门类 | 地址\n--- | --- \n前端入门教程|http://www.cnblogs.com/jikey/p/3613082.html\n瘳雪峰的Javascript教程|http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000\njQuery基础教程|http://www.imooc.com/view/11\n前端工程师必备的PS技能——切图篇|http://www.imooc.com/view/506\n结合个人经历总结的前端入门方法|https://github.com/qiu-deqing/FE-learning\n\n\n效果类 | 地址\n--- | --- \n弹出层|http://www.imooc.com/learn/58\n焦点图轮播特效|http://www.imooc.com/learn/18\n    \n\n工具类| 地址\n--- | --- \ncss sprite 雪碧图制作|http://www.imooc.com/learn/93\n版本控制入门 – 搬进 Github|http://www.imooc.com/learn/390\nGrunt-beginner前端自动化工具|http://www.imooc.com/learn/30\n\n\n慕课专题| 地址\n--- | --- \n张鑫旭 - 慕课系列|http://www.imooc.com/space/teacher/id/197450\nlyn - 慕课系列|http://www.imooc.com/space/teacher/id/104593\n艾伦 - 慕课系列|http://www.imooc.com/space/teacher/id/290139\n碧仔 - Hello，移动WEB|http://www.imooc.com/view/494\n\n\n周报类| 地址\n--- | --- \n平安科技移动开发二队技术周报|https://github.com/PaicHyperionDev/MobileDevWeekly\n\n###API:\n开发中心| 地址\n--- | --- \nmozilla js参考|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript\nchrome开发中心（chrome的内核已转向blink）|https://developer.chrome.com/extensions/api_index.html\nsafari开发中心|https://developer.apple.com/library/safari/navigation\nmicrosoft js参考|https://msdn.microsoft.com/zh-cn/library/d1et7k7c(v=vs.94.aspx\njs秘密花园|http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html\njs秘密花园|http://bonsaiden.github.io/JavaScript-Garden/zh\nw3help|http://www.w3help.org 综合Bug集合网站\n\n\n综合搜索| 地址\n--- | --- \njavascripting|http://www.javascripting.com\n各种流行库搜索|http://microjs.com\n\n\n综合API| 地址\n--- | ---    \nrunoob.com-包含各种API集合|http://www.runoob.com\n开源中国在线API文档合集|http://tool.oschina.net/apidocs\ndevdocs|http://devdocs.io 英文综合API网站\n\n\njQuery| 地址\n--- | ---    \njQuery API 中文文档|http://www.jquery123.com\nhemin 在线版|http://hemin.cn/jq\ncss88 jq api|http://www.css88.com/jqapi-1.9/on\ncss88 jqui api|http://www.css88.com/jquery-ui-api\n学习jquery|http://learn.jquery.com\njquery 源码查找|http://james.padolsey.com/jquery\n\n\nEcmascript| 地址\n--- | ---    \nUnderstanding ECMAScript 6 - Nicholas C. Zakas|https://leanpub.com/understandinges6/read\nexploring-es6|https://leanpub.com/exploring-es6/read\nexploring-es6翻译|https://github.com/es6-org/exploring-es6\nexploring-es6翻译后预览|http://es6-org.github.io/exploring-es6\n阮一峰 es6|http://es6.ruanyifeng.com\n阮一峰 Javascript|http://javascript.ruanyifeng.com\nECMA-262，第 5 版|http://yanhaijing.com/es5\nes5|http://es5.github.io\n\n\nJs template| 地址\n--- | ---    \ntemplate-chooser|http://garann.github.io/template-chooser\nartTemplate|https://github.com/aui/artTemplate\ntomdjs|https://github.com/aui/tmodjs/blob/master/README.md\n淘宝模板juicer模板|http://juicer.name/docs/docs_zh_cn.html\nFxtpl v1.0 繁星前端模板引擎|http://koen301.github.io/fxtpl\nlaytpl|http://laytpl.layui.com\nmozilla - nunjucks|https://github.com/mozilla/nunjucks\nJuicer|https://github.com/PaulGuo/Juicer\ndustjs|http://akdubya.github.io/dustjs\netpl|http://ecomfe.github.io/etpl\n\n\n弹出层| 地址\n--- | ---    \nartDialog 最新版|https://github.com/aui/artDialog\nartDialog 文档|http://aui.github.io/artDialog/doc/index.html\ngoogle code 下载地址|https://code.google.com/p/artdialog/downloads/list\n贤心弹出层|http://layer.layui.com\n响应式用户交互组件库|https://github.com/bh-lay/UI\nsweetalert-有css3动画弹出层|http://t4t5.github.io/sweetalert\n\n\nCSS| 地址\n--- | ---    \nCSS 语法参考|http://tympanus.net/codrops/css_reference\nCSS3动画手册|http://isux.tencent.com/css3/index.html\n腾讯css3动画制作工具|http://isux.tencent.com/css3/tools.html\n志爷css小工具集合|http://linxz.github.io/tianyizone\ncss3 js 移动大杂烩|http://www.note12.com/category/blog/2014-6-5/538fe0a9f786f1b7019a4dfb\nbouncejs 触摸库|http://bouncejs.com\ncss3 按钮动画|http://fian.my.id/Waves\nanimate.css|http://daneden.github.io/animate.css\n全局CSS的终结(狗带 [译]|http://www.alloyteam.com/2015/10/8536\n\n\nAngularjs| 地址\n--- | ---    \nAngular.js 的一些学习资源|https://github.com/dolymood/AngularLearning\nangularjs中文社区|http://angularjs.cn\nAngularjs源码学习|http://www.cnblogs.com/xuwenmin888/p/3739096.html\nAngularjs源码学习|http://www.ifeenan.com/?c=AngularJS\nangular对bootstrap的封装|http://angular-ui.github.io/bootstrap\nangularjs + nodejs|https://cnodejs.org/topic/51404e0f069911196d2e3923\n吕大豹 Angularjs|http://www.cnblogs.com/lvdabao/tag/AngularJs\nAngularJS 最佳实践|http://www.infoq.com/cn/news/2013/02/angular-web-app\nAngular的一些扩展指令|http://www.lovelucy.info/angularjs-best-practices.html\nAngular数据绑定原理|https://github.com/Pasvaz/bindonce\n一些扩展Angular UI组件|https://github.com/angular-ui\nEmber和AngularJS的性能测试|http://voidcanvas.com/emberjs-vs-angularjs-performance-testing\n带你走近AngularJS - 基本功能介绍|http://www.cnblogs.com/powertoolsteam/p/angularjs-introdection.html\nAngularjs开发指南|http://angular.duapp.com/docs/guide\nAngularjs学习|http://www.cnblogs.com/amosli/p/3710648.html\n不要带着jQuery的思维去学习AngularJS|http://www.rainweb.cn/article/angularjs-jquery.html\nangularjs 学习笔记|http://wangjiatao.diandian.com/?tag=angularjs\nangularjs 开发指南|http://www.angularjs.cn/T008\nangularjs 英文资料|https://github.com/jmcunningham/AngularJS-Learning\nangular bootstrap|http://angular-ui.github.io/bootstrap\nangular jq mobile|https://github.com/opitzconsulting/jquery-mobile-angular-adapter\nangular ui|http://mgcrea.github.io/angular-strap\n整合jQuery Mobile+AngularJS经验谈|http://www.tuicool.com/articles/7ZZVr2\n有jQuery背景，该如何用AngularJS编程思想|http://blog.jobbole.com/46589/ \nAngularJS在线教程|http://each.sinaapp.com/angular\nangular学习笔记|http://www.zouyesheng.com/angular.html\n\n\nReact| 地址\n--- | ---    \nreact.js 中文论坛|http://www.react-china.org\nreact.js 官方网址|https://facebook.github.io/react/index.html\nreact.js 官方文档|https://facebook.github.io/react/docs/getting-started.html\nreact.js material UI|http://material-ui.com/#\nreact.js TouchstoneJS UI|http://touchstonejs.io\nreact.js amazeui UI|http://amazeui.org/react\nReact 入门实例教程 - 阮一峰|http://www.ruanyifeng.com/blog/2015/03/react.html\nReact Native 中文版|http://wiki.jikexueyuan.com/project/react-native\nWebpack 和 React 小书 - 前端乱炖|http://www.html-js.com/article/Fakefish%203053\nWebpack 和 React 小书 - gitbook|https://fakefish.github.io/react-webpack-cookbook\nwebpack|https://github.com/webpack/webpack\nWebpack，101入门体验|http://html-js.com/article/3009\nwebpack入门教程|http://html-js.com/article/3113\n基于webpack搭建前端工程解决方案探索|http://segmentfault.com/a/1190000003499526\nReact原创实战视频教程|http://www.piliyu.com\n\n####移动端API\nAPI| 地址\n--- | --- \n99移动端知识集合|https://github.com/jtyjty99999/mobileTech\n移动端前端开发知识库|https://github.com/AlloyTeam/Mars\n移动前端的一些坑和解决方法（外观表现）|http://caibaojian.com/mobile-web-bug.html\n【原】移动web资源整理|http://www.cnblogs.com/PeunZhang/p/3407453.html\nzepto 1.0 中文手册|http://mweb.baidu.com/zeptoapi\nzepto 1.0 中文手册|http://www.html-5.cn/Manual/Zepto\nzepto 1.1.2|http://www.css88.com/doc/zeptojs_api\nzepto 中文注释|http://www.cnblogs.com/sky000/archive/2013/03/29/2988952.html\njqmobile 手册|http://app-framework-software.intel.com/api.php\n移动浏览器开发集合|https://github.com/maxzhang/maxzhang.github.com/issues\n移动开发大杂烩|https://github.com/hoosin/mobile-web-favorites\n微信webview中的一些问题|http://lin-chao.github.io/2014/11/14/%E5%BE%AE%E4%BF%A1webview%E4%B8%AD%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98\n2. 框架\n框架| 地址\n--- | --- \n特色的HTML框架可以创建精美的iOS应用|http://framework7.taobao.org\n淘宝SUI|http://m.sui.taobao.org\n\n####10. avalon\navalon| 地址\n--- | --- \navalonjs|http://avalonjs.github.io\nAvalon新一代UI库： OniUI|http://ued.qunar.com/oniui/index.html\navalon.oniui-基于avalon的组件库|https://github.com/RubyLouvre/avalon.oniui\n|\n\n####11. Requriejs\nRequriejs| 地址\n--- | --- \nJavascript模块化编程（一）：模块的写法 |http://www.ruanyifeng.com/blog/2012/10/javascript_module.html\nJavascript模块化编程（二）：AMD规范|http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html\nJavascript模块化编程（三）：require.js的用法|http://www.ruanyifeng.com/blog/2012/11/require_js.html\nRequireJS入门（一）|http://www.cnblogs.com/snandy/archive/2012/05/22/2513652.html\nRequireJS入门（二）|http://www.cnblogs.com/snandy/archive/2012/05/23/2513712.html\nRequireJS进阶（三）|http://www.cnblogs.com/snandy/archive/2012/06/08/2538001.html\nrequrie源码学习|http://www.cnblogs.com/yexiaochai/p/3632580.html \nrequrie 入门指南|http://www.oschina.net/translate/getting-started-with-the-requirejs-library \nrequrieJS 学习笔记|http://www.cnblogs.com/yexiaochai/p/3214926.html \nrequriejs 其一 |http://cyj.me/why-seajs/requirejs/ \nrequire backbone结合|http://www.cnblogs.com/yexiaochai/p/3221081.html \n\n####12. Seajs\nSeajs| 地址\n--- | --- \nseajs|http://seajs.org\nseajs 中文手册|http://cyj.me/why-seajs/zh\n\n####13. Less,sass\nLess,sass| 地址\n--- | --- \nsass|http://www.w3cplus.com/sassguide\nsass教程-sass中国|http://www.sass.hk\nSass 中文文档|http://sass.bootcss.com\nless|http://less.bootcss.com\n\n####14. Markdown\nMarkdown| 地址\n--- | --- \nMarkdown 语法说明 (简体中文版|http://wowubuntu.com/markdown\nmarkdown入门参考|https://github.com/LearnShare/Learning-Markdown/blob/master/README.md\ngitbook|https://www.gitbook.com 国外的在线markdown可编辑成书\nmdeditor|https://www.zybuluo.com/mdeditor  一款国内的在线markdown编辑器\nstackedit|https://stackedit.io 国外的在线markdown编辑器，功能强大，同步云盘\nmditor|http://bh-lay.github.io/mditor 一款轻量级的markdown编辑器\nlepture-editor|https://github.com/lepture/editor\nmarkdown-editor|https://github.com/jbt/markdown-editor\n\n####15. D3\nD3| 地址\n--- | --- \nd3 Tutorials|https://github.com/mbostock/d3/wiki/Tutorials\nGallery|https://github.com/mbostock/d3/wiki/Gallery\nlofter|http://datavisual.lofter.com/post/40cf3a_188e535\niteye|http://alanland.iteye.com/blog/1878595\nruanyifeng|http://javascript.ruanyifeng.com/library/d3.html\n\n####16. 兼容性\n兼容性| 地址\n--- | --- \nesma 兼容列表|http://kangax.github.io/compat-table/es6\nW3C CSS验证服务|http://jigsaw.w3.org/css-validator/validator.html.zh-cn\ncaniuse|http://caniuse.com/#index \ncsscreator|http://csscreator.com/properties\nmicrosoft|https://msdn.microsoft.com/zh-cn/library/cc351024(v=vs.85.aspx\n在线测兼容-移动端|http://www.responsinator.com\nemulators|https://www.manymo.com/emulators\n\n####17. UI相关\nUI相关| 地址\n--- | --- \nbootcss|http://v3.bootcss.com\nMetroUICSS|http://www.w3cplus.com/MetroUICSS\nsemantic|http://semantic-ui.com\nButtons|http://alexwolfe.github.io/Buttons\nkitecss|http://hiloki.github.io/kitecss\npintuer|http://www.pintuer.com\namazeui|http://amazeui.org\nworldhello|http://www.worldhello.net/gotgithub/index.html\nlinuxtoy|http://igit.linuxtoy.org/contents.html\ngitmagic|http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn\nrogerdudler|http://rogerdudler.github.io/git-guide/index.zh.html\ngitref|http://gitref.justjavac.com\nbook|http://git-scm.com/book/zh\ngogojimmy|http://gogojimmy.net/2012/01/17/how-to-use-git-1-git-basic\n\n####18. HTTP\nHTTP| 地址\n--- | --- \nHTTP API 设计指南|http://segmentfault.com/bookmark/1230000002521721\n\n####19. 其它API\n其它API| 地址\n--- | --- \njavascript流行库汇总|javascriptoo\n验证api|http://niceue.com/validator/demo/index.php\nunderscore 中文手册|http://www.css88.com/doc/underscore\nunderscore源码分析|http://www.html-js.com/article/Underscorejs-source-code-analysis-of-underscorejs-source-code-analysis%203031\nunderscore源码分析-亚里士朱德的博客|http://yalishizhude.github.io/tags/underscore\nunderscrejs en api|http://underscorejs.org\nlodash - underscore的代替品|https://lodash.com\next4api|http://extjs-doc-cn.github.io/ext4api\nbackbone 中文手册|http://www.csser.com/tools/backbone/backbone.js.html\nqwrap手册|http://dev.qwrap.com/resource/js/_docs/_youa/#/qw/base/loadJs_.htm\n缓动函数|http://easings.net/zh-cn\nsvg 中文参考|http://www.w3school.com.cn/svg/svg_reference.asp\nsvg mdn参考|https://developer.mozilla.org/en-US/docs/Web/SVG\nsvg 导出 canvas|https://github.com/gabelerner/canvg\nsvg 导出 png|https://github.com/exupero/saveSvgAsPng\nai-to-svg|http://www.zamzar.com/convert/ai-to-svg\nlocalStorage 库|https://github.com/machao/localStorage\n\n####20. 图表类\n图表类| 地址\n--- | --- \nHighcharts 中文API|http://www.hcharts.cn/api/index.php\nHighcharts 英文API|http://api.highcharts.com/highcharts\nECharts 百度的图表软件|http://echarts.baidu.com/ \n高德地图|http://lbs.amap.com/api\n开源的矢量图脚本框架|http://paperjs.org\nsvg 地图|http://jvectormap.com\n\n####21. vue\nvue| 地址\n--- | --- \nVue|http://cn.vuejs.org\nVue 论坛|http://forum.vuejs.org\nVue 入门指南|http://www.cnblogs.com/aaronjs/p/3660102.html\nVue 的一些资源索引|http://segmentfault.com/a/1190000000411057\nawesome-vue|https://github.com/vuejs/awesome-vue\n\n####21. 正则\n正则| 地址\n--- | --- \nJS正则表达式元字符|http://segmentfault.com/a/1190000002471140\n正则表达式30分钟入门教程|http://deerchao.net/tutorials/regex/regex.htm\nMDN-正则表达式|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions\nruanyifeng - RegExp对象|http://javascript.ruanyifeng.com/stdlib/regexp.html\n小胡子哥 - 进阶正则表达式|http://div.io/topic/764?page=1\nis.js|https://github.com/Cedriking/is.js/blob/master/is.js\n正则在线测试|http://regexper.com\n|\n\n####22. ionic\nionic| 地址\n--- | --- \nionic|https://github.com/ychow/ionic-guide\n\n####23. 其它\n其它| 地址\n--- | --- \nMock.js 是一款模拟数据生成器|http://mockjs.com\n\n###开发规范\n1. 前端\n\n前端| 地址\n--- | --- \n通过分析github代码库总结出来的工程师代码书写习惯|http://alloyteam.github.io/CodeGuide\nHTML&CSS编码规范 by @mdo|http://codeguide.bootcss.com\n团队合作的css命名规范-腾讯AlloyTeam前端团队|http://www.alloyteam.com/2011/10/107\n前端编码规范之js - by yuwenhui|http://yuwenhui.github.io\n前端编码规范之js - by 李靖|http://www.cnblogs.com/hustskyking/p/javascript-spec.html\n前端开发规范手册|http://zhibimo.com/read/Ashu/front-end-style-guide\nAirbnb JavaScript 编码规范（简体中文版）|https://github.com/yuche/javascript#table-of-contents\nAMD与CMD规范的区别|http://www.zhihu.com/question/20351507\nAMD与CMD规范的区别|http://www.cnblogs.com/tugenhua0707/p/3507957.html\nKISSY 源码规范|http://docs.kissyui.com/1.4/docs/html/tutorials/style-guide/kissy-source-style.html\nbt编码规范|http://codeguide.bootcss.com\n规范加强版|https://github.com/Suxiaogang/Code_Guide\n前端代码规范 及 最佳实践|http://blog.jobbole.com/79075\n百度前端规范|http://coderlmn.github.io/code-standards\n百度前端规范|http://isobar-idev.github.io/code-standards\n百度前端规范|http://zhuanlan.zhihu.com/fuyun/19884834\nECMAScript6 编码规范--广发证券前端团队|https://github.com/gf-rd/es6-coding-style\nJavaScript 风格指南/编码规范（Airbnb公司版）|http://blog.jobbole.com/79484\n网易前端开发规范|http://nec.netease.com/standard\ncss模块|http://www.75team.com/archives/1049\n前端规范资源列表|https://github.com/ecomfe/spec\n\n2. PHP\n\nPHP| 地址\n--- | --- \n最流行的PHP 代码规范|http://segmentfault.com/a/1190000000443795\n最流行的PHP 代码规范|https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-2-coding-style-guide.md\n        \n3. Android\n\nAndroid| 地址\n--- | --- \n【敏捷开发】Android团队开发规范|http://www.cnblogs.com/lcw/p/3619181.html\nAndroid 开发规范与应用|http://www.jianshu.com/p/4390f4fe19b3\n\n###其它收集\n\n####1. 各大公司开源项目\n各大公司开源项目| 地址\n--- | --- \nFacebook Projects|https://code.facebook.com/projects/web\n百度web前端研发部|http://fex.baidu.com\n百度EFE|http://efe.baidu.com\n百度github|https://github.com/fex-team\nalloyteam|http://www.alloyteam.com\nalloyteam-github|http://alloyteam.github.io\nalloyteam-AlloyGameEngine|https://github.com/AlloyTeam/AlloyGameEngine\nAlloyDesigner|http://alloyteam.github.io/AlloyDesigner 即时修改，即时保存，设计稿较正，其它开发辅助工具\nH5交互页编辑器AEditor介绍|http://www.alloyteam.com/2015/06/h5-jiao-hu-ye-bian-ji-qi-aeditor-jie-shao H5动画交互页开发的工具介绍\nAEditor|http://aeditor.alloyteam.com H5动画交互页开发的工具\nmaka|http://forum.maka.im/wordpress\n值得订阅的weekly|https://github.com/fenbility/weekly-feed\n腾讯html5|http://cube.qq.com\n奇舞团开源项目|http://75team.github.io\nQunar UED|http://ued.qunar.com\nScrat|http://scrat.io\n\n####2. Javascript\n\n1. 常用\n\n常用 |地址\n--- | --- \nieBetter.js-让IE6-IE8拥有IE9+,Chrome等浏览器特性|http://www.zhangxinxu.com/wordpress/2013/12/iebetter-js-make-ie6-ie8-like-modern-browser-ie9-chrome\n模拟键盘|http://mottie.github.io/Keyboard\n拼音|https://github.com/hotoo/pinyin\n中国个人身份证号验证|https://github.com/mc-zone/IDValidator\n\n2. 算法\n\n算法 | 地址\n--- | --- \n数据结构与算法 JavaScript 描述. 章节练习|https://github.com/Ralph-Wang/algorithm.in.js\n常见排序算法（JS版）|https://github.com/twobin/twobinSort\n经典排序|https://github.com/luofei2011/jsAgm/blob/master/js/sort.js\n常见排序算法-js版本|https://github.com/hechangmin/jssort\nJavaScript 算法与数据结构 精华集|https://github.com/lightningtgc/JavaScript-Algorithms\n面试常考算法题精讲|http://www.nowcoder.com/live/courses\n\n3. 移动端\n\n移动端 | 地址\n--- | --- \nfastclick|https://github.com/ftlabs/fastclick\nno-click-delay|https://github.com/mmastrac/jquery-noclickdelay\n\n4. JSON\n\nJSON | 地址\n--- | --- \n模拟生成JSON数据|http://beta.json-generator.com\n返回跨域JSONAPI|http://jsonp.afeld.me\n\n####3. Html5\nHtml5 | 地址\n--- | --- \nHTML5 有哪些让你惊艳的 demo？|http://www.zhihu.com/question/24398907\n\n####4. CSS\nCSS | 地址\n--- | --- \nbrowserhacks|http://browserhacks.com\n\n####5. jQuery\n\n1. 焦点图\n\n焦点图 | 地址\n--- | --- \nmyfocus|https://github.com/koen301/myfocus\nmyfocus-官方演示站|http://www.chhua.com/myfocus\nSuperSlidev2.1 -- 大话主席|http://www.superslide2.com\nsoChange|http://www.bujichong.com/sojs/soChange/index.html\n\n####6. Ext, EasyUI, J-UI 及其它各种UI方案\n1. Ext\n\nExt, EasyUI, J-UI 及其它各种UI方案 | 地址\n--- | ---\nextjs|https://www.sencha.com/products/extjs\next4英文api|http://docs.sencha.com/extjs/4.0.7\next4中文api|http://extjs-doc-cn.github.io/ext4api\n\n2. EasyUI\n\nEasyUI | 地址\n--- | --- \njquery easyui 未压缩源代码|http://jquery-easyui.googlecode.com/svn/trunk/src\n\n3. J-UI\n\nJ-UI | 地址\n--- | --- \nJ-UI|http://jui.org\n   \n4. Other\n\nOther | 地址\n--- | --- \nMUI-最接近原生APP体验的高性能前端框架|http://dcloudio.github.io/mui\nAmaze UI | 中国首个开源 HTML5 跨屏前端框架|http://amazeui.org\n淘宝 HTML5 前端框架|http://m.sui.taobao.org\nKISSY - 阿里前端JavaScript库|http://docs.kissyui.com\n网易Nej - Nice Easy Javascript|http://nej.netease.com\nKendo UI MVVM Demo|http://demos.telerik.com/kendo-ui/mvvm/index\nBootstrap|http://www.bootcss.com\nSmart UI|http://smartui.chinamzz.com\n雅虎UI - CSS UI|http://developer.yahoo.com/yui/grids\n\n####7. 页面 社会化 分享功能\n页面 社会化 分享功能 | 地址\n--- | --- \n百度分享|http://share.baidu.com pc端\nJiaThis|http://jiathis.com pc端\n社会化分享组件|http://developer.baidu.com/soc/share 移动端\nShareSDK 轻松实现社会化功能|http://www.mob.com/#/index 移动端\n友盟分享|http://dev.umeng.com/social/android/quick-integration 移动端\n\n####8. 富文本编辑器\n富文本编辑器 | 地址\n--- | --- \n功能齐全 tinymce|https://www.tinymce.com\n百度 ueditor|http://ueditor.baidu.com/website\n经典的ckeditor|http://ckeditor.com\n经典的kindeditor|http://kindeditor.net\nwysiwyg|http://www.bootcss.com/p/bootstrap-wysiwyg\n一个有情怀的编辑器。Bach's Editor|http://integ.github.io/BachEditor\ntower用的编辑器|https://github.com/mycolorway/simditor\nsummernote 编辑器|https://github.com/summernote/summernote\nhtml5编辑器|http://neilj.github.io/Squire\nXEditor|http://lab.hustlzp.com/XEditor\nwangEditor|https://github.com/wangfupeng1988/wangEditor \n\n####9. 日历\n\n1. PC\n\nPC | 地址\n--- | --- \n经典my97|http://www.my97.net/dp/demo/index.htm\n强大的独立日期选择器|http://www.cnblogs.com/gbin1/archive/2012/04/16/2452105.html\nfullcalendar|http://fullcalendar.io\nfullcalendar日历控件知识点集合 |http://blog.csdn.net/francislaw/article/details/7740630\n中文api|http://blog.sina.com.cn/s/blog_9475b1c101012c5f.html\n农历日历|https://github.com/zzyss86/LunarCalendar\n超酷的仿百度带节日日历老黄历控件|http://www.sucaisj.com/jiaoben/date/201509/16856.html\n日期格式化|http://momentjs.com\n大牛日历控件|https://github.com/Johnqing/QPAYCalendar\n我群某管理作品|https://github.com/Iamlars/dateMarker\ninput按位替换-官网|http://digitalbush.com/projects/masked-input-plugin\ninput按位替换-github|https://github.com/digitalBush/jquery.maskedinput/tree/1.2.2\nbootstrap-daterangepicker|https://github.com/dangrossman/bootstrap-daterangepicker\n国外30个插件集合|http://www.vandelaydesign.com/30-best-free-jquery-plugins\nJavaScript datepicker|http://dbushell.com/2012/10/09/pikaday-javascript-datepicker\nDatepair.js|http://jonthornton.github.io/Datepair.js\n一个风格多样的日历|https://github.com/glad/glDatePicker\n弹出层式的全日历|http://amsul.ca/pickadate.js/date\njquery双日历|http://www.daterangepicker.com\n\n2. 移动\n\n移动 | 地址\n--- | --- \n大气实用jQuery手机移动端日历日期选择插件|http://www.frankdemo.cn/index.php?c=content&a=show&id=115\njQuery Mobile 移动开发中的日期插件Mobiscroll |https://mobiscroll.com\n\n\n3. Date library\n\nDate library | 地址\n--- | --- \nDatejs|https://github.com/datejs/Datejs\nsugarjs|http://sugarjs.com/api/Date\n\n####10. 综合效果搜索平台\n\n综合效果搜索平台 | 地址\n--- | --- \n效果网|http://www.jq22.com\n17素材|http://www.17sucai.com\n常用的JavaScript代码片段|http://microjs.com\n\n####11. 前端工程化\n\n1. 概述\n\n概述 | 地址\n--- | --- \n前端工具大全|http://www.awesomes.cn\n什么是前端工程化|https://github.com/fouber/blog/issues/10?from=timeline&isappinstalled=0#\n\n2. Gulp \n\nGulp  | 地址\n--- | ---  \nGulp官网|http://gulpjs.com\nGulp中文网|http://www.gulpjs.com.cn\ngulp资料收集|https://github.com/Platform-CUF/use-gulp\nGulp：任务自动管理工具 - ruanyifeng|http://javascript.ruanyifeng.com/tool/gulp.html\nGulp插件|http://gulpjs.com/plugins\nGulp不完全入门教程|http://www.ido321.com/1622.html\n为什么使用gulp?|https://github.com/hjzheng/CUF_meeting_knowledge_share/issues/33\nGulp安装及配合组件构建前端开发一体化|http://www.dbpoo.com/getting-started-with-gulp\nGulp 入门指南|https://github.com/nimojs/gulp-book\nGulp 入门指南 - nimojs|https://github.com/nimojs/blog/issues/19\nGulp入门教程|http://markpop.github.io/2014/09/17/Gulp%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B\nGulp in Action|http://www.imooc.com/video/5692\nGulp开发教程（翻译）|http://www.w3ctech.com/topic/134\n前端构建工具gulpjs的使用介绍及技巧|http://www.cnblogs.com/2050/p/4198792.html\n\n3. Grunt\n\nGrunt  | 地址\n--- | ---  \ngruntjs|http://gruntjs.com\nGrunt中文网|http://www.gruntjs.net\n\n4. Fis\n\nFis  | 地址\n--- | ---  \nfis 官网|http://fex-team.github.io/fis-site/index.html\nfis|http://fis.baidu.com\n\n####12. 轮播图\n\n1. pc图轮\n\npc图轮  | 地址\n--- | ---  \n单屏轮播sochange|http://www.jsfoot.com/jquery/demo/2011-09-20/192.html\n左右按钮多图切换|http://bxslider.com/examples/carousel-demystified\nfullpage全屏轮播|https://github.com/alvarotrigo/fullPage.js\n\n2. 移动端\n\n移动端  | 地址\n--- | ---  \n无缝切换|http://www.swipejs.com\n滑屏效果|http://www.idangero.us/swiper\n全屏fullpage|https://github.com/peunzhang/fullpage\n单个图片切换|https://github.com/qiqiboy/touchslider\n单个全屏切换|https://github.com/peunzhang/slip.js\n百度的切换库|http://touch.code.baidu.com/examples.html?qq-pf-to=pcqq.group\n单个全屏切换|https://github.com/peunzhang/iSlider\n滑屏效果|https://github.com/saw/touch-interfaces\n旋转拖动设置|http://baijs.com/tinycircleslider\n类似于swipe切换|http://touchslider.com\n支持多种形式的触摸滑动|http://www.swiper.com.cn/demo/index.html\n滑屏效果|https://github.com/joker-ye/main/blob/master/wap/index.html\n大话主席pc移动图片轮换|http://www.superslide2.com\n滑屏效果|https://github.com/hahnzhu/parallax.js\n基于zepto的fullpage|https://github.com/yanhaijing/zepto.fullpage\n[WebApp]定宽网页设计下，固定宽度布局开发WebApp并实现多终端下WebApp布局自适应|http://www.cnblogs.com/plums/archive/2013/01/10/WebApp-fixed-width-layout-of-multi-terminal-adapter-since.html\n判断微信客户端的那些坑|http://loo2k.com/blog/detecting-wechat-client\n可以通过javascript直接调用原生分享的工具|https://github.com/JefferyWang/nativeShare.js\nJiaThis 分享到微信代码|http://www.jiathis.com/help/html/weixin-share-code\n聊聊移动端跨平台开发的各种技术|http://fex.baidu.com/blog/2015/05/cross-mobile\n前端自动化测试|http://www.zhihu.com/question/29922082\n多种轮换图片|http://ajccom.github.io/niceslider\n滑动侧边栏|https://mango.github.io/slideout\n\n####13. 文件上传\n\n文件上传  | 地址\n--- | ---  \n百度上传组件|http://fex.baidu.com/webuploader\n上传|https://blueimp.github.io/jQuery-File-Upload\nflash 头像上传|http://www.hdfu.net\n图片上传预览|http://www.dropzonejs.com\n图片裁剪|http://elemefe.github.io/image-cropper\n图片裁剪-shearphoto|http://www.shearphoto.com\njQuery图片处理|http://www.oschina.net/project/tag/284/jquery-image-tools?lang=0&os=0&sort=view&p=2\n|\n\n####14. 模拟select\n\n模拟select  | 地址\n--- | ---  \n糖饼 select|http://aui.github.io/popupjs/doc/selectbox.html\nflexselect|https://github.com/rmm5t/jquery-flexselect\n双select|http://loudev.com\nselect2|http://select2.github.io\n|\n\n####15. 取色插件\n\n取色插件  | 地址\n--- | ---  \n类似 Photoshop 的界面取色插件|http://www.jq22.com/plugin/367\njquery color|https://github.com/jquery/jquery-color\n取色插件集合|http://www.oschina.net/project/tag/287/color-picker\nfarbtastic 圆环＋正方形|https://github.com/mattfarina/farbtastic\n|\n\n####16. 城市联动\n\n城市联动  | 地址\n--- | ---  \njquery.cityselect.js基于jQuery+JSON的省市或自定义联动效果|http://www.ijquery.cn/?p=360\n|\n\n####17. 剪贴板\n\n剪贴板  | 地址\n--- | ---  \n剪贴板|https://github.com/zeroclipboard/zeroclipboard\nclipboard 最新的剪切方案|http://zenorocha.github.io/clipboard.js\n不是Flash的剪贴板|https://github.com/zenorocha/clipboard.js\n\n####18. 简繁转换\n\n简繁转换  | 地址\n--- | ---  \n简繁转换|https://github.com/BYVoid/OpenCC\n\n####19. 表格 Grid\n\n表格 Grid  | 地址\n--- | ---  \nfacebook表格|http://facebook.github.io/fixed-data-table\n类似于Excel编辑表格-handsontable|http://handsontable.com\nbootstrap-table插件|http://bootstrap-table.wenzhixin.net.cn\ndatatables|https://www.datatables.net\n\n####20. 在线演示\n\n在线演示  | 地址\n--- | ---  \njs 在线编辑 - runjs|http://runjs.cn\njs 在线编辑 - jsbin|http://jsbin.com\njs 在线编辑 - codepen|http://codepen.io\njs 在线编辑 - jsfiddle|http://jsfiddle.net\njava 在线编辑 - runjs|http://ideone.com\njs 在线编辑 - hcharts|http://code.hcharts.cn\njs 在线编辑 - jsdm|http://jsdm.com\nsql 在线编辑 - sqlfiddle|http://sqlfiddle.com\nmozilla 在线编辑器|https://thimble.mozilla.org\n\n####21. 播放器\n\n播放器  | 地址\n--- | ---  \nHtml5 VideoPlayer|https://github.com/zmmbreeze/DeadSimpleVideoPlayer\n\n####22. 粒子动画\n\n粒子动画  | 地址\n--- | ---  \nProton 烟花|http://a-jie.github.io/Proton/#example\n\n###九. Nodejs\n\nNodejs  | 地址\n--- | ---  \nnodejs 篇幅比较巨大|http://liuqing.pw\nNode.js 包教不包会|https://github.com/alsotang/node-lessons\n篇幅比较少|http://www.rainweb.cn/article/category/Nodejs\nnode express 入门教程|http://www.w3cfuns.com/article-5598538-1-1.html\nnodejs定时任务|http://my.oschina.net/u/568264/blog/193773\n一个nodejs博客|http://60sky.com\n【NodeJS 学习笔记04】新闻发布系统|http://www.cnblogs.com/yexiaochai/p/3536547.html\n过年7天乐，学nodejs 也快乐|http://www.cnblogs.com/qqloving/p/3541099.html\n七天学会NodeJS|https://github.com/nqdeng/7-days-nodejs\nNodejs学习笔记（二）--- 事件模块|http://www.cnblogs.com/zhongweiv/p/nodejs_events.html\nnodejs入门|http://www.cnblogs.com/liusuqi/p/3735491.html\nangularjs nodejs|https://github.com/zensh/jsgen\n从零开始nodejs系列文章|http://blog.fens.me/series-nodejs\n理解nodejs|http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb\nnodejs事件轮询|http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop\nnode入门|http://www.nodebeginner.org/index-zh-cn.html\nnodejs cms|http://ourjs.com/detail/53e1f281c5910a9806000001\nNode初学者入门，一本全面的NodeJS教程|http://ourjs.com/detail/529ca5950cb6498814000005\nNodeJS的代码调试和性能调优|http://www.barretlee.com/blog/2015/10/07/debug-nodejs-in-command-line\n\n###十. 性能优化\n\n1. 常规优化\n\n常规优化|地址\n--- | ---\nJavascript高性能动画与页面渲染|http://www.infoq.com/cn/articles/javascript-high-performance-animation-and-page-rendering\n移动H5前端性能优化指南|http://isux.tencent.com/h5-performance.html\n5173首页前端性能优化实践|http://ued.5173.com/?p=1731\n给网页设计师和前端开发者看的前端性能优化|http://www.uisdc.com/front-end-performance-for-web-designers-and-front-end-developers\n复杂应用的 CSS 性能分析和优化建议|http://www.orzpoint.com/profiling-css-and-optimization-notes\n张鑫旭——前端性能|http://www.zhangxinxu.com/wordpress/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD\n前端性能监控总结|http://www.xiaoqiang.org/javascript/font-end-performance-monitor.html\n网站性能优化之CSS无图片技术|http://udc.weibo.com/2013/05/%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8Bcss%E6%97%A0%E5%9B%BE%E7%89%87%E6%8A%80%E6%9C%AF\nweb前端性能优化进阶路|http://www.aliued.cn/2013/01/20/web%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E8%BF%9B%E9%98%B6%E8%B7%AF.html\n前端技术：网站性能优化之CSS无图片技术|http://my.eoe.cn/tuwandou/archive/4544.html\n浏览器的加载与页面性能优化|http://www.baiduux.com/blog/2011/02/15/browser-loading\n页面加载中的图片性能优化|http://www.w3ctech.com/p/1503\nHey——前端性能|http://www.feelcss.com/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD\nhtml优化|http://www.baiduux.com/blog/2010/03/15/html%E4%BC%98%E5%8C%96-2\n99css——性能|http://www.99css.com/tag/%e6%80%a7%e8%83%bd\nYslow——性能优化|http://www.yslow.net/category.php?cid=20\nYSLOW中文介绍|http://www.cnblogs.com/yslow\n转一篇Yahoo关于网站性能优化的文章，兼谈本站要做的优化|http://www.360ito.com/article/40.html\nYahoo!团队实践分享：网站性能|http://www.360doc.com/content/10/0928/09/2588264_56971287.shtml\n网站性能优化指南：什么使我们的网站变慢？|http://blog.jiasule.com/i/153\n网站性能优化实践，减少加载时间，提高用户体验|http://www.powereasy.net/helpyou/knowledge/ecommerce/9593.html\n浅谈网站性能优化 前端篇|http://www.umtry.com/archives/747.html\n前端重构实践之如何对网站性能优化？|http://www.adinnet.cn/blog/designview/2012-7-12/678.html\n前端性能优化：使用媒体查询加载指定大小的背景图片|http://www.gbin1.com/technology/javascript/20130708-front-end-performance-optimization-9\n网站性能系列博文|http://www.mykuer.com/post/factors-that-affect-the-speed-of-web-site-open.html\n加载，不只是少一点点|http://tgideas.qq.com/webplat/info/news_version3/804/808/811/m579/201109/41355.shtml\n前端性能的测试与优化|http://mzhou.me/article/95310\n分享网页加载速度优化的一些技巧？|http://www.gbin1.com/technology/html/20130217-tips-for-speed-up-page-loading\n页面加载中的图片性能优化|http://www.f2es.com/images-bytes-opt\nweb前端优化(基于Yslow|http://www.tcreator.info/webSchool/website/Front-end-Opt-Yslow.html\n网站性能优化工具大全|https://www.qianduan.net/website-performance-optimization-tool.html\n【高性能前端1】高性能HTML|http://www.alloyteam.com/2012/10/high-performance-html\n【高性能前端2】高性能CSS|http://www.alloyteam.com/2012/10/high-performance-css\n由12306谈谈网站前端性能和后端性能优化|http://coolshell.cn/articles/6470.html\nAlloyTeam——前端优化|http://www.alloyteam.com/webfrontend/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96\n毫秒必争，前端网页性能最佳实践|http://www.cnblogs.com/developersupport/p/3248695.html\n网站性能工具Yslow的使用方法|http://blog.sina.com.cn/s/blog_6e9d2e0701017kvu.html\n前端工程与性能优化（上）：静态资源版本更新与缓存|http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part1\n前端工程与性能优化（下）：静态资源管理与模板框架|http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part2\nHTTPS连接的前几毫秒发生了什么|http://blog.jobbole.com/48369\nYslow|http://uicss.cn/yslow/#more-12319\nEssential Web Performance Metrics — A Primer, Part 1|http://blog.smartbear.com/web-performance/essential-web-performance-metrics-a-primer-part-1\nEssential Web Performance Metrics — Part 2|http://blog.smartbear.com/performance/essential-web-performance-metrics-part-2\nYUISlide,针对移动设备的动画性能优化|http://jayli.github.io/blog/data/2011/12/23/yuislide.html\nImproving Site Performance|http://joelglovier.com/improving-site-performance\n让网站提速的最佳前端实践|http://segmentfault.com/a/1190000000367899\nWhy Website Speed is Important|http://sixrevisions.com/web-development/why-website-speed-is-important\nNeed for Speed – How to Improve your Website Performance|https://www.devbridge.com/articles/need-for-speed-how-to-improve-your-website-performance\n阿里无线前端性能优化指南 (Pt.1 加载期优化 |https://github.com/amfe/article/issues/1\n|\n\n2. 优化工具\n\n优化工具|地址\n--- | ---\nJavaScript 性能分析新工具 OneProfile|http://www.html-js.com/article/3083\nJavaScript 堆内存分析新工具 OneHeap|http://www.html-js.com/article/3091\n\n3. 在线工具\n\n在线工具|地址\n--- | ---\ngoogle在线工具|https://developers.google.com/speed/pagespeed/insights\n阿里测|http://www.alibench.com\n阿里-免费测试服务|http://itest.aliyun.com\n阿里-F2etest多浏览器兼容性测试解决方案|https://github.com/alibaba/f2etest\njs性能测试|http://jsperf.com\n|\n    \n###十一. 前端架构\n\n前端架构|地址\n--- | ---\n技术架构|http://www.zhihu.com/topic/19612641\n前端架构|http://saito.im/note/The-Architecture-of-F2E\n如何成为前端架构师|http://www.zhihu.com/question/24092572\n关于前端架构-张克军|http://hikejun.com/sharing/2010webrebuild/?file=fe-infrastructure.html\n百度腾讯offer比较（腾讯游戏VS百度基础架构）|http://www.zhihu.com/question/25583350\n|\n\n\n###十二. 个人作品\n\n####1. 推荐作品\n\n推荐作品|地址\n--- | ---\nwinter代码片段需要翻墙|https://gist.github.com/wintercn\nfgm|http://www.fgm.cc/learn\n岑安作品集|https://github.com/hongru/hongru.github.com\n当耐特demo集合|http://kmdjs.github.io\n米空格 js作品|http://www.laoshu133.com/Lab\nmyFocus|http://koen301.github.io\nSeaJS组件库|http://panxuepeng.github.io/seajslib\n颜海镜作品|http://yanhaijing.com/myProject\n脚儿网作品|http://jo2.org/category/myworks\njavascript个人作品|http://www.cnitblog.com/yemoo/category/3107.html\n妙味的雷东升游戏作品|http://bbs.miaov.com/forum.php?mod=viewthread&tid=7790\njavascript作品集|http://bbs.csdn.net/topics/380227212\n云五笔，灰度产生生成工具|https://github.com/TooBug/works\n项目主页|http://koen301.github.io\n个性的作品主页|http://zaole.net\n播放器|http://static.tingall.com/v2/player\nucren js demos 集|http://ucren.com/blog/demos\n智能社|http://www.zhinengshe.com/works_list.html\n实例陈列架|http://demos.shizuwu.cn\nzoye demo|http://zoye.sinaapp.com/demo\n王员外|http://lab.yuanwai.wang\n平凡|http://pingfan1990.sinaapp.com\njyg 游戏案例|http://www.lovewebgames.com\n很多jquery插件|http://www.helloweba.com/list.html\n不羁虫 - soJs 作品系列|http://www.bujichong.com/sojs/api/index.html\nfrozenui|http://frozenui.github.io/case.html\n黑白棋|http://js-game.github.io/othello\nfromone|http://yansm.github.io/fromone/index.html\n\n####2. 群员作品\n\n群员作品|地址\n--- | ---\nMDialog 合肥-M.J]|http://demo.webjyh.com\n轮播图 上海－冷静]|http://sandbox.runjs.cn/show/do6zlrrk \n[广州—坚壳]|http://www.replace5.com\n[成都 - 无痕]　感恩节专题|http://www.seejs.com/demos\n[球霸天]|http://hacke2.github.io/works\n[北京-小数]|http://www.cnblogs.com/mcat\n[ptf] Magix 工具|http://thx.github.io/magix\n[杭州-Pft] Magix 基于 MVC 结构和 Hash 驱动的 OPOA（One Page One Application）应用|http://thx.github.io/magix\n[上海-剧中人]-实验室|http://bh-lay.com/labs\n[上海-豪情 ] 作品集合|http://jikeytang.github.io\n[成都-feeling]|http://guoshan.sinaapp.com\n[上海-angela]|http://www.cnblogs.com/liyunhua\n[海南-hank]作品|http://hcjp.github.io/work/demo\n[上海-张力]博客|https://github.com/yibuyisheng/blogs/issues\n[上海-zenki]作品|http://zkske121.github.io\n移动端图案解锁|http://01google.sinaapp.com/locker.html\n[合肥-M.J] - MPreview 移动端图片预览组|https://github.com/webjyh/MPreview.mobile\n[合肥-M.J] - Mexam 移动端在线做题组|https://github.com/webjyh/Mexam\n[北京-苏瑞] - dancer小人|http://letyougo.github.io/dancer\n[上海-玄沐]- 个人网站|http://k.swao.cn/js\n[厦门-二哲]- 个人博客|http://www.meckodo.com\n\n####3. 国外大牛精品\n\n国外大牛精品|地址\n--- | ---\npazguille|http://pazguille.me\n\n###十三. 简历模板\n\n简历模板|地址\n--- | ---\n不错的个人简历|http://learnshare.github.io/about/index.html\n简历|http://hcy2367.github.io/resume\n张伦|http://ncuey.sinaapp.com/CrispElite/ \n简历|https://github.com/hacke2/ResumeSample\n翁天信|http://blog.dandyweng.com/2013/07/how-my-website-was-created\n动画方式的简历|http://www.webhek.com/misc/interactive-resume\n组件丰富简历|http://www.linqing07.com/resume.html\n简历池|http://www.mojianli.com/resume/view\nhaorooms博客|http://www.haorooms.com/about\nJustin Young|http://cv.youngdze.com\n|\n\n###十四. 面试题\n\n面试题|地址\n--- | ---\n那几个月在找工作（百度，网易游戏）|http://www.nowcoder.com/discuss/3196\n2014最新面试题|http://www.html-js.com/article/1743\n阿里前端面试题|http://www.w3cfuns.com/thread-5598563-2-1.html\n2016校招内推 -- 阿里巴巴前端 -- 三面面试经历 |http://www.cnblogs.com/imwtr/p/4685546.html\n腾讯面试题|http://www.w3cfuns.com/article-5599657-1-1.html\n年后跳槽那点事：乐视+金山+360面试之行|http://www.cnblogs.com/lvdabao/p/3660707.html\n阿里前端面试题上线|http://fatesinger.com/2722.html\n拉勾网js面试题|http://www.cnblogs.com/52cik/p/js-question-lg.html\n前端面试|http://www.cnblogs.com/allenxing/p/3724382.html\nWeb开发笔试面试题 大全|http://mianshiti.diandian.com\n前端开发面试题|http://segmentfault.com/a/1190000000465431\n2014最新前端面试题|https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions\n百度面试|https://github.com/fex-team/interview-questions\n面试题|http://www.w3cfuns.com/forum.php?mod=forumdisplay&fid=51&filter=typeid&typeid=177\n前端工作面试问题|https://github.com/darcyclarke/Front-end-Developer-Interview-Questions/tree/master/Chinese\n前端开发面试题|http://segmentfault.com/a/1190000000465431\n5个经典的前端面试问题|http://ourjs.com/detail/5%E4%B8%AA%E7%BB%8F%E5%85%B8%E7%9A%84%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98\n最全前端面试问题及答案总结 |http://segmentfault.com/a/1190000002562454\n如何面试一名前端开发工程师？|http://www.html-js.com/article/Large-search-front-team-column%202961\n史上最全 前端开发面试问题及答案整理|https://github.com/hawx1993/Front-end-Interview-questions\n前端实习生面试总结 |http://www.cnblogs.com/xiaoruo/p/4665163.html\n史上最全 前端开发面试问题及答案整理|https://github.com/hawx1993/Front-end-Interview-questions\nBAT及各大互联网公司2014前端笔试面试题：JavaScript篇|http://blog.jobbole.com/78738\n前端开发面试题大收集|https://github.com/paddingme/Front-end-Web-Development-Interview-Question\n收集的前端面试题和答案|https://github.com/qiu-deqing/FE-interview\n如何面试前端工程师|http://www.zhihu.com/question/19568008\n前端开发面试题|https://github.com/markyun/My-blog/blob/master/Front-end-Developer-Questions/Questions-and-Answers/README.md\n牛客网-笔试面经|http://www.nowcoder.com/discuss?type=2\n\n###十五. iconfont\n\niconfont|地址\n--- | ---\n中文字体|http://www.zhihu.com/question/21253343\n淘宝字库|http://iconfont.cn\n字体|http://mux.alimama.com/fonts\n制作教程|http://iconfont.cn/help/platform.html\nzhangxinxu-icommon|http://www.zhangxinxu.com/wordpress/?s=icomoon\nicommon|https://icomoon.io/app\n用字体在网页中画ICON图标(推荐教程|http://imooc.com/learn/243\n字体压缩工具|http://font-spider.org 感谢初级群　[深圳-小鱼] 的推荐\n\n###十六. 开发工具类\n\n1. 前端开发工具\n\n前端开发工具|地址\n--- | ---\nIntelliJ IDEA 简体中文专题教程|https://github.com/judasn/IntelliJ-IDEA-Tutorial\nWebstorm,InterllIdea,Phpstorm|http://t.cn/8kZZ1Uy\nSublimeText|https://github.com/jikeytang/sublime-text\nAtom|https://atom.io\nvisual studio code|https://code.visualstudio.com\n\n2. Chrome, Firebug, Filddle 调试\n\n\n1. Fiddler\n\nFiddler|地址\n--- | ---\nFiddler调式使用知多少(一深入研究|http://www.cnblogs.com/tugenhua0707/p/4623317.html\n微信fiddle|http://www.cnblogs.com/strick/p/4570006.html\n微信fiddle|http://gaoboy.com/article/26.html\n\n    \n2. Chrome\n\nChrome|地址\n--- | ---\nGoogle Chrome 官方|https://developer.chrome.com/devtools\nChrome - 基础|http://www.cnblogs.com/constantince/p/4565261.html\nChrome - 进阶|http://www.cnblogs.com/constantince/p/4579121.html\nChrome - 性能|http://www.cnblogs.com/constantince/p/4585983.html\nChrome - 性能进阶|http://www.cnblogs.com/constantince/p/4607497.html\nChrome - 移动|http://www.cnblogs.com/constantince/p/4624241.html\nChrome - 使用技巧|http://www.cnblogs.com/liyunhua/p/4544738.html\nChrome - Console控制台不完全指南|http://www.cnblogs.com/Wayou/p/chrome-console-tips-and-tricks.html\nChrome - Workspace使浏览器变成IDE|http://c7sky.com/chrome-devtools-workspace.html\nnetwork面板|http://www.html-js.com/article/Nothing-blind%202975\nchrome开发工具快捷键|http://anti-code.com/devtools-cheatsheet\nchrome调试工具常用功能整理|http://www.html-js.com/article/2327\nChrome 开发工具 Workspace 使用|http://www.iinterest.net/2014/05/09/chrome-dev-tool-workspace\nChrome神器Vimium快捷键学习记录 |http://www.cppblog.com/deercoder/archive/2011/10/22/158886.html\nsass调试-w3cplus|http://www.w3cplus.com/sassguide/debug.html\n如何更专业的使用Chrome开发者工具-w3cplus|http://www.w3cplus.com/tools/how-to-use-chrome-devtools-like-a-pro.html\nchrome调试canvas|http://sentsin.com/web/253.html\nchrome profiles1|https://developer.chrome.com/devtools/index\nchrome profiles2|http://h5dev.uc.cn/article-25-1.html\nchrome profiles3|http://www.oschina.net/translate/performance-optimisation-with-timeline-profiles\nchrome移动版调试|https://developer.chrome.com/devtools/docs/mobile-emulation\nchrome调试|http://ued.taobao.org/blog/2012/06/debug-with-chrome-dev-tool\nchrome的调试|http://www.cnblogs.com/QLeelulu/archive/2011/08/28/2156402.html\nchrome console 命令详解|https://developer.chrome.com/devtools/docs/commandline-api\n查看事件绑定1|http://www.cnblogs.com/leonkao/p/3809655.html\n查看事件绑定2|http://www.cnblogs.com/xiaoyao2011/p/3447421.html\n神器——Chrome开发者工具(一|http://segmentfault.com/a/1190000000683599\n奇趣百科性能优化(Chrome DevTools 中的 Timeline Profils 等工具使用介绍|https://xinranliu.me/2015-05-22-qiqu-performance\nchrome 开发者工具的 15 个小技巧|http://frontenddev.org/link/15-tips-of-chrome-developer-tools.html\nChrome开发者工具不完全指南|http://1ke.co/course/361\nChrome 开发者工具使用技巧|http://segmentfault.com/a/1190000003882567\n\n3. Firebug\n\nFirebug|地址\n--- | ---\nfirebug视频教程|http://www.imooc.com/learn/137\nfirefox 模拟器|https://developer.mozilla.org/zh-CN/docs/Tools/WebIDE\nconsole.log 命令详解|http://www.cnblogs.com/ctriphire/p/4116207.html\nFirebug入门指南|http://www.ruanyifeng.com/blog/2008/06/firebug_tutorial.html\nFirebug控制台详解|http://www.ruanyifeng.com/blog/2011/03/firebug_console_tutorial.html\n\n    \n4. 移动,微信调试\n\n移动,微信调试|地址\n--- | ---\n浏览器端调试安卓|https://openstf.github.io\n移动端前端开发调试|http://yujiangshui.com/multidevice-frontend-debug\n使用 Chrome 远程调试 Android 设备|https://github.com/yujiangshui/CN-Chrome-DevTools/blob/remote-debugging/md/Use-Tools/remote-debugging.md\nmac移动端调试|http://plus.uc.cn/document/webapp/doc5.html\nmac移动端调试|http://www.mihtool.com\n无线调试攻略|http://thx.github.io/mobile/debugging-in-mobile\n无线调试攻略|http://yanhaijing.com/mobile/2014/12/17/web-debug-for-mobile\n屌爆了,完美调试 微信webview(x5|http://www.jianshu.com/p/ccf124f1f74b\n微信调试的那些事|http://liyaodong.com/2015/07/06/%E5%BE%AE%E4%BF%A1%E8%B0%83%E8%AF%95%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B\n远程console|http://jsconsole.com\n微信调试工具|http://blog.qqbrowser.cc\n各种真机远程调试方法汇总|https://github.com/jieyou/remote_inspect_web_on_real_device\n    \n5. iOS Simulator\n\niOS Simulator|地址\n--- | ---\nSimulator|https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html\nXcode中的iOS模拟器(iOS Simulator的介绍和使用心得|http://www.crifan.com/intro_ios_simulator_in_xcode_and_usage_summary\n\n3. img\n\nimg|地址\n--- | ---\nloading img|http://preloaders.net/en/circular\n智图-图片优化平台|http://zhitu.isux.us\n在线png优化|https://tinypng.com\n\n4. 生成二维码\n\n生成二维码|地址\n--- | ---\n生成二维码|http://cli.im\n    \n5. 浏览器同步\n\n浏览器同步|地址\n--- | ---\npuer|https://github.com/leeluolee/puer\nliveReload|http://livereload.com\nf5|http://getf5.com\nFile Watchers|http://geek100.com/2608\n\n6. 在线PPT制作\n\n在线PPT制作|地址\n--- | ---\nnodePPT|http://js8.in/2013/11/16/%E6%8E%A8%E8%8D%90nodeppt%EF%BC%9A%E4%BD%BF%E7%94%A8markdown%E8%AF%AD%E6%B3%95%E6%9D%A5%E5%86%99%E7%BD%91%E9%A1%B5ppt\nPPT|https://github.com/ksky521/nodePPT\nreveal|https://github.com/hakimel/reveal.js\nslippy|https://github.com/Seldaek/slippy\n\n###十七. 前端导航网站\n\n前端导航网站|地址\n--- | ---\n界面清爽的前端导航|http://uxbees.com/index.html\n前端导航|http://whycss.com\n前端网址导航|http://www.daqianduan.com/nav\n前端名录|http://sentsin.com/daohang\n前端导航|http://123.jser.us\n前端开发资源|http://www.css88.com/nav\n网址导航|http://www.haourl.cn\n前端开发仓库 - 众多效果的收集地|http://code.ciaoca.com \n前端资源导航|https://github.com/jnoodle/f2e-collect\nF2E 前端导航|http://f2e.im/static/pages/nav/index.html\n\n###十八. 常用CDN\n\n常用CDN|地址\n--- | ---\n新浪CDN|http://lib.sinaapp.com\n百度静态资源公共库|http://cdn.code.baidu.com\n360网站卫士常用前端公共库CDN服务|http://libs.useso.com\nBootstrap中文网开源项目免费 CDN 服务|http://www.bootcdn.cn\n开放静态文件 CDN - 七牛|http://staticfile.org\nCDN加速 - jq22|http://www.jq22.com/cdn\njQuery CDN|http://code.jquery.com\nGoogle jQuery CDN|http://www.google-jquery-cdn.com\n微软CDN|http://www.asp.net/ajax/cdn\n\n###十九. Git,SVN,Github\n\n1. Git\n\nGit|地址\n--- | ---\ngit-scm|http://git-scm.com\n廖雪峰-Git教程|http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000\ngit-for-windows|https://git-for-windows.github.io\nGitHub 添加 SSH keys|http://daemon369.github.io/git/2015/03/10/add-ssh-keys-for-github\ngogithub|http://www.worldhello.net/gotgithub/index.html\ngit常规命令练习|http://pcottle.github.io/learnGitBranching\ngit的资料整理|https://github.com/xirong/my-git\n我所记录的git命令（非常实用）|http://www.cnblogs.com/fanfan259/p/4810517.html\n企业开发git工作流模式探索部分休整|https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md\nGitHub 漫游指南|https://github.com/phodal/github-roam\nGitHub秘籍|https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md\n使用git和github进行协同开发流程|http://livoras.com/post/28\n动画方式练习git|http://onlywei.github.io/explain-git-with-d3\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/Cache.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 2.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache extends CI_Driver_Library {\n\n\t/**\n\t * Valid cache drivers\n\t *\n\t * @var array\n\t */\n\tprotected $valid_drivers = array(\n\t\t'apc',\n\t\t'dummy',\n\t\t'file',\n\t\t'memcached',\n\t\t'redis',\n\t\t'wincache'\n\t);\n\n\t/**\n\t * Path of cache files (if file-based cache)\n\t *\n\t * @var string\n\t */\n\tprotected $_cache_path = NULL;\n\n\t/**\n\t * Reference to the driver\n\t *\n\t * @var mixed\n\t */\n\tprotected $_adapter = 'dummy';\n\n\t/**\n\t * Fallback driver\n\t *\n\t * @var string\n\t */\n\tprotected $_backup_driver = 'dummy';\n\n\t/**\n\t * Cache key prefix\n\t *\n\t * @var\tstring\n\t */\n\tpublic $key_prefix = '';\n\n\t/**\n\t * Constructor\n\t *\n\t * Initialize class properties based on the configuration array.\n\t *\n\t * @param\tarray\t$config = array()\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tisset($config['adapter']) && $this->_adapter = $config['adapter'];\n\t\tisset($config['backup']) && $this->_backup_driver = $config['backup'];\n\t\tisset($config['key_prefix']) && $this->key_prefix = $config['key_prefix'];\n\n\t\t// If the specified adapter isn't available, check the backup.\n\t\tif ( ! $this->is_supported($this->_adapter))\n\t\t{\n\t\t\tif ( ! $this->is_supported($this->_backup_driver))\n\t\t\t{\n\t\t\t\t// Backup isn't supported either. Default to 'Dummy' driver.\n\t\t\t\tlog_message('error', 'Cache adapter \"'.$this->_adapter.'\" and backup \"'.$this->_backup_driver.'\" are both unavailable. Cache is now using \"Dummy\" adapter.');\n\t\t\t\t$this->_adapter = 'dummy';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Backup is supported. Set it to primary.\n\t\t\t\tlog_message('debug', 'Cache adapter \"'.$this->_adapter.'\" is unavailable. Falling back to \"'.$this->_backup_driver.'\" backup adapter.');\n\t\t\t\t$this->_adapter = $this->_backup_driver;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get\n\t *\n\t * Look for a value in the cache. If it exists, return the data\n\t * if not, return FALSE\n\t *\n\t * @param\tstring\t$id\n\t * @return\tmixed\tvalue matching $id or FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\treturn $this->{$this->_adapter}->get($this->key_prefix.$id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttl\tCache TTL (in seconds)\n\t * @param\tbool\t$raw\tWhether to store the raw value\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\treturn $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl, $raw);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn $this->{$this->_adapter}->delete($this->key_prefix.$id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn $this->{$this->_adapter}->increment($this->key_prefix.$id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn $this->{$this->_adapter}->decrement($this->key_prefix.$id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function clean()\n\t{\n\t\treturn $this->{$this->_adapter}->clean();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @param\tstring\t$type = 'user'\tuser/filehits\n\t * @return\tmixed\tarray containing cache info on success OR FALSE on failure\n\t */\n\tpublic function cache_info($type = 'user')\n\t{\n\t\treturn $this->{$this->_adapter}->cache_info($type);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tstring\t$id\tkey to get cache metadata on\n\t * @return\tmixed\tcache item metadata\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\treturn $this->{$this->_adapter}->get_metadata($this->key_prefix.$id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is the requested driver supported in this environment?\n\t *\n\t * @param\tstring\t$driver\tThe driver to test\n\t * @return\tarray\n\t */\n\tpublic function is_supported($driver)\n\t{\n\t\tstatic $support;\n\n\t\tif ( ! isset($support, $support[$driver]))\n\t\t{\n\t\t\t$support[$driver] = $this->{$driver}->is_supported();\n\t\t}\n\n\t\treturn $support[$driver];\n\t}\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/drivers/Cache_apc.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 2.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter APC Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_apc extends CI_Driver {\n\n\t/**\n\t * Get\n\t *\n\t * Look for a value in the cache. If it exists, return the data\n\t * if not, return FALSE\n\t *\n\t * @param\tstring\n\t * @return\tmixed\tvalue that is stored/FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$success = FALSE;\n\t\t$data = apc_fetch($id, $success);\n\n\t\tif ($success === TRUE)\n\t\t{\n\t\t\treturn is_array($data)\n\t\t\t\t? unserialize($data[0])\n\t\t\t\t: $data;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttol\tLength of time (in seconds) to cache the data\n\t * @param\tbool\t$raw\tWhether to store the raw value\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\t$ttl = (int) $ttl;\n\n\t\treturn apc_store(\n\t\t\t$id,\n\t\t\t($raw === TRUE ? $data : array(serialize($data), time(), $ttl)),\n\t\t\t$ttl\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of the item in the cache\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn apc_delete($id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn apc_inc($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn apc_dec($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn apc_clear_cache('user');\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @param\tstring\tuser/filehits\n\t * @return\tmixed\tarray on success, false on failure\n\t */\n\t public function cache_info($type = NULL)\n\t {\n\t\t return apc_cache_info($type);\n\t }\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tmixed\tarray on success/false on failure\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\t$success = FALSE;\n\t\t$stored = apc_fetch($id, $success);\n\n\t\tif ($success === FALSE OR count($stored) !== 3)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tlist($data, $time, $ttl) = $stored;\n\n\t\treturn array(\n\t\t\t'expire'\t=> $time + $ttl,\n\t\t\t'mtime'\t\t=> $time,\n\t\t\t'data'\t\t=> unserialize($data)\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * is_supported()\n\t *\n\t * Check to see if APC is available on this system, bail if it isn't.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\tif ( ! extension_loaded('apc') OR ! ini_get('apc.enabled'))\n\t\t{\n\t\t\tlog_message('debug', 'The APC PHP extension must be loaded to use APC Cache.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/drivers/Cache_dummy.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 2.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Dummy Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_dummy extends CI_Driver {\n\n\t/**\n\t * Get\n\t *\n\t * Since this is the dummy class, it's always going to return FALSE.\n\t *\n\t * @param\tstring\n\t * @return\tbool\tFALSE\n\t */\n\tpublic function get($id)\n\t{\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\tUnique Key\n\t * @param\tmixed\tData to store\n\t * @param\tint\tLength of time (in seconds) to cache the data\n\t * @param\tbool\tWhether to store the raw value\n\t * @return\tbool\tTRUE, Simulating success\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of the item in the cache\n\t * @return\tbool\tTRUE, simulating success\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tTRUE, simulating success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @param\tstring\tuser/filehits\n\t * @return\tbool\tFALSE\n\t */\n\t public function cache_info($type = NULL)\n\t {\n\t\t return FALSE;\n\t }\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tbool\tFALSE\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is this caching driver supported on the system?\n\t * Of course this one is.\n\t *\n\t * @return\tbool\tTRUE\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/drivers/Cache_file.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 2.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter File Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_file extends CI_Driver {\n\n\t/**\n\t * Directory in which to save cache files\n\t *\n\t * @var string\n\t */\n\tprotected $_cache_path;\n\n\t/**\n\t * Initialize file-based cache\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->load->helper('file');\n\t\t$path = $CI->config->item('cache_path');\n\t\t$this->_cache_path = ($path === '') ? APPPATH.'cache/' : $path;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Fetch from cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tmixed\tData on success, FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$data = $this->_get($id);\n\t\treturn is_array($data) ? $data['data'] : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Save into cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttl\tTime to live in seconds\n\t * @param\tbool\t$raw\tWhether to store the raw value (unused)\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\t$contents = array(\n\t\t\t'time'\t\t=> time(),\n\t\t\t'ttl'\t\t=> $ttl,\n\t\t\t'data'\t\t=> $data\n\t\t);\n\n\t\tif (write_file($this->_cache_path.$id, serialize($contents)))\n\t\t{\n\t\t\tchmod($this->_cache_path.$id, 0640);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of item in cache\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn file_exists($this->_cache_path.$id) ? unlink($this->_cache_path.$id) : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tNew value on success, FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\t$data = $this->_get($id);\n\n\t\tif ($data === FALSE)\n\t\t{\n\t\t\t$data = array('data' => 0, 'ttl' => 60);\n\t\t}\n\t\telseif ( ! is_int($data['data']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$new_value = $data['data'] + $offset;\n\t\treturn $this->save($id, $new_value, $data['ttl'])\n\t\t\t? $new_value\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tNew value on success, FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\t$data = $this->_get($id);\n\n\t\tif ($data === FALSE)\n\t\t{\n\t\t\t$data = array('data' => 0, 'ttl' => 60);\n\t\t}\n\t\telseif ( ! is_int($data['data']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$new_value = $data['data'] - $offset;\n\t\treturn $this->save($id, $new_value, $data['ttl'])\n\t\t\t? $new_value\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the Cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn delete_files($this->_cache_path, FALSE, TRUE);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * Not supported by file-based caching\n\t *\n\t * @param\tstring\tuser/filehits\n\t * @return\tmixed\tFALSE\n\t */\n\tpublic function cache_info($type = NULL)\n\t{\n\t\treturn get_dir_file_info($this->_cache_path);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tmixed\tFALSE on failure, array on success.\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\tif ( ! file_exists($this->_cache_path.$id))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$data = unserialize(file_get_contents($this->_cache_path.$id));\n\n\t\tif (is_array($data))\n\t\t{\n\t\t\t$mtime = filemtime($this->_cache_path.$id);\n\n\t\t\tif ( ! isset($data['ttl']))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\treturn array(\n\t\t\t\t'expire' => $mtime + $data['ttl'],\n\t\t\t\t'mtime'\t => $mtime\n\t\t\t);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is supported\n\t *\n\t * In the file driver, check to see that the cache directory is indeed writable\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn is_really_writable($this->_cache_path);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get all data\n\t *\n\t * Internal method to get all the relevant data about a cache item\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tmixed\tData array on success or FALSE on failure\n\t */\n\tprotected function _get($id)\n\t{\n\t\tif ( ! is_file($this->_cache_path.$id))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$data = unserialize(file_get_contents($this->_cache_path.$id));\n\n\t\tif ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl'])\n\t\t{\n\t\t\tunlink($this->_cache_path.$id);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $data;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/drivers/Cache_memcached.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 2.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Memcached Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_memcached extends CI_Driver {\n\n\t/**\n\t * Holds the memcached object\n\t *\n\t * @var object\n\t */\n\tprotected $_memcached;\n\n\t/**\n\t * Memcached configuration\n\t *\n\t * @var array\n\t */\n\tprotected $_memcache_conf = array(\n\t\t'default' => array(\n\t\t\t'host'\t\t=> '127.0.0.1',\n\t\t\t'port'\t\t=> 11211,\n\t\t\t'weight'\t=> 1\n\t\t)\n\t);\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Setup Memcache(d)\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t// Try to load memcached server info from the config file.\n\t\t$CI =& get_instance();\n\t\t$defaults = $this->_memcache_conf['default'];\n\n\t\tif ($CI->config->load('memcached', TRUE, TRUE))\n\t\t{\n\t\t\tif (is_array($CI->config->config['memcached']))\n\t\t\t{\n\t\t\t\t$this->_memcache_conf = array();\n\n\t\t\t\tforeach ($CI->config->config['memcached'] as $name => $conf)\n\t\t\t\t{\n\t\t\t\t\t$this->_memcache_conf[$name] = $conf;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (class_exists('Memcached', FALSE))\n\t\t{\n\t\t\t$this->_memcached = new Memcached();\n\t\t}\n\t\telseif (class_exists('Memcache', FALSE))\n\t\t{\n\t\t\t$this->_memcached = new Memcache();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?');\n\t\t}\n\n\t\tforeach ($this->_memcache_conf as $cache_server)\n\t\t{\n\t\t\tisset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host'];\n\t\t\tisset($cache_server['port']) OR $cache_server['port'] = $defaults['port'];\n\t\t\tisset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight'];\n\n\t\t\tif (get_class($this->_memcached) === 'Memcache')\n\t\t\t{\n\t\t\t\t// Third parameter is persistance and defaults to TRUE.\n\t\t\t\t$this->_memcached->addServer(\n\t\t\t\t\t$cache_server['hostname'],\n\t\t\t\t\t$cache_server['port'],\n\t\t\t\t\tTRUE,\n\t\t\t\t\t$cache_server['weight']\n\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_memcached->addServer(\n\t\t\t\t\t$cache_server['hostname'],\n\t\t\t\t\t$cache_server['port'],\n\t\t\t\t\t$cache_server['weight']\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Fetch from cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tmixed\tData on success, FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$data = $this->_memcached->get($id);\n\n\t\treturn is_array($data) ? $data[0] : $data;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData being cached\n\t * @param\tint\t$ttl\tTime to live\n\t * @param\tbool\t$raw\tWhether to store the raw value\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\tif ($raw !== TRUE)\n\t\t{\n\t\t\t$data = array($data, time(), $ttl);\n\t\t}\n\n\t\tif (get_class($this->_memcached) === 'Memcached')\n\t\t{\n\t\t\treturn $this->_memcached->set($id, $data, $ttl);\n\t\t}\n\t\telseif (get_class($this->_memcached) === 'Memcache')\n\t\t{\n\t\t\treturn $this->_memcached->set($id, $data, 0, $ttl);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tkey to be deleted.\n\t * @return\tbool\ttrue on success, false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn $this->_memcached->delete($id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn $this->_memcached->increment($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn $this->_memcached->decrement($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the Cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn $this->_memcached->flush();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @return\tmixed\tarray on success, false on failure\n\t */\n\tpublic function cache_info()\n\t{\n\t\treturn $this->_memcached->getStats();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tmixed\tFALSE on failure, array on success.\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\t$stored = $this->_memcached->get($id);\n\n\t\tif (count($stored) !== 3)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tlist($data, $time, $ttl) = $stored;\n\n\t\treturn array(\n\t\t\t'expire'\t=> $time + $ttl,\n\t\t\t'mtime'\t\t=> $time,\n\t\t\t'data'\t\t=> $data\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is supported\n\t *\n\t * Returns FALSE if memcached is not supported on the system.\n\t * If it is, we setup the memcached object & return TRUE\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn (extension_loaded('memcached') OR extension_loaded('memcache'));\n\t}\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/drivers/Cache_redis.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Redis Caching Class\n *\n * @package\t   CodeIgniter\n * @subpackage Libraries\n * @category   Core\n * @author\t   Anton Lindqvist <anton@qvister.se>\n * @link\n */\nclass CI_Cache_redis extends CI_Driver\n{\n\t/**\n\t * Default config\n\t *\n\t * @static\n\t * @var\tarray\n\t */\n\tprotected static $_default_config = array(\n\t\t'socket_type' => 'tcp',\n\t\t'host' => '127.0.0.1',\n\t\t'password' => NULL,\n\t\t'port' => 6379,\n\t\t'timeout' => 0\n\t);\n\n\t/**\n\t * Redis connection\n\t *\n\t * @var\tRedis\n\t */\n\tprotected $_redis;\n\n\t/**\n\t * An internal cache for storing keys of serialized values.\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_serialized = array();\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Setup Redis\n\t *\n\t * Loads Redis config file if present. Will halt execution\n\t * if a Redis connection can't be established.\n\t *\n\t * @return\tvoid\n\t * @see\t\tRedis::connect()\n\t */\n\tpublic function __construct()\n\t{\n\t\t$config = array();\n\t\t$CI =& get_instance();\n\n\t\tif ($CI->config->load('redis', TRUE, TRUE))\n\t\t{\n\t\t\t$config = $CI->config->item('redis');\n\t\t}\n\n\t\t$config = array_merge(self::$_default_config, $config);\n\t\t$this->_redis = new Redis();\n\n\t\ttry\n\t\t{\n\t\t\tif ($config['socket_type'] === 'unix')\n\t\t\t{\n\t\t\t\t$success = $this->_redis->connect($config['socket']);\n\t\t\t}\n\t\t\telse // tcp socket\n\t\t\t{\n\t\t\t\t$success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);\n\t\t\t}\n\n\t\t\tif ( ! $success)\n\t\t\t{\n\t\t\t\tlog_message('error', 'Cache: Redis connection failed. Check your configuration.');\n\t\t\t}\n\n\t\t\tif (isset($config['password']) && ! $this->_redis->auth($config['password']))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Cache: Redis authentication failed.');\n\t\t\t}\n\t\t}\n\t\tcatch (RedisException $e)\n\t\t{\n\t\t\tlog_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');\n\t\t}\n\n\t\t// Initialize the index of serialized values.\n\t\t$serialized = $this->_redis->sMembers('_ci_redis_serialized');\n\t\tempty($serialized) OR $this->_serialized = array_flip($serialized);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get cache\n\t *\n\t * @param\tstring\tCache ID\n\t * @return\tmixed\n\t */\n\tpublic function get($key)\n\t{\n\t\t$value = $this->_redis->get($key);\n\n\t\tif ($value !== FALSE && isset($this->_serialized[$key]))\n\t\t{\n\t\t\treturn unserialize($value);\n\t\t}\n\n\t\treturn $value;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Save cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to save\n\t * @param\tint\t$ttl\tTime to live in seconds\n\t * @param\tbool\t$raw\tWhether to store the raw value (unused)\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\tif (is_array($data) OR is_object($data))\n\t\t{\n\t\t\tif ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tisset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE;\n\t\t\t$data = serialize($data);\n\t\t}\n\t\telseif (isset($this->_serialized[$id]))\n\t\t{\n\t\t\t$this->_serialized[$id] = NULL;\n\t\t\t$this->_redis->sRemove('_ci_redis_serialized', $id);\n\t\t}\n\n\t\treturn $this->_redis->set($id, $data, $ttl);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from cache\n\t *\n\t * @param\tstring\tCache key\n\t * @return\tbool\n\t */\n\tpublic function delete($key)\n\t{\n\t\tif ($this->_redis->delete($key) !== 1)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (isset($this->_serialized[$key]))\n\t\t{\n\t\t\t$this->_serialized[$key] = NULL;\n\t\t\t$this->_redis->sRemove('_ci_redis_serialized', $key);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn $this->_redis->incr($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn $this->_redis->decr($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean cache\n\t *\n\t * @return\tbool\n\t * @see\t\tRedis::flushDB()\n\t */\n\tpublic function clean()\n\t{\n\t\treturn $this->_redis->flushDB();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get cache driver info\n\t *\n\t * @param\tstring\tNot supported in Redis.\n\t *\t\t\tOnly included in order to offer a\n\t *\t\t\tconsistent cache API.\n\t * @return\tarray\n\t * @see\t\tRedis::info()\n\t */\n\tpublic function cache_info($type = NULL)\n\t{\n\t\treturn $this->_redis->info();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get cache metadata\n\t *\n\t * @param\tstring\tCache key\n\t * @return\tarray\n\t */\n\tpublic function get_metadata($key)\n\t{\n\t\t$value = $this->get($key);\n\n\t\tif ($value !== FALSE)\n\t\t{\n\t\t\treturn array(\n\t\t\t\t'expire' => time() + $this->_redis->ttl($key),\n\t\t\t\t'data' => $value\n\t\t\t);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Check if Redis driver is supported\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn extension_loaded('redis');\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class destructor\n\t *\n\t * Closes the connection to Redis if present.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __destruct()\n\t{\n\t\tif ($this->_redis)\n\t\t{\n\t\t\t$this->_redis->close();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/drivers/Cache_wincache.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Wincache Caching Class\n *\n * Read more about Wincache functions here:\n * http://www.php.net/manual/en/ref.wincache.php\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tMike Murkovic\n * @link\n */\nclass CI_Cache_wincache extends CI_Driver {\n\n\t/**\n\t * Get\n\t *\n\t * Look for a value in the cache. If it exists, return the data,\n\t * if not, return FALSE\n\t *\n\t * @param\tstring\t$id\tCache Ide\n\t * @return\tmixed\tValue that is stored/FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$success = FALSE;\n\t\t$data = wincache_ucache_get($id, $success);\n\n\t\t// Success returned by reference from wincache_ucache_get()\n\t\treturn ($success) ? $data : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttl\tTime to live (in seconds)\n\t * @param\tbool\t$raw\tWhether to store the raw value (unused)\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\treturn wincache_ucache_set($id, $data, $ttl);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of the item in the cache\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn wincache_ucache_delete($id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\t$success = FALSE;\n\t\t$value = wincache_ucache_inc($id, $offset, $success);\n\n\t\treturn ($success === TRUE) ? $value : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\t$success = FALSE;\n\t\t$value = wincache_ucache_dec($id, $offset, $success);\n\n\t\treturn ($success === TRUE) ? $value : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn wincache_ucache_clear();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @return\tmixed\tarray on success, false on failure\n\t */\n\t public function cache_info()\n\t {\n\t\t return wincache_ucache_info(TRUE);\n\t }\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tmixed\tarray on success/false on failure\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\tif ($stored = wincache_ucache_info(FALSE, $id))\n\t\t{\n\t\t\t$age = $stored['ucache_entries'][1]['age_seconds'];\n\t\t\t$ttl = $stored['ucache_entries'][1]['ttl_seconds'];\n\t\t\t$hitcount = $stored['ucache_entries'][1]['hitcount'];\n\n\t\t\treturn array(\n\t\t\t\t'expire'\t=> $ttl - $age,\n\t\t\t\t'hitcount'\t=> $hitcount,\n\t\t\t\t'age'\t\t=> $age,\n\t\t\t\t'ttl'\t\t=> $ttl\n\t\t\t);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * is_supported()\n\t *\n\t * Check to see if WinCache is available on this system, bail if it isn't.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\tif ( ! extension_loaded('wincache') OR ! ini_get('wincache.ucenabled'))\n\t\t{\n\t\t\tlog_message('debug', 'The Wincache PHP extension must be loaded to use Wincache Cache.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/drivers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cache/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Calendar.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Calendar Class\n *\n * This class enables the creation of calendars\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/calendar.html\n */\nclass CI_Calendar {\n\n\t/**\n\t * Calendar layout template\n\t *\n\t * @var mixed\n\t */\n\tpublic $template = '';\n\n\t/**\n\t * Replacements array for template\n\t *\n\t * @var array\n\t */\n\tpublic $replacements = array();\n\n\t/**\n\t * Day of the week to start the calendar on\n\t *\n\t * @var string\n\t */\n\tpublic $start_day = 'sunday';\n\n\t/**\n\t * How to display months\n\t *\n\t * @var string\n\t */\n\tpublic $month_type = 'long';\n\n\t/**\n\t * How to display names of days\n\t *\n\t * @var string\n\t */\n\tpublic $day_type = 'abr';\n\n\t/**\n\t * Whether to show next/prev month links\n\t *\n\t * @var bool\n\t */\n\tpublic $show_next_prev = FALSE;\n\n\t/**\n\t * Url base to use for next/prev month links\n\t *\n\t * @var bool\n\t */\n\tpublic $next_prev_url = '';\n\n\t/**\n\t * Show days of other months\n\t *\n\t * @var bool\n\t */\n\tpublic $show_other_days = FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CI Singleton\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Loads the calendar language file and sets the default time reference.\n\t *\n\t * @uses\tCI_Lang::$is_loaded\n\t *\n\t * @param\tarray\t$config\tCalendar options\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t$this->CI =& get_instance();\n\t\t$this->CI->lang->load('calendar');\n\n\t\tempty($config) OR $this->initialize($config);\n\n\t\tlog_message('info', 'Calendar Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize the user preferences\n\t *\n\t * Accepts an associative array as input, containing display preferences\n\t *\n\t * @param\tarray\tconfig preferences\n\t * @return\tCI_Calendar\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\tif (isset($this->$key))\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\t// Set the next_prev_url to the controller if required but not defined\n\t\tif ($this->show_next_prev === TRUE && empty($this->next_prev_url))\n\t\t{\n\t\t\t$this->next_prev_url = $this->CI->config->site_url($this->CI->router->class.'/'.$this->CI->router->method);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate the calendar\n\t *\n\t * @param\tint\tthe year\n\t * @param\tint\tthe month\n\t * @param\tarray\tthe data to be shown in the calendar cells\n\t * @return\tstring\n\t */\n\tpublic function generate($year = '', $month = '', $data = array())\n\t{\n\t\t$local_time = time();\n\n\t\t// Set and validate the supplied month/year\n\t\tif (empty($year))\n\t\t{\n\t\t\t$year = date('Y', $local_time);\n\t\t}\n\t\telseif (strlen($year) === 1)\n\t\t{\n\t\t\t$year = '200'.$year;\n\t\t}\n\t\telseif (strlen($year) === 2)\n\t\t{\n\t\t\t$year = '20'.$year;\n\t\t}\n\n\t\tif (empty($month))\n\t\t{\n\t\t\t$month = date('m', $local_time);\n\t\t}\n\t\telseif (strlen($month) === 1)\n\t\t{\n\t\t\t$month = '0'.$month;\n\t\t}\n\n\t\t$adjusted_date = $this->adjust_date($month, $year);\n\n\t\t$month\t= $adjusted_date['month'];\n\t\t$year\t= $adjusted_date['year'];\n\n\t\t// Determine the total days in the month\n\t\t$total_days = $this->get_total_days($month, $year);\n\n\t\t// Set the starting day of the week\n\t\t$start_days\t= array('sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6);\n\t\t$start_day\t= isset($start_days[$this->start_day]) ? $start_days[$this->start_day] : 0;\n\n\t\t// Set the starting day number\n\t\t$local_date = mktime(12, 0, 0, $month, 1, $year);\n\t\t$date = getdate($local_date);\n\t\t$day  = $start_day + 1 - $date['wday'];\n\n\t\twhile ($day > 1)\n\t\t{\n\t\t\t$day -= 7;\n\t\t}\n\n\t\t// Set the current month/year/day\n\t\t// We use this to determine the \"today\" date\n\t\t$cur_year\t= date('Y', $local_time);\n\t\t$cur_month\t= date('m', $local_time);\n\t\t$cur_day\t= date('j', $local_time);\n\n\t\t$is_current_month = ($cur_year == $year && $cur_month == $month);\n\n\t\t// Generate the template data array\n\t\t$this->parse_template();\n\n\t\t// Begin building the calendar output\n\t\t$out = $this->replacements['table_open'].\"\\n\\n\".$this->replacements['heading_row_start'].\"\\n\";\n\n\t\t// \"previous\" month link\n\t\tif ($this->show_next_prev === TRUE)\n\t\t{\n\t\t\t// Add a trailing slash to the URL if needed\n\t\t\t$this->next_prev_url = preg_replace('/(.+?)\\/*$/', '\\\\1/', $this->next_prev_url);\n\n\t\t\t$adjusted_date = $this->adjust_date($month - 1, $year);\n\t\t\t$out .= str_replace('{previous_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->replacements['heading_previous_cell']).\"\\n\";\n\t\t}\n\n\t\t// Heading containing the month/year\n\t\t$colspan = ($this->show_next_prev === TRUE) ? 5 : 7;\n\n\t\t$this->replacements['heading_title_cell'] = str_replace('{colspan}', $colspan,\n\t\t\t\t\t\t\t\tstr_replace('{heading}', $this->get_month_name($month).'&nbsp;'.$year, $this->replacements['heading_title_cell']));\n\n\t\t$out .= $this->replacements['heading_title_cell'].\"\\n\";\n\n\t\t// \"next\" month link\n\t\tif ($this->show_next_prev === TRUE)\n\t\t{\n\t\t\t$adjusted_date = $this->adjust_date($month + 1, $year);\n\t\t\t$out .= str_replace('{next_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->replacements['heading_next_cell']);\n\t\t}\n\n\t\t$out .= \"\\n\".$this->replacements['heading_row_end'].\"\\n\\n\"\n\t\t\t// Write the cells containing the days of the week\n\t\t\t.$this->replacements['week_row_start'].\"\\n\";\n\n\t\t$day_names = $this->get_day_names();\n\n\t\tfor ($i = 0; $i < 7; $i ++)\n\t\t{\n\t\t\t$out .= str_replace('{week_day}', $day_names[($start_day + $i) %7], $this->replacements['week_day_cell']);\n\t\t}\n\n\t\t$out .= \"\\n\".$this->replacements['week_row_end'].\"\\n\";\n\n\t\t// Build the main body of the calendar\n\t\twhile ($day <= $total_days)\n\t\t{\n\t\t\t$out .= \"\\n\".$this->replacements['cal_row_start'].\"\\n\";\n\n\t\t\tfor ($i = 0; $i < 7; $i++)\n\t\t\t{\n\t\t\t\tif ($day > 0 && $day <= $total_days)\n\t\t\t\t{\n\t\t\t\t\t$out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->replacements['cal_cell_start_today'] : $this->replacements['cal_cell_start'];\n\n\t\t\t\t\tif (isset($data[$day]))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Cells with content\n\t\t\t\t\t\t$temp = ($is_current_month === TRUE && $day == $cur_day) ?\n\t\t\t\t\t\t\t\t$this->replacements['cal_cell_content_today'] : $this->replacements['cal_cell_content'];\n\t\t\t\t\t\t$out .= str_replace(array('{content}', '{day}'), array($data[$day], $day), $temp);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Cells with no content\n\t\t\t\t\t\t$temp = ($is_current_month === TRUE && $day == $cur_day) ?\n\t\t\t\t\t\t\t\t$this->replacements['cal_cell_no_content_today'] : $this->replacements['cal_cell_no_content'];\n\t\t\t\t\t\t$out .= str_replace('{day}', $day, $temp);\n\t\t\t\t\t}\n\n\t\t\t\t\t$out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->replacements['cal_cell_end_today'] : $this->replacements['cal_cell_end'];\n\t\t\t\t}\n\t\t\t\telseif ($this->show_other_days === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$out .= $this->replacements['cal_cell_start_other'];\n\n\t\t\t\t\tif ($day <= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Day of previous month\n\t\t\t\t\t\t$prev_month = $this->adjust_date($month - 1, $year);\n\t\t\t\t\t\t$prev_month_days = $this->get_total_days($prev_month['month'], $prev_month['year']);\n\t\t\t\t\t\t$out .= str_replace('{day}', $prev_month_days + $day, $this->replacements['cal_cell_other']);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Day of next month\n\t\t\t\t\t\t$out .= str_replace('{day}', $day - $total_days, $this->replacements['cal_cell_other']);\n\t\t\t\t\t}\n\n\t\t\t\t\t$out .= $this->replacements['cal_cell_end_other'];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Blank cells\n\t\t\t\t\t$out .= $this->replacements['cal_cell_start'].$this->replacements['cal_cell_blank'].$this->replacements['cal_cell_end'];\n\t\t\t\t}\n\n\t\t\t\t$day++;\n\t\t\t}\n\n\t\t\t$out .= \"\\n\".$this->replacements['cal_row_end'].\"\\n\";\n\t\t}\n\n\t\treturn $out .= \"\\n\".$this->replacements['table_close'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Month Name\n\t *\n\t * Generates a textual month name based on the numeric\n\t * month provided.\n\t *\n\t * @param\tint\tthe month\n\t * @return\tstring\n\t */\n\tpublic function get_month_name($month)\n\t{\n\t\tif ($this->month_type === 'short')\n\t\t{\n\t\t\t$month_names = array('01' => 'cal_jan', '02' => 'cal_feb', '03' => 'cal_mar', '04' => 'cal_apr', '05' => 'cal_may', '06' => 'cal_jun', '07' => 'cal_jul', '08' => 'cal_aug', '09' => 'cal_sep', '10' => 'cal_oct', '11' => 'cal_nov', '12' => 'cal_dec');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$month_names = array('01' => 'cal_january', '02' => 'cal_february', '03' => 'cal_march', '04' => 'cal_april', '05' => 'cal_mayl', '06' => 'cal_june', '07' => 'cal_july', '08' => 'cal_august', '09' => 'cal_september', '10' => 'cal_october', '11' => 'cal_november', '12' => 'cal_december');\n\t\t}\n\n\t\treturn ($this->CI->lang->line($month_names[$month]) === FALSE)\n\t\t\t? ucfirst(substr($month_names[$month], 4))\n\t\t\t: $this->CI->lang->line($month_names[$month]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Day Names\n\t *\n\t * Returns an array of day names (Sunday, Monday, etc.) based\n\t * on the type. Options: long, short, abr\n\t *\n\t * @param\tstring\n\t * @return\tarray\n\t */\n\tpublic function get_day_names($day_type = '')\n\t{\n\t\tif ($day_type !== '')\n\t\t{\n\t\t\t$this->day_type = $day_type;\n\t\t}\n\n\t\tif ($this->day_type === 'long')\n\t\t{\n\t\t\t$day_names = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');\n\t\t}\n\t\telseif ($this->day_type === 'short')\n\t\t{\n\t\t\t$day_names = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$day_names = array('su', 'mo', 'tu', 'we', 'th', 'fr', 'sa');\n\t\t}\n\n\t\t$days = array();\n\t\tfor ($i = 0, $c = count($day_names); $i < $c; $i++)\n\t\t{\n\t\t\t$days[] = ($this->CI->lang->line('cal_'.$day_names[$i]) === FALSE) ? ucfirst($day_names[$i]) : $this->CI->lang->line('cal_'.$day_names[$i]);\n\t\t}\n\n\t\treturn $days;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Adjust Date\n\t *\n\t * This function makes sure that we have a valid month/year.\n\t * For example, if you submit 13 as the month, the year will\n\t * increment and the month will become January.\n\t *\n\t * @param\tint\tthe month\n\t * @param\tint\tthe year\n\t * @return\tarray\n\t */\n\tpublic function adjust_date($month, $year)\n\t{\n\t\t$date = array();\n\n\t\t$date['month']\t= $month;\n\t\t$date['year']\t= $year;\n\n\t\twhile ($date['month'] > 12)\n\t\t{\n\t\t\t$date['month'] -= 12;\n\t\t\t$date['year']++;\n\t\t}\n\n\t\twhile ($date['month'] <= 0)\n\t\t{\n\t\t\t$date['month'] += 12;\n\t\t\t$date['year']--;\n\t\t}\n\n\t\tif (strlen($date['month']) === 1)\n\t\t{\n\t\t\t$date['month'] = '0'.$date['month'];\n\t\t}\n\n\t\treturn $date;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Total days in a given month\n\t *\n\t * @param\tint\tthe month\n\t * @param\tint\tthe year\n\t * @return\tint\n\t */\n\tpublic function get_total_days($month, $year)\n\t{\n\t\t$this->CI->load->helper('date');\n\t\treturn days_in_month($month, $year);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Default Template Data\n\t *\n\t * This is used in the event that the user has not created their own template\n\t *\n\t * @return\tarray\n\t */\n\tpublic function default_template()\n\t{\n\t\treturn array(\n\t\t\t'table_open'\t\t\t\t=> '<table border=\"0\" cellpadding=\"4\" cellspacing=\"0\">',\n\t\t\t'heading_row_start'\t\t\t=> '<tr>',\n\t\t\t'heading_previous_cell'\t\t=> '<th><a href=\"{previous_url}\">&lt;&lt;</a></th>',\n\t\t\t'heading_title_cell'\t\t=> '<th colspan=\"{colspan}\">{heading}</th>',\n\t\t\t'heading_next_cell'\t\t\t=> '<th><a href=\"{next_url}\">&gt;&gt;</a></th>',\n\t\t\t'heading_row_end'\t\t\t=> '</tr>',\n\t\t\t'week_row_start'\t\t\t=> '<tr>',\n\t\t\t'week_day_cell'\t\t\t\t=> '<td>{week_day}</td>',\n\t\t\t'week_row_end'\t\t\t\t=> '</tr>',\n\t\t\t'cal_row_start'\t\t\t\t=> '<tr>',\n\t\t\t'cal_cell_start'\t\t\t=> '<td>',\n\t\t\t'cal_cell_start_today'\t\t=> '<td>',\n\t\t\t'cal_cell_start_other'\t\t=> '<td style=\"color: #666;\">',\n\t\t\t'cal_cell_content'\t\t\t=> '<a href=\"{content}\">{day}</a>',\n\t\t\t'cal_cell_content_today'\t=> '<a href=\"{content}\"><strong>{day}</strong></a>',\n\t\t\t'cal_cell_no_content'\t\t=> '{day}',\n\t\t\t'cal_cell_no_content_today'\t=> '<strong>{day}</strong>',\n\t\t\t'cal_cell_blank'\t\t\t=> '&nbsp;',\n\t\t\t'cal_cell_other'\t\t\t=> '{day}',\n\t\t\t'cal_cell_end'\t\t\t\t=> '</td>',\n\t\t\t'cal_cell_end_today'\t\t=> '</td>',\n\t\t\t'cal_cell_end_other'\t\t=> '</td>',\n\t\t\t'cal_row_end'\t\t\t\t=> '</tr>',\n\t\t\t'table_close'\t\t\t\t=> '</table>'\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse Template\n\t *\n\t * Harvests the data within the template {pseudo-variables}\n\t * used to display the calendar\n\t *\n\t * @return\tCI_Calendar\n\t */\n\tpublic function parse_template()\n\t{\n\t\t$this->replacements = $this->default_template();\n\n\t\tif (empty($this->template))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\n\t\tif (is_string($this->template))\n\t\t{\n\t\t\t$today = array('cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today');\n\n\t\t\tforeach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today', 'cal_cell_start_other', 'cal_cell_other', 'cal_cell_end_other') as $val)\n\t\t\t{\n\t\t\t\tif (preg_match('/\\{'.$val.'\\}(.*?)\\{\\/'.$val.'\\}/si', $this->template, $match))\n\t\t\t\t{\n\t\t\t\t\t$this->replacements[$val] = $match[1];\n\t\t\t\t}\n\t\t\t\telseif (in_array($val, $today, TRUE))\n\t\t\t\t{\n\t\t\t\t\t$this->replacements[$val] = $this->replacements[substr($val, 0, -6)];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telseif (is_array($this->template))\n\t\t{\n\t\t\t$this->replacements = array_merge($this->replacements, $this->template);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Cart.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Shopping Cart Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tShopping Cart\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/cart.html\n * @deprecated\t3.0.0\tThis class is too specific for CI.\n */\nclass CI_Cart {\n\n\t/**\n\t * These are the regular expression rules that we use to validate the product ID and product name\n\t * alpha-numeric, dashes, underscores, or periods\n\t *\n\t * @var string\n\t */\n\tpublic $product_id_rules = '\\.a-z0-9_-';\n\n\t/**\n\t * These are the regular expression rules that we use to validate the product ID and product name\n\t * alpha-numeric, dashes, underscores, colons or periods\n\t *\n\t * @var string\n\t */\n\tpublic $product_name_rules = '\\w \\-\\.\\:';\n\n\t/**\n\t * only allow safe product names\n\t *\n\t * @var bool\n\t */\n\tpublic $product_name_safe = TRUE;\n\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Reference to CodeIgniter instance\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t/**\n\t * Contents of the cart\n\t *\n\t * @var array\n\t */\n\tprotected $_cart_contents = array();\n\n\t/**\n\t * Shopping Class Constructor\n\t *\n\t * The constructor loads the Session class, used to store the shopping cart contents.\n\t *\n\t * @param\tarray\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params = array())\n\t{\n\t\t// Set the super object to a local variable for use later\n\t\t$this->CI =& get_instance();\n\n\t\t// Are any config settings being passed manually?  If so, set them\n\t\t$config = is_array($params) ? $params : array();\n\n\t\t// Load the Sessions class\n\t\t$this->CI->load->driver('session', $config);\n\n\t\t// Grab the shopping cart array from the session table\n\t\t$this->_cart_contents = $this->CI->session->userdata('cart_contents');\n\t\tif ($this->_cart_contents === NULL)\n\t\t{\n\t\t\t// No cart exists so we'll set some base values\n\t\t\t$this->_cart_contents = array('cart_total' => 0, 'total_items' => 0);\n\t\t}\n\n\t\tlog_message('info', 'Cart Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert items into the cart and save it to the session table\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function insert($items = array())\n\t{\n\t\t// Was any cart data passed? No? Bah...\n\t\tif ( ! is_array($items) OR count($items) === 0)\n\t\t{\n\t\t\tlog_message('error', 'The insert method must be passed an array containing data.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// You can either insert a single product using a one-dimensional array,\n\t\t// or multiple products using a multi-dimensional one. The way we\n\t\t// determine the array type is by looking for a required array key named \"id\"\n\t\t// at the top level. If it's not found, we will assume it's a multi-dimensional array.\n\n\t\t$save_cart = FALSE;\n\t\tif (isset($items['id']))\n\t\t{\n\t\t\tif (($rowid = $this->_insert($items)))\n\t\t\t{\n\t\t\t\t$save_cart = TRUE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($items as $val)\n\t\t\t{\n\t\t\t\tif (is_array($val) && isset($val['id']))\n\t\t\t\t{\n\t\t\t\t\tif ($this->_insert($val))\n\t\t\t\t\t{\n\t\t\t\t\t\t$save_cart = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Save the cart data if the insert was successful\n\t\tif ($save_cart === TRUE)\n\t\t{\n\t\t\t$this->_save_cart();\n\t\t\treturn isset($rowid) ? $rowid : TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tprotected function _insert($items = array())\n\t{\n\t\t// Was any cart data passed? No? Bah...\n\t\tif ( ! is_array($items) OR count($items) === 0)\n\t\t{\n\t\t\tlog_message('error', 'The insert method must be passed an array containing data.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Does the $items array contain an id, quantity, price, and name?  These are required\n\t\tif ( ! isset($items['id'], $items['qty'], $items['price'], $items['name']))\n\t\t{\n\t\t\tlog_message('error', 'The cart array must contain a product ID, quantity, price, and name.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Prep the quantity. It can only be a number.  Duh... also trim any leading zeros\n\t\t$items['qty'] = (float) $items['qty'];\n\n\t\t// If the quantity is zero or blank there's nothing for us to do\n\t\tif ($items['qty'] == 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Validate the product ID. It can only be alpha-numeric, dashes, underscores or periods\n\t\t// Not totally sure we should impose this rule, but it seems prudent to standardize IDs.\n\t\t// Note: These can be user-specified by setting the $this->product_id_rules variable.\n\t\tif ( ! preg_match('/^['.$this->product_id_rules.']+$/i', $items['id']))\n\t\t{\n\t\t\tlog_message('error', 'Invalid product ID.  The product ID can only contain alpha-numeric characters, dashes, and underscores');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Validate the product name. It can only be alpha-numeric, dashes, underscores, colons or periods.\n\t\t// Note: These can be user-specified by setting the $this->product_name_rules variable.\n\t\tif ($this->product_name_safe && ! preg_match('/^['.$this->product_name_rules.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $items['name']))\n\t\t{\n\t\t\tlog_message('error', 'An invalid name was submitted as the product name: '.$items['name'].' The name can only contain alpha-numeric characters, dashes, underscores, colons, and spaces');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Prep the price. Remove leading zeros and anything that isn't a number or decimal point.\n\t\t$items['price'] = (float) $items['price'];\n\n\t\t// We now need to create a unique identifier for the item being inserted into the cart.\n\t\t// Every time something is added to the cart it is stored in the master cart array.\n\t\t// Each row in the cart array, however, must have a unique index that identifies not only\n\t\t// a particular product, but makes it possible to store identical products with different options.\n\t\t// For example, what if someone buys two identical t-shirts (same product ID), but in\n\t\t// different sizes?  The product ID (and other attributes, like the name) will be identical for\n\t\t// both sizes because it's the same shirt. The only difference will be the size.\n\t\t// Internally, we need to treat identical submissions, but with different options, as a unique product.\n\t\t// Our solution is to convert the options array to a string and MD5 it along with the product ID.\n\t\t// This becomes the unique \"row ID\"\n\t\tif (isset($items['options']) && count($items['options']) > 0)\n\t\t{\n\t\t\t$rowid = md5($items['id'].serialize($items['options']));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// No options were submitted so we simply MD5 the product ID.\n\t\t\t// Technically, we don't need to MD5 the ID in this case, but it makes\n\t\t\t// sense to standardize the format of array indexes for both conditions\n\t\t\t$rowid = md5($items['id']);\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Now that we have our unique \"row ID\", we'll add our cart items to the master array\n\t\t// grab quantity if it's already there and add it on\n\t\t$old_quantity = isset($this->_cart_contents[$rowid]['qty']) ? (int) $this->_cart_contents[$rowid]['qty'] : 0;\n\n\t\t// Re-create the entry, just to make sure our index contains only the data from this submission\n\t\t$items['rowid'] = $rowid;\n\t\t$items['qty'] += $old_quantity;\n\t\t$this->_cart_contents[$rowid] = $items;\n\n\t\treturn $rowid;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update the cart\n\t *\n\t * This function permits the quantity of a given item to be changed.\n\t * Typically it is called from the \"view cart\" page if a user makes\n\t * changes to the quantity before checkout. That array must contain the\n\t * product ID and quantity for each item.\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function update($items = array())\n\t{\n\t\t// Was any cart data passed?\n\t\tif ( ! is_array($items) OR count($items) === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// You can either update a single product using a one-dimensional array,\n\t\t// or multiple products using a multi-dimensional one.  The way we\n\t\t// determine the array type is by looking for a required array key named \"rowid\".\n\t\t// If it's not found we assume it's a multi-dimensional array\n\t\t$save_cart = FALSE;\n\t\tif (isset($items['rowid']))\n\t\t{\n\t\t\tif ($this->_update($items) === TRUE)\n\t\t\t{\n\t\t\t\t$save_cart = TRUE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($items as $val)\n\t\t\t{\n\t\t\t\tif (is_array($val) && isset($val['rowid']))\n\t\t\t\t{\n\t\t\t\t\tif ($this->_update($val) === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$save_cart = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Save the cart data if the insert was successful\n\t\tif ($save_cart === TRUE)\n\t\t{\n\t\t\t$this->_save_cart();\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update the cart\n\t *\n\t * This function permits changing item properties.\n\t * Typically it is called from the \"view cart\" page if a user makes\n\t * changes to the quantity before checkout. That array must contain the\n\t * rowid and quantity for each item.\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tprotected function _update($items = array())\n\t{\n\t\t// Without these array indexes there is nothing we can do\n\t\tif ( ! isset($items['rowid'], $this->_cart_contents[$items['rowid']]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Prep the quantity\n\t\tif (isset($items['qty']))\n\t\t{\n\t\t\t$items['qty'] = (float) $items['qty'];\n\t\t\t// Is the quantity zero?  If so we will remove the item from the cart.\n\t\t\t// If the quantity is greater than zero we are updating\n\t\t\tif ($items['qty'] == 0)\n\t\t\t{\n\t\t\t\tunset($this->_cart_contents[$items['rowid']]);\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t}\n\n\t\t// find updatable keys\n\t\t$keys = array_intersect(array_keys($this->_cart_contents[$items['rowid']]), array_keys($items));\n\t\t// if a price was passed, make sure it contains valid data\n\t\tif (isset($items['price']))\n\t\t{\n\t\t\t$items['price'] = (float) $items['price'];\n\t\t}\n\n\t\t// product id & name shouldn't be changed\n\t\tforeach (array_diff($keys, array('id', 'name')) as $key)\n\t\t{\n\t\t\t$this->_cart_contents[$items['rowid']][$key] = $items[$key];\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Save the cart array to the session DB\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _save_cart()\n\t{\n\t\t// Let's add up the individual prices and set the cart sub-total\n\t\t$this->_cart_contents['total_items'] = $this->_cart_contents['cart_total'] = 0;\n\t\tforeach ($this->_cart_contents as $key => $val)\n\t\t{\n\t\t\t// We make sure the array contains the proper indexes\n\t\t\tif ( ! is_array($val) OR ! isset($val['price'], $val['qty']))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$this->_cart_contents['cart_total'] += ($val['price'] * $val['qty']);\n\t\t\t$this->_cart_contents['total_items'] += $val['qty'];\n\t\t\t$this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']);\n\t\t}\n\n\t\t// Is our cart empty? If so we delete it from the session\n\t\tif (count($this->_cart_contents) <= 2)\n\t\t{\n\t\t\t$this->CI->session->unset_userdata('cart_contents');\n\n\t\t\t// Nothing more to do... coffee time!\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// If we made it this far it means that our cart has data.\n\t\t// Let's pass it to the Session class so it can be stored\n\t\t$this->CI->session->set_userdata(array('cart_contents' => $this->_cart_contents));\n\n\t\t// Woot!\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Cart Total\n\t *\n\t * @return\tint\n\t */\n\tpublic function total()\n\t{\n\t\treturn $this->_cart_contents['cart_total'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove Item\n\t *\n\t * Removes an item from the cart\n\t *\n\t * @param\tint\n\t * @return\tbool\n\t */\n\t public function remove($rowid)\n\t {\n\t\t// unset & save\n\t\tunset($this->_cart_contents[$rowid]);\n\t\t$this->_save_cart();\n\t\treturn TRUE;\n\t }\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Total Items\n\t *\n\t * Returns the total item count\n\t *\n\t * @return\tint\n\t */\n\tpublic function total_items()\n\t{\n\t\treturn $this->_cart_contents['total_items'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Cart Contents\n\t *\n\t * Returns the entire cart array\n\t *\n\t * @param\tbool\n\t * @return\tarray\n\t */\n\tpublic function contents($newest_first = FALSE)\n\t{\n\t\t// do we want the newest first?\n\t\t$cart = ($newest_first) ? array_reverse($this->_cart_contents) : $this->_cart_contents;\n\n\t\t// Remove these so they don't create a problem when showing the cart table\n\t\tunset($cart['total_items']);\n\t\tunset($cart['cart_total']);\n\n\t\treturn $cart;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get cart item\n\t *\n\t * Returns the details of a specific item in the cart\n\t *\n\t * @param\tstring\t$row_id\n\t * @return\tarray\n\t */\n\tpublic function get_item($row_id)\n\t{\n\t\treturn (in_array($row_id, array('total_items', 'cart_total'), TRUE) OR ! isset($this->_cart_contents[$row_id]))\n\t\t\t? FALSE\n\t\t\t: $this->_cart_contents[$row_id];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Has options\n\t *\n\t * Returns TRUE if the rowid passed to this function correlates to an item\n\t * that has options associated with it.\n\t *\n\t * @param\tstring\t$row_id = ''\n\t * @return\tbool\n\t */\n\tpublic function has_options($row_id = '')\n\t{\n\t\treturn (isset($this->_cart_contents[$row_id]['options']) && count($this->_cart_contents[$row_id]['options']) !== 0);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Product options\n\t *\n\t * Returns the an array of options, for a particular product row ID\n\t *\n\t * @param\tstring\t$row_id = ''\n\t * @return\tarray\n\t */\n\tpublic function product_options($row_id = '')\n\t{\n\t\treturn isset($this->_cart_contents[$row_id]['options']) ? $this->_cart_contents[$row_id]['options'] : array();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Format Number\n\t *\n\t * Returns the supplied number with commas and a decimal point.\n\t *\n\t * @param\tfloat\n\t * @return\tstring\n\t */\n\tpublic function format_number($n = '')\n\t{\n\t\treturn ($n === '') ? '' : number_format( (float) $n, 2, '.', ',');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Destroy the cart\n\t *\n\t * Empties the cart and kills the session\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function destroy()\n\t{\n\t\t$this->_cart_contents = array('cart_total' => 0, 'total_items' => 0);\n\t\t$this->CI->session->unset_userdata('cart_contents');\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Driver Library Class\n *\n * This class enables you to create \"Driver\" libraries that add runtime ability\n * to extend the capabilities of a class via additional driver objects\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Driver_Library {\n\n\t/**\n\t * Array of drivers that are available to use with the driver class\n\t *\n\t * @var array\n\t */\n\tprotected $valid_drivers = array();\n\n\t/**\n\t * Name of the current class - usually the driver class\n\t *\n\t * @var string\n\t */\n\tprotected $lib_name;\n\n\t/**\n\t * Get magic method\n\t *\n\t * The first time a child is used it won't exist, so we instantiate it\n\t * subsequents calls will go straight to the proper child.\n\t *\n\t * @param\tstring\tChild class name\n\t * @return\tobject\tChild class\n\t */\n\tpublic function __get($child)\n\t{\n\t\t// Try to load the driver\n\t\treturn $this->load_driver($child);\n\t}\n\n\t/**\n\t * Load driver\n\t *\n\t * Separate load_driver call to support explicit driver load by library or user\n\t *\n\t * @param\tstring\tDriver name (w/o parent prefix)\n\t * @return\tobject\tChild class\n\t */\n\tpublic function load_driver($child)\n\t{\n\t\t// Get CodeIgniter instance and subclass prefix\n\t\t$prefix = config_item('subclass_prefix');\n\n\t\tif ( ! isset($this->lib_name))\n\t\t{\n\t\t\t// Get library name without any prefix\n\t\t\t$this->lib_name = str_replace(array('CI_', $prefix), '', get_class($this));\n\t\t}\n\n\t\t// The child will be prefixed with the parent lib\n\t\t$child_name = $this->lib_name.'_'.$child;\n\n\t\t// See if requested child is a valid driver\n\t\tif ( ! in_array($child, $this->valid_drivers))\n\t\t{\n\t\t\t// The requested driver isn't valid!\n\t\t\t$msg = 'Invalid driver requested: '.$child_name;\n\t\t\tlog_message('error', $msg);\n\t\t\tshow_error($msg);\n\t\t}\n\n\t\t// Get package paths and filename case variations to search\n\t\t$CI = get_instance();\n\t\t$paths = $CI->load->get_package_paths(TRUE);\n\n\t\t// Is there an extension?\n\t\t$class_name = $prefix.$child_name;\n\t\t$found = class_exists($class_name, FALSE);\n\t\tif ( ! $found)\n\t\t{\n\t\t\t// Check for subclass file\n\t\t\tforeach ($paths as $path)\n\t\t\t{\n\t\t\t\t// Does the file exist?\n\t\t\t\t$file = $path.'libraries/'.$this->lib_name.'/drivers/'.$prefix.$child_name.'.php';\n\t\t\t\tif (file_exists($file))\n\t\t\t\t{\n\t\t\t\t\t// Yes - require base class from BASEPATH\n\t\t\t\t\t$basepath = BASEPATH.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';\n\t\t\t\t\tif ( ! file_exists($basepath))\n\t\t\t\t\t{\n\t\t\t\t\t\t$msg = 'Unable to load the requested class: CI_'.$child_name;\n\t\t\t\t\t\tlog_message('error', $msg);\n\t\t\t\t\t\tshow_error($msg);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Include both sources and mark found\n\t\t\t\t\tinclude_once($basepath);\n\t\t\t\t\tinclude_once($file);\n\t\t\t\t\t$found = TRUE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Do we need to search for the class?\n\t\tif ( ! $found)\n\t\t{\n\t\t\t// Use standard class name\n\t\t\t$class_name = 'CI_'.$child_name;\n\t\t\tif ( ! class_exists($class_name, FALSE))\n\t\t\t{\n\t\t\t\t// Check package paths\n\t\t\t\tforeach ($paths as $path)\n\t\t\t\t{\n\t\t\t\t\t// Does the file exist?\n\t\t\t\t\t$file = $path.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';\n\t\t\t\t\tif (file_exists($file))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Include source\n\t\t\t\t\t\tinclude_once($file);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Did we finally find the class?\n\t\tif ( ! class_exists($class_name, FALSE))\n\t\t{\n\t\t\tif (class_exists($child_name, FALSE))\n\t\t\t{\n\t\t\t\t$class_name = $child_name;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$msg = 'Unable to load the requested driver: '.$class_name;\n\t\t\t\tlog_message('error', $msg);\n\t\t\t\tshow_error($msg);\n\t\t\t}\n\t\t}\n\n\t\t// Instantiate, decorate and add child\n\t\t$obj = new $class_name();\n\t\t$obj->decorate($this);\n\t\t$this->$child = $obj;\n\t\treturn $this->$child;\n\t}\n\n}\n\n// --------------------------------------------------------------------------\n\n/**\n * CodeIgniter Driver Class\n *\n * This class enables you to create drivers for a Library based on the Driver Library.\n * It handles the drivers' access to the parent library\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Driver {\n\n\t/**\n\t * Instance of the parent class\n\t *\n\t * @var object\n\t */\n\tprotected $_parent;\n\n\t/**\n\t * List of methods in the parent class\n\t *\n\t * @var array\n\t */\n\tprotected $_methods = array();\n\n\t/**\n\t * List of properties in the parent class\n\t *\n\t * @var array\n\t */\n\tprotected $_properties = array();\n\n\t/**\n\t * Array of methods and properties for the parent class(es)\n\t *\n\t * @static\n\t * @var\tarray\n\t */\n\tprotected static $_reflections = array();\n\n\t/**\n\t * Decorate\n\t *\n\t * Decorates the child with the parent driver lib's methods and properties\n\t *\n\t * @param\tobject\n\t * @return\tvoid\n\t */\n\tpublic function decorate($parent)\n\t{\n\t\t$this->_parent = $parent;\n\n\t\t// Lock down attributes to what is defined in the class\n\t\t// and speed up references in magic methods\n\n\t\t$class_name = get_class($parent);\n\n\t\tif ( ! isset(self::$_reflections[$class_name]))\n\t\t{\n\t\t\t$r = new ReflectionObject($parent);\n\n\t\t\tforeach ($r->getMethods() as $method)\n\t\t\t{\n\t\t\t\tif ($method->isPublic())\n\t\t\t\t{\n\t\t\t\t\t$this->_methods[] = $method->getName();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tforeach ($r->getProperties() as $prop)\n\t\t\t{\n\t\t\t\tif ($prop->isPublic())\n\t\t\t\t{\n\t\t\t\t\t$this->_properties[] = $prop->getName();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tself::$_reflections[$class_name] = array($this->_methods, $this->_properties);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlist($this->_methods, $this->_properties) = self::$_reflections[$class_name];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __call magic method\n\t *\n\t * Handles access to the parent driver library's methods\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @return\tmixed\n\t */\n\tpublic function __call($method, $args = array())\n\t{\n\t\tif (in_array($method, $this->_methods))\n\t\t{\n\t\t\treturn call_user_func_array(array($this->_parent, $method), $args);\n\t\t}\n\n\t\tthrow new BadMethodCallException('No such method: '.$method.'()');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __get magic method\n\t *\n\t * Handles reading of the parent driver library's properties\n\t *\n\t * @param\tstring\n\t * @return\tmixed\n\t */\n\tpublic function __get($var)\n\t{\n\t\tif (in_array($var, $this->_properties))\n\t\t{\n\t\t\treturn $this->_parent->$var;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __set magic method\n\t *\n\t * Handles writing to the parent driver library's properties\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @return\tmixed\n\t */\n\tpublic function __set($var, $val)\n\t{\n\t\tif (in_array($var, $this->_properties))\n\t\t{\n\t\t\t$this->_parent->$var = $val;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Email.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Email Class\n *\n * Permits email to be sent using Mail, Sendmail, or SMTP.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/email.html\n */\nclass CI_Email {\n\n\t/**\n\t * Used as the User-Agent and X-Mailer headers' value.\n\t *\n\t * @var\tstring\n\t */\n\tpublic $useragent\t= 'CodeIgniter';\n\n\t/**\n\t * Path to the Sendmail binary.\n\t *\n\t * @var\tstring\n\t */\n\tpublic $mailpath\t= '/usr/sbin/sendmail';\t// Sendmail path\n\n\t/**\n\t * Which method to use for sending e-mails.\n\t *\n\t * @var\tstring\t'mail', 'sendmail' or 'smtp'\n\t */\n\tpublic $protocol\t= 'mail';\t\t// mail/sendmail/smtp\n\n\t/**\n\t * STMP Server host\n\t *\n\t * @var\tstring\n\t */\n\tpublic $smtp_host\t= '';\n\n\t/**\n\t * SMTP Username\n\t *\n\t * @var\tstring\n\t */\n\tpublic $smtp_user\t= '';\n\n\t/**\n\t * SMTP Password\n\t *\n\t * @var\tstring\n\t */\n\tpublic $smtp_pass\t= '';\n\n\t/**\n\t * SMTP Server port\n\t *\n\t * @var\tint\n\t */\n\tpublic $smtp_port\t= 25;\n\n\t/**\n\t * SMTP connection timeout in seconds\n\t *\n\t * @var\tint\n\t */\n\tpublic $smtp_timeout\t= 5;\n\n\t/**\n\t * SMTP persistent connection\n\t *\n\t * @var\tbool\n\t */\n\tpublic $smtp_keepalive\t= FALSE;\n\n\t/**\n\t * SMTP Encryption\n\t *\n\t * @var\tstring\tempty, 'tls' or 'ssl'\n\t */\n\tpublic $smtp_crypto\t= '';\n\n\t/**\n\t * Whether to apply word-wrapping to the message body.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $wordwrap\t= TRUE;\n\n\t/**\n\t * Number of characters to wrap at.\n\t *\n\t * @see\tCI_Email::$wordwrap\n\t * @var\tint\n\t */\n\tpublic $wrapchars\t= 76;\n\n\t/**\n\t * Message format.\n\t *\n\t * @var\tstring\t'text' or 'html'\n\t */\n\tpublic $mailtype\t= 'text';\n\n\t/**\n\t * Character set (default: utf-8)\n\t *\n\t * @var\tstring\n\t */\n\tpublic $charset\t\t= 'utf-8';\n\n\t/**\n\t * Multipart message\n\t *\n\t * @var\tstring\t'mixed' (in the body) or 'related' (separate)\n\t */\n\tpublic $multipart\t= 'mixed';\t\t// \"mixed\" (in the body) or \"related\" (separate)\n\n\t/**\n\t * Alternative message (for HTML messages only)\n\t *\n\t * @var\tstring\n\t */\n\tpublic $alt_message\t= '';\n\n\t/**\n\t * Whether to validate e-mail addresses.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $validate\t= FALSE;\n\n\t/**\n\t * X-Priority header value.\n\t *\n\t * @var\tint\t1-5\n\t */\n\tpublic $priority\t= 3;\t\t\t// Default priority (1 - 5)\n\n\t/**\n\t * Newline character sequence.\n\t * Use \"\\r\\n\" to comply with RFC 822.\n\t *\n\t * @link\thttp://www.ietf.org/rfc/rfc822.txt\n\t * @var\tstring\t\"\\r\\n\" or \"\\n\"\n\t */\n\tpublic $newline\t\t= \"\\n\";\t\t\t// Default newline. \"\\r\\n\" or \"\\n\" (Use \"\\r\\n\" to comply with RFC 822)\n\n\t/**\n\t * CRLF character sequence\n\t *\n\t * RFC 2045 specifies that for 'quoted-printable' encoding,\n\t * \"\\r\\n\" must be used. However, it appears that some servers\n\t * (even on the receiving end) don't handle it properly and\n\t * switching to \"\\n\", while improper, is the only solution\n\t * that seems to work for all environments.\n\t *\n\t * @link\thttp://www.ietf.org/rfc/rfc822.txt\n\t * @var\tstring\n\t */\n\tpublic $crlf\t\t= \"\\n\";\n\n\t/**\n\t * Whether to use Delivery Status Notification.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $dsn\t\t= FALSE;\n\n\t/**\n\t * Whether to send multipart alternatives.\n\t * Yahoo! doesn't seem to like these.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $send_multipart\t= TRUE;\n\n\t/**\n\t * Whether to send messages to BCC recipients in batches.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $bcc_batch_mode\t= FALSE;\n\n\t/**\n\t * BCC Batch max number size.\n\t *\n\t * @see\tCI_Email::$bcc_batch_mode\n\t * @var\tint\n\t */\n\tpublic $bcc_batch_size\t= 200;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Whether PHP is running in safe mode. Initialized by the class constructor.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_safe_mode\t\t= FALSE;\n\n\t/**\n\t * Subject header\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_subject\t\t= '';\n\n\t/**\n\t * Message body\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_body\t\t= '';\n\n\t/**\n\t * Final message body to be sent.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_finalbody\t\t= '';\n\n\t/**\n\t * multipart/alternative boundary\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_alt_boundary\t= '';\n\n\t/**\n\t * Attachment boundary\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_atc_boundary\t= '';\n\n\t/**\n\t * Final headers to send\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_header_str\t\t= '';\n\n\t/**\n\t * SMTP Connection socket placeholder\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_smtp_connect\t= '';\n\n\t/**\n\t * Mail encoding\n\t *\n\t * @var\tstring\t'8bit' or '7bit'\n\t */\n\tprotected $_encoding\t\t= '8bit';\n\n\t/**\n\t * Whether to perform SMTP authentication\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_smtp_auth\t\t= FALSE;\n\n\t/**\n\t * Whether to send a Reply-To header\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_replyto_flag\t= FALSE;\n\n\t/**\n\t * Debug messages\n\t *\n\t * @see\tCI_Email::print_debugger()\n\t * @var\tstring\n\t */\n\tprotected $_debug_msg\t\t= array();\n\n\t/**\n\t * Recipients\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_recipients\t\t= array();\n\n\t/**\n\t * CC Recipients\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_cc_array\t\t= array();\n\n\t/**\n\t * BCC Recipients\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_bcc_array\t\t= array();\n\n\t/**\n\t * Message headers\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_headers\t\t= array();\n\n\t/**\n\t * Attachment data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_attachments\t\t= array();\n\n\t/**\n\t * Valid $protocol values\n\t *\n\t * @see\tCI_Email::$protocol\n\t * @var\tstring[]\n\t */\n\tprotected $_protocols\t\t= array('mail', 'sendmail', 'smtp');\n\n\t/**\n\t * Base charsets\n\t *\n\t * Character sets valid for 7-bit encoding,\n\t * excluding language suffix.\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_base_charsets\t= array('us-ascii', 'iso-2022-');\n\n\t/**\n\t * Bit depths\n\t *\n\t * Valid mail encodings\n\t *\n\t * @see\tCI_Email::$_encoding\n\t * @var\tstring[]\n\t */\n\tprotected $_bit_depths\t\t= array('7bit', '8bit');\n\n\t/**\n\t * $priority translations\n\t *\n\t * Actual values to send with the X-Priority header\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_priorities = array(\n\t\t1 => '1 (Highest)',\n\t\t2 => '2 (High)',\n\t\t3 => '3 (Normal)',\n\t\t4 => '4 (Low)',\n\t\t5 => '5 (Lowest)'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor - Sets Email Preferences\n\t *\n\t * The constructor can be passed an array of config values\n\t *\n\t * @param\tarray\t$config = array()\n\t * @return\tvoid\n\t */\n\tpublic function __construct(array $config = array())\n\t{\n\t\t$this->charset = config_item('charset');\n\n\t\tif (count($config) > 0)\n\t\t{\n\t\t\t$this->initialize($config);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');\n\t\t}\n\n\t\t$this->_safe_mode = ( ! is_php('5.4') && ini_get('safe_mode'));\n\t\t$this->charset = strtoupper($this->charset);\n\n\t\tlog_message('info', 'Email Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Destructor - Releases Resources\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __destruct()\n\t{\n\t\tif (is_resource($this->_smtp_connect))\n\t\t{\n\t\t\t$this->_send_command('quit');\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize preferences\n\t *\n\t * @param\tarray\n\t * @return\tCI_Email\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\tif (isset($this->$key))\n\t\t\t{\n\t\t\t\t$method = 'set_'.$key;\n\n\t\t\t\tif (method_exists($this, $method))\n\t\t\t\t{\n\t\t\t\t\t$this->$method($val);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->$key = $val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t$this->clear();\n\n\t\t$this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize the Email Data\n\t *\n\t * @param\tbool\n\t * @return\tCI_Email\n\t */\n\tpublic function clear($clear_attachments = FALSE)\n\t{\n\t\t$this->_subject\t\t= '';\n\t\t$this->_body\t\t= '';\n\t\t$this->_finalbody\t= '';\n\t\t$this->_header_str\t= '';\n\t\t$this->_replyto_flag\t= FALSE;\n\t\t$this->_recipients\t= array();\n\t\t$this->_cc_array\t= array();\n\t\t$this->_bcc_array\t= array();\n\t\t$this->_headers\t\t= array();\n\t\t$this->_debug_msg\t= array();\n\n\t\t$this->set_header('User-Agent', $this->useragent);\n\t\t$this->set_header('Date', $this->_set_date());\n\n\t\tif ($clear_attachments !== FALSE)\n\t\t{\n\t\t\t$this->_attachments = array();\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set FROM\n\t *\n\t * @param\tstring\t$from\n\t * @param\tstring\t$name\n\t * @param\tstring\t$return_path = NULL\tReturn-Path\n\t * @return\tCI_Email\n\t */\n\tpublic function from($from, $name = '', $return_path = NULL)\n\t{\n\t\tif (preg_match('/\\<(.*)\\>/', $from, $match))\n\t\t{\n\t\t\t$from = $match[1];\n\t\t}\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($this->_str_to_array($from));\n\t\t\tif ($return_path)\n\t\t\t{\n\t\t\t\t$this->validate_email($this->_str_to_array($return_path));\n\t\t\t}\n\t\t}\n\n\t\t// prepare the display name\n\t\tif ($name !== '')\n\t\t{\n\t\t\t// only use Q encoding if there are characters that would require it\n\t\t\tif ( ! preg_match('/[\\200-\\377]/', $name))\n\t\t\t{\n\t\t\t\t// add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes\n\t\t\t\t$name = '\"'.addcslashes($name, \"\\0..\\37\\177'\\\"\\\\\").'\"';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$name = $this->_prep_q_encoding($name);\n\t\t\t}\n\t\t}\n\n\t\t$this->set_header('From', $name.' <'.$from.'>');\n\n\t\tisset($return_path) OR $return_path = $from;\n\t\t$this->set_header('Return-Path', '<'.$return_path.'>');\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Reply-to\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function reply_to($replyto, $name = '')\n\t{\n\t\tif (preg_match('/\\<(.*)\\>/', $replyto, $match))\n\t\t{\n\t\t\t$replyto = $match[1];\n\t\t}\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($this->_str_to_array($replyto));\n\t\t}\n\n\t\tif ($name === '')\n\t\t{\n\t\t\t$name = $replyto;\n\t\t}\n\n\t\tif (strpos($name, '\"') !== 0)\n\t\t{\n\t\t\t$name = '\"'.$name.'\"';\n\t\t}\n\n\t\t$this->set_header('Reply-To', $name.' <'.$replyto.'>');\n\t\t$this->_replyto_flag = TRUE;\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Recipients\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function to($to)\n\t{\n\t\t$to = $this->_str_to_array($to);\n\t\t$to = $this->clean_email($to);\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($to);\n\t\t}\n\n\t\tif ($this->_get_protocol() !== 'mail')\n\t\t{\n\t\t\t$this->set_header('To', implode(', ', $to));\n\t\t}\n\n\t\t$this->_recipients = $to;\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set CC\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function cc($cc)\n\t{\n\t\t$cc = $this->clean_email($this->_str_to_array($cc));\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($cc);\n\t\t}\n\n\t\t$this->set_header('Cc', implode(', ', $cc));\n\n\t\tif ($this->_get_protocol() === 'smtp')\n\t\t{\n\t\t\t$this->_cc_array = $cc;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set BCC\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function bcc($bcc, $limit = '')\n\t{\n\t\tif ($limit !== '' && is_numeric($limit))\n\t\t{\n\t\t\t$this->bcc_batch_mode = TRUE;\n\t\t\t$this->bcc_batch_size = $limit;\n\t\t}\n\n\t\t$bcc = $this->clean_email($this->_str_to_array($bcc));\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($bcc);\n\t\t}\n\n\t\tif ($this->_get_protocol() === 'smtp' OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))\n\t\t{\n\t\t\t$this->_bcc_array = $bcc;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->set_header('Bcc', implode(', ', $bcc));\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Email Subject\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function subject($subject)\n\t{\n\t\t$subject = $this->_prep_q_encoding($subject);\n\t\t$this->set_header('Subject', $subject);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Body\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function message($body)\n\t{\n\t\t$this->_body = rtrim(str_replace(\"\\r\", '', $body));\n\n\t\t/* strip slashes only if magic quotes is ON\n\t\t   if we do it with magic quotes OFF, it strips real, user-inputted chars.\n\n\t\t   NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and\n\t\t\t it will probably not exist in future versions at all.\n\t\t*/\n\t\tif ( ! is_php('5.4') && get_magic_quotes_gpc())\n\t\t{\n\t\t\t$this->_body = stripslashes($this->_body);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Assign file attachments\n\t *\n\t * @param\tstring\t$file\tCan be local path, URL or buffered content\n\t * @param\tstring\t$disposition = 'attachment'\n\t * @param\tstring\t$newname = NULL\n\t * @param\tstring\t$mime = ''\n\t * @return\tCI_Email\n\t */\n\tpublic function attach($file, $disposition = '', $newname = NULL, $mime = '')\n\t{\n\t\tif ($mime === '')\n\t\t{\n\t\t\tif (strpos($file, '://') === FALSE && ! file_exists($file))\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_attachment_missing', $file);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ( ! $fp = @fopen($file, 'rb'))\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_attachment_unreadable', $file);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$file_content = stream_get_contents($fp);\n\t\t\t$mime = $this->_mime_types(pathinfo($file, PATHINFO_EXTENSION));\n\t\t\tfclose($fp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$file_content =& $file; // buffered file\n\t\t}\n\n\t\t$this->_attachments[] = array(\n\t\t\t'name'\t\t=> array($file, $newname),\n\t\t\t'disposition'\t=> empty($disposition) ? 'attachment' : $disposition,  // Can also be 'inline'  Not sure if it matters\n\t\t\t'type'\t\t=> $mime,\n\t\t\t'content'\t=> chunk_split(base64_encode($file_content))\n\t\t);\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set and return attachment Content-ID\n\t *\n\t * Useful for attached inline pictures\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tpublic function attachment_cid($filename)\n\t{\n\t\tif ($this->multipart !== 'related')\n\t\t{\n\t\t\t$this->multipart = 'related'; // Thunderbird need this for inline images\n\t\t}\n\n\t\tfor ($i = 0, $c = count($this->_attachments); $i < $c; $i++)\n\t\t{\n\t\t\tif ($this->_attachments[$i]['name'][0] === $filename)\n\t\t\t{\n\t\t\t\t$this->_attachments[$i]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@');\n\t\t\t\treturn $this->_attachments[$i]['cid'];\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add a Header Item\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_header($header, $value)\n\t{\n\t\t$this->_headers[$header] = str_replace(array(\"\\n\", \"\\r\"), '', $value);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert a String to an Array\n\t *\n\t * @param\tstring\n\t * @return\tarray\n\t */\n\tprotected function _str_to_array($email)\n\t{\n\t\tif ( ! is_array($email))\n\t\t{\n\t\t\treturn (strpos($email, ',') !== FALSE)\n\t\t\t\t? preg_split('/[\\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY)\n\t\t\t\t: (array) trim($email);\n\t\t}\n\n\t\treturn $email;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Multipart Value\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_alt_message($str)\n\t{\n\t\t$this->alt_message = (string) $str;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Mailtype\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_mailtype($type = 'text')\n\t{\n\t\t$this->mailtype = ($type === 'html') ? 'html' : 'text';\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Wordwrap\n\t *\n\t * @param\tbool\n\t * @return\tCI_Email\n\t */\n\tpublic function set_wordwrap($wordwrap = TRUE)\n\t{\n\t\t$this->wordwrap = (bool) $wordwrap;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Protocol\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_protocol($protocol = 'mail')\n\t{\n\t\t$this->protocol = in_array($protocol, $this->_protocols, TRUE) ? strtolower($protocol) : 'mail';\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Priority\n\t *\n\t * @param\tint\n\t * @return\tCI_Email\n\t */\n\tpublic function set_priority($n = 3)\n\t{\n\t\t$this->priority = preg_match('/^[1-5]$/', $n) ? (int) $n : 3;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Newline Character\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_newline($newline = \"\\n\")\n\t{\n\t\t$this->newline = in_array($newline, array(\"\\n\", \"\\r\\n\", \"\\r\")) ? $newline : \"\\n\";\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set CRLF\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_crlf($crlf = \"\\n\")\n\t{\n\t\t$this->crlf = ($crlf !== \"\\n\" && $crlf !== \"\\r\\n\" && $crlf !== \"\\r\") ? \"\\n\" : $crlf;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Message Boundary\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _set_boundaries()\n\t{\n\t\t$this->_alt_boundary = 'B_ALT_'.uniqid(''); // multipart/alternative\n\t\t$this->_atc_boundary = 'B_ATC_'.uniqid(''); // attachment boundary\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Message ID\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_message_id()\n\t{\n\t\t$from = str_replace(array('>', '<'), '', $this->_headers['Return-Path']);\n\t\treturn '<'.uniqid('').strstr($from, '@').'>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mail Protocol\n\t *\n\t * @param\tbool\n\t * @return\tmixed\n\t */\n\tprotected function _get_protocol($return = TRUE)\n\t{\n\t\t$this->protocol = strtolower($this->protocol);\n\t\tin_array($this->protocol, $this->_protocols, TRUE) OR $this->protocol = 'mail';\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn $this->protocol;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mail Encoding\n\t *\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tprotected function _get_encoding($return = TRUE)\n\t{\n\t\tin_array($this->_encoding, $this->_bit_depths) OR $this->_encoding = '8bit';\n\n\t\tforeach ($this->_base_charsets as $charset)\n\t\t{\n\t\t\tif (strpos($charset, $this->charset) === 0)\n\t\t\t{\n\t\t\t\t$this->_encoding = '7bit';\n\t\t\t}\n\t\t}\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn $this->_encoding;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get content type (text/html/attachment)\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_content_type()\n\t{\n\t\tif ($this->mailtype === 'html')\n\t\t{\n\t\t\treturn (count($this->_attachments) === 0) ? 'html' : 'html-attach';\n\t\t}\n\t\telseif\t($this->mailtype === 'text' && count($this->_attachments) > 0)\n\t\t{\n\t\t\treturn 'plain-attach';\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 'plain';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set RFC 822 Date\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _set_date()\n\t{\n\t\t$timezone = date('Z');\n\t\t$operator = ($timezone[0] === '-') ? '-' : '+';\n\t\t$timezone = abs($timezone);\n\t\t$timezone = floor($timezone/3600) * 100 + ($timezone % 3600) / 60;\n\n\t\treturn sprintf('%s %s%04d', date('D, j M Y H:i:s'), $operator, $timezone);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mime message\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_mime_message()\n\t{\n\t\treturn 'This is a multi-part message in MIME format.'.$this->newline.'Your email application may not support this format.';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Email Address\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function validate_email($email)\n\t{\n\t\tif ( ! is_array($email))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_must_be_array');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tforeach ($email as $val)\n\t\t{\n\t\t\tif ( ! $this->valid_email($val))\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_invalid_address', $val);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Email Validation\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_email($email)\n\t{\n\t\tif (function_exists('idn_to_ascii') && $atpos = strpos($email, '@'))\n\t\t{\n\t\t\t$email = substr($email, 0, ++$atpos).idn_to_ascii(substr($email, $atpos));\n\t\t}\n\n\t\treturn (bool) filter_var($email, FILTER_VALIDATE_EMAIL);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clean Extended Email Address: Joe Smith <joe@smith.com>\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function clean_email($email)\n\t{\n\t\tif ( ! is_array($email))\n\t\t{\n\t\t\treturn preg_match('/\\<(.*)\\>/', $email, $match) ? $match[1] : $email;\n\t\t}\n\n\t\t$clean_email = array();\n\n\t\tforeach ($email as $addy)\n\t\t{\n\t\t\t$clean_email[] = preg_match('/\\<(.*)\\>/', $addy, $match) ? $match[1] : $addy;\n\t\t}\n\n\t\treturn $clean_email;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build alternative plain text message\n\t *\n\t * Provides the raw message for use in plain-text headers of\n\t * HTML-formatted emails.\n\t * If the user hasn't specified his own alternative message\n\t * it creates one by stripping the HTML\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_alt_message()\n\t{\n\t\tif ( ! empty($this->alt_message))\n\t\t{\n\t\t\treturn ($this->wordwrap)\n\t\t\t\t? $this->word_wrap($this->alt_message, 76)\n\t\t\t\t: $this->alt_message;\n\t\t}\n\n\t\t$body = preg_match('/\\<body.*?\\>(.*)\\<\\/body\\>/si', $this->_body, $match) ? $match[1] : $this->_body;\n\t\t$body = str_replace(\"\\t\", '', preg_replace('#<!--(.*)--\\>#', '', trim(strip_tags($body))));\n\n\t\tfor ($i = 20; $i >= 3; $i--)\n\t\t{\n\t\t\t$body = str_replace(str_repeat(\"\\n\", $i), \"\\n\\n\", $body);\n\t\t}\n\n\t\t// Reduce multiple spaces\n\t\t$body = preg_replace('| +|', ' ', $body);\n\n\t\treturn ($this->wordwrap)\n\t\t\t? $this->word_wrap($body, 76)\n\t\t\t: $body;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Word Wrap\n\t *\n\t * @param\tstring\n\t * @param\tint\tline-length limit\n\t * @return\tstring\n\t */\n\tpublic function word_wrap($str, $charlim = NULL)\n\t{\n\t\t// Set the character limit, if not already present\n\t\tif (empty($charlim))\n\t\t{\n\t\t\t$charlim = empty($this->wrapchars) ? 76 : $this->wrapchars;\n\t\t}\n\n\t\t// Standardize newlines\n\t\tif (strpos($str, \"\\r\") !== FALSE)\n\t\t{\n\t\t\t$str = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\n\t\t}\n\n\t\t// Reduce multiple spaces at end of line\n\t\t$str = preg_replace('| +\\n|', \"\\n\", $str);\n\n\t\t// If the current word is surrounded by {unwrap} tags we'll\n\t\t// strip the entire chunk and replace it with a marker.\n\t\t$unwrap = array();\n\t\tif (preg_match_all('|\\{unwrap\\}(.+?)\\{/unwrap\\}|s', $str, $matches))\n\t\t{\n\t\t\tfor ($i = 0, $c = count($matches[0]); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$unwrap[] = $matches[1][$i];\n\t\t\t\t$str = str_replace($matches[0][$i], '{{unwrapped'.$i.'}}', $str);\n\t\t\t}\n\t\t}\n\n\t\t// Use PHP's native function to do the initial wordwrap.\n\t\t// We set the cut flag to FALSE so that any individual words that are\n\t\t// too long get left alone. In the next step we'll deal with them.\n\t\t$str = wordwrap($str, $charlim, \"\\n\", FALSE);\n\n\t\t// Split the string into individual lines of text and cycle through them\n\t\t$output = '';\n\t\tforeach (explode(\"\\n\", $str) as $line)\n\t\t{\n\t\t\t// Is the line within the allowed character count?\n\t\t\t// If so we'll join it to the output and continue\n\t\t\tif (mb_strlen($line) <= $charlim)\n\t\t\t{\n\t\t\t\t$output .= $line.$this->newline;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$temp = '';\n\t\t\tdo\n\t\t\t{\n\t\t\t\t// If the over-length word is a URL we won't wrap it\n\t\t\t\tif (preg_match('!\\[url.+\\]|://|www\\.!', $line))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Trim the word down\n\t\t\t\t$temp .= mb_substr($line, 0, $charlim - 1);\n\t\t\t\t$line = mb_substr($line, $charlim - 1);\n\t\t\t}\n\t\t\twhile (mb_strlen($line) > $charlim);\n\n\t\t\t// If $temp contains data it means we had to split up an over-length\n\t\t\t// word into smaller chunks so we'll add it back to our current line\n\t\t\tif ($temp !== '')\n\t\t\t{\n\t\t\t\t$output .= $temp.$this->newline;\n\t\t\t}\n\n\t\t\t$output .= $line.$this->newline;\n\t\t}\n\n\t\t// Put our markers back\n\t\tif (count($unwrap) > 0)\n\t\t{\n\t\t\tforeach ($unwrap as $key => $val)\n\t\t\t{\n\t\t\t\t$output = str_replace('{{unwrapped'.$key.'}}', $val, $output);\n\t\t\t}\n\t\t}\n\n\t\treturn $output;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build final headers\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _build_headers()\n\t{\n\t\t$this->set_header('X-Sender', $this->clean_email($this->_headers['From']));\n\t\t$this->set_header('X-Mailer', $this->useragent);\n\t\t$this->set_header('X-Priority', $this->_priorities[$this->priority]);\n\t\t$this->set_header('Message-ID', $this->_get_message_id());\n\t\t$this->set_header('Mime-Version', '1.0');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write Headers as a string\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _write_headers()\n\t{\n\t\tif ($this->protocol === 'mail')\n\t\t{\n\t\t\tif (isset($this->_headers['Subject']))\n\t\t\t{\n\t\t\t\t$this->_subject = $this->_headers['Subject'];\n\t\t\t\tunset($this->_headers['Subject']);\n\t\t\t}\n\t\t}\n\n\t\treset($this->_headers);\n\t\t$this->_header_str = '';\n\n\t\tforeach ($this->_headers as $key => $val)\n\t\t{\n\t\t\t$val = trim($val);\n\n\t\t\tif ($val !== '')\n\t\t\t{\n\t\t\t\t$this->_header_str .= $key.': '.$val.$this->newline;\n\t\t\t}\n\t\t}\n\n\t\tif ($this->_get_protocol() === 'mail')\n\t\t{\n\t\t\t$this->_header_str = rtrim($this->_header_str);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build Final Body and attachments\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _build_message()\n\t{\n\t\tif ($this->wordwrap === TRUE && $this->mailtype !== 'html')\n\t\t{\n\t\t\t$this->_body = $this->word_wrap($this->_body);\n\t\t}\n\n\t\t$this->_set_boundaries();\n\t\t$this->_write_headers();\n\n\t\t$hdr = ($this->_get_protocol() === 'mail') ? $this->newline : '';\n\t\t$body = '';\n\n\t\tswitch ($this->_get_content_type())\n\t\t{\n\t\t\tcase 'plain' :\n\n\t\t\t\t$hdr .= 'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding();\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t\t$this->_finalbody = $this->_body;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_finalbody = $hdr.$this->newline.$this->newline.$this->_body;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\n\t\t\tcase 'html' :\n\n\t\t\t\tif ($this->send_multipart === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$hdr .= 'Content-Type: text/html; charset='.$this->charset.$this->newline\n\t\t\t\t\t\t.'Content-Transfer-Encoding: quoted-printable';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$hdr .= 'Content-Type: multipart/alternative; boundary=\"'.$this->_alt_boundary.'\"';\n\n\t\t\t\t\t$body .= $this->_get_mime_message().$this->newline.$this->newline\n\t\t\t\t\t\t.'--'.$this->_alt_boundary.$this->newline\n\n\t\t\t\t\t\t.'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline\n\t\t\t\t\t\t.$this->_get_alt_message().$this->newline.$this->newline.'--'.$this->_alt_boundary.$this->newline\n\n\t\t\t\t\t\t.'Content-Type: text/html; charset='.$this->charset.$this->newline\n\t\t\t\t\t\t.'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline;\n\t\t\t\t}\n\n\t\t\t\t$this->_finalbody = $body.$this->_prep_quoted_printable($this->_body).$this->newline.$this->newline;\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_finalbody = $hdr.$this->newline.$this->newline.$this->_finalbody;\n\t\t\t\t}\n\n\t\t\t\tif ($this->send_multipart !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t$this->_finalbody .= '--'.$this->_alt_boundary.'--';\n\t\t\t\t}\n\n\t\t\t\treturn;\n\n\t\t\tcase 'plain-attach' :\n\n\t\t\t\t$hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary=\"'.$this->_atc_boundary.'\"';\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t}\n\n\t\t\t\t$body .= $this->_get_mime_message().$this->newline\n\t\t\t\t\t.$this->newline\n\t\t\t\t\t.'--'.$this->_atc_boundary.$this->newline\n\t\t\t\t\t.'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline\n\t\t\t\t\t.$this->newline\n\t\t\t\t\t.$this->_body.$this->newline.$this->newline;\n\n\t\t\tbreak;\n\t\t\tcase 'html-attach' :\n\n\t\t\t\t$hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary=\"'.$this->_atc_boundary.'\"';\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t}\n\n\t\t\t\t$body .= $this->_get_mime_message().$this->newline.$this->newline\n\t\t\t\t\t.'--'.$this->_atc_boundary.$this->newline\n\n\t\t\t\t\t.'Content-Type: multipart/alternative; boundary=\"'.$this->_alt_boundary.'\"'.$this->newline.$this->newline\n\t\t\t\t\t.'--'.$this->_alt_boundary.$this->newline\n\n\t\t\t\t\t.'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline\n\t\t\t\t\t.$this->_get_alt_message().$this->newline.$this->newline.'--'.$this->_alt_boundary.$this->newline\n\n\t\t\t\t\t.'Content-Type: text/html; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline\n\n\t\t\t\t\t.$this->_prep_quoted_printable($this->_body).$this->newline.$this->newline\n\t\t\t\t\t.'--'.$this->_alt_boundary.'--'.$this->newline.$this->newline;\n\n\t\t\tbreak;\n\t\t}\n\n\t\t$attachment = array();\n\t\tfor ($i = 0, $c = count($this->_attachments), $z = 0; $i < $c; $i++)\n\t\t{\n\t\t\t$filename = $this->_attachments[$i]['name'][0];\n\t\t\t$basename = ($this->_attachments[$i]['name'][1] === NULL)\n\t\t\t\t? basename($filename) : $this->_attachments[$i]['name'][1];\n\n\t\t\t$attachment[$z++] = '--'.$this->_atc_boundary.$this->newline\n\t\t\t\t.'Content-type: '.$this->_attachments[$i]['type'].'; '\n\t\t\t\t.'name=\"'.$basename.'\"'.$this->newline\n\t\t\t\t.'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline\n\t\t\t\t.'Content-Transfer-Encoding: base64'.$this->newline\n\t\t\t\t.(empty($this->_attachments[$i]['cid']) ? '' : 'Content-ID: <'.$this->_attachments[$i]['cid'].'>'.$this->newline);\n\n\t\t\t$attachment[$z++] = $this->_attachments[$i]['content'];\n\t\t}\n\n\t\t$body .= implode($this->newline, $attachment).$this->newline.'--'.$this->_atc_boundary.'--';\n\t\t$this->_finalbody = ($this->_get_protocol() === 'mail')\n\t\t\t? $body\n\t\t\t: $hdr.$this->newline.$this->newline.$body;\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Quoted Printable\n\t *\n\t * Prepares string for Quoted-Printable Content-Transfer-Encoding\n\t * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _prep_quoted_printable($str)\n\t{\n\t\t// We are intentionally wrapping so mail servers will encode characters\n\t\t// properly and MUAs will behave, so {unwrap} must go!\n\t\t$str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);\n\n\t\t// RFC 2045 specifies CRLF as \"\\r\\n\".\n\t\t// However, many developers choose to override that and violate\n\t\t// the RFC rules due to (apparently) a bug in MS Exchange,\n\t\t// which only works with \"\\n\".\n\t\tif ($this->crlf === \"\\r\\n\")\n\t\t{\n\t\t\tif (is_php('5.3'))\n\t\t\t{\n\t\t\t\treturn quoted_printable_encode($str);\n\t\t\t}\n\t\t\telseif (function_exists('imap_8bit'))\n\t\t\t{\n\t\t\t\treturn imap_8bit($str);\n\t\t\t}\n\t\t}\n\n\t\t// Reduce multiple spaces & remove nulls\n\t\t$str = preg_replace(array('| +|', '/\\x00+/'), array(' ', ''), $str);\n\n\t\t// Standardize newlines\n\t\tif (strpos($str, \"\\r\") !== FALSE)\n\t\t{\n\t\t\t$str = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\n\t\t}\n\n\t\t$escape = '=';\n\t\t$output = '';\n\n\t\tforeach (explode(\"\\n\", $str) as $line)\n\t\t{\n\t\t\t$length = strlen($line);\n\t\t\t$temp = '';\n\n\t\t\t// Loop through each character in the line to add soft-wrap\n\t\t\t// characters at the end of a line \" =\\r\\n\" and add the newly\n\t\t\t// processed line(s) to the output (see comment on $crlf class property)\n\t\t\tfor ($i = 0; $i < $length; $i++)\n\t\t\t{\n\t\t\t\t// Grab the next character\n\t\t\t\t$char = $line[$i];\n\t\t\t\t$ascii = ord($char);\n\n\t\t\t\t// Convert spaces and tabs but only if it's the end of the line\n\t\t\t\tif ($i === ($length - 1) && ($ascii === 32 OR $ascii === 9))\n\t\t\t\t{\n\t\t\t\t\t$char = $escape.sprintf('%02s', dechex($ascii));\n\t\t\t\t}\n\t\t\t\telseif ($ascii === 61) // encode = signs\n\t\t\t\t{\n\t\t\t\t\t$char = $escape.strtoupper(sprintf('%02s', dechex($ascii)));  // =3D\n\t\t\t\t}\n\n\t\t\t\t// If we're at the character limit, add the line to the output,\n\t\t\t\t// reset our temp variable, and keep on chuggin'\n\t\t\t\tif ((strlen($temp) + strlen($char)) >= 76)\n\t\t\t\t{\n\t\t\t\t\t$output .= $temp.$escape.$this->crlf;\n\t\t\t\t\t$temp = '';\n\t\t\t\t}\n\n\t\t\t\t// Add the character to our temporary line\n\t\t\t\t$temp .= $char;\n\t\t\t}\n\n\t\t\t// Add our completed line to the output\n\t\t\t$output .= $temp.$this->crlf;\n\t\t}\n\n\t\t// get rid of extra CRLF tacked onto the end\n\t\treturn substr($output, 0, strlen($this->crlf) * -1);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Q Encoding\n\t *\n\t * Performs \"Q Encoding\" on a string for use in email headers.\n\t * It's related but not identical to quoted-printable, so it has its\n\t * own method.\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _prep_q_encoding($str)\n\t{\n\t\t$str = str_replace(array(\"\\r\", \"\\n\"), '', $str);\n\n\t\tif ($this->charset === 'UTF-8')\n\t\t{\n\t\t\tif (MB_ENABLED === TRUE)\n\t\t\t{\n\t\t\t\treturn mb_encode_mimeheader($str, $this->charset, 'Q', $this->crlf);\n\t\t\t}\n\t\t\telseif (ICONV_ENABLED === TRUE)\n\t\t\t{\n\t\t\t\t$output = @iconv_mime_encode('', $str,\n\t\t\t\t\tarray(\n\t\t\t\t\t\t'scheme' => 'Q',\n\t\t\t\t\t\t'line-length' => 76,\n\t\t\t\t\t\t'input-charset' => $this->charset,\n\t\t\t\t\t\t'output-charset' => $this->charset,\n\t\t\t\t\t\t'line-break-chars' => $this->crlf\n\t\t\t\t\t)\n\t\t\t\t);\n\n\t\t\t\t// There are reports that iconv_mime_encode() might fail and return FALSE\n\t\t\t\tif ($output !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t// iconv_mime_encode() will always put a header field name.\n\t\t\t\t\t// We've passed it an empty one, but it still prepends our\n\t\t\t\t\t// encoded string with ': ', so we need to strip it.\n\t\t\t\t\treturn substr($output, 2);\n\t\t\t\t}\n\n\t\t\t\t$chars = iconv_strlen($str, 'UTF-8');\n\t\t\t}\n\t\t}\n\n\t\t// We might already have this set for UTF-8\n\t\tisset($chars) OR $chars = strlen($str);\n\n\t\t$output = '=?'.$this->charset.'?Q?';\n\t\tfor ($i = 0, $length = strlen($output); $i < $chars; $i++)\n\t\t{\n\t\t\t$chr = ($this->charset === 'UTF-8' && ICONV_ENABLED === TRUE)\n\t\t\t\t? '='.implode('=', str_split(strtoupper(bin2hex(iconv_substr($str, $i, 1, $this->charset))), 2))\n\t\t\t\t: '='.strtoupper(bin2hex($str[$i]));\n\n\t\t\t// RFC 2045 sets a limit of 76 characters per line.\n\t\t\t// We'll append ?= to the end of each line though.\n\t\t\tif ($length + ($l = strlen($chr)) > 74)\n\t\t\t{\n\t\t\t\t$output .= '?='.$this->crlf // EOL\n\t\t\t\t\t.' =?'.$this->charset.'?Q?'.$chr; // New line\n\t\t\t\t$length = 6 + strlen($this->charset) + $l; // Reset the length for the new line\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$output .= $chr;\n\t\t\t\t$length += $l;\n\t\t\t}\n\t\t}\n\n\t\t// End the header\n\t\treturn $output.'?=';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Email\n\t *\n\t * @param\tbool\t$auto_clear = TRUE\n\t * @return\tbool\n\t */\n\tpublic function send($auto_clear = TRUE)\n\t{\n\t\tif ( ! isset($this->_headers['From']))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_from');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->_replyto_flag === FALSE)\n\t\t{\n\t\t\t$this->reply_to($this->_headers['From']);\n\t\t}\n\n\t\tif ( ! isset($this->_recipients) && ! isset($this->_headers['To'])\n\t\t\t&& ! isset($this->_bcc_array) && ! isset($this->_headers['Bcc'])\n\t\t\t&& ! isset($this->_headers['Cc']))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_recipients');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_build_headers();\n\n\t\tif ($this->bcc_batch_mode && count($this->_bcc_array) > $this->bcc_batch_size)\n\t\t{\n\t\t\t$result = $this->batch_bcc_send();\n\n\t\t\tif ($result && $auto_clear)\n\t\t\t{\n\t\t\t\t$this->clear();\n\t\t\t}\n\n\t\t\treturn $result;\n\t\t}\n\n\t\tif ($this->_build_message() === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = $this->_spool_email();\n\n\t\tif ($result && $auto_clear)\n\t\t{\n\t\t\t$this->clear();\n\t\t}\n\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Batch Bcc Send. Sends groups of BCCs in batches\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function batch_bcc_send()\n\t{\n\t\t$float = $this->bcc_batch_size - 1;\n\t\t$set = '';\n\t\t$chunk = array();\n\n\t\tfor ($i = 0, $c = count($this->_bcc_array); $i < $c; $i++)\n\t\t{\n\t\t\tif (isset($this->_bcc_array[$i]))\n\t\t\t{\n\t\t\t\t$set .= ', '.$this->_bcc_array[$i];\n\t\t\t}\n\n\t\t\tif ($i === $float)\n\t\t\t{\n\t\t\t\t$chunk[] = substr($set, 1);\n\t\t\t\t$float += $this->bcc_batch_size;\n\t\t\t\t$set = '';\n\t\t\t}\n\n\t\t\tif ($i === $c-1)\n\t\t\t{\n\t\t\t\t$chunk[] = substr($set, 1);\n\t\t\t}\n\t\t}\n\n\t\tfor ($i = 0, $c = count($chunk); $i < $c; $i++)\n\t\t{\n\t\t\tunset($this->_headers['Bcc']);\n\n\t\t\t$bcc = $this->clean_email($this->_str_to_array($chunk[$i]));\n\n\t\t\tif ($this->protocol !== 'smtp')\n\t\t\t{\n\t\t\t\t$this->set_header('Bcc', implode(', ', $bcc));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_bcc_array = $bcc;\n\t\t\t}\n\n\t\t\tif ($this->_build_message() === FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_spool_email();\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Unwrap special elements\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _unwrap_specials()\n\t{\n\t\t$this->_finalbody = preg_replace_callback('/\\{unwrap\\}(.*?)\\{\\/unwrap\\}/si', array($this, '_remove_nl_callback'), $this->_finalbody);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Strip line-breaks via callback\n\t *\n\t * @param\tstring\t$matches\n\t * @return\tstring\n\t */\n\tprotected function _remove_nl_callback($matches)\n\t{\n\t\tif (strpos($matches[1], \"\\r\") !== FALSE OR strpos($matches[1], \"\\n\") !== FALSE)\n\t\t{\n\t\t\t$matches[1] = str_replace(array(\"\\r\\n\", \"\\r\", \"\\n\"), '', $matches[1]);\n\t\t}\n\n\t\treturn $matches[1];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Spool mail to the mail server\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _spool_email()\n\t{\n\t\t$this->_unwrap_specials();\n\n\t\t$method = '_send_with_'.$this->_get_protocol();\n\t\tif ( ! $this->$method())\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_send_failure_'.($this->_get_protocol() === 'mail' ? 'phpmail' : $this->_get_protocol()));\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_set_error_message('lang:email_sent', $this->_get_protocol());\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send using mail()\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _send_with_mail()\n\t{\n\t\tif (is_array($this->_recipients))\n\t\t{\n\t\t\t$this->_recipients = implode(', ', $this->_recipients);\n\t\t}\n\n\t\tif ($this->_safe_mode === TRUE)\n\t\t{\n\t\t\treturn mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// most documentation of sendmail using the \"-f\" flag lacks a space after it, however\n\t\t\t// we've encountered servers that seem to require it to be in place.\n\t\t\treturn mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$this->clean_email($this->_headers['Return-Path']));\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send using Sendmail\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _send_with_sendmail()\n\t{\n\t\t// is popen() enabled?\n\t\tif ( ! function_usable('popen')\n\t\t\tOR FALSE === ($fp = @popen(\n\t\t\t\t\t\t$this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From'])\n\t\t\t\t\t\t\t.' -t -r '.$this->clean_email($this->_headers['Return-Path'])\n\t\t\t\t\t\t, 'w'))\n\t\t) // server probably has popen disabled, so nothing we can do to get a verbose error.\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tfputs($fp, $this->_header_str);\n\t\tfputs($fp, $this->_finalbody);\n\n\t\t$status = pclose($fp);\n\n\t\tif ($status !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_exit_status', $status);\n\t\t\t$this->_set_error_message('lang:email_no_socket');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send using SMTP\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _send_with_smtp()\n\t{\n\t\tif ($this->smtp_host === '')\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_hostname');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! $this->_smtp_connect() OR ! $this->_smtp_authenticate())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! $this->_send_command('from', $this->clean_email($this->_headers['From'])))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tforeach ($this->_recipients as $val)\n\t\t{\n\t\t\tif ( ! $this->_send_command('to', $val))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\tif (count($this->_cc_array) > 0)\n\t\t{\n\t\t\tforeach ($this->_cc_array as $val)\n\t\t\t{\n\t\t\t\tif ($val !== '' && ! $this->_send_command('to', $val))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (count($this->_bcc_array) > 0)\n\t\t{\n\t\t\tforeach ($this->_bcc_array as $val)\n\t\t\t{\n\t\t\t\tif ($val !== '' && ! $this->_send_command('to', $val))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( ! $this->_send_command('data'))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// perform dot transformation on any lines that begin with a dot\n\t\t$this->_send_data($this->_header_str.preg_replace('/^\\./m', '..$1', $this->_finalbody));\n\n\t\t$this->_send_data('.');\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\t$this->_set_error_message($reply);\n\n\t\tif (strpos($reply, '250') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_error', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->smtp_keepalive)\n\t\t{\n\t\t\t$this->_send_command('reset');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_send_command('quit');\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * SMTP Connect\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _smtp_connect()\n\t{\n\t\tif (is_resource($this->_smtp_connect))\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t$ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : '';\n\n\t\t$this->_smtp_connect = fsockopen($ssl.$this->smtp_host,\n\t\t\t\t\t\t\t$this->smtp_port,\n\t\t\t\t\t\t\t$errno,\n\t\t\t\t\t\t\t$errstr,\n\t\t\t\t\t\t\t$this->smtp_timeout);\n\n\t\tif ( ! is_resource($this->_smtp_connect))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_error', $errno.' '.$errstr);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tstream_set_timeout($this->_smtp_connect, $this->smtp_timeout);\n\t\t$this->_set_error_message($this->_get_smtp_data());\n\n\t\tif ($this->smtp_crypto === 'tls')\n\t\t{\n\t\t\t$this->_send_command('hello');\n\t\t\t$this->_send_command('starttls');\n\n\t\t\t$crypto = stream_socket_enable_crypto($this->_smtp_connect, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);\n\n\t\t\tif ($crypto !== TRUE)\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_smtp_error', $this->_get_smtp_data());\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn $this->_send_command('hello');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send SMTP command\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _send_command($cmd, $data = '')\n\t{\n\t\tswitch ($cmd)\n\t\t{\n\t\t\tcase 'hello' :\n\n\t\t\t\t\t\tif ($this->_smtp_auth OR $this->_get_encoding() === '8bit')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('EHLO '.$this->_get_hostname());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('HELO '.$this->_get_hostname());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'starttls'\t:\n\n\t\t\t\t\t\t$this->_send_data('STARTTLS');\n\t\t\t\t\t\t$resp = 220;\n\t\t\tbreak;\n\t\t\tcase 'from' :\n\n\t\t\t\t\t\t$this->_send_data('MAIL FROM:<'.$data.'>');\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'to' :\n\n\t\t\t\t\t\tif ($this->dsn)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('RCPT TO:<'.$data.'>');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'data'\t:\n\n\t\t\t\t\t\t$this->_send_data('DATA');\n\t\t\t\t\t\t$resp = 354;\n\t\t\tbreak;\n\t\t\tcase 'reset':\n\n\t\t\t\t\t\t$this->_send_data('RSET');\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'quit'\t:\n\n\t\t\t\t\t\t$this->_send_data('QUIT');\n\t\t\t\t\t\t$resp = 221;\n\t\t\tbreak;\n\t\t}\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\t$this->_debug_msg[] = '<pre>'.$cmd.': '.$reply.'</pre>';\n\n\t\tif ((int) substr($reply, 0, 3) !== $resp)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_error', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($cmd === 'quit')\n\t\t{\n\t\t\tfclose($this->_smtp_connect);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * SMTP Authenticate\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _smtp_authenticate()\n\t{\n\t\tif ( ! $this->_smtp_auth)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ($this->smtp_user === '' && $this->smtp_pass === '')\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_smtp_unpw');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_send_data('AUTH LOGIN');\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\tif (strpos($reply, '503') === 0)\t// Already authenticated\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif (strpos($reply, '334') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_failed_smtp_login', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_send_data(base64_encode($this->smtp_user));\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\tif (strpos($reply, '334') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_auth_un', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_send_data(base64_encode($this->smtp_pass));\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\tif (strpos($reply, '235') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_auth_pw', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send SMTP data\n\t *\n\t * @param\tstring\t$data\n\t * @return\tbool\n\t */\n\tprotected function _send_data($data)\n\t{\n\t\t$data .= $this->newline;\n\t\tfor ($written = $timestamp = 0, $length = strlen($data); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($this->_smtp_connect, substr($data, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951\n\t\t\telseif ($result === 0)\n\t\t\t{\n\t\t\t\tif ($timestamp === 0)\n\t\t\t\t{\n\t\t\t\t\t$timestamp = time();\n\t\t\t\t}\n\t\t\t\telseif ($timestamp < (time() - $this->smtp_timeout))\n\t\t\t\t{\n\t\t\t\t\t$result = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tusleep(250000);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$timestamp = 0;\n\t\t\t}\n\t\t}\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_data_failure', $data);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get SMTP data\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_smtp_data()\n\t{\n\t\t$data = '';\n\n\t\twhile ($str = fgets($this->_smtp_connect, 512))\n\t\t{\n\t\t\t$data .= $str;\n\n\t\t\tif ($str[3] === ' ')\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Hostname\n\t *\n\t * There are only two legal types of hostname - either a fully\n\t * qualified domain name (eg: \"mail.example.com\") or an IP literal\n\t * (eg: \"[1.2.3.4]\").\n\t *\n\t * @link\thttps://tools.ietf.org/html/rfc5321#section-2.3.5\n\t * @link\thttp://cbl.abuseat.org/namingproblems.html\n\t * @return\tstring\n\t */\n\tprotected function _get_hostname()\n\t{\n\t\tif (isset($_SERVER['SERVER_NAME']))\n\t\t{\n\t\t\treturn $_SERVER['SERVER_NAME'];\n\t\t}\n\n\t\treturn isset($_SERVER['SERVER_ADDR']) ? '['.$_SERVER['SERVER_ADDR'].']' : '[127.0.0.1]';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Debug Message\n\t *\n\t * @param\tarray\t$include\tList of raw data chunks to include in the output\n\t *\t\t\t\t\tValid options are: 'headers', 'subject', 'body'\n\t * @return\tstring\n\t */\n\tpublic function print_debugger($include = array('headers', 'subject', 'body'))\n\t{\n\t\t$msg = '';\n\n\t\tif (count($this->_debug_msg) > 0)\n\t\t{\n\t\t\tforeach ($this->_debug_msg as $val)\n\t\t\t{\n\t\t\t\t$msg .= $val;\n\t\t\t}\n\t\t}\n\n\t\t// Determine which parts of our raw data needs to be printed\n\t\t$raw_data = '';\n\t\tis_array($include) OR $include = array($include);\n\n\t\tif (in_array('headers', $include, TRUE))\n\t\t{\n\t\t\t$raw_data = htmlspecialchars($this->_header_str).\"\\n\";\n\t\t}\n\n\t\tif (in_array('subject', $include, TRUE))\n\t\t{\n\t\t\t$raw_data .= htmlspecialchars($this->_subject).\"\\n\";\n\t\t}\n\n\t\tif (in_array('body', $include, TRUE))\n\t\t{\n\t\t\t$raw_data .= htmlspecialchars($this->_finalbody);\n\t\t}\n\n\t\treturn $msg.($raw_data === '' ? '' : '<pre>'.$raw_data.'</pre>');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Message\n\t *\n\t * @param\tstring\t$msg\n\t * @param\tstring\t$val = ''\n\t * @return\tvoid\n\t */\n\tprotected function _set_error_message($msg, $val = '')\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('email');\n\n\t\tif (sscanf($msg, 'lang:%s', $line) !== 1 OR FALSE === ($line = $CI->lang->line($line)))\n\t\t{\n\t\t\t$this->_debug_msg[] = str_replace('%s', $val, $msg).'<br />';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_debug_msg[] = str_replace('%s', $val, $line).'<br />';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mime Types\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _mime_types($ext = '')\n\t{\n\t\t$ext = strtolower($ext);\n\n\t\t$mimes =& get_mimes();\n\n\t\tif (isset($mimes[$ext]))\n\t\t{\n\t\t\treturn is_array($mimes[$ext])\n\t\t\t\t? current($mimes[$ext])\n\t\t\t\t: $mimes[$ext];\n\t\t}\n\n\t\treturn 'application/x-unknown-content-type';\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Encrypt.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Encryption Class\n *\n * Provides two-way keyed encoding using Mcrypt\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/encryption.html\n */\nclass CI_Encrypt {\n\n\t/**\n\t * Reference to the user's encryption key\n\t *\n\t * @var string\n\t */\n\tpublic $encryption_key\t\t= '';\n\n\t/**\n\t * Type of hash operation\n\t *\n\t * @var string\n\t */\n\tprotected $_hash_type\t\t= 'sha1';\n\n\t/**\n\t * Flag for the existence of mcrypt\n\t *\n\t * @var bool\n\t */\n\tprotected $_mcrypt_exists\t= FALSE;\n\n\t/**\n\t * Current cipher to be used with mcrypt\n\t *\n\t * @var string\n\t */\n\tprotected $_mcrypt_cipher;\n\n\t/**\n\t * Method for encrypting/decrypting data\n\t *\n\t * @var int\n\t */\n\tprotected $_mcrypt_mode;\n\n\t/**\n\t * Initialize Encryption class\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tif (($this->_mcrypt_exists = function_exists('mcrypt_encrypt')) === FALSE)\n\t\t{\n\t\t\tshow_error('The Encrypt library requires the Mcrypt extension.');\n\t\t}\n\n\t\tlog_message('info', 'Encrypt Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch the encryption key\n\t *\n\t * Returns it as MD5 in order to have an exact-length 128 bit key.\n\t * Mcrypt is sensitive to keys that are not the correct length\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function get_key($key = '')\n\t{\n\t\tif ($key === '')\n\t\t{\n\t\t\tif ($this->encryption_key !== '')\n\t\t\t{\n\t\t\t\treturn $this->encryption_key;\n\t\t\t}\n\n\t\t\t$key = config_item('encryption_key');\n\n\t\t\tif ( ! strlen($key))\n\t\t\t{\n\t\t\t\tshow_error('In order to use the encryption class requires that you set an encryption key in your config file.');\n\t\t\t}\n\t\t}\n\n\t\treturn md5($key);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the encryption key\n\t *\n\t * @param\tstring\n\t * @return\tCI_Encrypt\n\t */\n\tpublic function set_key($key = '')\n\t{\n\t\t$this->encryption_key = $key;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encode\n\t *\n\t * Encodes the message string using bitwise XOR encoding.\n\t * The key is combined with a random hash, and then it\n\t * too gets converted using XOR. The whole thing is then run\n\t * through mcrypt using the randomized key. The end result\n\t * is a double-encrypted message string that is randomized\n\t * with each call to this function, even if the supplied\n\t * message and key are the same.\n\t *\n\t * @param\tstring\tthe string to encode\n\t * @param\tstring\tthe key\n\t * @return\tstring\n\t */\n\tpublic function encode($string, $key = '')\n\t{\n\t\treturn base64_encode($this->mcrypt_encode($string, $this->get_key($key)));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decode\n\t *\n\t * Reverses the above process\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function decode($string, $key = '')\n\t{\n\t\tif (preg_match('/[^a-zA-Z0-9\\/\\+=]/', $string) OR base64_encode(base64_decode($string)) !== $string)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->mcrypt_decode(base64_decode($string), $this->get_key($key));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encode from Legacy\n\t *\n\t * Takes an encoded string from the original Encryption class algorithms and\n\t * returns a newly encoded string using the improved method added in 2.0.0\n\t * This allows for backwards compatibility and a method to transition to the\n\t * new encryption algorithms.\n\t *\n\t * For more details, see http://codeigniter.com/user_guide/installation/upgrade_200.html#encryption\n\t *\n\t * @param\tstring\n\t * @param\tint\t\t(mcrypt mode constant)\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function encode_from_legacy($string, $legacy_mode = MCRYPT_MODE_ECB, $key = '')\n\t{\n\t\tif (preg_match('/[^a-zA-Z0-9\\/\\+=]/', $string))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// decode it first\n\t\t// set mode temporarily to what it was when string was encoded with the legacy\n\t\t// algorithm - typically MCRYPT_MODE_ECB\n\t\t$current_mode = $this->_get_mode();\n\t\t$this->set_mode($legacy_mode);\n\n\t\t$key = $this->get_key($key);\n\t\t$dec = base64_decode($string);\n\t\tif (($dec = $this->mcrypt_decode($dec, $key)) === FALSE)\n\t\t{\n\t\t\t$this->set_mode($current_mode);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$dec = $this->_xor_decode($dec, $key);\n\n\t\t// set the mcrypt mode back to what it should be, typically MCRYPT_MODE_CBC\n\t\t$this->set_mode($current_mode);\n\n\t\t// and re-encode\n\t\treturn base64_encode($this->mcrypt_encode($dec, $key));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XOR Decode\n\t *\n\t * Takes an encoded string and key as input and generates the\n\t * plain-text original message\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _xor_decode($string, $key)\n\t{\n\t\t$string = $this->_xor_merge($string, $key);\n\n\t\t$dec = '';\n\t\tfor ($i = 0, $l = strlen($string); $i < $l; $i++)\n\t\t{\n\t\t\t$dec .= ($string[$i++] ^ $string[$i]);\n\t\t}\n\n\t\treturn $dec;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XOR key + string Combiner\n\t *\n\t * Takes a string and key as input and computes the difference using XOR\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _xor_merge($string, $key)\n\t{\n\t\t$hash = $this->hash($key);\n\t\t$str = '';\n\t\tfor ($i = 0, $ls = strlen($string), $lh = strlen($hash); $i < $ls; $i++)\n\t\t{\n\t\t\t$str .= $string[$i] ^ $hash[($i % $lh)];\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt using Mcrypt\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function mcrypt_encode($data, $key)\n\t{\n\t\t$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());\n\t\t$init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);\n\t\treturn $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt using Mcrypt\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function mcrypt_decode($data, $key)\n\t{\n\t\t$data = $this->_remove_cipher_noise($data, $key);\n\t\t$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());\n\n\t\tif ($init_size > strlen($data))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$init_vect = substr($data, 0, $init_size);\n\t\t$data = substr($data, $init_size);\n\t\treturn rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), \"\\0\");\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Adds permuted noise to the IV + encrypted data to protect\n\t * against Man-in-the-middle attacks on CBC mode ciphers\n\t * http://www.ciphersbyritter.com/GLOSSARY.HTM#IV\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _add_cipher_noise($data, $key)\n\t{\n\t\t$key = $this->hash($key);\n\t\t$str = '';\n\n\t\tfor ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j)\n\t\t{\n\t\t\tif ($j >= $lk)\n\t\t\t{\n\t\t\t\t$j = 0;\n\t\t\t}\n\n\t\t\t$str .= chr((ord($data[$i]) + ord($key[$j])) % 256);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Removes permuted noise from the IV + encrypted data, reversing\n\t * _add_cipher_noise()\n\t *\n\t * Function description\n\t *\n\t * @param\tstring\t$data\n\t * @param\tstring\t$key\n\t * @return\tstring\n\t */\n\tprotected function _remove_cipher_noise($data, $key)\n\t{\n\t\t$key = $this->hash($key);\n\t\t$str = '';\n\n\t\tfor ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j)\n\t\t{\n\t\t\tif ($j >= $lk)\n\t\t\t{\n\t\t\t\t$j = 0;\n\t\t\t}\n\n\t\t\t$temp = ord($data[$i]) - ord($key[$j]);\n\n\t\t\tif ($temp < 0)\n\t\t\t{\n\t\t\t\t$temp += 256;\n\t\t\t}\n\n\t\t\t$str .= chr($temp);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Mcrypt Cipher\n\t *\n\t * @param\tint\n\t * @return\tCI_Encrypt\n\t */\n\tpublic function set_cipher($cipher)\n\t{\n\t\t$this->_mcrypt_cipher = $cipher;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Mcrypt Mode\n\t *\n\t * @param\tint\n\t * @return\tCI_Encrypt\n\t */\n\tpublic function set_mode($mode)\n\t{\n\t\t$this->_mcrypt_mode = $mode;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mcrypt cipher Value\n\t *\n\t * @return\tint\n\t */\n\tprotected function _get_cipher()\n\t{\n\t\tif ($this->_mcrypt_cipher === NULL)\n\t\t{\n\t\t\treturn $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;\n\t\t}\n\n\t\treturn $this->_mcrypt_cipher;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mcrypt Mode Value\n\t *\n\t * @return\tint\n\t */\n\tprotected function _get_mode()\n\t{\n\t\tif ($this->_mcrypt_mode === NULL)\n\t\t{\n\t\t\treturn $this->_mcrypt_mode = MCRYPT_MODE_CBC;\n\t\t}\n\n\t\treturn $this->_mcrypt_mode;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Hash type\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_hash($type = 'sha1')\n\t{\n\t\t$this->_hash_type = in_array($type, hash_algos()) ? $type : 'sha1';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hash encode a string\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function hash($str)\n\t{\n\t\treturn hash($this->_hash_type, $str);\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Encryption.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Encryption Class\n *\n * Provides two-way keyed encryption via PHP's MCrypt and/or OpenSSL extensions.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tAndrey Andreev\n * @link\t\thttp://codeigniter.com/user_guide/libraries/encryption.html\n */\nclass CI_Encryption {\n\n\t/**\n\t * Encryption cipher\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_cipher = 'aes-128';\n\n\t/**\n\t * Cipher mode\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_mode = 'cbc';\n\n\t/**\n\t * Cipher handle\n\t *\n\t * @var\tmixed\n\t */\n\tprotected $_handle;\n\n\t/**\n\t * Encryption key\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_key;\n\n\t/**\n\t * PHP extension to be used\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_driver;\n\n\t/**\n\t * List of usable drivers (PHP extensions)\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_drivers = array();\n\n\t/**\n\t * List of available modes\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_modes = array(\n\t\t'mcrypt' => array(\n\t\t\t'cbc' => 'cbc',\n\t\t\t'ecb' => 'ecb',\n\t\t\t'ofb' => 'nofb',\n\t\t\t'ofb8' => 'ofb',\n\t\t\t'cfb' => 'ncfb',\n\t\t\t'cfb8' => 'cfb',\n\t\t\t'ctr' => 'ctr',\n\t\t\t'stream' => 'stream'\n\t\t),\n\t\t'openssl' => array(\n\t\t\t'cbc' => 'cbc',\n\t\t\t'ecb' => 'ecb',\n\t\t\t'ofb' => 'ofb',\n\t\t\t'cfb' => 'cfb',\n\t\t\t'cfb8' => 'cfb8',\n\t\t\t'ctr' => 'ctr',\n\t\t\t'stream' => '',\n\t\t\t'xts' => 'xts'\n\t\t)\n\t);\n\n\t/**\n\t * List of supported HMAC algorithms\n\t *\n\t * name => digest size pairs\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_digests = array(\n\t\t'sha224' => 28,\n\t\t'sha256' => 32,\n\t\t'sha384' => 48,\n\t\t'sha512' => 64\n\t);\n\n\t/**\n\t * mbstring.func_override flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected static $func_override;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(array $params = array())\n\t{\n\t\t$this->_drivers = array(\n\t\t\t'mcrypt' => defined('MCRYPT_DEV_URANDOM'),\n\t\t\t// While OpenSSL is available for PHP 5.3.0, an IV parameter\n\t\t\t// for the encrypt/decrypt functions is only available since 5.3.3\n\t\t\t'openssl' => (is_php('5.3.3') && extension_loaded('openssl'))\n\t\t);\n\n\t\tif ( ! $this->_drivers['mcrypt'] && ! $this->_drivers['openssl'])\n\t\t{\n\t\t\tshow_error('Encryption: Unable to find an available encryption driver.');\n\t\t}\n\n\t\tisset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));\n\t\t$this->initialize($params);\n\n\t\tif ( ! isset($this->_key) && self::strlen($key = config_item('encryption_key')) > 0)\n\t\t{\n\t\t\t$this->_key = $key;\n\t\t}\n\n\t\tlog_message('info', 'Encryption Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tCI_Encryption\n\t */\n\tpublic function initialize(array $params)\n\t{\n\t\tif ( ! empty($params['driver']))\n\t\t{\n\t\t\tif (isset($this->_drivers[$params['driver']]))\n\t\t\t{\n\t\t\t\tif ($this->_drivers[$params['driver']])\n\t\t\t\t{\n\t\t\t\t\t$this->_driver = $params['driver'];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlog_message('error', \"Encryption: Driver '\".$params['driver'].\"' is not available.\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_message('error', \"Encryption: Unknown driver '\".$params['driver'].\"' cannot be configured.\");\n\t\t\t}\n\t\t}\n\n\t\tif (empty($this->_driver))\n\t\t{\n\t\t\t$this->_driver = ($this->_drivers['openssl'] === TRUE)\n\t\t\t\t? 'openssl'\n\t\t\t\t: 'mcrypt';\n\n\t\t\tlog_message('debug', \"Encryption: Auto-configured driver '\".$this->_driver.\"'.\");\n\t\t}\n\n\t\tempty($params['cipher']) && $params['cipher'] = $this->_cipher;\n\t\tempty($params['key']) OR $this->_key = $params['key'];\n\t\t$this->{'_'.$this->_driver.'_initialize'}($params);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize MCrypt\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tprotected function _mcrypt_initialize($params)\n\t{\n\t\tif ( ! empty($params['cipher']))\n\t\t{\n\t\t\t$params['cipher'] = strtolower($params['cipher']);\n\t\t\t$this->_cipher_alias($params['cipher']);\n\n\t\t\tif ( ! in_array($params['cipher'], mcrypt_list_algorithms(), TRUE))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: MCrypt cipher '.strtoupper($params['cipher']).' is not available.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_cipher = $params['cipher'];\n\t\t\t}\n\t\t}\n\n\t\tif ( ! empty($params['mode']))\n\t\t{\n\t\t\t$params['mode'] = strtolower($params['mode']);\n\t\t\tif ( ! isset($this->_modes['mcrypt'][$params['mode']]))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: MCrypt mode '.strtoupper($params['mode']).' is not available.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_mode = $this->_modes['mcrypt'][$params['mode']];\n\t\t\t}\n\t\t}\n\n\t\tif (isset($this->_cipher, $this->_mode))\n\t\t{\n\t\t\tif (is_resource($this->_handle)\n\t\t\t\t&& (strtolower(mcrypt_enc_get_algorithms_name($this->_handle)) !== $this->_cipher\n\t\t\t\t\tOR strtolower(mcrypt_enc_get_modes_name($this->_handle)) !== $this->_mode)\n\t\t\t)\n\t\t\t{\n\t\t\t\tmcrypt_module_close($this->_handle);\n\t\t\t}\n\n\t\t\tif ($this->_handle = mcrypt_module_open($this->_cipher, '', $this->_mode, ''))\n\t\t\t{\n\t\t\t\tlog_message('info', 'Encryption: MCrypt cipher '.strtoupper($this->_cipher).' initialized in '.strtoupper($this->_mode).' mode.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: Unable to initialize MCrypt with cipher '.strtoupper($this->_cipher).' in '.strtoupper($this->_mode).' mode.');\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize OpenSSL\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tprotected function _openssl_initialize($params)\n\t{\n\t\tif ( ! empty($params['cipher']))\n\t\t{\n\t\t\t$params['cipher'] = strtolower($params['cipher']);\n\t\t\t$this->_cipher_alias($params['cipher']);\n\t\t\t$this->_cipher = $params['cipher'];\n\t\t}\n\n\t\tif ( ! empty($params['mode']))\n\t\t{\n\t\t\t$params['mode'] = strtolower($params['mode']);\n\t\t\tif ( ! isset($this->_modes['openssl'][$params['mode']]))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: OpenSSL mode '.strtoupper($params['mode']).' is not available.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_mode = $this->_modes['openssl'][$params['mode']];\n\t\t\t}\n\t\t}\n\n\t\tif (isset($this->_cipher, $this->_mode))\n\t\t{\n\t\t\t// This is mostly for the stream mode, which doesn't get suffixed in OpenSSL\n\t\t\t$handle = empty($this->_mode)\n\t\t\t\t? $this->_cipher\n\t\t\t\t: $this->_cipher.'-'.$this->_mode;\n\n\t\t\tif ( ! in_array($handle, openssl_get_cipher_methods(), TRUE))\n\t\t\t{\n\t\t\t\t$this->_handle = NULL;\n\t\t\t\tlog_message('error', 'Encryption: Unable to initialize OpenSSL with method '.strtoupper($handle).'.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_handle = $handle;\n\t\t\t\tlog_message('info', 'Encryption: OpenSSL initialized with method '.strtoupper($handle).'.');\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create a random key\n\t *\n\t * @param\tint\t$length\tOutput length\n\t * @return\tstring\n\t */\n\tpublic function create_key($length)\n\t{\n\t\treturn ($this->_driver === 'mcrypt')\n\t\t\t? mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)\n\t\t\t: openssl_random_pseudo_bytes($length);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt\n\t *\n\t * @param\tstring\t$data\tInput data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tpublic function encrypt($data, array $params = NULL)\n\t{\n\t\tif (($params = $this->_get_params($params)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tisset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');\n\n\t\tif (($data = $this->{'_'.$this->_driver.'_encrypt'}($data, $params)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$params['base64'] && $data = base64_encode($data);\n\n\t\tif (isset($params['hmac_digest']))\n\t\t{\n\t\t\tisset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');\n\t\t\treturn hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']).$data;\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt via MCrypt\n\t *\n\t * @param\tstring\t$data\tInput data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _mcrypt_encrypt($data, $params)\n\t{\n\t\tif ( ! is_resource($params['handle']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// The greater-than-1 comparison is mostly a work-around for a bug,\n\t\t// where 1 is returned for ARCFour instead of 0.\n\t\t$iv = (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)\n\t\t\t? mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM)\n\t\t\t: NULL;\n\n\t\tif (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)\n\t\t{\n\t\t\tif ($params['handle'] !== $this->_handle)\n\t\t\t{\n\t\t\t\tmcrypt_module_close($params['handle']);\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Use PKCS#7 padding in order to ensure compatibility with OpenSSL\n\t\t// and other implementations outside of PHP.\n\t\tif (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))\n\t\t{\n\t\t\t$block_size = mcrypt_enc_get_block_size($params['handle']);\n\t\t\t$pad = $block_size - (self::strlen($data) % $block_size);\n\t\t\t$data .= str_repeat(chr($pad), $pad);\n\t\t}\n\n\t\t// Work-around for yet another strange behavior in MCrypt.\n\t\t//\n\t\t// When encrypting in ECB mode, the IV is ignored. Yet\n\t\t// mcrypt_enc_get_iv_size() returns a value larger than 0\n\t\t// even if ECB is used AND mcrypt_generic_init() complains\n\t\t// if you don't pass an IV with length equal to the said\n\t\t// return value.\n\t\t//\n\t\t// This probably would've been fine (even though still wasteful),\n\t\t// but OpenSSL isn't that dumb and we need to make the process\n\t\t// portable, so ...\n\t\t$data = (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')\n\t\t\t? $iv.mcrypt_generic($params['handle'], $data)\n\t\t\t: mcrypt_generic($params['handle'], $data);\n\n\t\tmcrypt_generic_deinit($params['handle']);\n\t\tif ($params['handle'] !== $this->_handle)\n\t\t{\n\t\t\tmcrypt_module_close($params['handle']);\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt via OpenSSL\n\t *\n\t * @param\tstring\t$data\tInput data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _openssl_encrypt($data, $params)\n\t{\n\t\tif (empty($params['handle']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$iv = ($iv_size = openssl_cipher_iv_length($params['handle']))\n\t\t\t? openssl_random_pseudo_bytes($iv_size)\n\t\t\t: NULL;\n\n\t\t$data = openssl_encrypt(\n\t\t\t$data,\n\t\t\t$params['handle'],\n\t\t\t$params['key'],\n\t\t\t1, // DO NOT TOUCH!\n\t\t\t$iv\n\t\t);\n\n\t\tif ($data === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $iv.$data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt\n\t *\n\t * @param\tstring\t$data\tEncrypted data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tpublic function decrypt($data, array $params = NULL)\n\t{\n\t\tif (($params = $this->_get_params($params)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (isset($params['hmac_digest']))\n\t\t{\n\t\t\t// This might look illogical, but it is done during encryption as well ...\n\t\t\t// The 'base64' value is effectively an inverted \"raw data\" parameter\n\t\t\t$digest_size = ($params['base64'])\n\t\t\t\t? $this->_digests[$params['hmac_digest']] * 2\n\t\t\t\t: $this->_digests[$params['hmac_digest']];\n\n\t\t\tif (self::strlen($data) <= $digest_size)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$hmac_input = self::substr($data, 0, $digest_size);\n\t\t\t$data = self::substr($data, $digest_size);\n\n\t\t\tisset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');\n\t\t\t$hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']);\n\n\t\t\t// Time-attack-safe comparison\n\t\t\t$diff = 0;\n\t\t\tfor ($i = 0; $i < $digest_size; $i++)\n\t\t\t{\n\t\t\t\t$diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]);\n\t\t\t}\n\n\t\t\tif ($diff !== 0)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\tif ($params['base64'])\n\t\t{\n\t\t\t$data = base64_decode($data);\n\t\t}\n\n\t\tisset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');\n\n\t\treturn $this->{'_'.$this->_driver.'_decrypt'}($data, $params);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt via MCrypt\n\t *\n\t * @param\tstring\t$data\tEncrypted data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _mcrypt_decrypt($data, $params)\n\t{\n\t\tif ( ! is_resource($params['handle']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// The greater-than-1 comparison is mostly a work-around for a bug,\n\t\t// where 1 is returned for ARCFour instead of 0.\n\t\tif (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)\n\t\t{\n\t\t\tif (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')\n\t\t\t{\n\t\t\t\t$iv = self::substr($data, 0, $iv_size);\n\t\t\t\t$data = self::substr($data, $iv_size);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// MCrypt is dumb and this is ignored, only size matters\n\t\t\t\t$iv = str_repeat(\"\\x0\", $iv_size);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$iv = NULL;\n\t\t}\n\n\t\tif (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)\n\t\t{\n\t\t\tif ($params['handle'] !== $this->_handle)\n\t\t\t{\n\t\t\t\tmcrypt_module_close($params['handle']);\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$data = mdecrypt_generic($params['handle'], $data);\n\t\t// Remove PKCS#7 padding, if necessary\n\t\tif (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))\n\t\t{\n\t\t\t$data = self::substr($data, 0, -ord($data[self::strlen($data)-1]));\n\t\t}\n\n\t\tmcrypt_generic_deinit($params['handle']);\n\t\tif ($params['handle'] !== $this->_handle)\n\t\t{\n\t\t\tmcrypt_module_close($params['handle']);\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt via OpenSSL\n\t *\n\t * @param\tstring\t$data\tEncrypted data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _openssl_decrypt($data, $params)\n\t{\n\t\tif ($iv_size = openssl_cipher_iv_length($params['handle']))\n\t\t{\n\t\t\t$iv = self::substr($data, 0, $iv_size);\n\t\t\t$data = self::substr($data, $iv_size);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$iv = NULL;\n\t\t}\n\n\t\treturn empty($params['handle'])\n\t\t\t? FALSE\n\t\t\t: openssl_decrypt(\n\t\t\t\t$data,\n\t\t\t\t$params['handle'],\n\t\t\t\t$params['key'],\n\t\t\t\t1, // DO NOT TOUCH!\n\t\t\t\t$iv\n\t\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get params\n\t *\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tarray\n\t */\n\tprotected function _get_params($params)\n\t{\n\t\tif (empty($params))\n\t\t{\n\t\t\treturn isset($this->_cipher, $this->_mode, $this->_key, $this->_handle)\n\t\t\t\t? array(\n\t\t\t\t\t'handle' => $this->_handle,\n\t\t\t\t\t'cipher' => $this->_cipher,\n\t\t\t\t\t'mode' => $this->_mode,\n\t\t\t\t\t'key' => NULL,\n\t\t\t\t\t'base64' => TRUE,\n\t\t\t\t\t'hmac_digest' => 'sha512',\n\t\t\t\t\t'hmac_key' => NULL\n\t\t\t\t)\n\t\t\t\t: FALSE;\n\t\t}\n\t\telseif ( ! isset($params['cipher'], $params['mode'], $params['key']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (isset($params['mode']))\n\t\t{\n\t\t\t$params['mode'] = strtolower($params['mode']);\n\t\t\tif ( ! isset($this->_modes[$this->_driver][$params['mode']]))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$params['mode'] = $this->_modes[$this->_driver][$params['mode']];\n\t\t\t}\n\t\t}\n\n\t\tif (isset($params['hmac']) && $params['hmac'] === FALSE)\n\t\t{\n\t\t\t$params['hmac_digest'] = $params['hmac_key'] = NULL;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( ! isset($params['hmac_key']))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\telseif (isset($params['hmac_digest']))\n\t\t\t{\n\t\t\t\t$params['hmac_digest'] = strtolower($params['hmac_digest']);\n\t\t\t\tif ( ! isset($this->_digests[$params['hmac_digest']]))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$params['hmac_digest'] = 'sha512';\n\t\t\t}\n\t\t}\n\n\t\t$params = array(\n\t\t\t'handle' => NULL,\n\t\t\t'cipher' => $params['cipher'],\n\t\t\t'mode' => $params['mode'],\n\t\t\t'key' => $params['key'],\n\t\t\t'base64' => isset($params['raw_data']) ? ! $params['raw_data'] : FALSE,\n\t\t\t'hmac_digest' => $params['hmac_digest'],\n\t\t\t'hmac_key' => $params['hmac_key']\n\t\t);\n\n\t\t$this->_cipher_alias($params['cipher']);\n\t\t$params['handle'] = ($params['cipher'] !== $this->_cipher OR $params['mode'] !== $this->_mode)\n\t\t\t? $this->{'_'.$this->_driver.'_get_handle'}($params['cipher'], $params['mode'])\n\t\t\t: $this->_handle;\n\n\t\treturn $params;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get MCrypt handle\n\t *\n\t * @param\tstring\t$cipher\tCipher name\n\t * @param\tstring\t$mode\tEncryption mode\n\t * @return\tresource\n\t */\n\tprotected function _mcrypt_get_handle($cipher, $mode)\n\t{\n\t\treturn mcrypt_module_open($cipher, '', $mode, '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get OpenSSL handle\n\t *\n\t * @param\tstring\t$cipher\tCipher name\n\t * @param\tstring\t$mode\tEncryption mode\n\t * @return\tstring\n\t */\n\tprotected function _openssl_get_handle($cipher, $mode)\n\t{\n\t\t// OpenSSL methods aren't suffixed with '-stream' for this mode\n\t\treturn ($mode === 'stream')\n\t\t\t? $cipher\n\t\t\t: $cipher.'-'.$mode;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Cipher alias\n\t *\n\t * Tries to translate cipher names between MCrypt and OpenSSL's \"dialects\".\n\t *\n\t * @param\tstring\t$cipher\tCipher name\n\t * @return\tvoid\n\t */\n\tprotected function _cipher_alias(&$cipher)\n\t{\n\t\tstatic $dictionary;\n\n\t\tif (empty($dictionary))\n\t\t{\n\t\t\t$dictionary = array(\n\t\t\t\t'mcrypt' => array(\n\t\t\t\t\t'aes-128' => 'rijndael-128',\n\t\t\t\t\t'aes-192' => 'rijndael-128',\n\t\t\t\t\t'aes-256' => 'rijndael-128',\n\t\t\t\t\t'des3-ede3' => 'tripledes',\n\t\t\t\t\t'bf' => 'blowfish',\n\t\t\t\t\t'cast5' => 'cast-128',\n\t\t\t\t\t'rc4' => 'arcfour',\n\t\t\t\t\t'rc4-40' => 'arcfour'\n\t\t\t\t),\n\t\t\t\t'openssl' => array(\n\t\t\t\t\t'rijndael-128' => 'aes-128',\n\t\t\t\t\t'tripledes' => 'des-ede3',\n\t\t\t\t\t'blowfish' => 'bf',\n\t\t\t\t\t'cast-128' => 'cast5',\n\t\t\t\t\t'arcfour' => 'rc4-40',\n\t\t\t\t\t'rc4' => 'rc4-40'\n\t\t\t\t)\n\t\t\t);\n\n\t\t\t// Notes:\n\t\t\t//\n\t\t\t// - Rijndael-128 is, at the same time all three of AES-128,\n\t\t\t//   AES-192 and AES-256. The only difference between them is\n\t\t\t//   the key size. Rijndael-192, Rijndael-256 on the other hand\n\t\t\t//   also have different block sizes and are NOT AES-compatible.\n\t\t\t//\n\t\t\t// - Blowfish is said to be supporting key sizes between\n\t\t\t//   4 and 56 bytes, but it appears that between MCrypt and\n\t\t\t//   OpenSSL, only those of 16 and more bytes are compatible.\n\t\t\t//   Also, don't know what MCrypt's 'blowfish-compat' is.\n\t\t\t//\n\t\t\t// - CAST-128/CAST5 produces a longer cipher when encrypted via\n\t\t\t//   OpenSSL, but (strangely enough) can be decrypted by either\n\t\t\t//   extension anyway.\n\t\t\t//   Also, it appears that OpenSSL uses 16 rounds regardless of\n\t\t\t//   the key size, while RFC2144 says that for key sizes lower\n\t\t\t//   than 11 bytes, only 12 rounds should be used. This makes\n\t\t\t//   it portable only with keys of between 11 and 16 bytes.\n\t\t\t//\n\t\t\t// - RC4 (ARCFour) has a strange implementation under OpenSSL.\n\t\t\t//   Its 'rc4-40' cipher method seems to work flawlessly, yet\n\t\t\t//   there's another one, 'rc4' that only works with a 16-byte key.\n\t\t\t//\n\t\t\t// - DES is compatible, but doesn't need an alias.\n\t\t\t//\n\t\t\t// Other seemingly matching ciphers between MCrypt, OpenSSL:\n\t\t\t//\n\t\t\t// - RC2 is NOT compatible and only an obscure forum post\n\t\t\t//   confirms that it is MCrypt's fault.\n\t\t}\n\n\t\tif (isset($dictionary[$this->_driver][$cipher]))\n\t\t{\n\t\t\t$cipher = $dictionary[$this->_driver][$cipher];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * HKDF\n\t *\n\t * @link\thttps://tools.ietf.org/rfc/rfc5869.txt\n\t * @param\t$key\tInput key\n\t * @param\t$digest\tA SHA-2 hashing algorithm\n\t * @param\t$salt\tOptional salt\n\t * @param\t$length\tOutput length (defaults to the selected digest size)\n\t * @param\t$info\tOptional context/application-specific info\n\t * @return\tstring\tA pseudo-random key\n\t */\n\tpublic function hkdf($key, $digest = 'sha512', $salt = NULL, $length = NULL, $info = '')\n\t{\n\t\tif ( ! isset($this->_digests[$digest]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (empty($length) OR ! is_int($length))\n\t\t{\n\t\t\t$length = $this->_digests[$digest];\n\t\t}\n\t\telseif ($length > (255 * $this->_digests[$digest]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tself::strlen($salt) OR $salt = str_repeat(\"\\0\", $this->_digests[$digest]);\n\n\t\t$prk = hash_hmac($digest, $key, $salt, TRUE);\n\t\t$key = '';\n\t\tfor ($key_block = '', $block_index = 1; self::strlen($key) < $length; $block_index++)\n\t\t{\n\t\t\t$key_block = hash_hmac($digest, $key_block.$info.chr($block_index), $prk, TRUE);\n\t\t\t$key .= $key_block;\n\t\t}\n\n\t\treturn self::substr($key, 0, $length);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __get() magic\n\t *\n\t * @param\tstring\t$key\tProperty name\n\t * @return\tmixed\n\t */\n\tpublic function __get($key)\n\t{\n\t\t// Because aliases\n\t\tif ($key === 'mode')\n\t\t{\n\t\t\treturn array_search($this->_mode, $this->_modes[$this->_driver], TRUE);\n\t\t}\n\t\telseif (in_array($key, array('cipher', 'driver', 'drivers', 'digests'), TRUE))\n\t\t{\n\t\t\treturn $this->{'_'.$key};\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Byte-safe strlen()\n\t *\n\t * @param\tstring\t$str\n\t * @return\tinteger\n\t */\n\tprotected static function strlen($str)\n\t{\n\t\treturn (self::$func_override)\n\t\t\t? mb_strlen($str, '8bit')\n\t\t\t: strlen($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Byte-safe substr()\n\t *\n\t * @param\tstring\t$str\n\t * @param\tint\t$start\n\t * @param\tint\t$length\n\t * @return\tstring\n\t */\n\tprotected static function substr($str, $start, $length = NULL)\n\t{\n\t\tif (self::$func_override)\n\t\t{\n\t\t\t// mb_substr($str, $start, null, '8bit') returns an empty\n\t\t\t// string on PHP 5.3\n\t\t\tisset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);\n\t\t\treturn mb_substr($str, $start, $length, '8bit');\n\t\t}\n\n\t\treturn isset($length)\n\t\t\t? substr($str, $start, $length)\n\t\t\t: substr($str, $start);\n\t}\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Form_validation.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Form Validation Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tValidation\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/form_validation.html\n */\nclass CI_Form_validation {\n\n\t/**\n\t * Reference to the CodeIgniter instance\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t/**\n\t * Validation data for the current form submission\n\t *\n\t * @var array\n\t */\n\tprotected $_field_data\t\t= array();\n\n\t/**\n\t * Validation rules for the current form\n\t *\n\t * @var array\n\t */\n\tprotected $_config_rules\t= array();\n\n\t/**\n\t * Array of validation errors\n\t *\n\t * @var array\n\t */\n\tprotected $_error_array\t\t= array();\n\n\t/**\n\t * Array of custom error messages\n\t *\n\t * @var array\n\t */\n\tprotected $_error_messages\t= array();\n\n\t/**\n\t * Start tag for error wrapping\n\t *\n\t * @var string\n\t */\n\tprotected $_error_prefix\t= '<p>';\n\n\t/**\n\t * End tag for error wrapping\n\t *\n\t * @var string\n\t */\n\tprotected $_error_suffix\t= '</p>';\n\n\t/**\n\t * Custom error message\n\t *\n\t * @var string\n\t */\n\tprotected $error_string\t\t= '';\n\n\t/**\n\t * Whether the form data has been validated as safe\n\t *\n\t * @var bool\n\t */\n\tprotected $_safe_form_data\t= FALSE;\n\n\t/**\n\t * Custom data to validate\n\t *\n\t * @var array\n\t */\n\tpublic $validation_data\t= array();\n\n\t/**\n\t * Initialize Form_Validation class\n\t *\n\t * @param\tarray\t$rules\n\t * @return\tvoid\n\t */\n\tpublic function __construct($rules = array())\n\t{\n\t\t$this->CI =& get_instance();\n\n\t\t// applies delimiters set in config file.\n\t\tif (isset($rules['error_prefix']))\n\t\t{\n\t\t\t$this->_error_prefix = $rules['error_prefix'];\n\t\t\tunset($rules['error_prefix']);\n\t\t}\n\t\tif (isset($rules['error_suffix']))\n\t\t{\n\t\t\t$this->_error_suffix = $rules['error_suffix'];\n\t\t\tunset($rules['error_suffix']);\n\t\t}\n\n\t\t// Validation rules can be stored in a config file.\n\t\t$this->_config_rules = $rules;\n\n\t\t// Automatically load the form helper\n\t\t$this->CI->load->helper('form');\n\n\t\tlog_message('info', 'Form Validation Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Rules\n\t *\n\t * This function takes an array of field names and validation\n\t * rules as input, any custom error messages, validates the info,\n\t * and stores it\n\t *\n\t * @param\tmixed\t$field\n\t * @param\tstring\t$label\n\t * @param\tmixed\t$rules\n\t * @param\tarray\t$errors\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_rules($field, $label = '', $rules = array(), $errors = array())\n\t{\n\t\t// No reason to set rules if we have no POST data\n\t\t// or a validation array has not been specified\n\t\tif ($this->CI->input->method() !== 'post' && empty($this->validation_data))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\n\t\t// If an array was passed via the first parameter instead of individual string\n\t\t// values we cycle through it and recursively call this function.\n\t\tif (is_array($field))\n\t\t{\n\t\t\tforeach ($field as $row)\n\t\t\t{\n\t\t\t\t// Houston, we have a problem...\n\t\t\t\tif ( ! isset($row['field'], $row['rules']))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// If the field label wasn't passed we use the field name\n\t\t\t\t$label = isset($row['label']) ? $row['label'] : $row['field'];\n\n\t\t\t\t// Add the custom error message array\n\t\t\t\t$errors = (isset($row['errors']) && is_array($row['errors'])) ? $row['errors'] : array();\n\n\t\t\t\t// Here we go!\n\t\t\t\t$this->set_rules($row['field'], $label, $row['rules'], $errors);\n\t\t\t}\n\n\t\t\treturn $this;\n\t\t}\n\n\t\t// No fields or no rules? Nothing to do...\n\t\tif ( ! is_string($field) OR $field === '' OR empty($rules))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\t\telseif ( ! is_array($rules))\n\t\t{\n\t\t\t// BC: Convert pipe-separated rules string to an array\n\t\t\tif ( ! is_string($rules))\n\t\t\t{\n\t\t\t\treturn $this;\n\t\t\t}\n\n\t\t\t$rules = preg_split('/\\|(?![^\\[]*\\])/', $rules);\n\t\t}\n\n\t\t// If the field label wasn't passed we use the field name\n\t\t$label = ($label === '') ? $field : $label;\n\n\t\t$indexes = array();\n\n\t\t// Is the field name an array? If it is an array, we break it apart\n\t\t// into its components so that we can fetch the corresponding POST data later\n\t\tif (($is_array = (bool) preg_match_all('/\\[(.*?)\\]/', $field, $matches)) === TRUE)\n\t\t{\n\t\t\tsscanf($field, '%[^[][', $indexes[0]);\n\n\t\t\tfor ($i = 0, $c = count($matches[0]); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ($matches[1][$i] !== '')\n\t\t\t\t{\n\t\t\t\t\t$indexes[] = $matches[1][$i];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Build our master array\n\t\t$this->_field_data[$field] = array(\n\t\t\t'field'\t\t=> $field,\n\t\t\t'label'\t\t=> $label,\n\t\t\t'rules'\t\t=> $rules,\n\t\t\t'errors'\t=> $errors,\n\t\t\t'is_array'\t=> $is_array,\n\t\t\t'keys'\t\t=> $indexes,\n\t\t\t'postdata'\t=> NULL,\n\t\t\t'error'\t\t=> ''\n\t\t);\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * By default, form validation uses the $_POST array to validate\n\t *\n\t * If an array is set through this method, then this array will\n\t * be used instead of the $_POST array\n\t *\n\t * Note that if you are validating multiple arrays, then the\n\t * reset_validation() function should be called after validating\n\t * each array due to the limitations of CI's singleton\n\t *\n\t * @param\tarray\t$data\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_data(array $data)\n\t{\n\t\tif ( ! empty($data))\n\t\t{\n\t\t\t$this->validation_data = $data;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Error Message\n\t *\n\t * Lets users set their own error messages on the fly. Note:\n\t * The key name has to match the function name that it corresponds to.\n\t *\n\t * @param\tarray\n\t * @param\tstring\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_message($lang, $val = '')\n\t{\n\t\tif ( ! is_array($lang))\n\t\t{\n\t\t\t$lang = array($lang => $val);\n\t\t}\n\n\t\t$this->_error_messages = array_merge($this->_error_messages, $lang);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set The Error Delimiter\n\t *\n\t * Permits a prefix/suffix to be added to each error message\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_error_delimiters($prefix = '<p>', $suffix = '</p>')\n\t{\n\t\t$this->_error_prefix = $prefix;\n\t\t$this->_error_suffix = $suffix;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Error Message\n\t *\n\t * Gets the error message associated with a particular field\n\t *\n\t * @param\tstring\t$field\tField name\n\t * @param\tstring\t$prefix\tHTML start tag\n\t * @param \tstring\t$suffix\tHTML end tag\n\t * @return\tstring\n\t */\n\tpublic function error($field, $prefix = '', $suffix = '')\n\t{\n\t\tif (empty($this->_field_data[$field]['error']))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif ($prefix === '')\n\t\t{\n\t\t\t$prefix = $this->_error_prefix;\n\t\t}\n\n\t\tif ($suffix === '')\n\t\t{\n\t\t\t$suffix = $this->_error_suffix;\n\t\t}\n\n\t\treturn $prefix.$this->_field_data[$field]['error'].$suffix;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Array of Error Messages\n\t *\n\t * Returns the error messages as an array\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error_array()\n\t{\n\t\treturn $this->_error_array;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error String\n\t *\n\t * Returns the error messages as a string, wrapped in the error delimiters\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function error_string($prefix = '', $suffix = '')\n\t{\n\t\t// No errors, validation passes!\n\t\tif (count($this->_error_array) === 0)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif ($prefix === '')\n\t\t{\n\t\t\t$prefix = $this->_error_prefix;\n\t\t}\n\n\t\tif ($suffix === '')\n\t\t{\n\t\t\t$suffix = $this->_error_suffix;\n\t\t}\n\n\t\t// Generate the error string\n\t\t$str = '';\n\t\tforeach ($this->_error_array as $val)\n\t\t{\n\t\t\tif ($val !== '')\n\t\t\t{\n\t\t\t\t$str .= $prefix.$val.$suffix.\"\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the Validator\n\t *\n\t * This function does all the work.\n\t *\n\t * @param\tstring\t$group\n\t * @return\tbool\n\t */\n\tpublic function run($group = '')\n\t{\n\t\t// Do we even have any data to process?  Mm?\n\t\t$validation_array = empty($this->validation_data) ? $_POST : $this->validation_data;\n\t\tif (count($validation_array) === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Does the _field_data array containing the validation rules exist?\n\t\t// If not, we look to see if they were assigned via a config file\n\t\tif (count($this->_field_data) === 0)\n\t\t{\n\t\t\t// No validation rules?  We're done...\n\t\t\tif (count($this->_config_rules) === 0)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (empty($group))\n\t\t\t{\n\t\t\t\t// Is there a validation rule for the particular URI being accessed?\n\t\t\t\t$group = trim($this->CI->uri->ruri_string(), '/');\n\t\t\t\tisset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method;\n\t\t\t}\n\n\t\t\t$this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules);\n\n\t\t\t// Were we able to set the rules correctly?\n\t\t\tif (count($this->_field_data) === 0)\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Unable to find validation rules');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// Load the language file containing error messages\n\t\t$this->CI->lang->load('form_validation');\n\n\t\t// Cycle through the rules for each field and match the corresponding $validation_data item\n\t\tforeach ($this->_field_data as $field => $row)\n\t\t{\n\t\t\t// Fetch the data from the validation_data array item and cache it in the _field_data array.\n\t\t\t// Depending on whether the field name is an array or a string will determine where we get it from.\n\t\t\tif ($row['is_array'] === TRUE)\n\t\t\t{\n\t\t\t\t$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);\n\t\t\t}\n\t\t\telseif (isset($validation_array[$field]))\n\t\t\t{\n\t\t\t\t$this->_field_data[$field]['postdata'] = $validation_array[$field];\n\t\t\t}\n\t\t}\n\n\t\t// Execute validation rules\n\t\t// Note: A second foreach (for now) is required in order to avoid false-positives\n\t\t//\t for rules like 'matches', which correlate to other validation fields.\n\t\tforeach ($this->_field_data as $field => $row)\n\t\t{\n\t\t\t// Don't try to validate if we have no rules set\n\t\t\tif (empty($row['rules']))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$this->_execute($row, $row['rules'], $this->_field_data[$field]['postdata']);\n\t\t}\n\n\t\t// Did we end up with any errors?\n\t\t$total_errors = count($this->_error_array);\n\t\tif ($total_errors > 0)\n\t\t{\n\t\t\t$this->_safe_form_data = TRUE;\n\t\t}\n\n\t\t// Now we need to re-set the POST data with the new, processed data\n\t\t$this->_reset_post_array();\n\n\t\treturn ($total_errors === 0);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Traverse a multidimensional $_POST array index until the data is found\n\t *\n\t * @param\tarray\n\t * @param\tarray\n\t * @param\tint\n\t * @return\tmixed\n\t */\n\tprotected function _reduce_array($array, $keys, $i = 0)\n\t{\n\t\tif (is_array($array) && isset($keys[$i]))\n\t\t{\n\t\t\treturn isset($array[$keys[$i]]) ? $this->_reduce_array($array[$keys[$i]], $keys, ($i+1)) : NULL;\n\t\t}\n\n\t\t// NULL must be returned for empty fields\n\t\treturn ($array === '') ? NULL : $array;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Re-populate the _POST array with our finalized and processed data\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _reset_post_array()\n\t{\n\t\tforeach ($this->_field_data as $field => $row)\n\t\t{\n\t\t\tif ($row['postdata'] !== NULL)\n\t\t\t{\n\t\t\t\tif ($row['is_array'] === FALSE)\n\t\t\t\t{\n\t\t\t\t\tif (isset($_POST[$row['field']]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$_POST[$row['field']] = $row['postdata'];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// start with a reference\n\t\t\t\t\t$post_ref =& $_POST;\n\n\t\t\t\t\t// before we assign values, make a reference to the right POST key\n\t\t\t\t\tif (count($row['keys']) === 1)\n\t\t\t\t\t{\n\t\t\t\t\t\t$post_ref =& $post_ref[current($row['keys'])];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tforeach ($row['keys'] as $val)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$post_ref =& $post_ref[$val];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (is_array($row['postdata']))\n\t\t\t\t\t{\n\t\t\t\t\t\t$array = array();\n\t\t\t\t\t\tforeach ($row['postdata'] as $k => $v)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$array[$k] = $v;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$post_ref = $array;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$post_ref = $row['postdata'];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Executes the Validation routines\n\t *\n\t * @param\tarray\n\t * @param\tarray\n\t * @param\tmixed\n\t * @param\tint\n\t * @return\tmixed\n\t */\n\tprotected function _execute($row, $rules, $postdata = NULL, $cycles = 0)\n\t{\n\t\t// If the $_POST data is an array we will run a recursive call\n\t\tif (is_array($postdata))\n\t\t{\n\t\t\tforeach ($postdata as $key => $val)\n\t\t\t{\n\t\t\t\t$this->_execute($row, $rules, $val, $key);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// If the field is blank, but NOT required, no further tests are necessary\n\t\t$callback = FALSE;\n\t\tif ( ! in_array('required', $rules) && ($postdata === NULL OR $postdata === ''))\n\t\t{\n\t\t\t// Before we bail out, does the rule contain a callback?\n\t\t\tforeach ($rules as &$rule)\n\t\t\t{\n\t\t\t\tif (is_string($rule))\n\t\t\t\t{\n\t\t\t\t\tif (strncmp($rule, 'callback_', 9) === 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t$callback = TRUE;\n\t\t\t\t\t\t$rules = array(1 => $rule);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telseif (is_callable($rule))\n\t\t\t\t{\n\t\t\t\t\t$callback = TRUE;\n\t\t\t\t\t$rules = array(1 => $rule);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))\n\t\t\t\t{\n\t\t\t\t\t$callback = TRUE;\n\t\t\t\t\t$rules = array(array($rule[0], $rule[1]));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( ! $callback)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Isset Test. Typically this rule will only apply to checkboxes.\n\t\tif (($postdata === NULL OR $postdata === '') && ! $callback)\n\t\t{\n\t\t\tif (in_array('isset', $rules, TRUE) OR in_array('required', $rules))\n\t\t\t{\n\t\t\t\t// Set the message type\n\t\t\t\t$type = in_array('required', $rules) ? 'required' : 'isset';\n\n\t\t\t\t// Check if a custom message is defined\n\t\t\t\tif (isset($this->_field_data[$row['field']]['errors'][$type]))\n\t\t\t\t{\n\t\t\t\t\t$line = $this->_field_data[$row['field']]['errors'][$type];\n\t\t\t\t}\n\t\t\t\telseif (isset($this->_error_messages[$type]))\n\t\t\t\t{\n\t\t\t\t\t$line = $this->_error_messages[$type];\n\t\t\t\t}\n\t\t\t\telseif (FALSE === ($line = $this->CI->lang->line('form_validation_'.$type))\n\t\t\t\t\t// DEPRECATED support for non-prefixed keys\n\t\t\t\t\t&& FALSE === ($line = $this->CI->lang->line($type, FALSE)))\n\t\t\t\t{\n\t\t\t\t\t$line = 'The field was not set';\n\t\t\t\t}\n\n\t\t\t\t// Build the error message\n\t\t\t\t$message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']));\n\n\t\t\t\t// Save the error message\n\t\t\t\t$this->_field_data[$row['field']]['error'] = $message;\n\n\t\t\t\tif ( ! isset($this->_error_array[$row['field']]))\n\t\t\t\t{\n\t\t\t\t\t$this->_error_array[$row['field']] = $message;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Cycle through each rule and run it\n\t\tforeach ($rules as $rule)\n\t\t{\n\t\t\t$_in_array = FALSE;\n\n\t\t\t// We set the $postdata variable with the current data in our master array so that\n\t\t\t// each cycle of the loop is dealing with the processed data from the last cycle\n\t\t\tif ($row['is_array'] === TRUE && is_array($this->_field_data[$row['field']]['postdata']))\n\t\t\t{\n\t\t\t\t// We shouldn't need this safety, but just in case there isn't an array index\n\t\t\t\t// associated with this cycle we'll bail out\n\t\t\t\tif ( ! isset($this->_field_data[$row['field']]['postdata'][$cycles]))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$postdata = $this->_field_data[$row['field']]['postdata'][$cycles];\n\t\t\t\t$_in_array = TRUE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If we get an array field, but it's not expected - then it is most likely\n\t\t\t\t// somebody messing with the form on the client side, so we'll just consider\n\t\t\t\t// it an empty field\n\t\t\t\t$postdata = is_array($this->_field_data[$row['field']]['postdata'])\n\t\t\t\t\t? NULL\n\t\t\t\t\t: $this->_field_data[$row['field']]['postdata'];\n\t\t\t}\n\n\t\t\t// Is the rule a callback?\n\t\t\t$callback = $callable = FALSE;\n\t\t\tif (is_string($rule))\n\t\t\t{\n\t\t\t\tif (strpos($rule, 'callback_') === 0)\n\t\t\t\t{\n\t\t\t\t\t$rule = substr($rule, 9);\n\t\t\t\t\t$callback = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (is_callable($rule))\n\t\t\t{\n\t\t\t\t$callable = TRUE;\n\t\t\t}\n\t\t\telseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))\n\t\t\t{\n\t\t\t\t// We have a \"named\" callable, so save the name\n\t\t\t\t$callable = $rule[0];\n\t\t\t\t$rule = $rule[1];\n\t\t\t}\n\n\t\t\t// Strip the parameter (if exists) from the rule\n\t\t\t// Rules can contain a parameter: max_length[5]\n\t\t\t$param = FALSE;\n\t\t\tif ( ! $callable && preg_match('/(.*?)\\[(.*)\\]/', $rule, $match))\n\t\t\t{\n\t\t\t\t$rule = $match[1];\n\t\t\t\t$param = $match[2];\n\t\t\t}\n\n\t\t\t// Call the function that corresponds to the rule\n\t\t\tif ($callback OR $callable !== FALSE)\n\t\t\t{\n\t\t\t\tif ($callback)\n\t\t\t\t{\n\t\t\t\t\tif ( ! method_exists($this->CI, $rule))\n\t\t\t\t\t{\n\t\t\t\t\t\tlog_message('debug', 'Unable to find callback validation rule: '.$rule);\n\t\t\t\t\t\t$result = FALSE;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Run the function and grab the result\n\t\t\t\t\t\t$result = $this->CI->$rule($postdata, $param);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$result = is_array($rule)\n\t\t\t\t\t\t? $rule[0]->{$rule[1]}($postdata)\n\t\t\t\t\t\t: $rule($postdata);\n\n\t\t\t\t\t// Is $callable set to a rule name?\n\t\t\t\t\tif ($callable !== FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$rule = $callable;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Re-assign the result to the master data array\n\t\t\t\tif ($_in_array === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\n\t\t\t\t// If the field isn't required and we just processed a callback we'll move on...\n\t\t\t\tif ( ! in_array('required', $rules, TRUE) && $result !== FALSE)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! method_exists($this, $rule))\n\t\t\t{\n\t\t\t\t// If our own wrapper function doesn't exist we see if a native PHP function does.\n\t\t\t\t// Users can use any native PHP function call that has one param.\n\t\t\t\tif (function_exists($rule))\n\t\t\t\t{\n\t\t\t\t\t// Native PHP functions issue warnings if you pass them more parameters than they use\n\t\t\t\t\t$result = ($param !== FALSE) ? $rule($postdata, $param) : $rule($postdata);\n\n\t\t\t\t\tif ($_in_array === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlog_message('debug', 'Unable to find validation rule: '.$rule);\n\t\t\t\t\t$result = FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$result = $this->$rule($postdata, $param);\n\n\t\t\t\tif ($_in_array === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Did the rule test negatively? If so, grab the error.\n\t\t\tif ($result === FALSE)\n\t\t\t{\n\t\t\t\t// Callable rules might not have named error messages\n\t\t\t\tif ( ! is_string($rule))\n\t\t\t\t{\n\t\t\t\t\t$line = $this->CI->lang->line('form_validation_error_message_not_set').'(Anonymous function)';\n\t\t\t\t}\n\t\t\t\t// Check if a custom message is defined\n\t\t\t\telseif (isset($this->_field_data[$row['field']]['errors'][$rule]))\n\t\t\t\t{\n\t\t\t\t\t$line = $this->_field_data[$row['field']]['errors'][$rule];\n\t\t\t\t}\n\t\t\t\telseif ( ! isset($this->_error_messages[$rule]))\n\t\t\t\t{\n\t\t\t\t\tif (FALSE === ($line = $this->CI->lang->line('form_validation_'.$rule))\n\t\t\t\t\t\t// DEPRECATED support for non-prefixed keys\n\t\t\t\t\t\t&& FALSE === ($line = $this->CI->lang->line($rule, FALSE)))\n\t\t\t\t\t{\n\t\t\t\t\t\t$line = $this->CI->lang->line('form_validation_error_message_not_set').'('.$rule.')';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$line = $this->_error_messages[$rule];\n\t\t\t\t}\n\n\t\t\t\t// Is the parameter we are inserting into the error message the name\n\t\t\t\t// of another field? If so we need to grab its \"field label\"\n\t\t\t\tif (isset($this->_field_data[$param], $this->_field_data[$param]['label']))\n\t\t\t\t{\n\t\t\t\t\t$param = $this->_translate_fieldname($this->_field_data[$param]['label']);\n\t\t\t\t}\n\n\t\t\t\t// Build the error message\n\t\t\t\t$message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']), $param);\n\n\t\t\t\t// Save the error message\n\t\t\t\t$this->_field_data[$row['field']]['error'] = $message;\n\n\t\t\t\tif ( ! isset($this->_error_array[$row['field']]))\n\t\t\t\t{\n\t\t\t\t\t$this->_error_array[$row['field']] = $message;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Translate a field name\n\t *\n\t * @param\tstring\tthe field name\n\t * @return\tstring\n\t */\n\tprotected function _translate_fieldname($fieldname)\n\t{\n\t\t// Do we need to translate the field name? We look for the prefix 'lang:' to determine this\n\t\t// If we find one, but there's no translation for the string - just return it\n\t\tif (sscanf($fieldname, 'lang:%s', $line) === 1 && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))\n\t\t{\n\t\t\treturn $line;\n\t\t}\n\n\t\treturn $fieldname;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build an error message using the field and param.\n\t *\n\t * @param\tstring\tThe error message line\n\t * @param\tstring\tA field's human name\n\t * @param\tmixed\tA rule's optional parameter\n\t * @return\tstring\n\t */\n\tprotected function _build_error_msg($line, $field = '', $param = '')\n\t{\n\t\t// Check for %s in the string for legacy support.\n\t\tif (strpos($line, '%s') !== FALSE)\n\t\t{\n\t\t\treturn sprintf($line, $field, $param);\n\t\t}\n\n\t\treturn str_replace(array('{field}', '{param}'), array($field, $param), $line);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Checks if the rule is present within the validator\n\t *\n\t * Permits you to check if a rule is present within the validator\n\t *\n\t * @param\tstring\tthe field name\n\t * @return\tbool\n\t */\n\tpublic function has_rule($field)\n\t{\n\t\treturn isset($this->_field_data[$field]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the value from a form\n\t *\n\t * Permits you to repopulate a form field with the value it was submitted\n\t * with, or, if that value doesn't exist, with the default\n\t *\n\t * @param\tstring\tthe field name\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function set_value($field = '', $default = '')\n\t{\n\t\tif ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn $default;\n\t\t}\n\n\t\t// If the data is an array output them one at a time.\n\t\t//\tE.g: form_input('name[]', set_value('name[]');\n\t\tif (is_array($this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn array_shift($this->_field_data[$field]['postdata']);\n\t\t}\n\n\t\treturn $this->_field_data[$field]['postdata'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Select\n\t *\n\t * Enables pull-down lists to be set to the value the user\n\t * selected in the event of an error\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function set_select($field = '', $value = '', $default = FALSE)\n\t{\n\t\tif ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn ($default === TRUE && count($this->_field_data) === 0) ? ' selected=\"selected\"' : '';\n\t\t}\n\n\t\t$field = $this->_field_data[$field]['postdata'];\n\t\t$value = (string) $value;\n\t\tif (is_array($field))\n\t\t{\n\t\t\t// Note: in_array('', array(0)) returns TRUE, do not use it\n\t\t\tforeach ($field as &$v)\n\t\t\t{\n\t\t\t\tif ($value === $v)\n\t\t\t\t{\n\t\t\t\t\treturn ' selected=\"selected\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\t\telseif (($field === '' OR $value === '') OR ($field !== $value))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn ' selected=\"selected\"';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Radio\n\t *\n\t * Enables radio buttons to be set to the value the user\n\t * selected in the event of an error\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function set_radio($field = '', $value = '', $default = FALSE)\n\t{\n\t\tif ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn ($default === TRUE && count($this->_field_data) === 0) ? ' checked=\"checked\"' : '';\n\t\t}\n\n\t\t$field = $this->_field_data[$field]['postdata'];\n\t\t$value = (string) $value;\n\t\tif (is_array($field))\n\t\t{\n\t\t\t// Note: in_array('', array(0)) returns TRUE, do not use it\n\t\t\tforeach ($field as &$v)\n\t\t\t{\n\t\t\t\tif ($value === $v)\n\t\t\t\t{\n\t\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\t\telseif (($field === '' OR $value === '') OR ($field !== $value))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn ' checked=\"checked\"';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Checkbox\n\t *\n\t * Enables checkboxes to be set to the value the user\n\t * selected in the event of an error\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function set_checkbox($field = '', $value = '', $default = FALSE)\n\t{\n\t\t// Logic is exactly the same as for radio fields\n\t\treturn $this->set_radio($field, $value, $default);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Required\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function required($str)\n\t{\n\t\treturn is_array($str) ? (bool) count($str) : (trim($str) !== '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Performs a Regular Expression match test.\n\t *\n\t * @param\tstring\n\t * @param\tstring\tregex\n\t * @return\tbool\n\t */\n\tpublic function regex_match($str, $regex)\n\t{\n\t\treturn (bool) preg_match($regex, $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Match one field to another\n\t *\n\t * @param\tstring\t$str\tstring to compare against\n\t * @param\tstring\t$field\n\t * @return\tbool\n\t */\n\tpublic function matches($str, $field)\n\t{\n\t\treturn isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])\n\t\t\t? ($str === $this->_field_data[$field]['postdata'])\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Differs from another field\n\t *\n\t * @param\tstring\n\t * @param\tstring\tfield\n\t * @return\tbool\n\t */\n\tpublic function differs($str, $field)\n\t{\n\t\treturn ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Unique\n\t *\n\t * Check if the input value doesn't already exist\n\t * in the specified database field.\n\t *\n\t * @param\tstring\t$str\n\t * @param\tstring\t$field\n\t * @return\tbool\n\t */\n\tpublic function is_unique($str, $field)\n\t{\n\t\tsscanf($field, '%[^.].%[^.]', $table, $field);\n\t\treturn isset($this->CI->db)\n\t\t\t? ($this->CI->db->limit(1)->get_where($table, array($field => $str))->num_rows() === 0)\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Minimum Length\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function min_length($str, $val)\n\t{\n\t\tif ( ! is_numeric($val))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn ($val <= mb_strlen($str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Max Length\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function max_length($str, $val)\n\t{\n\t\tif ( ! is_numeric($val))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn ($val >= mb_strlen($str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Exact Length\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function exact_length($str, $val)\n\t{\n\t\tif ( ! is_numeric($val))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn (mb_strlen($str) === (int) $val);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid URL\n\t *\n\t * @param\tstring\t$str\n\t * @return\tbool\n\t */\n\tpublic function valid_url($str)\n\t{\n\t\tif (empty($str))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif (preg_match('/^(?:([^:]*)\\:)?\\/\\/(.+)$/', $str, $matches))\n\t\t{\n\t\t\tif (empty($matches[2]))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\telseif ( ! in_array($matches[1], array('http', 'https'), TRUE))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$str = $matches[2];\n\t\t}\n\n\t\t$str = 'http://'.$str;\n\n\t\t// There's a bug affecting PHP 5.2.13, 5.3.2 that considers the\n\t\t// underscore to be a valid hostname character instead of a dash.\n\t\t// Reference: https://bugs.php.net/bug.php?id=51192\n\t\tif (version_compare(PHP_VERSION, '5.2.13', '==') OR version_compare(PHP_VERSION, '5.3.2', '=='))\n\t\t{\n\t\t\tsscanf($str, 'http://%[^/]', $host);\n\t\t\t$str = substr_replace($str, strtr($host, array('_' => '-', '-' => '_')), 7, strlen($host));\n\t\t}\n\n\t\treturn (filter_var($str, FILTER_VALIDATE_URL) !== FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid Email\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_email($str)\n\t{\n\t\tif (function_exists('idn_to_ascii') && $atpos = strpos($str, '@'))\n\t\t{\n\t\t\t$str = substr($str, 0, ++$atpos).idn_to_ascii(substr($str, $atpos));\n\t\t}\n\n\t\treturn (bool) filter_var($str, FILTER_VALIDATE_EMAIL);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid Emails\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_emails($str)\n\t{\n\t\tif (strpos($str, ',') === FALSE)\n\t\t{\n\t\t\treturn $this->valid_email(trim($str));\n\t\t}\n\n\t\tforeach (explode(',', $str) as $email)\n\t\t{\n\t\t\tif (trim($email) !== '' && $this->valid_email(trim($email)) === FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate IP Address\n\t *\n\t * @param\tstring\n\t * @param\tstring\t'ipv4' or 'ipv6' to validate a specific IP format\n\t * @return\tbool\n\t */\n\tpublic function valid_ip($ip, $which = '')\n\t{\n\t\treturn $this->CI->input->valid_ip($ip, $which);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha($str)\n\t{\n\t\treturn ctype_alpha($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha-numeric\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha_numeric($str)\n\t{\n\t\treturn ctype_alnum((string) $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha-numeric w/ spaces\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha_numeric_spaces($str)\n\t{\n\t\treturn (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha-numeric with underscores and dashes\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha_dash($str)\n\t{\n\t\treturn (bool) preg_match('/^[a-z0-9_-]+$/i', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Numeric\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function numeric($str)\n\t{\n\t\treturn (bool) preg_match('/^[\\-+]?[0-9]*\\.?[0-9]+$/', $str);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Integer\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function integer($str)\n\t{\n\t\treturn (bool) preg_match('/^[\\-+]?[0-9]+$/', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decimal number\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function decimal($str)\n\t{\n\t\treturn (bool) preg_match('/^[\\-+]?[0-9]+\\.[0-9]+$/', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Greater than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function greater_than($str, $min)\n\t{\n\t\treturn is_numeric($str) ? ($str > $min) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Equal to or Greater than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function greater_than_equal_to($str, $min)\n\t{\n\t\treturn is_numeric($str) ? ($str >= $min) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Less than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function less_than($str, $max)\n\t{\n\t\treturn is_numeric($str) ? ($str < $max) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Equal to or Less than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function less_than_equal_to($str, $max)\n\t{\n\t\treturn is_numeric($str) ? ($str <= $max) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Value should be within an array of values\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function in_list($value, $list)\n\t{\n\t\treturn in_array($value, explode(',', $list), TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is a Natural number  (0,1,2,3, etc.)\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function is_natural($str)\n\t{\n\t\treturn ctype_digit((string) $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is a Natural number, but not a zero  (1,2,3, etc.)\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function is_natural_no_zero($str)\n\t{\n\t\treturn ($str != 0 && ctype_digit((string) $str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid Base64\n\t *\n\t * Tests a string for characters outside of the Base64 alphabet\n\t * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_base64($str)\n\t{\n\t\treturn (base64_encode(base64_decode($str)) === $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep data for form\n\t *\n\t * This function allows HTML to be safely shown in a form.\n\t * Special characters are converted.\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function prep_for_form($data = '')\n\t{\n\t\tif ($this->_safe_form_data === FALSE OR empty($data))\n\t\t{\n\t\t\treturn $data;\n\t\t}\n\n\t\tif (is_array($data))\n\t\t{\n\t\t\tforeach ($data as $key => $val)\n\t\t\t{\n\t\t\t\t$data[$key] = $this->prep_for_form($val);\n\t\t\t}\n\n\t\t\treturn $data;\n\t\t}\n\n\t\treturn str_replace(array(\"'\", '\"', '<', '>'), array('&#39;', '&quot;', '&lt;', '&gt;'), stripslashes($data));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep URL\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function prep_url($str = '')\n\t{\n\t\tif ($str === 'http://' OR $str === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)\n\t\t{\n\t\t\treturn 'http://'.$str;\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Strip Image Tags\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function strip_image_tags($str)\n\t{\n\t\treturn $this->CI->security->strip_image_tags($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert PHP tags to entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function encode_php_tags($str)\n\t{\n\t\treturn str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reset validation vars\n\t *\n\t * Prevents subsequent validation routines from being affected by the\n\t * results of any previous validation routine due to the CI singleton.\n\t *\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function reset_validation()\n\t{\n\t\t$this->_field_data = array();\n\t\t$this->_error_array = array();\n\t\t$this->_error_messages = array();\n\t\t$this->error_string = '';\n\t\treturn $this;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Ftp.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * FTP Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/ftp.html\n */\nclass CI_FTP {\n\n\t/**\n\t * FTP Server hostname\n\t *\n\t * @var\tstring\n\t */\n\tpublic $hostname = '';\n\n\t/**\n\t * FTP Username\n\t *\n\t * @var\tstring\n\t */\n\tpublic $username = '';\n\n\t/**\n\t * FTP Password\n\t *\n\t * @var\tstring\n\t */\n\tpublic $password = '';\n\n\t/**\n\t * FTP Server port\n\t *\n\t * @var\tint\n\t */\n\tpublic $port = 21;\n\n\t/**\n\t * Passive mode flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $passive = TRUE;\n\n\t/**\n\t * Debug flag\n\t *\n\t * Specifies whether to display error messages.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $debug = FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Connection ID\n\t *\n\t * @var\tresource\n\t */\n\tprotected $conn_id;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tempty($config) OR $this->initialize($config);\n\t\tlog_message('info', 'FTP Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize preferences\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\tif (isset($this->$key))\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\t// Prep the hostname\n\t\t$this->hostname = preg_replace('|.+?://|', '', $this->hostname);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FTP Connect\n\t *\n\t * @param\tarray\t $config\tConnection values\n\t * @return\tbool\n\t */\n\tpublic function connect($config = array())\n\t{\n\t\tif (count($config) > 0)\n\t\t{\n\t\t\t$this->initialize($config);\n\t\t}\n\n\t\tif (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_connect');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! $this->_login())\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_login');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set passive mode if needed\n\t\tif ($this->passive === TRUE)\n\t\t{\n\t\t\tftp_pasv($this->conn_id, TRUE);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FTP Login\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _login()\n\t{\n\t\treturn @ftp_login($this->conn_id, $this->username, $this->password);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validates the connection ID\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _is_conn()\n\t{\n\t\tif ( ! is_resource($this->conn_id))\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_no_connection');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Change directory\n\t *\n\t * The second parameter lets us momentarily turn off debugging so that\n\t * this function can be used to test for the existence of a folder\n\t * without throwing an error. There's no FTP equivalent to is_dir()\n\t * so we do it by trying to change to a particular directory.\n\t * Internally, this parameter is only used by the \"mirror\" function below.\n\t *\n\t * @param\tstring\t$path\n\t * @param\tbool\t$suppress_debug\n\t * @return\tbool\n\t */\n\tpublic function changedir($path, $suppress_debug = FALSE)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_chdir($this->conn_id, $path);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE && $suppress_debug === FALSE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_changedir');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create a directory\n\t *\n\t * @param\tstring\t$path\n\t * @param\tint\t$permissions\n\t * @return\tbool\n\t */\n\tpublic function mkdir($path, $permissions = NULL)\n\t{\n\t\tif ($path === '' OR ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_mkdir($this->conn_id, $path);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_mkdir');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set file permissions if needed\n\t\tif ($permissions !== NULL)\n\t\t{\n\t\t\t$this->chmod($path, (int) $permissions);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Upload a file to the server\n\t *\n\t * @param\tstring\t$locpath\n\t * @param\tstring\t$rempath\n\t * @param\tstring\t$mode\n\t * @param\tint\t$permissions\n\t * @return\tbool\n\t */\n\tpublic function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! file_exists($locpath))\n\t\t{\n\t\t\t$this->_error('ftp_no_source_file');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the mode if not specified\n\t\tif ($mode === 'auto')\n\t\t{\n\t\t\t// Get the file extension so we can set the upload type\n\t\t\t$ext = $this->_getext($locpath);\n\t\t\t$mode = $this->_settype($ext);\n\t\t}\n\n\t\t$mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;\n\n\t\t$result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_upload');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set file permissions if needed\n\t\tif ($permissions !== NULL)\n\t\t{\n\t\t\t$this->chmod($rempath, (int) $permissions);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Download a file from a remote server to the local server\n\t *\n\t * @param\tstring\t$rempath\n\t * @param\tstring\t$locpath\n\t * @param\tstring\t$mode\n\t * @return\tbool\n\t */\n\tpublic function download($rempath, $locpath, $mode = 'auto')\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the mode if not specified\n\t\tif ($mode === 'auto')\n\t\t{\n\t\t\t// Get the file extension so we can set the upload type\n\t\t\t$ext = $this->_getext($rempath);\n\t\t\t$mode = $this->_settype($ext);\n\t\t}\n\n\t\t$mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;\n\n\t\t$result = @ftp_get($this->conn_id, $locpath, $rempath, $mode);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_download');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rename (or move) a file\n\t *\n\t * @param\tstring\t$old_file\n\t * @param\tstring\t$new_file\n\t * @param\tbool\t$move\n\t * @return\tbool\n\t */\n\tpublic function rename($old_file, $new_file, $move = FALSE)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_rename($this->conn_id, $old_file, $new_file);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_'.($move === FALSE ? 'rename' : 'move'));\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Move a file\n\t *\n\t * @param\tstring\t$old_file\n\t * @param\tstring\t$new_file\n\t * @return\tbool\n\t */\n\tpublic function move($old_file, $new_file)\n\t{\n\t\treturn $this->rename($old_file, $new_file, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rename (or move) a file\n\t *\n\t * @param\tstring\t$filepath\n\t * @return\tbool\n\t */\n\tpublic function delete_file($filepath)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_delete($this->conn_id, $filepath);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_delete');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete a folder and recursively delete everything (including sub-folders)\n\t * contained within it.\n\t *\n\t * @param\tstring\t$filepath\n\t * @return\tbool\n\t */\n\tpublic function delete_dir($filepath)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Add a trailing slash to the file path if needed\n\t\t$filepath = preg_replace('/(.+?)\\/*$/', '\\\\1/', $filepath);\n\n\t\t$list = $this->list_files($filepath);\n\t\tif ( ! empty($list))\n\t\t{\n\t\t\tfor ($i = 0, $c = count($list); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// If we can't delete the item it's probaly a directory,\n\t\t\t\t// so we'll recursively call delete_dir()\n\t\t\t\tif ( ! preg_match('#/\\.\\.?$#', $list[$i]) && ! @ftp_delete($this->conn_id, $list[$i]))\n\t\t\t\t{\n\t\t\t\t\t$this->delete_dir($filepath.$list[$i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (@ftp_rmdir($this->conn_id, $filepath) === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_delete');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set file permissions\n\t *\n\t * @param\tstring\t$path\tFile path\n\t * @param\tint\t$perm\tPermissions\n\t * @return\tbool\n\t */\n\tpublic function chmod($path, $perm)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (@ftp_chmod($this->conn_id, $perm, $path) === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_chmod');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FTP List files in the specified directory\n\t *\n\t * @param\tstring\t$path\n\t * @return\tarray\n\t */\n\tpublic function list_files($path = '.')\n\t{\n\t\treturn $this->_is_conn()\n\t\t\t? ftp_nlist($this->conn_id, $path)\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read a directory and recreate it remotely\n\t *\n\t * This function recursively reads a folder and everything it contains\n\t * (including sub-folders) and creates a mirror via FTP based on it.\n\t * Whatever the directory structure of the original file path will be\n\t * recreated on the server.\n\t *\n\t * @param\tstring\t$locpath\tPath to source with trailing slash\n\t * @param\tstring\t$rempath\tPath to destination - include the base folder with trailing slash\n\t * @return\tbool\n\t */\n\tpublic function mirror($locpath, $rempath)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Open the local file path\n\t\tif ($fp = @opendir($locpath))\n\t\t{\n\t\t\t// Attempt to open the remote file path and try to create it, if it doesn't exist\n\t\t\tif ( ! $this->changedir($rempath, TRUE) && ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath)))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t// Recursively read the local directory\n\t\t\twhile (FALSE !== ($file = readdir($fp)))\n\t\t\t{\n\t\t\t\tif (is_dir($locpath.$file) && $file[0] !== '.')\n\t\t\t\t{\n\t\t\t\t\t$this->mirror($locpath.$file.'/', $rempath.$file.'/');\n\t\t\t\t}\n\t\t\t\telseif ($file[0] !== '.')\n\t\t\t\t{\n\t\t\t\t\t// Get the file extension so we can se the upload type\n\t\t\t\t\t$ext = $this->_getext($file);\n\t\t\t\t\t$mode = $this->_settype($ext);\n\n\t\t\t\t\t$this->upload($locpath.$file, $rempath.$file, $mode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extract the file extension\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tprotected function _getext($filename)\n\t{\n\t\treturn (($dot = strrpos($filename, '.')) === FALSE)\n\t\t\t? 'txt'\n\t\t\t: substr($filename, $dot + 1);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the upload type\n\t *\n\t * @param\tstring\t$ext\tFilename extension\n\t * @return\tstring\n\t */\n\tprotected function _settype($ext)\n\t{\n\t\treturn in_array($ext, array('txt', 'text', 'php', 'phps', 'php4', 'js', 'css', 'htm', 'html', 'phtml', 'shtml', 'log', 'xml'), TRUE)\n\t\t\t? 'ascii'\n\t\t\t: 'binary';\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close the connection\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\treturn $this->_is_conn()\n\t\t\t? @ftp_close($this->conn_id)\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Display error message\n\t *\n\t * @param\tstring\t$line\n\t * @return\tvoid\n\t */\n\tprotected function _error($line)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('ftp');\n\t\tshow_error($CI->lang->line($line));\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Image_lib.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Image Manipulation class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tImage_lib\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/image_lib.html\n */\nclass CI_Image_lib {\n\n\t/**\n\t * PHP extension/library to use for image manipulation\n\t * Can be: imagemagick, netpbm, gd, gd2\n\t *\n\t * @var string\n\t */\n\tpublic $image_library\t\t= 'gd2';\n\n\t/**\n\t * Path to the graphic library (if applicable)\n\t *\n\t * @var string\n\t */\n\tpublic $library_path\t\t= '';\n\n\t/**\n\t * Whether to send to browser or write to disk\n\t *\n\t * @var bool\n\t */\n\tpublic $dynamic_output\t\t= FALSE;\n\n\t/**\n\t * Path to original image\n\t *\n\t * @var string\n\t */\n\tpublic $source_image\t\t= '';\n\n\t/**\n\t * Path to the modified image\n\t *\n\t * @var string\n\t */\n\tpublic $new_image\t\t= '';\n\n\t/**\n\t * Image width\n\t *\n\t * @var int\n\t */\n\tpublic $width\t\t\t= '';\n\n\t/**\n\t * Image height\n\t *\n\t * @var int\n\t */\n\tpublic $height\t\t\t= '';\n\n\t/**\n\t * Quality percentage of new image\n\t *\n\t * @var int\n\t */\n\tpublic $quality\t\t\t= 90;\n\n\t/**\n\t * Whether to create a thumbnail\n\t *\n\t * @var bool\n\t */\n\tpublic $create_thumb\t\t= FALSE;\n\n\t/**\n\t * String to add to thumbnail version of image\n\t *\n\t * @var string\n\t */\n\tpublic $thumb_marker\t\t= '_thumb';\n\n\t/**\n\t * Whether to maintain aspect ratio when resizing or use hard values\n\t *\n\t * @var bool\n\t */\n\tpublic $maintain_ratio\t\t= TRUE;\n\n\t/**\n\t * auto, height, or width.  Determines what to use as the master dimension\n\t *\n\t * @var string\n\t */\n\tpublic $master_dim\t\t= 'auto';\n\n\t/**\n\t * Angle at to rotate image\n\t *\n\t * @var string\n\t */\n\tpublic $rotation_angle\t\t= '';\n\n\t/**\n\t * X Coordinate for manipulation of the current image\n\t *\n\t * @var int\n\t */\n\tpublic $x_axis\t\t\t= '';\n\n\t/**\n\t * Y Coordinate for manipulation of the current image\n\t *\n\t * @var int\n\t */\n\tpublic $y_axis\t\t\t= '';\n\n\t// --------------------------------------------------------------------------\n\t// Watermark Vars\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Watermark text if graphic is not used\n\t *\n\t * @var string\n\t */\n\tpublic $wm_text\t\t\t= '';\n\n\t/**\n\t * Type of watermarking.  Options:  text/overlay\n\t *\n\t * @var string\n\t */\n\tpublic $wm_type\t\t\t= 'text';\n\n\t/**\n\t * Default transparency for watermark\n\t *\n\t * @var int\n\t */\n\tpublic $wm_x_transp\t\t= 4;\n\n\t/**\n\t * Default transparency for watermark\n\t *\n\t * @var int\n\t */\n\tpublic $wm_y_transp\t\t= 4;\n\n\t/**\n\t * Watermark image path\n\t *\n\t * @var string\n\t */\n\tpublic $wm_overlay_path\t\t= '';\n\n\t/**\n\t * TT font\n\t *\n\t * @var string\n\t */\n\tpublic $wm_font_path\t\t= '';\n\n\t/**\n\t * Font size (different versions of GD will either use points or pixels)\n\t *\n\t * @var int\n\t */\n\tpublic $wm_font_size\t\t= 17;\n\n\t/**\n\t * Vertical alignment:   T M B\n\t *\n\t * @var string\n\t */\n\tpublic $wm_vrt_alignment\t= 'B';\n\n\t/**\n\t * Horizontal alignment: L R C\n\t *\n\t * @var string\n\t */\n\tpublic $wm_hor_alignment\t= 'C';\n\n\t/**\n\t * Padding around text\n\t *\n\t * @var int\n\t */\n\tpublic $wm_padding\t\t\t= 0;\n\n\t/**\n\t * Lets you push text to the right\n\t *\n\t * @var int\n\t */\n\tpublic $wm_hor_offset\t\t= 0;\n\n\t/**\n\t * Lets you push text down\n\t *\n\t * @var int\n\t */\n\tpublic $wm_vrt_offset\t\t= 0;\n\n\t/**\n\t * Text color\n\t *\n\t * @var string\n\t */\n\tprotected $wm_font_color\t= '#ffffff';\n\n\t/**\n\t * Dropshadow color\n\t *\n\t * @var string\n\t */\n\tprotected $wm_shadow_color\t= '';\n\n\t/**\n\t * Dropshadow distance\n\t *\n\t * @var int\n\t */\n\tpublic $wm_shadow_distance\t= 2;\n\n\t/**\n\t * Image opacity: 1 - 100  Only works with image\n\t *\n\t * @var int\n\t */\n\tpublic $wm_opacity\t\t= 50;\n\n\t// --------------------------------------------------------------------------\n\t// Private Vars\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Source image folder\n\t *\n\t * @var string\n\t */\n\tpublic $source_folder\t\t= '';\n\n\t/**\n\t * Destination image folder\n\t *\n\t * @var string\n\t */\n\tpublic $dest_folder\t\t= '';\n\n\t/**\n\t * Image mime-type\n\t *\n\t * @var string\n\t */\n\tpublic $mime_type\t\t= '';\n\n\t/**\n\t * Original image width\n\t *\n\t * @var int\n\t */\n\tpublic $orig_width\t\t= '';\n\n\t/**\n\t * Original image height\n\t *\n\t * @var int\n\t */\n\tpublic $orig_height\t\t= '';\n\n\t/**\n\t * Image format\n\t *\n\t * @var string\n\t */\n\tpublic $image_type\t\t= '';\n\n\t/**\n\t * Size of current image\n\t *\n\t * @var string\n\t */\n\tpublic $size_str\t\t= '';\n\n\t/**\n\t * Full path to source image\n\t *\n\t * @var string\n\t */\n\tpublic $full_src_path\t\t= '';\n\n\t/**\n\t * Full path to destination image\n\t *\n\t * @var string\n\t */\n\tpublic $full_dst_path\t\t= '';\n\n\t/**\n\t * File permissions\n\t *\n\t * @var\tint\n\t */\n\tpublic $file_permissions = 0644;\n\n\t/**\n\t * Name of function to create image\n\t *\n\t * @var string\n\t */\n\tpublic $create_fnc\t\t= 'imagecreatetruecolor';\n\n\t/**\n\t * Name of function to copy image\n\t *\n\t * @var string\n\t */\n\tpublic $copy_fnc\t\t= 'imagecopyresampled';\n\n\t/**\n\t * Error messages\n\t *\n\t * @var array\n\t */\n\tpublic $error_msg\t\t= array();\n\n\t/**\n\t * Whether to have a drop shadow on watermark\n\t *\n\t * @var bool\n\t */\n\tprotected $wm_use_drop_shadow\t= FALSE;\n\n\t/**\n\t * Whether to use truetype fonts\n\t *\n\t * @var bool\n\t */\n\tpublic $wm_use_truetype\t= FALSE;\n\n\t/**\n\t * Initialize Image Library\n\t *\n\t * @param\tarray\t$props\n\t * @return\tvoid\n\t */\n\tpublic function __construct($props = array())\n\t{\n\t\tif (count($props) > 0)\n\t\t{\n\t\t\t$this->initialize($props);\n\t\t}\n\n\t\tlog_message('info', 'Image Lib Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize image properties\n\t *\n\t * Resets values in case this class is used in a loop\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function clear()\n\t{\n\t\t$props = array('thumb_marker', 'library_path', 'source_image', 'new_image', 'width', 'height', 'rotation_angle', 'x_axis', 'y_axis', 'wm_text', 'wm_overlay_path', 'wm_font_path', 'wm_shadow_color', 'source_folder', 'dest_folder', 'mime_type', 'orig_width', 'orig_height', 'image_type', 'size_str', 'full_src_path', 'full_dst_path');\n\n\t\tforeach ($props as $val)\n\t\t{\n\t\t\t$this->$val = '';\n\t\t}\n\n\t\t$this->image_library \t\t= 'gd2';\n\t\t$this->dynamic_output \t\t= FALSE;\n\t\t$this->quality \t\t\t\t= 90;\n\t\t$this->create_thumb \t\t= FALSE;\n\t\t$this->thumb_marker \t\t= '_thumb';\n\t\t$this->maintain_ratio \t\t= TRUE;\n\t\t$this->master_dim \t\t\t= 'auto';\n\t\t$this->wm_type \t\t\t\t= 'text';\n\t\t$this->wm_x_transp \t\t\t= 4;\n\t\t$this->wm_y_transp \t\t\t= 4;\n\t\t$this->wm_font_size \t\t= 17;\n\t\t$this->wm_vrt_alignment \t= 'B';\n\t\t$this->wm_hor_alignment \t= 'C';\n\t\t$this->wm_padding \t\t\t= 0;\n\t\t$this->wm_hor_offset \t\t= 0;\n\t\t$this->wm_vrt_offset \t\t= 0;\n\t\t$this->wm_font_color\t\t= '#ffffff';\n\t\t$this->wm_shadow_distance \t= 2;\n\t\t$this->wm_opacity \t\t\t= 50;\n\t\t$this->create_fnc \t\t\t= 'imagecreatetruecolor';\n\t\t$this->copy_fnc \t\t\t= 'imagecopyresampled';\n\t\t$this->error_msg \t\t\t= array();\n\t\t$this->wm_use_drop_shadow \t= FALSE;\n\t\t$this->wm_use_truetype \t\t= FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * initialize image preferences\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function initialize($props = array())\n\t{\n\t\t// Convert array elements into class variables\n\t\tif (count($props) > 0)\n\t\t{\n\t\t\tforeach ($props as $key => $val)\n\t\t\t{\n\t\t\t\tif (property_exists($this, $key))\n\t\t\t\t{\n\t\t\t\t\tif (in_array($key, array('wm_font_color', 'wm_shadow_color')))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (preg_match('/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i', $val, $matches))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* $matches[1] contains our hex color value, but it might be\n\t\t\t\t\t\t\t * both in the full 6-length format or the shortened 3-length\n\t\t\t\t\t\t\t * value.\n\t\t\t\t\t\t\t * We'll later need the full version, so we keep it if it's\n\t\t\t\t\t\t\t * already there and if not - we'll convert to it. We can\n\t\t\t\t\t\t\t * access string characters by their index as in an array,\n\t\t\t\t\t\t\t * so we'll do that and use concatenation to form the final\n\t\t\t\t\t\t\t * value:\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t$val = (strlen($matches[1]) === 6)\n\t\t\t\t\t\t\t\t? '#'.$matches[1]\n\t\t\t\t\t\t\t\t: '#'.$matches[1][0].$matches[1][0].$matches[1][1].$matches[1][1].$matches[1][2].$matches[1][2];\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t$this->$key = $val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Is there a source image? If not, there's no reason to continue\n\t\tif ($this->source_image === '')\n\t\t{\n\t\t\t$this->set_error('imglib_source_image_required');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/* Is getimagesize() available?\n\t\t *\n\t\t * We use it to determine the image properties (width/height).\n\t\t * Note: We need to figure out how to determine image\n\t\t * properties using ImageMagick and NetPBM\n\t\t */\n\t\tif ( ! function_exists('getimagesize'))\n\t\t{\n\t\t\t$this->set_error('imglib_gd_required_for_props');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->image_library = strtolower($this->image_library);\n\n\t\t/* Set the full server path\n\t\t *\n\t\t * The source image may or may not contain a path.\n\t\t * Either way, we'll try use realpath to generate the\n\t\t * full server path in order to more reliably read it.\n\t\t */\n\t\tif (($full_source_path = realpath($this->source_image)) !== FALSE)\n\t\t{\n\t\t\t$full_source_path = str_replace('\\\\', '/', $full_source_path);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$full_source_path = $this->source_image;\n\t\t}\n\n\t\t$x = explode('/', $full_source_path);\n\t\t$this->source_image = end($x);\n\t\t$this->source_folder = str_replace($this->source_image, '', $full_source_path);\n\n\t\t// Set the Image Properties\n\t\tif ( ! $this->get_image_properties($this->source_folder.$this->source_image))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/*\n\t\t * Assign the \"new\" image name/path\n\t\t *\n\t\t * If the user has set a \"new_image\" name it means\n\t\t * we are making a copy of the source image. If not\n\t\t * it means we are altering the original. We'll\n\t\t * set the destination filename and path accordingly.\n\t\t */\n\t\tif ($this->new_image === '')\n\t\t{\n\t\t\t$this->dest_image = $this->source_image;\n\t\t\t$this->dest_folder = $this->source_folder;\n\t\t}\n\t\telseif (strpos($this->new_image, '/') === FALSE)\n\t\t{\n\t\t\t$this->dest_folder = $this->source_folder;\n\t\t\t$this->dest_image = $this->new_image;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (strpos($this->new_image, '/') === FALSE && strpos($this->new_image, '\\\\') === FALSE)\n\t\t\t{\n\t\t\t\t$full_dest_path = str_replace('\\\\', '/', realpath($this->new_image));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$full_dest_path = $this->new_image;\n\t\t\t}\n\n\t\t\t// Is there a file name?\n\t\t\tif ( ! preg_match('#\\.(jpg|jpeg|gif|png)$#i', $full_dest_path))\n\t\t\t{\n\t\t\t\t$this->dest_folder = $full_dest_path.'/';\n\t\t\t\t$this->dest_image = $this->source_image;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$x = explode('/', $full_dest_path);\n\t\t\t\t$this->dest_image = end($x);\n\t\t\t\t$this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);\n\t\t\t}\n\t\t}\n\n\t\t/* Compile the finalized filenames/paths\n\t\t *\n\t\t * We'll create two master strings containing the\n\t\t * full server path to the source image and the\n\t\t * full server path to the destination image.\n\t\t * We'll also split the destination image name\n\t\t * so we can insert the thumbnail marker if needed.\n\t\t */\n\t\tif ($this->create_thumb === FALSE OR $this->thumb_marker === '')\n\t\t{\n\t\t\t$this->thumb_marker = '';\n\t\t}\n\n\t\t$xp = $this->explode_name($this->dest_image);\n\n\t\t$filename = $xp['name'];\n\t\t$file_ext = $xp['ext'];\n\n\t\t$this->full_src_path = $this->source_folder.$this->source_image;\n\t\t$this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;\n\n\t\t/* Should we maintain image proportions?\n\t\t *\n\t\t * When creating thumbs or copies, the target width/height\n\t\t * might not be in correct proportion with the source\n\t\t * image's width/height. We'll recalculate it here.\n\t\t */\n\t\tif ($this->maintain_ratio === TRUE && ($this->width !== 0 OR $this->height !== 0))\n\t\t{\n\t\t\t$this->image_reproportion();\n\t\t}\n\n\t\t/* Was a width and height specified?\n\t\t *\n\t\t * If the destination width/height was not submitted we\n\t\t * will use the values from the actual file\n\t\t */\n\t\tif ($this->width === '')\n\t\t{\n\t\t\t$this->width = $this->orig_width;\n\t\t}\n\n\t\tif ($this->height === '')\n\t\t{\n\t\t\t$this->height = $this->orig_height;\n\t\t}\n\n\t\t// Set the quality\n\t\t$this->quality = trim(str_replace('%', '', $this->quality));\n\n\t\tif ($this->quality === '' OR $this->quality === 0 OR ! ctype_digit($this->quality))\n\t\t{\n\t\t\t$this->quality = 90;\n\t\t}\n\n\t\t// Set the x/y coordinates\n\t\tis_numeric($this->x_axis) OR $this->x_axis = 0;\n\t\tis_numeric($this->y_axis) OR $this->y_axis = 0;\n\n\t\t// Watermark-related Stuff...\n\t\tif ($this->wm_overlay_path !== '')\n\t\t{\n\t\t\t$this->wm_overlay_path = str_replace('\\\\', '/', realpath($this->wm_overlay_path));\n\t\t}\n\n\t\tif ($this->wm_shadow_color !== '')\n\t\t{\n\t\t\t$this->wm_use_drop_shadow = TRUE;\n\t\t}\n\t\telseif ($this->wm_use_drop_shadow === TRUE && $this->wm_shadow_color === '')\n\t\t{\n\t\t\t$this->wm_use_drop_shadow = FALSE;\n\t\t}\n\n\t\tif ($this->wm_font_path !== '')\n\t\t{\n\t\t\t$this->wm_use_truetype = TRUE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Resize\n\t *\n\t * This is a wrapper function that chooses the proper\n\t * resize function based on the protocol specified\n\t *\n\t * @return\tbool\n\t */\n\tpublic function resize()\n\t{\n\t\t$protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;\n\t\treturn $this->$protocol('resize');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Crop\n\t *\n\t * This is a wrapper function that chooses the proper\n\t * cropping function based on the protocol specified\n\t *\n\t * @return\tbool\n\t */\n\tpublic function crop()\n\t{\n\t\t$protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;\n\t\treturn $this->$protocol('crop');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Rotate\n\t *\n\t * This is a wrapper function that chooses the proper\n\t * rotation function based on the protocol specified\n\t *\n\t * @return\tbool\n\t */\n\tpublic function rotate()\n\t{\n\t\t// Allowed rotation values\n\t\t$degs = array(90, 180, 270, 'vrt', 'hor');\n\n\t\tif ($this->rotation_angle === '' OR ! in_array($this->rotation_angle, $degs))\n\t\t{\n\t\t\t$this->set_error('imglib_rotation_angle_required');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Reassign the width and height\n\t\tif ($this->rotation_angle === 90 OR $this->rotation_angle === 270)\n\t\t{\n\t\t\t$this->width\t= $this->orig_height;\n\t\t\t$this->height\t= $this->orig_width;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->width\t= $this->orig_width;\n\t\t\t$this->height\t= $this->orig_height;\n\t\t}\n\n\t\t// Choose resizing function\n\t\tif ($this->image_library === 'imagemagick' OR $this->image_library === 'netpbm')\n\t\t{\n\t\t\t$protocol = 'image_process_'.$this->image_library;\n\t\t\treturn $this->$protocol('rotate');\n\t\t}\n\n\t\treturn ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')\n\t\t\t? $this->image_mirror_gd()\n\t\t\t: $this->image_rotate_gd();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Process Using GD/GD2\n\t *\n\t * This function will resize or crop\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function image_process_gd($action = 'resize')\n\t{\n\t\t$v2_override = FALSE;\n\n\t\t// If the target width/height match the source, AND if the new file name is not equal to the old file name\n\t\t// we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.\n\t\tif ($this->dynamic_output === FALSE && $this->orig_width === $this->width && $this->orig_height === $this->height)\n\t\t{\n\t\t\tif ($this->source_image !== $this->new_image && @copy($this->full_src_path, $this->full_dst_path))\n\t\t\t{\n\t\t\t\tchmod($this->full_dst_path, $this->file_permissions);\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Let's set up our values based on the action\n\t\tif ($action === 'crop')\n\t\t{\n\t\t\t// Reassign the source width/height if cropping\n\t\t\t$this->orig_width  = $this->width;\n\t\t\t$this->orig_height = $this->height;\n\n\t\t\t// GD 2.0 has a cropping bug so we'll test for it\n\t\t\tif ($this->gd_version() !== FALSE)\n\t\t\t{\n\t\t\t\t$gd_version = str_replace('0', '', $this->gd_version());\n\t\t\t\t$v2_override = ($gd_version == 2);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// If resizing the x/y axis must be zero\n\t\t\t$this->x_axis = 0;\n\t\t\t$this->y_axis = 0;\n\t\t}\n\n\t\t// Create the image handle\n\t\tif ( ! ($src_img = $this->image_create_gd()))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/* Create the image\n\t\t *\n\t\t * Old conditional which users report cause problems with shared GD libs who report themselves as \"2.0 or greater\"\n\t\t * it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment\n\t\t * below should that ever prove inaccurate.\n\t\t *\n\t\t * if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor') && $v2_override === FALSE)\n\t\t */\n\t\tif ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor'))\n\t\t{\n\t\t\t$create\t= 'imagecreatetruecolor';\n\t\t\t$copy\t= 'imagecopyresampled';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$create\t= 'imagecreate';\n\t\t\t$copy\t= 'imagecopyresized';\n\t\t}\n\n\t\t$dst_img = $create($this->width, $this->height);\n\n\t\tif ($this->image_type === 3) // png we can actually preserve transparency\n\t\t{\n\t\t\timagealphablending($dst_img, FALSE);\n\t\t\timagesavealpha($dst_img, TRUE);\n\t\t}\n\n\t\t$copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);\n\n\t\t// Show the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($dst_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($dst_img)) // Or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Kill the file handles\n\t\timagedestroy($dst_img);\n\t\timagedestroy($src_img);\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Process Using ImageMagick\n\t *\n\t * This function will resize, crop or rotate\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function image_process_imagemagick($action = 'resize')\n\t{\n\t\t// Do we have a vaild library path?\n\t\tif ($this->library_path === '')\n\t\t{\n\t\t\t$this->set_error('imglib_libpath_invalid');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! preg_match('/convert$/i', $this->library_path))\n\t\t{\n\t\t\t$this->library_path = rtrim($this->library_path, '/').'/convert';\n\t\t}\n\n\t\t// Execute the command\n\t\t$cmd = $this->library_path.' -quality '.$this->quality;\n\n\t\tif ($action === 'crop')\n\t\t{\n\t\t\t$cmd .= ' -crop '.$this->width.'x'.$this->height.'+'.$this->x_axis.'+'.$this->y_axis.' \"'.$this->full_src_path.'\" \"'.$this->full_dst_path .'\" 2>&1';\n\t\t}\n\t\telseif ($action === 'rotate')\n\t\t{\n\t\t\t$angle = ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')\n\t\t\t\t\t? '-flop' : '-rotate '.$this->rotation_angle;\n\n\t\t\t$cmd .= ' '.$angle.' \"'.$this->full_src_path.'\" \"'.$this->full_dst_path.'\" 2>&1';\n\t\t}\n\t\telse // Resize\n\t\t{\n\t\t\tif($this->maintain_ratio === TRUE)\n\t\t\t{\n\t\t\t\t$cmd .= ' -resize '.$this->width.'x'.$this->height.' \"'.$this->full_src_path.'\" \"'.$this->full_dst_path.'\" 2>&1';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$cmd .= ' -resize '.$this->width.'x'.$this->height.'\\! \"'.$this->full_src_path.'\" \"'.$this->full_dst_path.'\" 2>&1';\n\t\t\t}\n\t\t}\n\n\t\t$retval = 1;\n\t\t// exec() might be disabled\n\t\tif (function_usable('exec'))\n\t\t{\n\t\t\t@exec($cmd, $output, $retval);\n\t\t}\n\n\t\t// Did it work?\n\t\tif ($retval > 0)\n\t\t{\n\t\t\t$this->set_error('imglib_image_process_failed');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Process Using NetPBM\n\t *\n\t * This function will resize, crop or rotate\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function image_process_netpbm($action = 'resize')\n\t{\n\t\tif ($this->library_path === '')\n\t\t{\n\t\t\t$this->set_error('imglib_libpath_invalid');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Build the resizing command\n\t\tswitch ($this->image_type)\n\t\t{\n\t\t\tcase 1 :\n\t\t\t\t$cmd_in\t\t= 'giftopnm';\n\t\t\t\t$cmd_out\t= 'ppmtogif';\n\t\t\t\tbreak;\n\t\t\tcase 2 :\n\t\t\t\t$cmd_in\t\t= 'jpegtopnm';\n\t\t\t\t$cmd_out\t= 'ppmtojpeg';\n\t\t\t\tbreak;\n\t\t\tcase 3 :\n\t\t\t\t$cmd_in\t\t= 'pngtopnm';\n\t\t\t\t$cmd_out\t= 'ppmtopng';\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ($action === 'crop')\n\t\t{\n\t\t\t$cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;\n\t\t}\n\t\telseif ($action === 'rotate')\n\t\t{\n\t\t\tswitch ($this->rotation_angle)\n\t\t\t{\n\t\t\t\tcase 90:\t$angle = 'r270';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 180:\t$angle = 'r180';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 270:\t$angle = 'r90';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'vrt':\t$angle = 'tb';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'hor':\t$angle = 'lr';\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$cmd_inner = 'pnmflip -'.$angle.' ';\n\t\t}\n\t\telse // Resize\n\t\t{\n\t\t\t$cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;\n\t\t}\n\n\t\t$cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';\n\n\t\t$retval = 1;\n\t\t// exec() might be disabled\n\t\tif (function_usable('exec'))\n\t\t{\n\t\t\t@exec($cmd, $output, $retval);\n\t\t}\n\n\t\t// Did it work?\n\t\tif ($retval > 0)\n\t\t{\n\t\t\t$this->set_error('imglib_image_process_failed');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// With NetPBM we have to create a temporary image.\n\t\t// If you try manipulating the original it fails so\n\t\t// we have to rename the temp file.\n\t\tcopy($this->dest_folder.'netpbm.tmp', $this->full_dst_path);\n\t\tunlink($this->dest_folder.'netpbm.tmp');\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Rotate Using GD\n\t *\n\t * @return\tbool\n\t */\n\tpublic function image_rotate_gd()\n\t{\n\t\t// Create the image handle\n\t\tif ( ! ($src_img = $this->image_create_gd()))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the background color\n\t\t// This won't work with transparent PNG files so we are\n\t\t// going to have to figure out how to determine the color\n\t\t// of the alpha channel in a future release.\n\n\t\t$white = imagecolorallocate($src_img, 255, 255, 255);\n\n\t\t// Rotate it!\n\t\t$dst_img = imagerotate($src_img, $this->rotation_angle, $white);\n\n\t\t// Show the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($dst_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($dst_img)) // ... or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Kill the file handles\n\t\timagedestroy($dst_img);\n\t\timagedestroy($src_img);\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Mirror Image using GD\n\t *\n\t * This function will flip horizontal or vertical\n\t *\n\t * @return\tbool\n\t */\n\tpublic function image_mirror_gd()\n\t{\n\t\tif ( ! $src_img = $this->image_create_gd())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$width  = $this->orig_width;\n\t\t$height = $this->orig_height;\n\n\t\tif ($this->rotation_angle === 'hor')\n\t\t{\n\t\t\tfor ($i = 0; $i < $height; $i++)\n\t\t\t{\n\t\t\t\t$left = 0;\n\t\t\t\t$right = $width - 1;\n\n\t\t\t\twhile ($left < $right)\n\t\t\t\t{\n\t\t\t\t\t$cl = imagecolorat($src_img, $left, $i);\n\t\t\t\t\t$cr = imagecolorat($src_img, $right, $i);\n\n\t\t\t\t\timagesetpixel($src_img, $left, $i, $cr);\n\t\t\t\t\timagesetpixel($src_img, $right, $i, $cl);\n\n\t\t\t\t\t$left++;\n\t\t\t\t\t$right--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor ($i = 0; $i < $width; $i++)\n\t\t\t{\n\t\t\t\t$top = 0;\n\t\t\t\t$bottom = $height - 1;\n\n\t\t\t\twhile ($top < $bottom)\n\t\t\t\t{\n\t\t\t\t\t$ct = imagecolorat($src_img, $i, $top);\n\t\t\t\t\t$cb = imagecolorat($src_img, $i, $bottom);\n\n\t\t\t\t\timagesetpixel($src_img, $i, $top, $cb);\n\t\t\t\t\timagesetpixel($src_img, $i, $bottom, $ct);\n\n\t\t\t\t\t$top++;\n\t\t\t\t\t$bottom--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Show the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($src_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($src_img)) // ... or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Kill the file handles\n\t\timagedestroy($src_img);\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Watermark\n\t *\n\t * This is a wrapper function that chooses the type\n\t * of watermarking based on the specified preference.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function watermark()\n\t{\n\t\treturn ($this->wm_type === 'overlay') ? $this->overlay_watermark() : $this->text_watermark();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Watermark - Graphic Version\n\t *\n\t * @return\tbool\n\t */\n\tpublic function overlay_watermark()\n\t{\n\t\tif ( ! function_exists('imagecolortransparent'))\n\t\t{\n\t\t\t$this->set_error('imglib_gd_required');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Fetch source image properties\n\t\t$this->get_image_properties();\n\n\t\t// Fetch watermark image properties\n\t\t$props\t\t= $this->get_image_properties($this->wm_overlay_path, TRUE);\n\t\t$wm_img_type\t= $props['image_type'];\n\t\t$wm_width\t= $props['width'];\n\t\t$wm_height\t= $props['height'];\n\n\t\t// Create two image resources\n\t\t$wm_img  = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);\n\t\t$src_img = $this->image_create_gd($this->full_src_path);\n\n\t\t// Reverse the offset if necessary\n\t\t// When the image is positioned at the bottom\n\t\t// we don't want the vertical offset to push it\n\t\t// further down. We want the reverse, so we'll\n\t\t// invert the offset. Same with the horizontal\n\t\t// offset when the image is at the right\n\n\t\t$this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);\n\t\t$this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);\n\n\t\tif ($this->wm_vrt_alignment === 'B')\n\t\t\t$this->wm_vrt_offset = $this->wm_vrt_offset * -1;\n\n\t\tif ($this->wm_hor_alignment === 'R')\n\t\t\t$this->wm_hor_offset = $this->wm_hor_offset * -1;\n\n\t\t// Set the base x and y axis values\n\t\t$x_axis = $this->wm_hor_offset + $this->wm_padding;\n\t\t$y_axis = $this->wm_vrt_offset + $this->wm_padding;\n\n\t\t// Set the vertical position\n\t\tif ($this->wm_vrt_alignment === 'M')\n\t\t{\n\t\t\t$y_axis += ($this->orig_height / 2) - ($wm_height / 2);\n\t\t}\n\t\telseif ($this->wm_vrt_alignment === 'B')\n\t\t{\n\t\t\t$y_axis += $this->orig_height - $wm_height;\n\t\t}\n\n\t\t// Set the horizontal position\n\t\tif ($this->wm_hor_alignment === 'C')\n\t\t{\n\t\t\t$x_axis += ($this->orig_width / 2) - ($wm_width / 2);\n\t\t}\n\t\telseif ($this->wm_hor_alignment === 'R')\n\t\t{\n\t\t\t$x_axis += $this->orig_width - $wm_width;\n\t\t}\n\n\t\t// Build the finalized image\n\t\tif ($wm_img_type === 3 && function_exists('imagealphablending'))\n\t\t{\n\t\t\t@imagealphablending($src_img, TRUE);\n\t\t}\n\n\t\t// Set RGB values for text and shadow\n\t\t$rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);\n\t\t$alpha = ($rgba & 0x7F000000) >> 24;\n\n\t\t// make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency\n\t\tif ($alpha > 0)\n\t\t{\n\t\t\t// copy the image directly, the image's alpha transparency being the sole determinant of blending\n\t\t\timagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// set our RGB value from above to be transparent and merge the images with the specified opacity\n\t\t\timagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));\n\t\t\timagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);\n\t\t}\n\n\t\t// We can preserve transparency for PNG images\n\t\tif ($this->image_type === 3)\n\t\t{\n\t\t\timagealphablending($src_img, FALSE);\n\t\t\timagesavealpha($src_img, TRUE);\n\t\t}\n\n\t\t// Output the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($src_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($src_img)) // ... or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\timagedestroy($src_img);\n\t\timagedestroy($wm_img);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Watermark - Text Version\n\t *\n\t * @return\tbool\n\t */\n\tpublic function text_watermark()\n\t{\n\t\tif ( ! ($src_img = $this->image_create_gd()))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->wm_use_truetype === TRUE && ! file_exists($this->wm_font_path))\n\t\t{\n\t\t\t$this->set_error('imglib_missing_font');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Fetch source image properties\n\t\t$this->get_image_properties();\n\n\t\t// Reverse the vertical offset\n\t\t// When the image is positioned at the bottom\n\t\t// we don't want the vertical offset to push it\n\t\t// further down. We want the reverse, so we'll\n\t\t// invert the offset. Note: The horizontal\n\t\t// offset flips itself automatically\n\n\t\tif ($this->wm_vrt_alignment === 'B')\n\t\t{\n\t\t\t$this->wm_vrt_offset = $this->wm_vrt_offset * -1;\n\t\t}\n\n\t\tif ($this->wm_hor_alignment === 'R')\n\t\t{\n\t\t\t$this->wm_hor_offset = $this->wm_hor_offset * -1;\n\t\t}\n\n\t\t// Set font width and height\n\t\t// These are calculated differently depending on\n\t\t// whether we are using the true type font or not\n\t\tif ($this->wm_use_truetype === TRUE)\n\t\t{\n\t\t\tif (empty($this->wm_font_size))\n\t\t\t{\n\t\t\t\t$this->wm_font_size = 17;\n\t\t\t}\n\n\t\t\tif (function_exists('imagettfbbox'))\n\t\t\t{\n\t\t\t\t$temp = imagettfbbox($this->wm_font_size, 0, $this->wm_font_path, $this->wm_text);\n\t\t\t\t$temp = $temp[2] - $temp[0];\n\n\t\t\t\t$fontwidth = $temp / strlen($this->wm_text);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$fontwidth = $this->wm_font_size - ($this->wm_font_size / 4);\n\t\t\t}\n\n\t\t\t$fontheight = $this->wm_font_size;\n\t\t\t$this->wm_vrt_offset += $this->wm_font_size;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$fontwidth  = imagefontwidth($this->wm_font_size);\n\t\t\t$fontheight = imagefontheight($this->wm_font_size);\n\t\t}\n\n\t\t// Set base X and Y axis values\n\t\t$x_axis = $this->wm_hor_offset + $this->wm_padding;\n\t\t$y_axis = $this->wm_vrt_offset + $this->wm_padding;\n\n\t\tif ($this->wm_use_drop_shadow === FALSE)\n\t\t{\n\t\t\t$this->wm_shadow_distance = 0;\n\t\t}\n\n\t\t$this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);\n\t\t$this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);\n\n\t\t// Set vertical alignment\n\t\tif ($this->wm_vrt_alignment === 'M')\n\t\t{\n\t\t\t$y_axis += ($this->orig_height / 2) + ($fontheight / 2);\n\t\t}\n\t\telseif ($this->wm_vrt_alignment === 'B')\n\t\t{\n\t\t\t$y_axis += $this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight / 2);\n\t\t}\n\n\t\t// Set horizontal alignment\n\t\tif ($this->wm_hor_alignment === 'R')\n\t\t{\n\t\t\t$x_axis += $this->orig_width - ($fontwidth * strlen($this->wm_text)) - $this->wm_shadow_distance;\n\t\t}\n\t\telseif ($this->wm_hor_alignment === 'C')\n\t\t{\n\t\t\t$x_axis += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);\n\t\t}\n\n\t\tif ($this->wm_use_drop_shadow)\n\t\t{\n\t\t\t// Offset from text\n\t\t\t$x_shad = $x_axis + $this->wm_shadow_distance;\n\t\t\t$y_shad = $y_axis + $this->wm_shadow_distance;\n\n\t\t\t/* Set RGB values for shadow\n\t\t\t *\n\t\t\t * First character is #, so we don't really need it.\n\t\t\t * Get the rest of the string and split it into 2-length\n\t\t\t * hex values:\n\t\t\t */\n\t\t\t$drp_color = str_split(substr($this->wm_shadow_color, 1, 6), 2);\n\t\t\t$drp_color = imagecolorclosest($src_img, hexdec($drp_color[0]), hexdec($drp_color[1]), hexdec($drp_color[2]));\n\n\t\t\t// Add the shadow to the source image\n\t\t\tif ($this->wm_use_truetype)\n\t\t\t{\n\t\t\t\timagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\timagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);\n\t\t\t}\n\t\t}\n\n\t\t/* Set RGB values for text\n\t\t *\n\t\t * First character is #, so we don't really need it.\n\t\t * Get the rest of the string and split it into 2-length\n\t\t * hex values:\n\t\t */\n\t\t$txt_color = str_split(substr($this->wm_font_color, 1, 6), 2);\n\t\t$txt_color = imagecolorclosest($src_img, hexdec($txt_color[0]), hexdec($txt_color[1]), hexdec($txt_color[2]));\n\n\t\t// Add the text to the source image\n\t\tif ($this->wm_use_truetype)\n\t\t{\n\t\t\timagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);\n\t\t}\n\t\telse\n\t\t{\n\t\t\timagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);\n\t\t}\n\n\t\t// We can preserve transparency for PNG images\n\t\tif ($this->image_type === 3)\n\t\t{\n\t\t\timagealphablending($src_img, FALSE);\n\t\t\timagesavealpha($src_img, TRUE);\n\t\t}\n\n\t\t// Output the final image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($src_img);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->image_save_gd($src_img);\n\t\t}\n\n\t\timagedestroy($src_img);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Image - GD\n\t *\n\t * This simply creates an image resource handle\n\t * based on the type of image being processed\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tresource\n\t */\n\tpublic function image_create_gd($path = '', $image_type = '')\n\t{\n\t\tif ($path === '')\n\t\t{\n\t\t\t$path = $this->full_src_path;\n\t\t}\n\n\t\tif ($image_type === '')\n\t\t{\n\t\t\t$image_type = $this->image_type;\n\t\t}\n\n\t\tswitch ($image_type)\n\t\t{\n\t\t\tcase 1:\n\t\t\t\tif ( ! function_exists('imagecreatefromgif'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\treturn imagecreatefromgif($path);\n\t\t\tcase 2:\n\t\t\t\tif ( ! function_exists('imagecreatefromjpeg'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\treturn imagecreatefromjpeg($path);\n\t\t\tcase 3:\n\t\t\t\tif ( ! function_exists('imagecreatefrompng'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\treturn imagecreatefrompng($path);\n\t\t\tdefault:\n\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate'));\n\t\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write image file to disk - GD\n\t *\n\t * Takes an image resource as input and writes the file\n\t * to the specified destination\n\t *\n\t * @param\tresource\n\t * @return\tbool\n\t */\n\tpublic function image_save_gd($resource)\n\t{\n\t\tswitch ($this->image_type)\n\t\t{\n\t\t\tcase 1:\n\t\t\t\tif ( ! function_exists('imagegif'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tif ( ! @imagegif($resource, $this->full_dst_path))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error('imglib_save_failed');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif ( ! function_exists('imagejpeg'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tif ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error('imglib_save_failed');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tif ( ! function_exists('imagepng'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tif ( ! @imagepng($resource, $this->full_dst_path))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error('imglib_save_failed');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate'));\n\t\t\t\treturn FALSE;\n\t\t\tbreak;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Dynamically outputs an image\n\t *\n\t * @param\tresource\n\t * @return\tvoid\n\t */\n\tpublic function image_display_gd($resource)\n\t{\n\t\theader('Content-Disposition: filename='.$this->source_image.';');\n\t\theader('Content-Type: '.$this->mime_type);\n\t\theader('Content-Transfer-Encoding: binary');\n\t\theader('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');\n\n\t\tswitch ($this->image_type)\n\t\t{\n\t\t\tcase 1\t:\timagegif($resource);\n\t\t\t\tbreak;\n\t\t\tcase 2\t:\timagejpeg($resource, NULL, $this->quality);\n\t\t\t\tbreak;\n\t\t\tcase 3\t:\timagepng($resource);\n\t\t\t\tbreak;\n\t\t\tdefault:\techo 'Unable to display the image';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Re-proportion Image Width/Height\n\t *\n\t * When creating thumbs, the desired width/height\n\t * can end up warping the image due to an incorrect\n\t * ratio between the full-sized image and the thumb.\n\t *\n\t * This function lets us re-proportion the width/height\n\t * if users choose to maintain the aspect ratio when resizing.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function image_reproportion()\n\t{\n\t\tif (($this->width === 0 && $this->height === 0) OR $this->orig_width === 0 OR $this->orig_height === 0\n\t\t\tOR ( ! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height))\n\t\t\tOR ! ctype_digit((string) $this->orig_width) OR ! ctype_digit((string) $this->orig_height))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// Sanitize\n\t\t$this->width = (int) $this->width;\n\t\t$this->height = (int) $this->height;\n\n\t\tif ($this->master_dim !== 'width' && $this->master_dim !== 'height')\n\t\t{\n\t\t\tif ($this->width > 0 && $this->height > 0)\n\t\t\t{\n\t\t\t\t$this->master_dim = ((($this->orig_height/$this->orig_width) - ($this->height/$this->width)) < 0)\n\t\t\t\t\t\t\t? 'width' : 'height';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->master_dim = ($this->height === 0) ? 'width' : 'height';\n\t\t\t}\n\t\t}\n\t\telseif (($this->master_dim === 'width' && $this->width === 0)\n\t\t\tOR ($this->master_dim === 'height' && $this->height === 0))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif ($this->master_dim === 'width')\n\t\t{\n\t\t\t$this->height = (int) ceil($this->width*$this->orig_height/$this->orig_width);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->width = (int) ceil($this->orig_width*$this->height/$this->orig_height);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get image properties\n\t *\n\t * A helper function that gets info about the file\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tmixed\n\t */\n\tpublic function get_image_properties($path = '', $return = FALSE)\n\t{\n\t\t// For now we require GD but we should\n\t\t// find a way to determine this using IM or NetPBM\n\n\t\tif ($path === '')\n\t\t{\n\t\t\t$path = $this->full_src_path;\n\t\t}\n\n\t\tif ( ! file_exists($path))\n\t\t{\n\t\t\t$this->set_error('imglib_invalid_path');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$vals = getimagesize($path);\n\t\t$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');\n\t\t$mime = (isset($types[$vals[2]])) ? 'image/'.$types[$vals[2]] : 'image/jpg';\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn array(\n\t\t\t\t\t'width' =>\t$vals[0],\n\t\t\t\t\t'height' =>\t$vals[1],\n\t\t\t\t\t'image_type' =>\t$vals[2],\n\t\t\t\t\t'size_str' =>\t$vals[3],\n\t\t\t\t\t'mime_type' =>\t$mime\n\t\t\t\t);\n\t\t}\n\n\t\t$this->orig_width\t= $vals[0];\n\t\t$this->orig_height\t= $vals[1];\n\t\t$this->image_type\t= $vals[2];\n\t\t$this->size_str\t\t= $vals[3];\n\t\t$this->mime_type\t= $mime;\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Size calculator\n\t *\n\t * This function takes a known width x height and\n\t * recalculates it to a new size. Only one\n\t * new variable needs to be known\n\t *\n\t *\t$props = array(\n\t *\t\t\t'width'\t\t=> $width,\n\t *\t\t\t'height'\t=> $height,\n\t *\t\t\t'new_width'\t=> 40,\n\t *\t\t\t'new_height'\t=> ''\n\t *\t\t);\n\t *\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tpublic function size_calculator($vals)\n\t{\n\t\tif ( ! is_array($vals))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$allowed = array('new_width', 'new_height', 'width', 'height');\n\n\t\tforeach ($allowed as $item)\n\t\t{\n\t\t\tif (empty($vals[$item]))\n\t\t\t{\n\t\t\t\t$vals[$item] = 0;\n\t\t\t}\n\t\t}\n\n\t\tif ($vals['width'] === 0 OR $vals['height'] === 0)\n\t\t{\n\t\t\treturn $vals;\n\t\t}\n\n\t\tif ($vals['new_width'] === 0)\n\t\t{\n\t\t\t$vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);\n\t\t}\n\t\telseif ($vals['new_height'] === 0)\n\t\t{\n\t\t\t$vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);\n\t\t}\n\n\t\treturn $vals;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Explode source_image\n\t *\n\t * This is a helper function that extracts the extension\n\t * from the source_image.  This function lets us deal with\n\t * source_images with multiple periods, like: my.cool.jpg\n\t * It returns an associative array with two elements:\n\t * $array['ext']  = '.jpg';\n\t * $array['name'] = 'my.cool';\n\t *\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tpublic function explode_name($source_image)\n\t{\n\t\t$ext = strrchr($source_image, '.');\n\t\t$name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));\n\n\t\treturn array('ext' => $ext, 'name' => $name);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is GD Installed?\n\t *\n\t * @return\tbool\n\t */\n\tpublic function gd_loaded()\n\t{\n\t\tif ( ! extension_loaded('gd'))\n\t\t{\n\t\t\t/* As it is stated in the PHP manual, dl() is not always available\n\t\t\t * and even if so - it could generate an E_WARNING message on failure\n\t\t\t */\n\t\t\treturn (function_exists('dl') && @dl('gd.so'));\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get GD version\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function gd_version()\n\t{\n\t\tif (function_exists('gd_info'))\n\t\t{\n\t\t\t$gd_version = @gd_info();\n\t\t\treturn preg_replace('/\\D/', '', $gd_version['GD Version']);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set error message\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_error($msg)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('imglib');\n\n\t\tif (is_array($msg))\n\t\t{\n\t\t\tforeach ($msg as $val)\n\t\t\t{\n\t\t\t\t$msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);\n\t\t\t\t$this->error_msg[] = $msg;\n\t\t\t\tlog_message('error', $msg);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);\n\t\t\t$this->error_msg[] = $msg;\n\t\t\tlog_message('error', $msg);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show error messages\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function display_errors($open = '<p>', $close = '</p>')\n\t{\n\t\treturn (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Javascript/Jquery.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Jquery Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLoader\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/javascript.html\n */\nclass CI_Jquery extends CI_Javascript {\n\n\t/**\n\t * JavaScript directory location\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_javascript_folder = 'js';\n\n\t/**\n\t * JQuery code for load\n\t *\n\t * @var\tarray\n\t */\n\tpublic $jquery_code_for_load = array();\n\n\t/**\n\t * JQuery code for compile\n\t *\n\t * @var\tarray\n\t */\n\tpublic $jquery_code_for_compile = array();\n\n\t/**\n\t * JQuery corner active flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $jquery_corner_active = FALSE;\n\n\t/**\n\t * JQuery table sorter active flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $jquery_table_sorter_active = FALSE;\n\n\t/**\n\t * JQuery table sorter pager active\n\t *\n\t * @var\tbool\n\t */\n\tpublic $jquery_table_sorter_pager_active = FALSE;\n\n\t/**\n\t * JQuery AJAX image\n\t *\n\t * @var\tstring\n\t */\n\tpublic $jquery_ajax_img = '';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\t$this->CI =& get_instance();\n\t\textract($params);\n\n\t\tif ($autoload === TRUE)\n\t\t{\n\t\t\t$this->script();\n\t\t}\n\n\t\tlog_message('info', 'Jquery Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Event Code\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Blur\n\t *\n\t * Outputs a jQuery blur event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _blur($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'blur');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Change\n\t *\n\t * Outputs a jQuery change event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _change($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'change');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Click\n\t *\n\t * Outputs a jQuery click event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @param\tbool\twhether or not to return false\n\t * @return\tstring\n\t */\n\tprotected function _click($element = 'this', $js = '', $ret_false = TRUE)\n\t{\n\t\tis_array($js) OR $js = array($js);\n\n\t\tif ($ret_false)\n\t\t{\n\t\t\t$js[] = 'return false;';\n\t\t}\n\n\t\treturn $this->_add_event($element, $js, 'click');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Double Click\n\t *\n\t * Outputs a jQuery dblclick event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _dblclick($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'dblclick');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Outputs a jQuery error event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _error($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'error');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Focus\n\t *\n\t * Outputs a jQuery focus event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _focus($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'focus');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hover\n\t *\n\t * Outputs a jQuery hover event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Javascript code for mouse over\n\t * @param\tstring\t- Javascript code for mouse out\n\t * @return\tstring\n\t */\n\tprotected function _hover($element = 'this', $over = '', $out = '')\n\t{\n\t\t$event = \"\\n\\t$(\".$this->_prep_element($element).\").hover(\\n\\t\\tfunction()\\n\\t\\t{\\n\\t\\t\\t{$over}\\n\\t\\t}, \\n\\t\\tfunction()\\n\\t\\t{\\n\\t\\t\\t{$out}\\n\\t\\t});\\n\";\n\n\t\t$this->jquery_code_for_compile[] = $event;\n\n\t\treturn $event;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keydown\n\t *\n\t * Outputs a jQuery keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _keydown($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'keydown');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keyup\n\t *\n\t * Outputs a jQuery keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _keyup($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'keyup');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load\n\t *\n\t * Outputs a jQuery load event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _load($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'load');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mousedown\n\t *\n\t * Outputs a jQuery mousedown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mousedown($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mousedown');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Out\n\t *\n\t * Outputs a jQuery mouseout event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mouseout($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mouseout');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Over\n\t *\n\t * Outputs a jQuery mouseover event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mouseover($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mouseover');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouseup\n\t *\n\t * Outputs a jQuery mouseup event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mouseup($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mouseup');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Output\n\t *\n\t * Outputs script directly\n\t *\n\t * @param\tarray\t$array_js = array()\n\t * @return\tvoid\n\t */\n\tprotected function _output($array_js = array())\n\t{\n\t\tif ( ! is_array($array_js))\n\t\t{\n\t\t\t$array_js = array($array_js);\n\t\t}\n\n\t\tforeach ($array_js as $js)\n\t\t{\n\t\t\t$this->jquery_code_for_compile[] = \"\\t\".$js.\"\\n\";\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Resize\n\t *\n\t * Outputs a jQuery resize event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _resize($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'resize');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Scroll\n\t *\n\t * Outputs a jQuery scroll event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _scroll($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'scroll');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Unload\n\t *\n\t * Outputs a jQuery unload event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _unload($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'unload');\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Effects\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Class\n\t *\n\t * Outputs a jQuery addClass event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tstring\t$class\n\t * @return\tstring\n\t */\n\tprotected function _addClass($element = 'this', $class = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').addClass(\"'.$class.'\");';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Animate\n\t *\n\t * Outputs a jQuery animate event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tarray\t$params\n\t * @param\tstring\t$speed\t'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t$extra\n\t * @return\tstring\n\t */\n\tprotected function _animate($element = 'this', $params = array(), $speed = '', $extra = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\t$animations = \"\\t\\t\\t\";\n\n\t\tforeach ($params as $param => $value)\n\t\t{\n\t\t\t$animations .= $param.\": '\".$value.\"', \";\n\t\t}\n\n\t\t$animations = substr($animations, 0, -2); // remove the last \", \"\n\n\t\tif ($speed !== '')\n\t\t{\n\t\t\t$speed = ', '.$speed;\n\t\t}\n\n\t\tif ($extra !== '')\n\t\t{\n\t\t\t$extra = ', '.$extra;\n\t\t}\n\n\t\treturn \"$({$element}).animate({\\n$animations\\n\\t\\t}\".$speed.$extra.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade In\n\t *\n\t * Outputs a jQuery hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _fadeIn($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn \"$({$element}).fadeIn({$speed}{$callback});\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade Out\n\t *\n\t * Outputs a jQuery hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _fadeOut($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').fadeOut('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hide\n\t *\n\t * Outputs a jQuery hide action\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _hide($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn \"$({$element}).hide({$speed}{$callback});\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove Class\n\t *\n\t * Outputs a jQuery remove class event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tstring\t$class\n\t * @return\tstring\n\t */\n\tprotected function _removeClass($element = 'this', $class = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').removeClass(\"'.$class.'\");';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Up\n\t *\n\t * Outputs a jQuery slideUp event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _slideUp($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').slideUp('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Down\n\t *\n\t * Outputs a jQuery slideDown event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _slideDown($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').slideDown('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Toggle\n\t *\n\t * Outputs a jQuery slideToggle event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _slideToggle($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').slideToggle('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle\n\t *\n\t * Outputs a jQuery toggle event\n\t *\n\t * @param\tstring\t- element\n\t * @return\tstring\n\t */\n\tprotected function _toggle($element = 'this')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').toggle();';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle Class\n\t *\n\t * Outputs a jQuery toggle class event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tstring\t$class\n\t * @return\tstring\n\t */\n\tprotected function _toggleClass($element = 'this', $class = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').toggleClass(\"'.$class.'\");';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show\n\t *\n\t * Outputs a jQuery show event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _show($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').show('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Updater\n\t *\n\t * An Ajax call that populates the designated DOM node with\n\t * returned content\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tthe controller to run the call against\n\t * @param\tstring\toptional parameters\n\t * @return\tstring\n\t */\n\n\tprotected function _updater($container = 'this', $controller = '', $options = '')\n\t{\n\t\t$container = $this->_prep_element($container);\n\t\t$controller = (strpos('://', $controller) === FALSE) ? $controller : $this->CI->config->site_url($controller);\n\n\t\t// ajaxStart and ajaxStop are better choices here... but this is a stop gap\n\t\tif ($this->CI->config->item('javascript_ajax_img') === '')\n\t\t{\n\t\t\t$loading_notifier = 'Loading...';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$loading_notifier = '<img src=\"'.$this->CI->config->slash_item('base_url').$this->CI->config->item('javascript_ajax_img').'\" alt=\"Loading\" />';\n\t\t}\n\n\t\t$updater = '$('.$container.\").empty();\\n\" // anything that was in... get it out\n\t\t\t.\"\\t\\t$(\".$container.').prepend(\"'.$loading_notifier.\"\\\");\\n\"; // to replace with an image\n\n\t\t$request_options = '';\n\t\tif ($options !== '')\n\t\t{\n\t\t\t$request_options .= ', {'\n\t\t\t\t\t.(is_array($options) ? \"'\".implode(\"', '\", $options).\"'\" : \"'\".str_replace(':', \"':'\", $options).\"'\")\n\t\t\t\t\t.'}';\n\t\t}\n\n\t\treturn $updater.\"\\t\\t$($container).load('$controller'$request_options);\";\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Pre-written handy stuff\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Zebra tables\n\t *\n\t * @param\tstring\t$class\n\t * @param\tstring\t$odd\n\t * @param\tstring\t$hover\n\t * @return\tstring\n\t */\n\tprotected function _zebraTables($class = '', $odd = 'odd', $hover = '')\n\t{\n\t\t$class = ($class !== '') ? '.'.$class : '';\n\t\t$zebra = \"\\t\\$(\\\"table{$class} tbody tr:nth-child(even)\\\").addClass(\\\"{$odd}\\\");\";\n\n\t\t$this->jquery_code_for_compile[] = $zebra;\n\n\t\tif ($hover !== '')\n\t\t{\n\t\t\t$hover = $this->hover(\"table{$class} tbody tr\", \"$(this).addClass('hover');\", \"$(this).removeClass('hover');\");\n\t\t}\n\n\t\treturn $zebra;\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Plugins\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Corner Plugin\n\t *\n\t * @link\thttp://www.malsup.com/jquery/corner/\n\t * @param\tstring\t$element\n\t * @param\tstring\t$corner_style\n\t * @return\tstring\n\t */\n\tpublic function corner($element = '', $corner_style = '')\n\t{\n\t\t// may want to make this configurable down the road\n\t\t$corner_location = '/plugins/jquery.corner.js';\n\n\t\tif ($corner_style !== '')\n\t\t{\n\t\t\t$corner_style = '\"'.$corner_style.'\"';\n\t\t}\n\n\t\treturn '$('.$this->_prep_element($element).').corner('.$corner_style.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Modal window\n\t *\n\t * Load a thickbox modal window\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function modal($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Effect\n\t *\n\t * Load an Effect library\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function effect($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Plugin\n\t *\n\t * Load a plugin library\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function plugin($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * UI\n\t *\n\t * Load a user interface library\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function ui($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sortable\n\t *\n\t * Creates a jQuery sortable\n\t *\n\t * @param\tstring\t$element\n\t * @param\tarray\t$options\n\t * @return\tstring\n\t */\n\tpublic function sortable($element, $options = array())\n\t{\n\t\tif (count($options) > 0)\n\t\t{\n\t\t\t$sort_options = array();\n\t\t\tforeach ($options as $k=>$v)\n\t\t\t{\n\t\t\t\t$sort_options[] = \"\\n\\t\\t\".$k.': '.$v;\n\t\t\t}\n\t\t\t$sort_options = implode(',', $sort_options);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$sort_options = '';\n\t\t}\n\n\t\treturn '$('.$this->_prep_element($element).').sortable({'.$sort_options.\"\\n\\t});\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Table Sorter Plugin\n\t *\n\t * @param\tstring\ttable name\n\t * @param\tstring\tplugin location\n\t * @return\tstring\n\t */\n\tpublic function tablesorter($table = '', $options = '')\n\t{\n\t\t$this->jquery_code_for_compile[] = \"\\t$(\".$this->_prep_element($table).').tablesorter('.$options.\");\\n\";\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Class functions\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Event\n\t *\n\t * Constructs the syntax for an event, and adds to into the array for compilation\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @param\tstring\tThe event to pass\n\t * @return\tstring\n\t */\n\tprotected function _add_event($element, $js, $event)\n\t{\n\t\tif (is_array($js))\n\t\t{\n\t\t\t$js = implode(\"\\n\\t\\t\", $js);\n\t\t}\n\n\t\t$event = \"\\n\\t$(\".$this->_prep_element($element).').'.$event.\"(function(){\\n\\t\\t{$js}\\n\\t});\\n\";\n\t\t$this->jquery_code_for_compile[] = $event;\n\t\treturn $event;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile\n\t *\n\t * As events are specified, they are stored in an array\n\t * This function compiles them all for output on a page\n\t *\n\t * @param\tstring\t$view_var\n\t * @param\tbool\t$script_tags\n\t * @return\tvoid\n\t */\n\tprotected function _compile($view_var = 'script_foot', $script_tags = TRUE)\n\t{\n\t\t// External references\n\t\t$external_scripts = implode('', $this->jquery_code_for_load);\n\t\t$this->CI->load->vars(array('library_src' => $external_scripts));\n\n\t\tif (count($this->jquery_code_for_compile) === 0)\n\t\t{\n\t\t\t// no inline references, let's just return\n\t\t\treturn;\n\t\t}\n\n\t\t// Inline references\n\t\t$script = '$(document).ready(function() {'.\"\\n\"\n\t\t\t.implode('', $this->jquery_code_for_compile)\n\t\t\t.'});';\n\n\t\t$output = ($script_tags === FALSE) ? $script : $this->inline($script);\n\n\t\t$this->CI->load->vars(array($view_var => $output));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clear Compile\n\t *\n\t * Clears the array of script events collected for output\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _clear_compile()\n\t{\n\t\t$this->jquery_code_for_compile = array();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Document Ready\n\t *\n\t * A wrapper for writing document.ready()\n\t *\n\t * @param\tarray\t$js\n\t * @return\tvoid\n\t */\n\tprotected function _document_ready($js)\n\t{\n\t\tis_array($js) OR $js = array($js);\n\n\t\tforeach ($js as $script)\n\t\t{\n\t\t\t$this->jquery_code_for_compile[] = $script;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Script Tag\n\t *\n\t * Outputs the script tag that loads the jquery.js file into an HTML document\n\t *\n\t * @param\tstring\t$library_src\n\t * @param\tbool\t$relative\n\t * @return\tstring\n\t */\n\tpublic function script($library_src = '', $relative = FALSE)\n\t{\n\t\t$library_src = $this->external($library_src, $relative);\n\t\t$this->jquery_code_for_load[] = $library_src;\n\t\treturn $library_src;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Element\n\t *\n\t * Puts HTML element in quotes for use in jQuery code\n\t * unless the supplied element is the Javascript 'this'\n\t * object, in which case no quotes are added\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _prep_element($element)\n\t{\n\t\tif ($element !== 'this')\n\t\t{\n\t\t\t$element = '\"'.$element.'\"';\n\t\t}\n\n\t\treturn $element;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Speed\n\t *\n\t * Ensures the speed parameter is valid for jQuery\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _validate_speed($speed)\n\t{\n\t\tif (in_array($speed, array('slow', 'normal', 'fast')))\n\t\t{\n\t\t\treturn '\"'.$speed.'\"';\n\t\t}\n\t\telseif (preg_match('/[^0-9]/', $speed))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn $speed;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Javascript/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Javascript.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Javascript Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tJavascript\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/javascript.html\n * @deprecated\t3.0.0\tThis was never a good idea in the first place.\n */\nclass CI_Javascript {\n\n\t/**\n\t * JavaScript location\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_javascript_location = 'js';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params = array())\n\t{\n\t\t$defaults = array('js_library_driver' => 'jquery', 'autoload' => TRUE);\n\n\t\tforeach ($defaults as $key => $val)\n\t\t{\n\t\t\tif (isset($params[$key]) && $params[$key] !== '')\n\t\t\t{\n\t\t\t\t$defaults[$key] = $params[$key];\n\t\t\t}\n\t\t}\n\n\t\textract($defaults);\n\n\t\t$this->CI =& get_instance();\n\n\t\t// load the requested js library\n\t\t$this->CI->load->library('Javascript/'.$js_library_driver, array('autoload' => $autoload));\n\t\t// make js to refer to current library\n\t\t$this->js =& $this->CI->$js_library_driver;\n\n\t\tlog_message('info', 'Javascript Class Initialized and loaded. Driver used: '.$js_library_driver);\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Event Code\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Blur\n\t *\n\t * Outputs a javascript library blur event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function blur($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_blur($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Change\n\t *\n\t * Outputs a javascript library change event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function change($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_change($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Click\n\t *\n\t * Outputs a javascript library click event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @param\tbool\twhether or not to return false\n\t * @return\tstring\n\t */\n\tpublic function click($element = 'this', $js = '', $ret_false = TRUE)\n\t{\n\t\treturn $this->js->_click($element, $js, $ret_false);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Double Click\n\t *\n\t * Outputs a javascript library dblclick event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function dblclick($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_dblclick($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Outputs a javascript library error event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function error($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_error($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Focus\n\t *\n\t * Outputs a javascript library focus event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function focus($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_focus($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hover\n\t *\n\t * Outputs a javascript library hover event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Javascript code for mouse over\n\t * @param\tstring\t- Javascript code for mouse out\n\t * @return\tstring\n\t */\n\tpublic function hover($element = 'this', $over = '', $out = '')\n\t{\n\t\treturn $this->js->_hover($element, $over, $out);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keydown\n\t *\n\t * Outputs a javascript library keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function keydown($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_keydown($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keyup\n\t *\n\t * Outputs a javascript library keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function keyup($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_keyup($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load\n\t *\n\t * Outputs a javascript library load event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function load($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_load($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mousedown\n\t *\n\t * Outputs a javascript library mousedown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mousedown($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mousedown($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Out\n\t *\n\t * Outputs a javascript library mouseout event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mouseout($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mouseout($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Over\n\t *\n\t * Outputs a javascript library mouseover event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mouseover($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mouseover($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouseup\n\t *\n\t * Outputs a javascript library mouseup event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mouseup($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mouseup($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Output\n\t *\n\t * Outputs the called javascript to the screen\n\t *\n\t * @param\tstring\tThe code to output\n\t * @return\tstring\n\t */\n\tpublic function output($js)\n\t{\n\t\treturn $this->js->_output($js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Ready\n\t *\n\t * Outputs a javascript library mouseup event\n\t *\n\t * @param\tstring\t$js\tCode to execute\n\t * @return\tstring\n\t */\n\tpublic function ready($js)\n\t{\n\t\treturn $this->js->_document_ready($js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Resize\n\t *\n\t * Outputs a javascript library resize event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function resize($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_resize($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Scroll\n\t *\n\t * Outputs a javascript library scroll event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function scroll($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_scroll($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Unload\n\t *\n\t * Outputs a javascript library unload event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function unload($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_unload($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Effects\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Class\n\t *\n\t * Outputs a javascript library addClass event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Class to add\n\t * @return\tstring\n\t */\n\tpublic function addClass($element = 'this', $class = '')\n\t{\n\t\treturn $this->js->_addClass($element, $class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Animate\n\t *\n\t * Outputs a javascript library animate event\n\t *\n\t * @param\tstring\t$element = 'this'\n\t * @param\tarray\t$params = array()\n\t * @param\tmixed\t$speed\t\t\t'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t$extra\n\t * @return\tstring\n\t */\n\tpublic function animate($element = 'this', $params = array(), $speed = '', $extra = '')\n\t{\n\t\treturn $this->js->_animate($element, $params, $speed, $extra);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade In\n\t *\n\t * Outputs a javascript library hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function fadeIn($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_fadeIn($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade Out\n\t *\n\t * Outputs a javascript library hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function fadeOut($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_fadeOut($element, $speed, $callback);\n\t}\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Up\n\t *\n\t * Outputs a javascript library slideUp event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function slideUp($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_slideUp($element, $speed, $callback);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove Class\n\t *\n\t * Outputs a javascript library removeClass event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Class to add\n\t * @return\tstring\n\t */\n\tpublic function removeClass($element = 'this', $class = '')\n\t{\n\t\treturn $this->js->_removeClass($element, $class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Down\n\t *\n\t * Outputs a javascript library slideDown event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function slideDown($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_slideDown($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Toggle\n\t *\n\t * Outputs a javascript library slideToggle event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function slideToggle($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_slideToggle($element, $speed, $callback);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hide\n\t *\n\t * Outputs a javascript library hide action\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function hide($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_hide($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle\n\t *\n\t * Outputs a javascript library toggle event\n\t *\n\t * @param\tstring\t- element\n\t * @return\tstring\n\t */\n\tpublic function toggle($element = 'this')\n\t{\n\t\treturn $this->js->_toggle($element);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle Class\n\t *\n\t * Outputs a javascript library toggle class event\n\t *\n\t * @param\tstring\t$element = 'this'\n\t * @param\tstring\t$class = ''\n\t * @return\tstring\n\t */\n\tpublic function toggleClass($element = 'this', $class = '')\n\t{\n\t\treturn $this->js->_toggleClass($element, $class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show\n\t *\n\t * Outputs a javascript library show event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function show($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_show($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile\n\t *\n\t * gather together all script needing to be output\n\t *\n\t * @param\tstring\t$view_var\n\t * @param\tbool\t$script_tags\n\t * @return\tstring\n\t */\n\tpublic function compile($view_var = 'script_foot', $script_tags = TRUE)\n\t{\n\t\t$this->js->_compile($view_var, $script_tags);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clear Compile\n\t *\n\t * Clears any previous javascript collected for output\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function clear_compile()\n\t{\n\t\t$this->js->_clear_compile();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * External\n\t *\n\t * Outputs a <script> tag with the source as an external js file\n\t *\n\t * @param\tstring\t$external_file\n\t * @param\tbool\t$relative\n\t * @return\tstring\n\t */\n\tpublic function external($external_file = '', $relative = FALSE)\n\t{\n\t\tif ($external_file !== '')\n\t\t{\n\t\t\t$this->_javascript_location = $external_file;\n\t\t}\n\t\telseif ($this->CI->config->item('javascript_location') !== '')\n\t\t{\n\t\t\t$this->_javascript_location = $this->CI->config->item('javascript_location');\n\t\t}\n\n\t\tif ($relative === TRUE OR strpos($external_file, 'http://') === 0 OR strpos($external_file, 'https://') === 0)\n\t\t{\n\t\t\t$str = $this->_open_script($external_file);\n\t\t}\n\t\telseif (strpos($this->_javascript_location, 'http://') !== FALSE)\n\t\t{\n\t\t\t$str = $this->_open_script($this->_javascript_location.$external_file);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$str = $this->_open_script($this->CI->config->slash_item('base_url').$this->_javascript_location.$external_file);\n\t\t}\n\n\t\treturn $str.$this->_close_script();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Inline\n\t *\n\t * Outputs a <script> tag\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tbool\tIf a CDATA section should be added\n\t * @return\tstring\n\t */\n\tpublic function inline($script, $cdata = TRUE)\n\t{\n\t\treturn $this->_open_script()\n\t\t\t. ($cdata ? \"\\n// <![CDATA[\\n\".$script.\"\\n// ]]>\\n\" : \"\\n\".$script.\"\\n\")\n\t\t\t. $this->_close_script();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Open Script\n\t *\n\t * Outputs an opening <script>\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _open_script($src = '')\n\t{\n\t\treturn '<script type=\"text/javascript\" charset=\"'.strtolower($this->CI->config->item('charset')).'\"'\n\t\t\t.($src === '' ? '>' : ' src=\"'.$src.'\">');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close Script\n\t *\n\t * Outputs an closing </script>\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _close_script($extra = \"\\n\")\n\t{\n\t\treturn '</script>'.$extra;\n\t}\n\n\t// --------------------------------------------------------------------\n\t// AJAX-Y STUFF - still a testbed\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update\n\t *\n\t * Outputs a javascript library slideDown event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function update($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_updater($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate JSON\n\t *\n\t * Can be passed a database result or associative array and returns a JSON formatted string\n\t *\n\t * @param\tmixed\tresult set or array\n\t * @param\tbool\tmatch array types (defaults to objects)\n\t * @return\tstring\ta json formatted string\n\t */\n\tpublic function generate_json($result = NULL, $match_array_type = FALSE)\n\t{\n\t\t// JSON data can optionally be passed to this function\n\t\t// either as a database result object or an array, or a user supplied array\n\t\tif ($result !== NULL)\n\t\t{\n\t\t\tif (is_object($result))\n\t\t\t{\n\t\t\t\t$json_result = is_callable(array($result, 'result_array')) ? $result->result_array() : (array) $result;\n\t\t\t}\n\t\t\telseif (is_array($result))\n\t\t\t{\n\t\t\t\t$json_result = $result;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $this->_prep_args($result);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 'null';\n\t\t}\n\n\t\t$json = array();\n\t\t$_is_assoc = TRUE;\n\n\t\tif ( ! is_array($json_result) && empty($json_result))\n\t\t{\n\t\t\tshow_error('Generate JSON Failed - Illegal key, value pair.');\n\t\t}\n\t\telseif ($match_array_type)\n\t\t{\n\t\t\t$_is_assoc = $this->_is_associative_array($json_result);\n\t\t}\n\n\t\tforeach ($json_result as $k => $v)\n\t\t{\n\t\t\tif ($_is_assoc)\n\t\t\t{\n\t\t\t\t$json[] = $this->_prep_args($k, TRUE).':'.$this->generate_json($v, $match_array_type);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$json[] = $this->generate_json($v, $match_array_type);\n\t\t\t}\n\t\t}\n\n\t\t$json = implode(',', $json);\n\n\t\treturn $_is_assoc ? '{'.$json.'}' : '['.$json.']';\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is associative array\n\t *\n\t * Checks for an associative array\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tprotected function _is_associative_array($arr)\n\t{\n\t\tforeach (array_keys($arr) as $key => $val)\n\t\t{\n\t\t\tif ($key !== $val)\n\t\t\t{\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Args\n\t *\n\t * Ensures a standard json value and escapes values\n\t *\n\t * @param\tmixed\t$result\n\t * @param\tbool\t$is_key = FALSE\n\t * @return\tstring\n\t */\n\tprotected function _prep_args($result, $is_key = FALSE)\n\t{\n\t\tif ($result === NULL)\n\t\t{\n\t\t\treturn 'null';\n\t\t}\n\t\telseif (is_bool($result))\n\t\t{\n\t\t\treturn ($result === TRUE) ? 'true' : 'false';\n\t\t}\n\t\telseif (is_string($result) OR $is_key)\n\t\t{\n\t\t\treturn '\"'.str_replace(array('\\\\', \"\\t\", \"\\n\", \"\\r\", '\"', '/'), array('\\\\\\\\', '\\\\t', '\\\\n', \"\\\\r\", '\\\"', '\\/'), $result).'\"';\n\t\t}\n\t\telseif (is_scalar($result))\n\t\t{\n\t\t\treturn $result;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Migration.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Migration Class\n *\n * All migrations should implement this, forces up() and down() and gives\n * access to the CI super-global.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tReactor Engineers\n * @link\n */\nclass CI_Migration {\n\n\t/**\n\t * Whether the library is enabled\n\t *\n\t * @var bool\n\t */\n\tprotected $_migration_enabled = FALSE;\n\n\t/**\n\t * Migration numbering type\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_migration_type = 'sequential';\n\n\t/**\n\t * Path to migration classes\n\t *\n\t * @var string\n\t */\n\tprotected $_migration_path = NULL;\n\n\t/**\n\t * Current migration version\n\t *\n\t * @var mixed\n\t */\n\tprotected $_migration_version = 0;\n\n\t/**\n\t * Database table with migration info\n\t *\n\t * @var string\n\t */\n\tprotected $_migration_table = 'migrations';\n\n\t/**\n\t * Whether to automatically run migrations\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_migration_auto_latest = FALSE;\n\n\t/**\n\t * Migration basename regex\n\t *\n\t * @var bool\n\t */\n\tprotected $_migration_regex = NULL;\n\n\t/**\n\t * Error message\n\t *\n\t * @var string\n\t */\n\tprotected $_error_string = '';\n\n\t/**\n\t * Initialize Migration Class\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t// Only run this constructor on main library load\n\t\tif ( ! in_array(get_class($this), array('CI_Migration', config_item('subclass_prefix').'Migration'), TRUE))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\t$this->{'_'.$key} = $val;\n\t\t}\n\n\t\tlog_message('info', 'Migrations Class Initialized');\n\n\t\t// Are they trying to use migrations while it is disabled?\n\t\tif ($this->_migration_enabled !== TRUE)\n\t\t{\n\t\t\tshow_error('Migrations has been loaded but is disabled or set up incorrectly.');\n\t\t}\n\n\t\t// If not set, set it\n\t\t$this->_migration_path !== '' OR $this->_migration_path = APPPATH.'migrations/';\n\n\t\t// Add trailing slash if not set\n\t\t$this->_migration_path = rtrim($this->_migration_path, '/').'/';\n\n\t\t// Load migration language\n\t\t$this->lang->load('migration');\n\n\t\t// They'll probably be using dbforge\n\t\t$this->load->dbforge();\n\n\t\t// Make sure the migration table name was set.\n\t\tif (empty($this->_migration_table))\n\t\t{\n\t\t\tshow_error('Migrations configuration file (migration.php) must have \"migration_table\" set.');\n\t\t}\n\n\t\t// Migration basename regex\n\t\t$this->_migration_regex = ($this->_migration_type === 'timestamp')\n\t\t\t? '/^\\d{14}_(\\w+)$/'\n\t\t\t: '/^\\d{3}_(\\w+)$/';\n\n\t\t// Make sure a valid migration numbering type was set.\n\t\tif ( ! in_array($this->_migration_type, array('sequential', 'timestamp')))\n\t\t{\n\t\t\tshow_error('An invalid migration numbering type was specified: '.$this->_migration_type);\n\t\t}\n\n\t\t// If the migrations table is missing, make it\n\t\tif ( ! $this->db->table_exists($this->_migration_table))\n\t\t{\n\t\t\t$this->dbforge->add_field(array(\n\t\t\t\t'version' => array('type' => 'BIGINT', 'constraint' => 20),\n\t\t\t));\n\n\t\t\t$this->dbforge->create_table($this->_migration_table, TRUE);\n\n\t\t\t$this->db->insert($this->_migration_table, array('version' => 0));\n\t\t}\n\n\t\t// Do we auto migrate to the latest migration?\n\t\tif ($this->_migration_auto_latest === TRUE && ! $this->latest())\n\t\t{\n\t\t\tshow_error($this->error_string());\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Migrate to a schema version\n\t *\n\t * Calls each migration step required to get to the schema version of\n\t * choice\n\t *\n\t * @param\tstring\t$target_version\tTarget schema version\n\t * @return\tmixed\tTRUE if no migrations are found, current version string on success, FALSE on failure\n\t */\n\tpublic function version($target_version)\n\t{\n\t\t// Note: We use strings, so that timestamp versions work on 32-bit systems\n\t\t$current_version = $this->_get_version();\n\n\t\tif ($this->_migration_type === 'sequential')\n\t\t{\n\t\t\t$target_version = sprintf('%03d', $target_version);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$target_version = (string) $target_version;\n\t\t}\n\n\t\t$migrations = $this->find_migrations();\n\n\t\tif ($target_version > 0 && ! isset($migrations[$target_version]))\n\t\t{\n\t\t\t$this->_error_string = sprintf($this->lang->line('migration_not_found'), $target_version);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($target_version > $current_version)\n\t\t{\n\t\t\t// Moving Up\n\t\t\t$method = 'up';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Moving Down, apply in reverse order\n\t\t\t$method = 'down';\n\t\t\tkrsort($migrations);\n\t\t}\n\n\t\tif (empty($migrations))\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t$previous = FALSE;\n\n\t\t// Validate all available migrations, and run the ones within our target range\n\t\tforeach ($migrations as $number => $file)\n\t\t{\n\t\t\t// Check for sequence gaps\n\t\t\tif ($this->_migration_type === 'sequential' && $previous !== FALSE && abs($number - $previous) > 1)\n\t\t\t{\n\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_sequence_gap'), $number);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tinclude_once($file);\n\t\t\t$class = 'Migration_'.ucfirst(strtolower($this->_get_migration_name(basename($file, '.php'))));\n\n\t\t\t// Validate the migration file structure\n\t\t\tif ( ! class_exists($class, FALSE))\n\t\t\t{\n\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$previous = $number;\n\n\t\t\t// Run migrations that are inside the target range\n\t\t\tif (\n\t\t\t\t($method === 'up'   && $number > $current_version && $number <= $target_version) OR\n\t\t\t\t($method === 'down' && $number <= $current_version && $number > $target_version)\n\t\t\t)\n\t\t\t{\n\t\t\t\t$instance = new $class();\n\t\t\t\tif ( ! is_callable(array($instance, $method)))\n\t\t\t\t{\n\t\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tlog_message('debug', 'Migrating '.$method.' from version '.$current_version.' to version '.$number);\n\t\t\t\tcall_user_func(array($instance, $method));\n\t\t\t\t$current_version = $number;\n\t\t\t\t$this->_update_version($current_version);\n\t\t\t}\n\t\t}\n\n\t\t// This is necessary when moving down, since the the last migration applied\n\t\t// will be the down() method for the next migration up from the target\n\t\tif ($current_version <> $target_version)\n\t\t{\n\t\t\t$current_version = $target_version;\n\t\t\t$this->_update_version($current_version);\n\t\t}\n\n\t\tlog_message('debug', 'Finished migrating to '.$current_version);\n\n\t\treturn $current_version;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sets the schema to the latest migration\n\t *\n\t * @return\tmixed\tCurrent version string on success, FALSE on failure\n\t */\n\tpublic function latest()\n\t{\n\t\t$migrations = $this->find_migrations();\n\n\t\tif (empty($migrations))\n\t\t{\n\t\t\t$this->_error_string = $this->lang->line('migration_none_found');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$last_migration = basename(end($migrations));\n\n\t\t// Calculate the last migration step from existing migration\n\t\t// filenames and proceed to the standard version migration\n\t\treturn $this->version($this->_get_migration_number($last_migration));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sets the schema to the migration version set in config\n\t *\n\t * @return\tmixed\tTRUE if no migrations are found, current version string on success, FALSE on failure\n\t */\n\tpublic function current()\n\t{\n\t\treturn $this->version($this->_migration_version);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error string\n\t *\n\t * @return\tstring\tError message returned as a string\n\t */\n\tpublic function error_string()\n\t{\n\t\treturn $this->_error_string;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Retrieves list of available migration scripts\n\t *\n\t * @return\tarray\tlist of migration file paths sorted by version\n\t */\n\tpublic function find_migrations()\n\t{\n\t\t$migrations = array();\n\n\t\t// Load all *_*.php files in the migrations path\n\t\tforeach (glob($this->_migration_path.'*_*.php') as $file)\n\t\t{\n\t\t\t$name = basename($file, '.php');\n\n\t\t\t// Filter out non-migration files\n\t\t\tif (preg_match($this->_migration_regex, $name))\n\t\t\t{\n\t\t\t\t$number = $this->_get_migration_number($name);\n\n\t\t\t\t// There cannot be duplicate migration numbers\n\t\t\t\tif (isset($migrations[$number]))\n\t\t\t\t{\n\t\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $number);\n\t\t\t\t\tshow_error($this->_error_string);\n\t\t\t\t}\n\n\t\t\t\t$migrations[$number] = $file;\n\t\t\t}\n\t\t}\n\n\t\tksort($migrations);\n\t\treturn $migrations;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extracts the migration number from a filename\n\t *\n\t * @param\tstring\t$migration\n\t * @return\tstring\tNumeric portion of a migration filename\n\t */\n\tprotected function _get_migration_number($migration)\n\t{\n\t\treturn sscanf($migration, '%[0-9]+', $number)\n\t\t\t? $number : '0';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extracts the migration class name from a filename\n\t *\n\t * @param\tstring\t$migration\n\t * @return\tstring\ttext portion of a migration filename\n\t */\n\tprotected function _get_migration_name($migration)\n\t{\n\t\t$parts = explode('_', $migration);\n\t\tarray_shift($parts);\n\t\treturn implode('_', $parts);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Retrieves current schema version\n\t *\n\t * @return\tstring\tCurrent migration version\n\t */\n\tprotected function _get_version()\n\t{\n\t\t$row = $this->db->select('version')->get($this->_migration_table)->row();\n\t\treturn $row ? $row->version : '0';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Stores the current schema version\n\t *\n\t * @param\tstring\t$migration\tMigration reached\n\t * @return\tvoid\n\t */\n\tprotected function _update_version($migration)\n\t{\n\t\t$this->db->update($this->_migration_table, array(\n\t\t\t'version' => $migration\n\t\t));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Enable the use of CI super-global\n\t *\n\t * @param\tstring\t$var\n\t * @return\tmixed\n\t */\n\tpublic function __get($var)\n\t{\n\t\treturn get_instance()->$var;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Pagination.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Pagination Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tPagination\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/pagination.html\n */\nclass CI_Pagination {\n\n\t/**\n\t * Base URL\n\t *\n\t * The page that we're linking to\n\t *\n\t * @var\tstring\n\t */\n\tprotected $base_url\t\t= '';\n\n\t/**\n\t * Prefix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prefix = '';\n\n\t/**\n\t * Suffix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $suffix = '';\n\n\t/**\n\t * Total number of items\n\t *\n\t * @var\tint\n\t */\n\tprotected $total_rows = 0;\n\n\t/**\n\t * Number of links to show\n\t *\n\t * Relates to \"digit\" type links shown before/after\n\t * the currently viewed page.\n\t *\n\t * @var\tint\n\t */\n\tprotected $num_links = 2;\n\n\t/**\n\t * Items per page\n\t *\n\t * @var\tint\n\t */\n\tpublic $per_page = 10;\n\n\t/**\n\t * Current page\n\t *\n\t * @var\tint\n\t */\n\tpublic $cur_page = 0;\n\n\t/**\n\t * Use page numbers flag\n\t *\n\t * Whether to use actual page numbers instead of an offset\n\t *\n\t * @var\tbool\n\t */\n\tprotected $use_page_numbers = FALSE;\n\n\t/**\n\t * First link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_link = '&lsaquo; First';\n\n\t/**\n\t * Next link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $next_link = '&gt;';\n\n\t/**\n\t * Previous link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prev_link = '&lt;';\n\n\t/**\n\t * Last link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $last_link = 'Last &rsaquo;';\n\n\t/**\n\t * URI Segment\n\t *\n\t * @var\tint\n\t */\n\tprotected $uri_segment = 0;\n\n\t/**\n\t * Full tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $full_tag_open = '';\n\n\t/**\n\t * Full tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $full_tag_close = '';\n\n\t/**\n\t * First tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_tag_open = '';\n\n\t/**\n\t * First tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_tag_close = '';\n\n\t/**\n\t * Last tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $last_tag_open = '';\n\n\t/**\n\t * Last tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $last_tag_close = '';\n\n\t/**\n\t * First URL\n\t *\n\t * An alternative URL for the first page\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_url = '';\n\n\t/**\n\t * Current tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $cur_tag_open = '<strong>';\n\n\t/**\n\t * Current tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $cur_tag_close = '</strong>';\n\n\t/**\n\t * Next tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $next_tag_open = '';\n\n\t/**\n\t * Next tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $next_tag_close = '';\n\n\t/**\n\t * Previous tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prev_tag_open = '';\n\n\t/**\n\t * Previous tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prev_tag_close = '';\n\n\t/**\n\t * Number tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $num_tag_open = '';\n\n\t/**\n\t * Number tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $num_tag_close = '';\n\n\t/**\n\t * Page query string flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $page_query_string = FALSE;\n\n\t/**\n\t * Query string segment\n\t *\n\t * @var\tstring\n\t */\n\tprotected $query_string_segment = 'per_page';\n\n\t/**\n\t * Display pages flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $display_pages = TRUE;\n\n\t/**\n\t * Attributes\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_attributes = '';\n\n\t/**\n\t * Link types\n\t *\n\t * \"rel\" attribute\n\t *\n\t * @see\tCI_Pagination::_attr_rel()\n\t * @var\tarray\n\t */\n\tprotected $_link_types = array();\n\n\t/**\n\t * Reuse query string flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $reuse_query_string = FALSE;\n\n\t/**\n\t * Use global URL suffix flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $use_global_url_suffix = FALSE;\n\n\t/**\n\t * Data page attribute\n\t *\n\t * @var\tstring\n\t */\n\tprotected $data_page_attr = 'data-ci-pagination-page';\n\n\t/**\n\t * CI Singleton\n\t *\n\t * @var\tobject\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$params\tInitialization parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params = array())\n\t{\n\t\t$this->CI =& get_instance();\n\t\t$this->CI->load->language('pagination');\n\t\tforeach (array('first_link', 'next_link', 'prev_link', 'last_link') as $key)\n\t\t{\n\t\t\tif (($val = $this->CI->lang->line('pagination_'.$key)) !== FALSE)\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\t$this->initialize($params);\n\t\tlog_message('info', 'Pagination Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize Preferences\n\t *\n\t * @param\tarray\t$params\tInitialization parameters\n\t * @return\tCI_Pagination\n\t */\n\tpublic function initialize(array $params = array())\n\t{\n\t\tisset($params['attributes']) OR $params['attributes'] = array();\n\t\tif (is_array($params['attributes']))\n\t\t{\n\t\t\t$this->_parse_attributes($params['attributes']);\n\t\t\tunset($params['attributes']);\n\t\t}\n\n\t\t// Deprecated legacy support for the anchor_class option\n\t\t// Should be removed in CI 3.1+\n\t\tif (isset($params['anchor_class']))\n\t\t{\n\t\t\tempty($params['anchor_class']) OR $attributes['class'] = $params['anchor_class'];\n\t\t\tunset($params['anchor_class']);\n\t\t}\n\n\t\tforeach ($params as $key => $val)\n\t\t{\n\t\t\tif (property_exists($this, $key))\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\tif ($this->CI->config->item('enable_query_strings') === TRUE)\n\t\t{\n\t\t\t$this->page_query_string = TRUE;\n\t\t}\n\n\t\tif ($this->use_global_url_suffix === TRUE)\n\t\t{\n\t\t\t$this->suffix = $this->CI->config->item('url_suffix');\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate the pagination links\n\t *\n\t * @return\tstring\n\t */\n\tpublic function create_links()\n\t{\n\t\t// If our item count or per-page total is zero there is no need to continue.\n\t\t// Note: DO NOT change the operator to === here!\n\t\tif ($this->total_rows == 0 OR $this->per_page == 0)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t// Calculate the total number of pages\n\t\t$num_pages = (int) ceil($this->total_rows / $this->per_page);\n\n\t\t// Is there only one page? Hm... nothing more to do here then.\n\t\tif ($num_pages === 1)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t// Check the user defined number of links.\n\t\t$this->num_links = (int) $this->num_links;\n\n\t\tif ($this->num_links < 0)\n\t\t{\n\t\t\tshow_error('Your number of links must be a non-negative number.');\n\t\t}\n\n\t\t// Keep any existing query string items.\n\t\t// Note: Has nothing to do with any other query string option.\n\t\tif ($this->reuse_query_string === TRUE)\n\t\t{\n\t\t\t$get = $this->CI->input->get();\n\n\t\t\t// Unset the controll, method, old-school routing options\n\t\t\tunset($get['c'], $get['m'], $get[$this->query_string_segment]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$get = array();\n\t\t}\n\n\t\t// Put together our base and first URLs.\n\t\t// Note: DO NOT append to the properties as that would break successive calls\n\t\t$base_url = trim($this->base_url);\n\t\t$first_url = $this->first_url;\n\n\t\t$query_string = '';\n\t\t$query_string_sep = (strpos($base_url, '?') === FALSE) ? '?' : '&amp;';\n\n\t\t// Are we using query strings?\n\t\tif ($this->page_query_string === TRUE)\n\t\t{\n\t\t\t// If a custom first_url hasn't been specified, we'll create one from\n\t\t\t// the base_url, but without the page item.\n\t\t\tif ($first_url === '')\n\t\t\t{\n\t\t\t\t$first_url = $base_url;\n\n\t\t\t\t// If we saved any GET items earlier, make sure they're appended.\n\t\t\t\tif ( ! empty($get))\n\t\t\t\t{\n\t\t\t\t\t$first_url .= $query_string_sep.http_build_query($get);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the page segment to the end of the query string, where the\n\t\t\t// page number will be appended.\n\t\t\t$base_url .= $query_string_sep.http_build_query(array_merge($get, array($this->query_string_segment => '')));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Standard segment mode.\n\t\t\t// Generate our saved query string to append later after the page number.\n\t\t\tif ( ! empty($get))\n\t\t\t{\n\t\t\t\t$query_string = $query_string_sep.http_build_query($get);\n\t\t\t\t$this->suffix .= $query_string;\n\t\t\t}\n\n\t\t\t// Does the base_url have the query string in it?\n\t\t\t// If we're supposed to save it, remove it so we can append it later.\n\t\t\tif ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($base_url, '?')) !== FALSE)\n\t\t\t{\n\t\t\t\t$base_url = substr($base_url, 0, $base_query_pos);\n\t\t\t}\n\n\t\t\tif ($first_url === '')\n\t\t\t{\n\t\t\t\t$first_url = $base_url.$query_string;\n\t\t\t}\n\n\t\t\t$base_url = rtrim($base_url, '/').'/';\n\t\t}\n\n\t\t// Determine the current page number.\n\t\t$base_page = ($this->use_page_numbers) ? 1 : 0;\n\n\t\t// Are we using query strings?\n\t\tif ($this->page_query_string === TRUE)\n\t\t{\n\t\t\t$this->cur_page = $this->CI->input->get($this->query_string_segment);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Default to the last segment number if one hasn't been defined.\n\t\t\tif ($this->uri_segment === 0)\n\t\t\t{\n\t\t\t\t$this->uri_segment = count($this->CI->uri->segment_array());\n\t\t\t}\n\n\t\t\t$this->cur_page = $this->CI->uri->segment($this->uri_segment);\n\n\t\t\t// Remove any specified prefix/suffix from the segment.\n\t\t\tif ($this->prefix !== '' OR $this->suffix !== '')\n\t\t\t{\n\t\t\t\t$this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);\n\t\t\t}\n\t\t}\n\n\t\t// If something isn't quite right, back to the default base page.\n\t\tif ( ! ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0))\n\t\t{\n\t\t\t$this->cur_page = $base_page;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Make sure we're using integers for comparisons later.\n\t\t\t$this->cur_page = (int) $this->cur_page;\n\t\t}\n\n\t\t// Is the page number beyond the result range?\n\t\t// If so, we show the last page.\n\t\tif ($this->use_page_numbers)\n\t\t{\n\t\t\tif ($this->cur_page > $num_pages)\n\t\t\t{\n\t\t\t\t$this->cur_page = $num_pages;\n\t\t\t}\n\t\t}\n\t\telseif ($this->cur_page > $this->total_rows)\n\t\t{\n\t\t\t$this->cur_page = ($num_pages - 1) * $this->per_page;\n\t\t}\n\n\t\t$uri_page_number = $this->cur_page;\n\n\t\t// If we're using offset instead of page numbers, convert it\n\t\t// to a page number, so we can generate the surrounding number links.\n\t\tif ( ! $this->use_page_numbers)\n\t\t{\n\t\t\t$this->cur_page = (int) floor(($this->cur_page/$this->per_page) + 1);\n\t\t}\n\n\t\t// Calculate the start and end numbers. These determine\n\t\t// which number to start and end the digit links with.\n\t\t$start\t= (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;\n\t\t$end\t= (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;\n\n\t\t// And here we go...\n\t\t$output = '';\n\n\t\t// Render the \"First\" link.\n\t\tif ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1 + ! $this->num_links))\n\t\t{\n\t\t\t// Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, 1);\n\n\t\t\t$output .= $this->first_tag_open.'<a href=\"'.$first_url.'\"'.$attributes.$this->_attr_rel('start').'>'\n\t\t\t\t.$this->first_link.'</a>'.$this->first_tag_close;\n\t\t}\n\n\t\t// Render the \"Previous\" link.\n\t\tif ($this->prev_link !== FALSE && $this->cur_page !== 1)\n\t\t{\n\t\t\t$i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;\n\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));\n\n\t\t\tif ($i === $base_page)\n\t\t\t{\n\t\t\t\t// First page\n\t\t\t\t$output .= $this->prev_tag_open.'<a href=\"'.$first_url.'\"'.$attributes.$this->_attr_rel('prev').'>'\n\t\t\t\t\t.$this->prev_link.'</a>'.$this->prev_tag_close;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$append = $this->prefix.$i.$this->suffix;\n\t\t\t\t$output .= $this->prev_tag_open.'<a href=\"'.$base_url.$append.'\"'.$attributes.$this->_attr_rel('prev').'>'\n\t\t\t\t\t.$this->prev_link.'</a>'.$this->prev_tag_close;\n\t\t\t}\n\n\t\t}\n\n\t\t// Render the pages\n\t\tif ($this->display_pages !== FALSE)\n\t\t{\n\t\t\t// Write the digit links\n\t\t\tfor ($loop = $start - 1; $loop <= $end; $loop++)\n\t\t\t{\n\t\t\t\t$i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;\n\n\t\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, $loop);\n\n\t\t\t\tif ($i >= $base_page)\n\t\t\t\t{\n\t\t\t\t\tif ($this->cur_page === $loop)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Current page\n\t\t\t\t\t\t$output .= $this->cur_tag_open.$loop.$this->cur_tag_close;\n\t\t\t\t\t}\n\t\t\t\t\telseif ($i === $base_page)\n\t\t\t\t\t{\n\t\t\t\t\t\t// First page\n\t\t\t\t\t\t$output .= $this->num_tag_open.'<a href=\"'.$first_url.'\"'.$attributes.$this->_attr_rel('start').'>'\n\t\t\t\t\t\t\t.$loop.'</a>'.$this->num_tag_close;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$append = $this->prefix.$i.$this->suffix;\n\t\t\t\t\t\t$output .= $this->num_tag_open.'<a href=\"'.$base_url.$append.'\"'.$attributes.'>'\n\t\t\t\t\t\t\t.$loop.'</a>'.$this->num_tag_close;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Render the \"next\" link\n\t\tif ($this->next_link !== FALSE && $this->cur_page < $num_pages)\n\t\t{\n\t\t\t$i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;\n\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);\n\n\t\t\t$output .= $this->next_tag_open.'<a href=\"'.$base_url.$this->prefix.$i.$this->suffix.'\"'.$attributes\n\t\t\t\t.$this->_attr_rel('next').'>'.$this->next_link.'</a>'.$this->next_tag_close;\n\t\t}\n\n\t\t// Render the \"Last\" link\n\t\tif ($this->last_link !== FALSE && ($this->cur_page + $this->num_links + ! $this->num_links) < $num_pages)\n\t\t{\n\t\t\t$i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;\n\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, $num_pages);\n\n\t\t\t$output .= $this->last_tag_open.'<a href=\"'.$base_url.$this->prefix.$i.$this->suffix.'\"'.$attributes.'>'\n\t\t\t\t.$this->last_link.'</a>'.$this->last_tag_close;\n\t\t}\n\n\t\t// Kill double slashes. Note: Sometimes we can end up with a double slash\n\t\t// in the penultimate link so we'll kill all double slashes.\n\t\t$output = preg_replace('#([^:\"])//+#', '\\\\1/', $output);\n\n\t\t// Add the wrapper HTML if exists\n\t\treturn $this->full_tag_open.$output.$this->full_tag_close;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse attributes\n\t *\n\t * @param\tarray\t$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _parse_attributes($attributes)\n\t{\n\t\tisset($attributes['rel']) OR $attributes['rel'] = TRUE;\n\t\t$this->_link_types = ($attributes['rel'])\n\t\t\t? array('start' => 'start', 'prev' => 'prev', 'next' => 'next')\n\t\t\t: array();\n\t\tunset($attributes['rel']);\n\n\t\t$this->_attributes = '';\n\t\tforeach ($attributes as $key => $value)\n\t\t{\n\t\t\t$this->_attributes .= ' '.$key.'=\"'.$value.'\"';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add \"rel\" attribute\n\t *\n\t * @link\thttp://www.w3.org/TR/html5/links.html#linkTypes\n\t * @param\tstring\t$type\n\t * @return\tstring\n\t */\n\tprotected function _attr_rel($type)\n\t{\n\t\tif (isset($this->_link_types[$type]))\n\t\t{\n\t\t\tunset($this->_link_types[$type]);\n\t\t\treturn ' rel=\"'.$type.'\"';\n\t\t}\n\n\t\treturn '';\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Parser.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Parser Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tParser\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/parser.html\n */\nclass CI_Parser {\n\n\t/**\n\t * Left delimiter character for pseudo vars\n\t *\n\t * @var string\n\t */\n\tpublic $l_delim = '{';\n\n\t/**\n\t * Right delimiter character for pseudo vars\n\t *\n\t * @var string\n\t */\n\tpublic $r_delim = '}';\n\n\t/**\n\t * Reference to CodeIgniter instance\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->CI =& get_instance();\n\t\tlog_message('info', 'Parser Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a template\n\t *\n\t * Parses pseudo-variables contained in the specified template view,\n\t * replacing them with the data in the second param\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function parse($template, $data, $return = FALSE)\n\t{\n\t\t$template = $this->CI->load->view($template, $data, TRUE);\n\n\t\treturn $this->_parse($template, $data, $return);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a String\n\t *\n\t * Parses pseudo-variables contained in the specified string,\n\t * replacing them with the data in the second param\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function parse_string($template, $data, $return = FALSE)\n\t{\n\t\treturn $this->_parse($template, $data, $return);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a template\n\t *\n\t * Parses pseudo-variables contained in the specified template,\n\t * replacing them with the data in the second param\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tprotected function _parse($template, $data, $return = FALSE)\n\t{\n\t\tif ($template === '')\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$replace = array();\n\t\tforeach ($data as $key => $val)\n\t\t{\n\t\t\t$replace = array_merge(\n\t\t\t\t$replace,\n\t\t\t\tis_array($val)\n\t\t\t\t\t? $this->_parse_pair($key, $val, $template)\n\t\t\t\t\t: $this->_parse_single($key, (string) $val, $template)\n\t\t\t);\n\t\t}\n\n\t\tunset($data);\n\t\t$template = strtr($template, $replace);\n\n\t\tif ($return === FALSE)\n\t\t{\n\t\t\t$this->CI->output->append_output($template);\n\t\t}\n\n\t\treturn $template;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the left/right variable delimiters\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_delimiters($l = '{', $r = '}')\n\t{\n\t\t$this->l_delim = $l;\n\t\t$this->r_delim = $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a single key/value\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _parse_single($key, $val, $string)\n\t{\n\t\treturn array($this->l_delim.$key.$this->r_delim => (string) $val);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a tag pair\n\t *\n\t * Parses tag pairs: {some_tag} string... {/some_tag}\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _parse_pair($variable, $data, $string)\n\t{\n\t\t$replace = array();\n\t\tpreg_match_all(\n\t\t\t'#'.preg_quote($this->l_delim.$variable.$this->r_delim).'(.+?)'.preg_quote($this->l_delim.'/'.$variable.$this->r_delim).'#s',\n\t\t\t$string,\n\t\t\t$matches,\n\t\t\tPREG_SET_ORDER\n\t\t);\n\n\t\tforeach ($matches as $match)\n\t\t{\n\t\t\t$str = '';\n\t\t\tforeach ($data as $row)\n\t\t\t{\n\t\t\t\t$temp = array();\n\t\t\t\tforeach ($row as $key => $val)\n\t\t\t\t{\n\t\t\t\t\tif (is_array($val))\n\t\t\t\t\t{\n\t\t\t\t\t\t$pair = $this->_parse_pair($key, $val, $match[1]);\n\t\t\t\t\t\tif ( ! empty($pair))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$temp = array_merge($temp, $pair);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t$temp[$this->l_delim.$key.$this->r_delim] = $val;\n\t\t\t\t}\n\n\t\t\t\t$str .= strtr($match[1], $temp);\n\t\t\t}\n\n\t\t\t$replace[$match[0]] = $str;\n\t\t}\n\n\t\treturn $replace;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Profiler.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Profiler Class\n *\n * This class enables you to display benchmark, query, and other data\n * in order to help with debugging and optimization.\n *\n * Note: At some point it would be good to move all the HTML in this class\n * into a set of template files in order to allow customization.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/general/profiling.html\n */\nclass CI_Profiler {\n\n\t/**\n\t * List of profiler sections available to show\n\t *\n\t * @var array\n\t */\n\tprotected $_available_sections = array(\n\t\t'benchmarks',\n\t\t'get',\n\t\t'memory_usage',\n\t\t'post',\n\t\t'uri_string',\n\t\t'controller_info',\n\t\t'queries',\n\t\t'http_headers',\n\t\t'session_data',\n\t\t'config'\n\t);\n\n\t/**\n\t * Number of queries to show before making the additional queries togglable\n\t *\n\t * @var int\n\t */\n\tprotected $_query_toggle_count = 25;\n\n\t/**\n\t * Reference to the CodeIgniter singleton\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Initialize Profiler\n\t *\n\t * @param\tarray\t$config\tParameters\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t$this->CI =& get_instance();\n\t\t$this->CI->load->language('profiler');\n\n\t\t// default all sections to display\n\t\tforeach ($this->_available_sections as $section)\n\t\t{\n\t\t\tif ( ! isset($config[$section]))\n\t\t\t{\n\t\t\t\t$this->_compile_{$section} = TRUE;\n\t\t\t}\n\t\t}\n\n\t\t$this->set_sections($config);\n\t\tlog_message('info', 'Profiler Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Sections\n\t *\n\t * Sets the private _compile_* properties to enable/disable Profiler sections\n\t *\n\t * @param\tmixed\t$config\n\t * @return\tvoid\n\t */\n\tpublic function set_sections($config)\n\t{\n\t\tif (isset($config['query_toggle_count']))\n\t\t{\n\t\t\t$this->_query_toggle_count = (int) $config['query_toggle_count'];\n\t\t\tunset($config['query_toggle_count']);\n\t\t}\n\n\t\tforeach ($config as $method => $enable)\n\t\t{\n\t\t\tif (in_array($method, $this->_available_sections))\n\t\t\t{\n\t\t\t\t$this->_compile_{$method} = ($enable !== FALSE);\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Auto Profiler\n\t *\n\t * This function cycles through the entire array of mark points and\n\t * matches any two points that are named identically (ending in \"_start\"\n\t * and \"_end\" respectively).  It then compiles the execution times for\n\t * all points and returns it as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _compile_benchmarks()\n\t{\n\t\t$profile = array();\n\t\tforeach ($this->CI->benchmark->marker as $key => $val)\n\t\t{\n\t\t\t// We match the \"end\" marker so that the list ends\n\t\t\t// up in the order that it was defined\n\t\t\tif (preg_match('/(.+?)_end$/i', $key, $match)\n\t\t\t\t&& isset($this->CI->benchmark->marker[$match[1].'_end'], $this->CI->benchmark->marker[$match[1].'_start']))\n\t\t\t{\n\t\t\t\t$profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key);\n\t\t\t}\n\t\t}\n\n\t\t// Build a table containing the profile data.\n\t\t// Note: At some point we should turn this into a template that can\n\t\t// be modified. We also might want to make this data available to be logged\n\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_benchmarks\" style=\"border:1px solid #900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#900;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_benchmarks').\"&nbsp;&nbsp;</legend>\"\n\t\t\t.\"\\n\\n\\n<table style=\\\"width:100%;\\\">\\n\";\n\n\t\tforeach ($profile as $key => $val)\n\t\t{\n\t\t\t$key = ucwords(str_replace(array('_', '-'), ' ', $key));\n\t\t\t$output .= '<tr><td style=\"padding:5px;width:50%;color:#000;font-weight:bold;background-color:#ddd;\">'\n\t\t\t\t\t.$key.'&nbsp;&nbsp;</td><td style=\"padding:5px;width:50%;color:#900;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t.$val.\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile Queries\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_queries()\n\t{\n\t\t$dbs = array();\n\n\t\t// Let's determine which databases are currently connected to\n\t\tforeach (get_object_vars($this->CI) as $name => $cobject)\n\t\t{\n\t\t\tif (is_object($cobject))\n\t\t\t{\n\t\t\t\tif ($cobject instanceof CI_DB)\n\t\t\t\t{\n\t\t\t\t\t$dbs[get_class($this->CI).':$'.$name] = $cobject;\n\t\t\t\t}\n\t\t\t\telseif ($cobject instanceof CI_Model)\n\t\t\t\t{\n\t\t\t\t\tforeach (get_object_vars($cobject) as $mname => $mobject)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ($mobject instanceof CI_DB)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$dbs[get_class($cobject).':$'.$mname] = $mobject;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (count($dbs) === 0)\n\t\t{\n\t\t\treturn \"\\n\\n\"\n\t\t\t\t.'<fieldset id=\"ci_profiler_queries\" style=\"border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t\t.\"\\n\"\n\t\t\t\t.'<legend style=\"color:#0000FF;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries').'&nbsp;&nbsp;</legend>'\n\t\t\t\t.\"\\n\\n\\n<table style=\\\"border:none; width:100%;\\\">\\n\"\n\t\t\t\t.'<tr><td style=\"width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;\">'\n\t\t\t\t.$this->CI->lang->line('profiler_no_db')\n\t\t\t\t.\"</td></tr>\\n</table>\\n</fieldset>\";\n\t\t}\n\n\t\t// Load the text helper so we can highlight the SQL\n\t\t$this->CI->load->helper('text');\n\n\t\t// Key words we want bolded\n\t\t$highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT&nbsp;JOIN', 'ORDER&nbsp;BY', 'GROUP&nbsp;BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR&nbsp;', 'HAVING', 'OFFSET', 'NOT&nbsp;IN', 'IN', 'LIKE', 'NOT&nbsp;LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')');\n\n\t\t$output  = \"\\n\\n\";\n\t\t$count = 0;\n\n\t\tforeach ($dbs as $name => $db)\n\t\t{\n\t\t\t$hide_queries = (count($db->queries) > $this->_query_toggle_count) ? ' display:none' : '';\n\t\t\t$total_time = number_format(array_sum($db->query_times), 4).' '.$this->CI->lang->line('profiler_seconds');\n\n\t\t\t$show_hide_js = '(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_queries_db_'.$count.'\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_hide').'\\'?\\''.$this->CI->lang->line('profiler_section_show').'\\':\\''.$this->CI->lang->line('profiler_section_hide').'\\';\">'.$this->CI->lang->line('profiler_section_hide').'</span>)';\n\n\t\t\tif ($hide_queries !== '')\n\t\t\t{\n\t\t\t\t$show_hide_js = '(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_queries_db_'.$count.'\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').'</span>)';\n\t\t\t}\n\n\t\t\t$output .= '<fieldset style=\"border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t\t.\"\\n\"\n\t\t\t\t.'<legend style=\"color:#0000FF;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_database')\n\t\t\t\t.':&nbsp; '.$db->database.' ('.$name.')&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries')\n\t\t\t\t.': '.count($db->queries).' ('.$total_time.')&nbsp;&nbsp;'.$show_hide_js.\"</legend>\\n\\n\\n\"\n\t\t\t\t.'<table style=\"width:100%;'.$hide_queries.'\" id=\"ci_profiler_queries_db_'.$count.\"\\\">\\n\";\n\n\t\t\tif (count($db->queries) === 0)\n\t\t\t{\n\t\t\t\t$output .= '<tr><td style=\"width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;\">'\n\t\t\t\t\t\t.$this->CI->lang->line('profiler_no_queries').\"</td></tr>\\n\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tforeach ($db->queries as $key => $val)\n\t\t\t\t{\n\t\t\t\t\t$time = number_format($db->query_times[$key], 4);\n\t\t\t\t\t$val = highlight_code($val);\n\n\t\t\t\t\tforeach ($highlight as $bold)\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = str_replace($bold, '<strong>'.$bold.'</strong>', $val);\n\t\t\t\t\t}\n\n\t\t\t\t\t$output .= '<tr><td style=\"padding:5px;vertical-align:top;width:1%;color:#900;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t\t\t.$time.'&nbsp;&nbsp;</td><td style=\"padding:5px;color:#000;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t\t\t.$val.\"</td></tr>\\n\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$output .= \"</table>\\n</fieldset>\";\n\t\t\t$count++;\n\t\t}\n\n\t\treturn $output;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile $_GET Data\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_get()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_get\" style=\"border:1px solid #cd6e00;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#cd6e00;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_get_data').\"&nbsp;&nbsp;</legend>\\n\";\n\n\t\tif (count($_GET) === 0)\n\t\t{\n\t\t\t$output .= '<div style=\"color:#cd6e00;font-weight:normal;padding:4px 0 4px 0;\">'.$this->CI->lang->line('profiler_no_get').'</div>';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$output .= \"\\n\\n<table style=\\\"width:100%;border:none;\\\">\\n\";\n\n\t\t\tforeach ($_GET as $key => $val)\n\t\t\t{\n\t\t\t\tis_int($key) OR $key = \"'\".$key.\"'\";\n\n\t\t\t\t$output .= '<tr><td style=\"width:50%;color:#000;background-color:#ddd;padding:5px;\">&#36;_GET['\n\t\t\t\t\t.$key.']&nbsp;&nbsp; </td><td style=\"width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t.((is_array($val) OR is_object($val)) ? '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>' : htmlspecialchars(stripslashes($val)))\n\t\t\t\t\t.\"</td></tr>\\n\";\n\t\t\t}\n\n\t\t\t$output .= \"</table>\\n\";\n\t\t}\n\n\t\treturn $output.'</fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile $_POST Data\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_post()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_post\" style=\"border:1px solid #009900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#009900;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data').\"&nbsp;&nbsp;</legend>\\n\";\n\n\t\tif (count($_POST) === 0 && count($_FILES) === 0)\n\t\t{\n\t\t\t$output .= '<div style=\"color:#009900;font-weight:normal;padding:4px 0 4px 0;\">'.$this->CI->lang->line('profiler_no_post').'</div>';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$output .= \"\\n\\n<table style=\\\"width:100%;\\\">\\n\";\n\n\t\t\tforeach ($_POST as $key => $val)\n\t\t\t{\n\t\t\t\tis_int($key) OR $key = \"'\".$key.\"'\";\n\n\t\t\t\t$output .= '<tr><td style=\"width:50%;padding:5px;color:#000;background-color:#ddd;\">&#36;_POST['\n\t\t\t\t\t.$key.']&nbsp;&nbsp; </td><td style=\"width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;\">';\n\n\t\t\t\tif (is_array($val) OR is_object($val))\n\t\t\t\t{\n\t\t\t\t\t$output .= '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$output .= htmlspecialchars(stripslashes($val));\n\t\t\t\t}\n\n\t\t\t\t$output .= \"</td></tr>\\n\";\n\t\t\t}\n\n\t\t\tforeach ($_FILES as $key => $val)\n\t\t\t{\n\t\t\t\tis_int($key) OR $key = \"'\".$key.\"'\";\n\n\t\t\t\t$output .= '<tr><td style=\"width:50%;padding:5px;color:#000;background-color:#ddd;\">&#36;_FILES['\n\t\t\t\t\t.$key.']&nbsp;&nbsp; </td><td style=\"width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;\">';\n\n\t\t\t\tif (is_array($val) OR is_object($val))\n\t\t\t\t{\n\t\t\t\t\t$output .= '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>';\n\t\t\t\t}\n\n\t\t\t\t$output .= \"</td></tr>\\n\";\n\t\t\t}\n\n\t\t\t$output .= \"</table>\\n\";\n\t\t}\n\n\t\treturn $output.'</fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show query string\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_uri_string()\n\t{\n\t\treturn \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_uri_string\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_uri_string').\"&nbsp;&nbsp;</legend>\\n\"\n\t\t\t.'<div style=\"color:#000;font-weight:normal;padding:4px 0 4px 0;\">'\n\t\t\t.($this->CI->uri->uri_string === '' ? $this->CI->lang->line('profiler_no_uri') : $this->CI->uri->uri_string)\n\t\t\t.'</div></fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show the controller and function that were called\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_controller_info()\n\t{\n\t\treturn \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_controller_info\" style=\"border:1px solid #995300;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#995300;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_controller_info').\"&nbsp;&nbsp;</legend>\\n\"\n\t\t\t.'<div style=\"color:#995300;font-weight:normal;padding:4px 0 4px 0;\">'.$this->CI->router->class.'/'.$this->CI->router->method\n\t\t\t.'</div></fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile memory usage\n\t *\n\t * Display total used memory\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_memory_usage()\n\t{\n\t\treturn \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_memory_usage\" style=\"border:1px solid #5a0099;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#5a0099;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_memory_usage').\"&nbsp;&nbsp;</legend>\\n\"\n\t\t\t.'<div style=\"color:#5a0099;font-weight:normal;padding:4px 0 4px 0;\">'\n\t\t\t.(($usage = memory_get_usage()) != '' ? number_format($usage).' bytes' : $this->CI->lang->line('profiler_no_memory'))\n\t\t\t.'</div></fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile header information\n\t *\n\t * Lists HTTP headers\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_http_headers()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_http_headers\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_headers')\n\t\t\t.'&nbsp;&nbsp;(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_httpheaders_table\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').\"</span>)</legend>\\n\\n\\n\"\n\t\t\t.'<table style=\"width:100%;display:none;\" id=\"ci_profiler_httpheaders_table\">'.\"\\n\";\n\n\t\tforeach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR', 'HTTP_DNT') as $header)\n\t\t{\n\t\t\t$val = isset($_SERVER[$header]) ? $_SERVER[$header] : '';\n\t\t\t$output .= '<tr><td style=\"vertical-align:top;width:50%;padding:5px;color:#900;background-color:#ddd;\">'\n\t\t\t\t.$header.'&nbsp;&nbsp;</td><td style=\"width:50%;padding:5px;color:#000;background-color:#ddd;\">'.$val.\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile config information\n\t *\n\t * Lists developer config variables\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_config()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_config\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_config').'&nbsp;&nbsp;(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_config_table\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').\"</span>)</legend>\\n\\n\\n\"\n\t\t\t.'<table style=\"width:100%;display:none;\" id=\"ci_profiler_config_table\">'.\"\\n\";\n\n\t\tforeach ($this->CI->config->config as $config => $val)\n\t\t{\n\t\t\tif (is_array($val) OR is_object($val))\n\t\t\t{\n\t\t\t\t$val = print_r($val, TRUE);\n\t\t\t}\n\n\t\t\t$output .= '<tr><td style=\"padding:5px;vertical-align:top;color:#900;background-color:#ddd;\">'\n\t\t\t\t.$config.'&nbsp;&nbsp;</td><td style=\"padding:5px;color:#000;background-color:#ddd;\">'.htmlspecialchars($val).\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile session userdata\n\t *\n\t * @return \tstring\n\t */\n\tprotected function _compile_session_data()\n\t{\n\t\tif ( ! isset($this->CI->session))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$output = '<fieldset id=\"ci_profiler_csession\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_session_data').'&nbsp;&nbsp;(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_session_data\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').'</span>)</legend>'\n\t\t\t.'<table style=\"width:100%;display:none;\" id=\"ci_profiler_session_data\">';\n\n\t\tforeach ($this->CI->session->userdata() as $key => $val)\n\t\t{\n\t\t\tif (is_array($val) OR is_object($val))\n\t\t\t{\n\t\t\t\t$val = print_r($val, TRUE);\n\t\t\t}\n\n\t\t\t$output .= '<tr><td style=\"padding:5px;vertical-align:top;color:#900;background-color:#ddd;\">'\n\t\t\t\t.$key.'&nbsp;&nbsp;</td><td style=\"padding:5px;color:#000;background-color:#ddd;\">'.htmlspecialchars($val).\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the Profiler\n\t *\n\t * @return\tstring\n\t */\n\tpublic function run()\n\t{\n\t\t$output = '<div id=\"codeigniter_profiler\" style=\"clear:both;background-color:#fff;padding:10px;\">';\n\t\t$fields_displayed = 0;\n\n\t\tforeach ($this->_available_sections as $section)\n\t\t{\n\t\t\tif ($this->_compile_{$section} !== FALSE)\n\t\t\t{\n\t\t\t\t$func = '_compile_'.$section;\n\t\t\t\t$output .= $this->{$func}();\n\t\t\t\t$fields_displayed++;\n\t\t\t}\n\t\t}\n\n\t\tif ($fields_displayed === 0)\n\t\t{\n\t\t\t$output .= '<p style=\"border:1px solid #5a0099;padding:10px;margin:20px 0;background-color:#eee;\">'\n\t\t\t\t.$this->CI->lang->line('profiler_no_profiles').'</p>';\n\t\t}\n\n\t\treturn $output.'</div>';\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/README.php",
    "content": "<?php\n\n$content='Talk about your understanding of closures\n\nUsing closures designed primarily to private methods and variables. Closure advantage of global variables are avoided contamination, the disadvantage is the closure will be permanent memory, the memory usage increases, improper use is likely to cause a memory leak.\n\nClosures have three characteristics:\n\n1. Function 2. The internal function nested function can refer to external parameters and variables 3. The parameters and variables will not be garbage collection mechanism Recycling\nYou talk about the shortcomings of Cookie\n\ncookie Although persistent client data to provide a convenient, sharing the burden of server storage, but there are still many limitations. Generates up to 20 under each specific domain: the first cookie\n\n1.IE6 or earlier up to 20 cookie \n2.IE7 later version and last may have 50 cookie. \n3.Firefox up to 50 cookie \n4.chrome and Safari does not do hard limit\nIE and Opera will clean up the least recently used cookie , Firefox will randomly to clean cookie .\n\ncookie maximum of approximately 4096 bytes, for compatibility, generally can not exceed 4095 bytes.\n\nIE can provide a way to store persistent user data, called UserData , from IE5.0 has supported. Each data up to 128K, under each domain up to 1M. The persistent data in the cache, if not cleaned the cache, it will always exist.\n\nAdvantages: high scalability and availability\n\n1. Good programming, control the size of the session cookie stored in the object. \n2. encryption and secure transmission technology (SSL), to reduce the possibility of cookie to crack. \n3. Only non-sensitive data is stored in a cookie, even if stolen will not have significant losses. \n4. Control cookie lifetime, so it will not always be effective. Theft are likely to get an expired cookie.\nDisadvantages:\n\n1.`Cookie` limit the number and length. Each domain can have a maximum of 20 cookie, each cookie length can not exceed 4KB, otherwise it will be truncated. \n\n2. The security issues. If the cookie is intercepted, that person can get all the session information. Even if encryption is also unhelpful, because Interceptor does not need to know the meaning of the cookie, cookie forwarding as long as he can achieve their goals. \n\n3. Some state can not be stored in the client. For example, in order to prevent duplicate submission form, we need to save a counter on the server side. If we put this counter is stored in the client, then it will not achieve any effect.\nBrowser local storage\n\nIn later versions of the browser, JS provides sessionStorage and globalStorage . In HTML5 provides in localStorage to replace globalStorage .\n\nhtml5 The Web Storage includes two storage methods: sessionStorage and localStorage .\n\nsessionStorage data stored locally for a session (session) in which the data only in the same session of the page to access data, and when the end of the session also will be destroyed. So sessionStorage not a persistent local storage, just session-level storage.\n\nAnd localStorage for persistent local storage, unless the initiative to remove the data, or the data is never out of date.\n\nthe difference between web storage and a cookie\n\nWeb Storage concept and cookie similar, except that it is designed for higher-capacity storage. Cookie size is limited, and every time you request a new page when the Cookie will be sent in the past, so that virtually waste bandwidth, another cookie also need to specify the scope, not cross-domain calls.\n\nIn addition, Web Storage has setItem, getItem, removeItem, clear methods, unlike the cookie front-end developers need their own package setCookie, getCookie .\n\nBut the cookie is not indispensable: cookie 's role is to interact with the server as HTTP part of the specification exists, and Web Storage simply to the local \"store\" raw data\n\nBrowser support in addition to IE7 and below are not supported, other standard browsers fully support (ie and FF need to run a web server in), it is worth mentioning that IE always good things, such as IE7, IE6 in the userData fact is javascript local storage solutions. By simple code package can be unified to all the browsers support Web storage .\n\nlocalStorage and sessionStorage have the same method of operation, for example setItem, getItem and removeItem etc.\n\ncookie and session distinction:\n\n1, cookie data is stored on the customer's browser, session data on the server. \n 2, cookie is not very safe, others can be analyzed at a local store and COOKIE COOKIE cheat \n    should be used taking into account the security session. \n 3, session will be within a certain time saved on the server. When accessing the increase, it would be more occupy the performance of your server \n     consider to reduce server performance, you should use COOKIE. \n 4, the data stored in a single cookie can not exceed 4K, many browsers are limited to a maximum of one site to save 20 cookie. \n 5, so personal recommendations: \n    the login information and other important information is stored as SESSION \n    additional information, if necessary, it can be placed in COOKIE\nCSS-related issues\n\ndisplay: none and visibility: hidden difference?\n\ndisplay: none to hide the corresponding elements in the document layout is no longer space allocated to it, it is the element of each side will be closed, \non when he never existed. \n\nvisibility: hidden hides the corresponding elements, but still retain the original layout of the space in the document.\nThe difference in the link andimport CSS is?\n\n(1) link belong to HTML tags, and CSSimport is provided; \n(2) the page is loaded, link will also be loaded, but referencesimport CSS will wait until the page is finished loading reloading; \n(3) Import only to recognize in IE5 or more, while link is HTML tag, no compatibility issues; \nstyle right (4) linkimport way of weight above the weight of heavy.\nSimilarities and Differences between absolute and float attributes: position\n\nA: common: \ninline element set `float` and` absolute` property allows elements from the document flow, and can set its width and height. \n\nB: Different point: \nfloat will still occupy the position, position overrides other elements in the document flow.\nIntroduce the box-sizing property?\n\nbox-sizing property is primarily used to control element analytical model box model. The default value is content-Box .\n\ncontent-Box : Let element to maintain the standard W3C box model. Width / height of the element / height is determined by the border + padding + content width, set width / height attribute refers to the content portion of the width / height\n\nborder-Box : Let element to maintain the traditional box model IE (IE6 and IE6 ~ 7 the following versions of quirks mode). Set width / height attribute refers to the border + padding + content\n\nUnder standard browser, according to W3C box model specification analysis, once the border or modify the elements within distance, it will affect the size of the box element, you have to recalculate the box the size of the elements, thus affecting the layout of the entire page.\n\nCSS selectors are there? Which attributes can be inherited? Priority algorithm calculated? Added CSS3 pseudo-classes are those?\n\n1.id selector (# myid) \n2. Class selector (.myclassname) \n3. Tag selectors (div, h1, P) \n4. adjacent selector (h1 + P) \n5. child selector (ul> li ) \n6. descendant selectors (li a) \n7. wildcard selector (*) \n8. attribute selector (a [rel = \"external\"]) \n9. pseudo-class selectors (a: hover, li: nth-child)\nInheritable style: font-size font-family color, text-indent;\n\nNon Inherited Styles: border padding margin width height;\n\nPriority under the principle of proximity, with weights whichever the case recently defined style;\n\nLoading last loaded positioning styles to prevail;\n\nPriority:\n! Important> ID> class> tag   \n\nImportant priority higher than inline, inline but higher than the id\nAdded CSS3 pseudo-class examples:\np: first-of-type select each <p> element belongs to the first element of its parent <p> element. \np: last-of-type select each <p> element belongs to its parent last <p> element. \np: only-of-type select each <p> element belongs to its parent element only <p> elements. \np: only-child selects each <p> element belongs to its parent element only child element. \np: nth-child (2) Select each <p> element belongs to the parent element of the second sub-element. \n: Enabled: disabled control form control disabled. \n: Checked radio button or checkbox is selected.\nposition values, relative and absolute are positioned with respect to whom?\n\nabsolute \n        generate absolute element positioned relative to the recent level is not static positioned parent element to be positioned. \n\nfixed (old IE does not support) \n    to generate absolute element positioned relative to the browser window positioning. \n\nrelative \n    generating element relative positioning, relative to its position in the general stream positioning. \n\nstatic default. No positioning element occurs in the normal stream\nCSS3 What's new?\n\nCSS3 rounded corners (border-radius), shadow (box-shadow), \nadd special effects to the text (text-shadow,), a linear gradient (gradient), rotation (transform) \ntransform: Rotate (9deg) Scale (0.85,0.90) translate (0px, -30px) skew (-9deg, 0deg); // rotation, scaling, positioning, tilt \nadds more CSS selectors more background rgba \nunique introduced in CSS3 pseudo-elements :: selection. \nMedia queries , multi-column layout \nborder-image\nXML and JSON difference?\n\n(1) The data volume terms. \nXML JSON relative terms, the volume of data is small, the speed of delivery faster. \n(2) aspects of data exchange. \nJSON and JavaScript interaction more convenient and easier to parse processing, better data interaction. \n(3) The data described aspects. \nJSON description of data than XML poor. \n(4) The transmission speed. \nJSON's speed is much faster than XML.\nBFC norms of understanding?\n\n      BFC, block-level formatting context, a BFC created a new box is an independent layout, style, child elements inside the box will not affect the outside elements. In the same BFC two adjoining block-level box in the vertical direction (the direction of a relationship and layout) of margin will collapse from happening. \n    (A concept W3C CSS 2.1 specification, which determines how the elements in the layout of its contents, and its relationship with other elements and interactions.)\nUnder explain CSS sprites, and how you want to use it in a page or site.\n\nCSS Sprites in fact, the number of pages in the background image into an image file, and then use the CSS \"background-image\", \"background- repeat\", \"background-position\" a combination of background positioning, background-position can be used Digital can accurately locate the position of the background image. This can reduce the cost of many pictures request because the request takes a relatively long; although requests can be complicated, but there are limits, are six general browser. For the future, there is no need to do so, and because of `http2`.\nhtml part\n\nTalk about your understanding of the semantic?\n\n1, removed or lost when allowing page style showing clear structure \n2, is conducive to SEO: search engines and to establish good communication helps crawlers to crawl more useful information: reptiles rely on labels to determine the context and the individual right keyword weight; \n3, easy to resolve other devices (such as a screen reader, blind readers, mobile devices) in meaningful ways to render web pages; \n4, easy to team development and maintenance, more readable semantic, is under Important Trends step right of the page, follow the W3C standards team follow this standard, the difference can be reduced.\nDoctype role? Strict mode and mixed mode how to distinguish? They mean?\n\n(1), <! DOCTYPE> declaration in the document in the front, in the <html> tag before. Tells the browser to render the document in which mode. \n\n(2) strict mode layout and JS mode of operation is based on the highest standards of the browser supports running. \n\n(3), in promiscuous mode, page backward compatible with liberal display. Simulate the behavior of older browsers do not work to prevent the site. \n\n(4), DOCTYPE does not exist or incorrectly formatted document will lead to promiscuous mode rendering.   \nDo you know how many document types Doctype?\n\nThe label can be declared DTD three types, respectively strict version, interim version and an HTML-based documentation framework. \n HTML 4.01 specifies three document types: Strict, Transitional, and Frameset. \n XHTML 1.0 specifies three XML document types: Strict, Transitional, and Frameset. \nStandards (standard) mode (that is, in strict rendering mode) complies with the latest standards for rendering Web pages, while Quirks \n (inclusive) mode (that is, loose rendering mode or compatibility mode) is used to render conventional web browser designed.\nHTML and XHTML-- What is the difference between the two\n\nDifference: \n1. All tags must have a corresponding end tag \nelement and attribute names 2. All tags must be lowercase \n3. All the XML tags must be properly nested \n4. All attributes must be quoted. \" \"enclosed \n5. Put all the <and & special symbols with the coded representation \n6. assign a value to all of the properties \nin the comment 7. Do not manipulation \"-\" \n8. The image must have caption\nCommon compatibility problems?\n\n* Png24 bit image appears on iE6 browser background, the solution is made ​​PNG8. It can refer to a script processing. \n\n* The browser's default margin and padding. The solution is to add a global * {margin: 0; padding: 0;} to unify. \n\n* IE6 bilateral Distance bug: After the block attribute labels float, there are rampant margin circumstances, in ie6 show larger margin than the settings. \n\n* Double ie generated from the float (IE6 bilateral distance problem: In IE6, if the element is set to float, while setting the margin-left or margin-right, margin value will double.) \n  #box {float: left; width: 10px; margin: 0 0 0 100px;} \n\n Under such circumstances IE will produce 20px distance, the solution is to add --_ display in the label style float control: inline; be converted to inline property. (_ This symbol identifies only ie6) \n\n* gradual recognition of the way from the local population gradually excluded. \n\n  First, the clever use of \"\\ 9\" This marks the IE's browser separated out from all the circumstances. \n  Then, again using the \"+\" to IE8 and IE7, IE6 separated, so that IE8 has been independently identified. \n\n  CSS \n      .bb { \n       background-color: # f1ee18; / * All identification * / \n      .background-color: # 00deff \\ 9; / * IE6,7,8 identification * / \n      + background-color: # a200ff; / * IE6, 7 Identification * / \n      _background-color: # 1e0bd1; / * IE6 recognition * / \n      } \n\n* under IE, you can use the method to get the general properties for custom properties, \n   you can also use getAttribute () Gets the custom attributes; \n   under Firefox, only Use getAttribute () Gets custom attributes. \n   Workaround: Uniform for custom properties through getAttribute (). \n\n* Under IE, event object has x, y attributes, but no pageX, pageY property; \n  under Firefox, event object has pageX, pageY property, but there is no x, y properties. \n\n* Solution :( conditional comments) drawback is that in IE browser may add additional HTTP requests. \n\n* Under Chrome Chinese interface will be smaller than default to force the 12px 12px text display, \n  by the addition of CSS properties -webkit-text-size-adjust: none; resolved. \n\n* After hover style is not accessible by hyperlink is clicked appears visited The Hyperlink style does not have hover and active the solution is to change the order of CSS properties: \nLVHA: a: link {} a: visited {} a: hover {} a: Active {} \n\n* weird modalities: Leakage write DTD statement, Firefox will still be in accordance with the standard model to resolve the page, but IE will trigger quirks mode. To avoid quirks mode gives us unnecessary trouble, it is best to develop the good habit of writing DTD declaration. You can now use [html5] (http://www.w3.org/TR/html5/single-page.html) recommended notation: `<DOCTYPE html>` \n\n* top and bottom margin overlap problem \nie and ff are present, adjacent both margin-left and margin-right does not coincide div, but margin-top and margin-bottom but it will coincide occur. \nSolution, to develop good coding habits, while using margin-top or while using margin-bottom. \n* Ie6 png image format support is not good for (quote a script processing)\nFloating and explain how it works? Clear float tips\n\nFloating elements from the document flow, does not occupy space. Floats across the border to stay its borders contain or floating elements. \n\n1. Clear float with an empty label. \n   This method is to add an empty label definition css clear in all floating behind the label: both the disadvantages is to increase the meaningless labels. \n2. Use the overflow. \n   To a parent tag contains floating elements add css property overflow: auto; zoom: 1; zoom: 1 for compatibility with IE6. \n3. Use after pseudo remove floating objects. \n   This method applies only to non-IE browsers. Specific wording may refer to the following examples. Use should pay attention to the following points. First, the method must be set to clear the height of the floating element's pseudo-objects: 0, otherwise the element will be much higher than the actual number of pixels;\nProblems caused by floating elements and solutions?\n\nProblems caused by the floating elements: \n\n(1) height of the parent element can not be softened, peer influence and elements of the parent element \n(2) and non-floating elements floating element siblings (inline elements) will follow thereafter \n(3) if not the first element of float, then that element is also required before the float, otherwise it will affect the structure of the page displayed\nWorkaround: use CSS in Clear: Both ; attribute to clear floating elements 2,3 resolve the problem, the problem 1, add the following styles to parent element Add clearfix style:\n\n.clearfix: after {content:; display \".\": Block; height: 0; Clear: Both; visibility: hidden;} \n.clearfix {display: inline-Block;} / * for IE / Mac * /\nClear float several ways:\n\n1, additional labeling, <div style = \"clear: both;\"> </ div> (disadvantage: But this approach would cause additional HTML tag structure looks simple enough) \n2, use after pseudo-class \n\n#parent: after { \n    content:; \".\" \n    height: 0; \n    visibility: hidden; \n    display: Block; \n    Clear: Both; \n    } \n\n3, floating external element \n4, is set to `hidden`` overflow` or auto\nIE 8 the following versions of the browser box model What is the difference\n\nThe following box model IE8 browser's width and height defined elements does not include padding and border\nDOM manipulation - how to add, remove, move, copy, create, and find nodes.\n\n(1) Create a new node \n\n      createDocumentFragment () // Create a DOM fragment \n\n      createElement () // create a specific element \n\n      createTextNode () // Create a text node \n\n(2) to add, remove, replace, insert \n\n      appendChild () \n\n      removeChild ( ) \n\n      replaceChild () \n\n      insertBefore () // before the existing child node into a new child node \n\n(3) Find \n\n      getElementsByTagName () // by tag name \n\n      getElementsByName () // by the value of the Name property of the element (IE fault tolerance Strong, will be an array, including name id equal value) \n\n      getElementById () // by elemental Id, uniqueness\nWhat's new html5, removing those elements? How to deal with a new label HTML5 browser compatibility problems? How to distinguish between HTML and HTML5?\n\n* HTML5 now is not a subset of SGML, mainly to increase with respect to the image, location, storage, multi-tasking and other features. \n\n* Drag release (Drag and drop) API \n  semantic content better label (header, nav, footer, aside, article, section) \n  audio, video, API (audio, video) \n  canvas (Canvas) API \n  geography (Geolocation) API \n  Local localStorage offline storage for long term storage of data, the browser is closed after data is not lost; \n  sessionStorage of data after the browser is closed automatically delete \n\n  form controls, calendar, date, time, email, url, search   \n  WebWorker new technologies, websocket, Geolocation \n\n* Remove The elements of \n\nthe element of pure performance: basefont, big, center, font, s, strike, tt, u; \n\nadversely affect the availability of the elements of: frame, frameset, noframes; \n\nsupport HTML5 new label: \n\n* IE8 / IE7 / IE6 support through document.createElement method of producing labels, \n  can use this feature to allow these browsers support HTML5 new label, \n\n  after the browser to support the new label, you also need to add tags default style: \n\n* Of course, the best way is the direct use of mature framework, use the most is html5shim framework \n   <-! [if lt IE 9]> \n   <Script> src = \"http://html5shim.googlecode.com/svn/trunk/html5.js\" </ Script> \n   <[ENDIF]! -> \nHow to distinguish: DOCTYPE declaration \\ new structural elements \\ functional elements\niframe advantages and disadvantages?\n\n: 1.` <iframe> `merit \n\n    solve slow to load third-party content such as icons and advertisements of loading problems \n    Security sandbox \n    parallel load script \n\nshortcomings 2.` <iframe> `are: \n\n\n    * iframes clog Onload event of the main page; \n\n    * Instant content is empty, it takes time to load \n    * no semantics\nHow to communicate within the browser between multiple tabs?\n\nCall localstorge, cookies and other local storage\nThe difference between threads and processes\n\nA program has at least one process, a process has at least one thread. \ndivided scale smaller than the thread process, making multi-threaded program concurrency high. \nIn addition, the process has a separate memory unit in the implementation process, and multiple threads shared memory, thereby greatly enhancing the operational efficiency of the program. \nThreads in the implementation process and the process is still a difference. Each has a separate thread running entry, exit sequence and procedure execution order. But the thread is not able to perform independent, it must exist according to the application, providing multiple threads of execution is controlled by the application. \nFrom a logical point of view, the significance of a multi-threaded application, there are a plurality of the operative part can execute simultaneously. But the operating system is not seen as multiple threads multiple independent applications to achieve scheduling and management and resource allocation process. This is an important distinction between processes and threads.\nHow do you document and optimize resource site?\n\nExpect solutions include: \n file merge \n file Minimize / file compression \n using CDN hosted \n cache usage (multiple domain names to provide caching) \n Other\nPlease name three reduce page load time.\n\n1. Optimize image \n 2. Select the image format (GIF: color offered fewer colors used in some of the less demanding areas) \n 3. Optimize CSS (compression merge css, such as margin-top, margin-left ... ) \n 4. slash site (eg www.campr.com/ directory, will determine the \"directory what file type or directory.) \n 5. indicate the height and width (if the browser does not find these two parameters, It needs to calculate the size of one side while downloading pictures, if the picture a lot, browsers need to constantly adjust the page. This will not only affect the speed, but also affect browsing experience. \nWhen the browser know the height and width parameters, even if the picture is temporarily unable to display the page will make pictures of space, and then continue to load the contents back thus loading time faster browsing experience is better.) \n\n6. To reduce http requests (merge files, merge pictures).\nWhich tools you use to test the performance of the code?\n\nProfiler, JSPerf (http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout), Dromaeo\nWhat is FOUC (free style content flicker)? How do you avoid FOUC?\n\nFOUC - Flash Of Unstyled Content document style flashing \n <style type = \"text / css\" media = \"all\"> @ import \"../ fouc.css\"; </ style> \nimport CSS file and references that is causing the problem the culprit. IE will first load the DOM entire HTML document, and then go to import external CSS files, so the page DOM has finished loading content into CSS import is completed there will be a time in the middle on the page is not the style, the length of this period of time with network speed, computer speed have a relationship. \n Workaround surprisingly simple, as long as between the <head> add a <link> or <script> element on it.\nnull and undefined difference?\n\nnull is a \"no,\" the object representation when converted to a value of 0; undefined is a indicating \"no,\" the original value when converted value NaN .\n\nWhen the variable declaration has not been initialized, the default variable is undefined . null object has not been used to indicate the presence, used to represent the function attempts to return an object that does not exist.\n\nundefined means \"missing value\", that is where it should have a value, but not yet defined. Typical usage is:\n\n(1) variable is declared, but no assignment, it means undefined. \n\n(2) When you call the function, the parameters should be provided not provided, this parameter is equal to undefined. \n\n(3) The object has no assignment of property, which is undefined. \n\n(4) function does not return a value, the default returns undefined.\nnull means \"no object\", ie where there should be no value. Typical usage is:\n\n(1) as a function of the parameters, it indicates that the function of the parameter is not an object. \n\n(2) as the end point of the object's prototype chain.\nWhat specific new operator did it?\n\n   1. Create an empty object, and this variable refers to the object, but also inherited the prototype of the function. \n   2, attributes and methods are added to this reference object. \n   3, the newly created object referenced by this, and the last implicit return this. \n\nvar obj = {}; \nobj .__ proto__ = Base.prototype; \nBase.call (obj);\njs lazy loading options?\n\ndefer and async, dynamically created DOM mode (create script, is inserted into the DOM, after loading is completed callBack), asynchronous load demand js\nHow to solve cross-border issues?\n\n    jsonp, document.domain + iframe, window.name, window.postMessage proxy server settings on the page, \n\nJSONP principle is dynamically inserted script tag\nFor details, see: Detailed js cross-border issues\n\nand innerHTML of difference documen.write\n\ndocument.write only redraw the entire page \n\ninnerHTML can redraw part of a page\n.call () and .apply () and the difference between the role?\n\nRole: dynamically changing operating environment of a method of a class. See the difference: JavaScript study summary (iv) function function section\n\nWhat action will cause a memory leak?\n\nA memory leak means any object is no longer owned or persists after you need it. \nGarbage collector periodically scans the object, and calculate the number of references to other objects of each object. If an object reference number is 0 (no references to other objects through the object), or only a reference to the object is circular, then the object's memory can be recovered. \n\nThe first parameter setTimeout function using strings instead of words, can cause a memory leak. \nClosures, console log, cycling (at two object references to each other and each other to retain, it will generate a cycle)\nSee: Detailed js variables, scopes and memory\n\nJavaScript variable declarations in scope and upgrade?\n\nSee: Detailed JavaScript function mode\n\nHow to determine the current script to run in the browser or node environment?\n\nGlobal objects by judging whether the window, if not for the window, the current script is not running in the browser\nOther questions?\n\nHave you ever had more difficult technical problem? How did you solve it?\n\nLists and other browsers are not the same characteristics IE?\n\nWhat is graceful degradation and progressive enhancement?\n\nGraceful degradation: Web sites can work in all modern browsers, if you are using an older browser, the code checks to confirm whether they can work properly. Due to the unique IE box model layout issues, for different versions of the IE hack practiced graceful degradation, and increase candidate solutions for those who can not support the browser, so that the legacy browser to experience some form but not downgrade completely ineffective. \n\nProgressive enhancement: from the basic functions are supported by all browsers start, gradually add that only a modern browser supported features, additional styles to the page on the basis of sound and features of the browser. When the browser support, they will be presented automatically and play a role.\nSee: CSS study summarized (a)\n\nWEB application from the server to the client Data initiative to push those ways?\n\nJavascript data push\n\nCommet: HTTP long connection based server push technology\n\nPush program based WebSocket\n\nSSE (Server-Send Event): new ways to push data server\nFront-end interface for this post is how engineers understood? It is the prospect of what would happen?\n\nThe front is the most close to the user's programmers are closer than the back-end database, product manager, operations, safety. \n    1, to achieve interactive interface \n    2, to enhance the user experience \n    3, with Node.js, the front end can achieve some of the things the service side of \n\n\nthe front end is closest to the user's programmers, the ability of the front end is to make the product evolved from 90 points to 100 points, even better \n\n involved in the project, to complete the implementation of high-quality renderings fast, accurate to 1px; \n\n , UI design, product manager of communication with team members; \n\n good page structure, page reconstruction and user experience; \n\n processing hack, compatible, write beautiful code format; \n\n optimized for the server, embracing the latest front-end technology.\nWhat are your ways to optimize performance?\n\n( For more details, please see Yahoo 14 performance optimization principle ).\n\n  (1) reduce the number of requests http: CSS Sprites, JS, CSS source code compression, image size control is appropriate; page Gzip, CDN hosting, data caching, image server. \n\n  (2) front-end template JS + data, reduce wasted bandwidth due HTML tags caused the front end with a variable holds AJAX request, before each operation a local variable, not a request to reduce the number of requests \n\n  (3) instead of using innerHTML DOM operations, reducing the number of operations DOM and optimize javascript performance. \n\n  (4) When the style you want to set a lot of time to set className instead of directly operating style. \n\n  (5) less global variables, DOM node cache lookup results. Reducing the IO read operations. \n\n  (6) avoid the use of CSS Expression (css expression), also known as Dynamic properties (dynamic properties). \n\n  (7) Pictures preloaded style sheet on top, plus a timestamp at the bottom of the script.\nDetails: http://segmentfault.com/blog/trigkit4/1190000000691919\n\nA page is loaded from the URL to the page display input is completed, the process what happened?\n\n    Divided into four steps: \n    (1) when sending a URL request, regardless of whether the URL is the URL of each resource on the Web page URL, or Web page, the browser will open a thread to handle the request, while in remote DNS Start a DNS query on the server. This enables the browser to get requests the corresponding IP address. \n    (2), the browser and the remote Web server through TCP three-way handshake negotiation to establish a TCP / IP connection. The handshake includes a synchronous packet, one sync - reply message and a reply message, these three packets transmitted between the browser and the server. The handshake first attempts by the client to establish communication, then the server response and to accept the request of the client, the last issue of the request has been accepted by the client packets. \n    (3) Once the TCP / IP connection is established, the browser sends an HTTP GET request to a remote server over the connection. Remote server to find the resources and the use of HTTP response back to the resource, HTTP response status value of 200 represents a correct response. \n    (4) In this case, Web servers provide resources and services, the client begins to download resources. \n\nAfter the request returns, they entered the front-end module of our attention \nsimply, the browser will parse the HTML generated DOM Tree, secondly generated according to CSS CSS Rule Tree, and javascript and can manipulate DOM DOM API\nDetails: What happened to the process from entering the URL in the browser receives?\n\nUsually how to manage your project?\n\nAdvance team must determine a good global style (globe.css), coding mode (utf-8) and the like; \n\n        coding habits must be consistent (for example, are based on the inherited type of writing, all written in a single line style); \n\n        to prepare people dimension styles, each module They are promptly labeled (labeled key style local calls); \n\n        annotate pages (page modules such as start and end); \n\n        CSS with HTML parallel sub-folder storage, had named Unity (such as style.css); \n\n        JS points in folders named JS function subject to the English translation. \n\n        Images.png png8 format pictures with an integrated use of integrated and easy to use as possible future management\nMost popular talk recently something, right? Which sites frequented?\n\nNode.js, Mongodb, npm, MVVM, MEAN, three.js, React. \nWebsite: w3cfuns, sf, hacknews, CSDN, Mu classes, blog garden, InfoQ, w3cplus etc.\nSeveral ways to create a javascript object\n\n1, factory mode \n2, the constructor mode \n3, the prototype mode \n4, mixing the constructor and prototype mode \n5, the dynamic prototype model \n6, the parasitic constructor mode \n7, sound constructor mode\n6 ways inherited javascript\n\n1, the prototype inheritance chain \n2, to borrow the constructor inherited \n3, a combination of inheritance (Prototype + loan structure) \n4, prototype inherited, \n5, Parasitic succession \n6, parasitic combined inheritance\nDetails: Detailed JavaScript inheritance\n\najax process\n\n(1) create XMLHttpRequest object, the object is to create an asynchronous call. \n\n(2) create a new HTTP request, and specify the method of the HTTP request, URL and authentication information. \n\n(3) Set the response function HTTP request status changes. \n\n(4) sends an HTTP request. \n\n(5) to obtain the asynchronous call returns the data. \n\n(6) using JavaScript and DOM implementations partial refresh.\nDetails: JavaScript study summary (vii) Ajax and Http Status Word\n\nAsynchronous loading and delayed loading\n\n1. asynchronous loading of programs: dynamically inserted script tag \n2. js code to get through ajax, then performed by eval \nadding defer the 3.script tag or async attribute \n4. Create and insert the iframe, it asynchronous execution JS \n5. delay loading : Some js code is not initialized when the page immediately need, and only later in certain circumstances require.\nFront-end security issues?\n\nsql injection principle\n\nIt is through the SQL commands into Web form submit or enter the domain name or page request query string, and ultimately achieve deceive server to execute malicious SQL commands.\n\nIn general the following points:\n\n1. Never trust user input, to check for user input, you can use regular expressions, or limit the length of the single and double \"-\" in conversion. \n2. Never use dynamic assembly SQL, you can use parameterized SQL or stored procedures directly access data query. \n3. Never use administrator privileges database connection, use limited individual permissions for each application database connection. \n4. Do not put the confidential information stored in clear text, please encryption or hash out passwords and sensitive information.\nXSS principle and Prevention\n\nXss (cross-site scripting) attack means that an attacker to insert malicious Web page in html tags or javascript code. For example: the attacker in the forums to put a seemingly secure link, the user clicks cheat, steal private information in the cookie; or attacker in the forum, adding a malicious form, when the user submits the form, yet the information transfer to the attacker's server, rather than trust the site that the user originally thought.\n\nXSS prevention methods\n\n1. Code in the right place and the user input variables need to be carefully check the length and \"<\", \">\", \";\", \"'\" and other characters do filter; followed before any of the contents must be written pages encode , Avoid accidentally html tag to get out. This is a good level, at least you can block more than half of XSS attacks. \n2. Avoid direct cookie disclosure of user privacy, such as Email , password, and so on. 3. By cookie and systems ip binding to reduce cookie dangerous leak after. Thus the attacker obtained cookie no practical value, it is impossible brought replay. \n4. Try to use GET rather than POST submission form\n\nXSS and CSRF What's the difference?\n\nXSS is to obtain information, other users do not need to know in advance the code page and the data packet. CSRF is to replace the user completes a specified action, you need to know the code page to other users and data packets.\n\nTo complete a CSRF attack, the victim must be followed by the completion of two steps:\n\n　　1. Log trusted site A, and generates Cookie locally. 2. Under no circumstances logout A visiting dangerous sites B.\n\nCSRF defense\n\n1. The service side of the CSRF ways like a lot, but the general idea is the same, that is, an increase in the Clients page pseudo-random numbers. 2. Use the verification code\n\nie chrome versions and how many resources can be downloaded in parallel\n\nIE6 two concurrent, six concurrent iE7 after the upgrade version is also after 6 \n\nFirefox, chrome is 6\njavascript how to achieve inside the inheritance, how to avoid the prototype chain above object sharing\n\nWith mixed mode constructor and prototype chain to achieve inheritance, avoid sharing objects can refer to the classic extend () function, and many have a front frame of the package, it is to use an empty function as an intermediate variable\ngrunt, YUI compressor and google clojure used for code compression usage.\n\nYUI Compressor is a tool compress JS and CSS files used, the use of Java development. \n\nUsage: \n\n// compress JS \nJava -jar YUICompressor-2.4.2.jar --type JS --charset UTF-8 -v src.js> packed.js \n// compress CSS \nJava -jar YUICompressor-2.4.2.jar --type css --charset utf-8 -v src.css> packed.css\nFor more information: you need to master the front-end code performance optimization tools\n\nFlash, Ajax respective advantages and disadvantages, in use how to choose?\n\n1, Flash ajax contrast \nFlash for handling multimedia, vector graphics, to access the machine; on the CSS, inadequate handling text, not easy to be searched. \nAjax for CSS, text support is very good, support search; multimedia, vector graphics, inadequate machine access. \nCommon: with no server refresh deliver the message, the user is offline and online, manipulate DOM\nPlease explain the JavaScript same origin policy.\n\nConcept: homologous strategy is client-side script (especially Javascript ) important safety metrics. It first from Netscape Navigator2.0 , its purpose is to prevent a document or script loaded from several different sources.\n\nHere's same-origin policy refers to: protocol name, the same port, same origin policy is a security protocol. Refers to a script read-only attribute window and documents from the same source.\n\nWhy have homologous limit?\n\nWe illustrate: For example, a hacker program, he used Iframe the real bank login page insert to his page, when you use a real user name, password, he can page through Javascript read your form the input in the content, so the user name, password easily at hand.\n\nWhat is a \"use strict\";? Advantages and disadvantages of using it are what?\n\nECMAscript 5 added a second operating modes: \"strict mode\" (strict mode). As the name suggests, this model allows Javascript to run under more stringent conditions.\n\nThe purpose of the \"strict mode\", mainly in the following:\n\n- Eliminate some unreasonable Javascript syntax, not rigorous place, reducing the number of bizarre behavior; \n- eliminate some code running unsafe place to ensure the safety of code to run; \n- improve compiler efficiency, increase the operating speed; \n- for the future of new Javascript version pave the way.\nNOTE: After testing IE6,7,8,9 strict mode is not supported.\n\nCons: Now site JS will compress files with the strict mode, while others do not. Then these documents could have been strict mode is merge after the string on to the middle of the file, not only does not indicate strict mode, but a waste of bytes after compression.\n\nThe difference between GET and POST, and when to use POST?\n\n    GET: generally used for information access, use URL parameters to pass on information to send the numbers are limited, in the 2000 general character \n    POST: Usually used to modify resources on the server, there is no restriction on the transmitted information. \n\n    GET requires the use of Request.QueryString to get the value of a variable, while the POST method to get the value of a variable through Request.Form, \n    ie Get through the address bar to traditional values, while Post by submitting the form to traditional values. \n\nHowever, in the following cases, please use the POST request: \nYou can not use a cache file (a file or database on the update server) \nto send large amounts of data (POST does not limit the amount of data) to the server \nwhen a user sends an unknown character input, POST than GET more stable and more reliable\nWhere there will be css obstruction, where there will be js blocked?\n\njs of blocking characteristic: all browsers to download JS time, will stop all other activities, such as downloading other resources, presentation content and so on. Until JS download, parse, after finished resumes parallel downloading other resources and render content. In order to improve the user experience, a new generation of browsers support concurrent download JS , but JS download still blocking other resources to download (such as Image, css files, etc.).\n\nBecause the browser in order to prevent JS modify DOM tree, you need to rebuild the DOM tree of the case, so it will block other downloads and rendering.\n\nEmbed JS will block all content presentation, and external JS will only clog the subsequent content display, 2 ways to download later resources will be blocked. That style does not block external loading external script, but will block the implementation of an external script.\n\nCSS how can clog loaded? CSS could have been downloaded in parallel, in what circumstances would appear blocked loaded (in the test observation, IE6 under CSS are blocking load)\n\nWhen CSS followed by embedding JS when the CSS will block behind resources situation. When to embed JS into CSS front, it does not appear the case of obstruction.\n\nFundamental reason: because the browser will remain html in css and js order, the stylesheet must be loaded before the embedding of JS execution, analytical end. The embedding of JS can block behind resource loading, it will appear above the CSS case blocking the download.\n\nEmbed JS should be placed on what position?\n\n   1, on the bottom, although still on the bottom will block all presented, but will not block resources. \n\n   2, if the embedded JS on the head, please send embed CSS JS on the head. \n\n   3. Use defer (only supports IE) \n\n   4, do not call a function of time in the long run embedded JS, if must use, can be used to call `setTimeout`\nJavascript blocking load specific ways\n\nThe script at the bottom. <Link> or on the head , and to ensure js before loading, to load the page properly displayed. <Script> tag on the </ body> ago.\nA set of scripts : Because each <script> tag download blocking page resolution process, so limiting the page <script> total can also improve performance. Suitable for inline scripts and external scripts.\n\nNon-blocking script : such as the page finishes loading, reloading js code. That is, in window.onload issued after the event to start the download code. (1) defer attributes: support IE4 and fierfox3.5 later browser (2) dynamic script elements: Document Object Model (DOM) allows you to use js dynamically create HTML almost the entire contents of the document. Code is as follows:\n\n\n\n<Script> \nvar Script = document.createElement (\"Script\"); \nscript.type = \"text / JavaScript\"; \nscript.src = \"file.js\"; \ndocument.getElementsByTagName (\"head\") [0] .appendChild (Script ); \n</ Script>\nThis technique focuses on: Wherever start downloading, file downloading and running the amount will not block other page processing. Even in the head inside (except http link for downloading the file).\n\nClosure-related issues?\n\nFor more information: Detailed js Closures\n\njs event handler problem?\n\nFor details, see: JavaScript study summary (ix) event Comments\n\neval is doing what?\n\nIts function is to parse the string corresponding to the JS code and run; \nyou should avoid using eval, unsafe, very time consuming properties (2 times, once parsed into js statement, once executed).\nJavaScript prototype, the prototype chain? What are the characteristics?\n\n* Prototype object is an ordinary object is an object that comes with implicit __proto__ property, prototypes may also have its own prototype, if the prototype of a prototype object is not null, then we call the prototype chain. \n* Prototype chain used by some inheritance and shared properties of objects of the (limited) object chain.\nEvent mechanism event, IE and Firefox What is the difference? How to stop the bubble?\n\n1. We operate in a web page (some operations corresponding to multiple events). For example: When we click on a button will generate an event. JavaScript can be detected behavior.  \n 2. Event handling mechanism: IE is the event bubbling, firefox supports both event model, that is: type of event capture and bubbling type events. ; \n 3. ev.stopPropagation (); Note that the old method ie ev.cancelBubble = true;\najax What is? ajax interaction model? synchronous and asynchronous difference? How to solve cross-border issues?\n\nFor details, see: JavaScript study summary (vii) Ajax and Http Status Word\n\n1. Adoption of the asynchronous model to enhance the user experience \n\n  2. Optimize the transmission between the browser and the server, reducing unnecessary data back and forth, reducing the bandwidth \n\n  portion 3. Ajax running on the client, undertaken originally borne by the server work, reducing the server load large amount of users under. \n\n  What is the biggest characteristic 2. Ajax is. \n\n  Ajax enables dynamic does not refresh (partial refresh) \n  readyState property state can have five values: 0 = uninitialized 1 = Start 2 = send, 3 = reception, 4 = complete \n\najax shortcomings \n\n  1, ajax do not support the browser back button. \n\n  2, AJAX security issues exposed the details of the server to interact with. \n\n  3, support for the search engines is relatively weak. \n\n  4, undermining the exception mechanism of the program. \n\n  5, it is not easy to debug. \n\nCross-domain: Setting proxy page on jsonp, iframe, window.name, window.postMessage, server\nDepth cloning js object\n\n  function clone (Obj) {    \n        var buf;    \n        if (Obj instanceof Array) {    \n            buf = []; // create an empty array \n            var i = Obj.length;    \n            while (I -) {    \n                buf [i] = clone (Obj [i]);    \n            }    \n            return buf;    \n        } else if (Obj instanceof Object) {    \n            buf = {}; // create an empty object \n            for (var k in Obj) {// add a new property to the object \n                buf [k] = clone (Obj [k]);    \n            }    \n            return buf;    \n        } else {    \n            return Obj;    \n        }    \n    }  \nThe difference between AMD and CMD norms?\n\nFor more information: Detailed JavaScript Modular Development\n\nSite reconstruction of understanding?\n\nReconstruction Site: without changing the external behavior of the premise, to simplify the structure, add readability, while the front end of the site to maintain consistent behavior. That is in the UI does not change the situation, to optimize the site, in the expansion while maintaining a consistent UI. \n\nReconstruction of the traditional web sites is usually: \n\ntable (table) layout to DIV + CSS \nfront end to make the site compatible with modern browsers (for irregularities in the CSS, such as IE6 valid) \nfor the mobile platform optimized \nfor ships SEO optimized \nsite reconstruction deeper aspects that should be considered \n\nto reduce the coupling between codes \nallow the code to maintain flexibility \nin strict accordance with specification code \nextensible API designed \nto replace the old framework, language (eg VB) \nenhance the user experience \ngenerally speaking for optimized for speed is also included in the reconstruction of the \n\ncompressed JS, CSS, image and other front-end resources (usually be resolved by the server) \nperformance optimization program (such as data read and write) \nusing CDN to accelerate resource loading \nfor JS DOM optimized \nHTTP server File Cache\nHow to obtain the UA?\n\n<Script> \n    whatBrowser function () {   \n        document.Browser.Name.value = navigator.appName;   \n        document.Browser.Version.value = navigator.appVersion;   \n        document.Browser.Code.value = navigator.appCodeName;   \n        document.Browser.Agent. value = navigator.userAgent;   \n    }   \n</ Script>\njs array to weight\n\nThe following are three ways to go heavy array:\n\nArray.prototype.unique1 = function () { \n  var N = []; // a new temporary array \n  for (var i = 0; i <this.length; i ++) // traverse the current array \n  { \n    // If the current array first i have saved into a temporary array, skip, \n    // otherwise the current term push to the temporary array inside \n    if (n.indexOf (this [i]) == -1) n.push (this [i]); \n  } \n  return N; \n} \n\nArray.prototype.unique2 = function () \n{ \n    var N = {}, r = []; // N is a hash table, r is a temporary array \n    for (var i = 0; i <this.length; i ++) // traverse the current array \n    { \n        if (N [this [i]]) // If the hash table does not have the current item! \n        { \n            N [this [i]] = true; // stored in the hash table \n            r.push (this [i]); // the current term push the current array to a temporary array inside \n        } \n    } \n    return r; \n} \n\nArray.prototype.unique3 = function () \n{ \n    var N = [this [0]]; // results array \n    for ( var i = 1; i <this.length; i ++) // iterate from the start of the second term \n    { \n        // if the current array of item i in the current array position is not the first occurrence of i, \n        it represents the i // entries are repeated, ignored. Otherwise, the result is stored in the array \n        if (this.indexOf (this [i]) == i) n.push (this [i]); \n    } \n    return N; \n}\nHTTP status code\n\nAfter 100 Continue to continue, generally when sending post request, sent the http header the server will return this message, to confirm, specific parameter information after sending \n200 OK normal return information \n201 Created request was successful and the server created a new resource \n202 Accepted The server has accepted the request, but not yet processed \n301 Moved Permanently The requested page has been permanently moved to a new location. \n302 Found temporary redirect. \n303 See Other temporary redirection, and always use a GET request a new URI. \n304 Not Modified since the last request, the requested page has not been modified. \n\nFormat 400 Bad Request Server can not understand the request, the client should not attempt to use the same content again initiated the request. \n401 Unauthorized Unauthorized request. \n403 Forbidden Forbidden. \n404 Not Found can not find how to match resources with URI. \n\n500 Internal Server Error The most common server-side error. \n503 Service Unavailable server is temporarily unable to process the request (may be overloaded or maintenance).\njs operations to get and set cookie\n\n// Create the cookie \nfunction setCookie (name, value, expires, path, domain, secure) { \n    var cookieText = encodeURIComponent (name) + '=' + encodeURIComponent (value); \n    if (expires instanceof Date) { \n        cookieText + = '; expires = '+ expires; \n    } \n    if (path) { \n        cookieText + = '; expires =' + expires; \n    } \n    if (domain) { \n        cookieText + = '; domain =' + domain; \n    } \n    if (secure) { \n        cookieText + = '; secure '; \n    } \n    document.cookie = cookieText; \n} \n\n// get the cookie \nfunction getCookie (name) { \n    var cookieName = encodeURIComponent (name) + '='; \n    var cookieStart = document.cookie.indexOf (cookieName); \n    var CookieValue = null; \n    if (cookieStart> -1) { \n        var cookieEnd = document.cookie.indexOf (';', cookieStart); \n        if (cookieEnd == -1) { \n            cookieEnd = document.cookie.length; \n        } \n        CookieValue = decodeURIComponent (document.cookie. substring (cookieStart + cookieName.length, cookieEnd)); \n    } \n    return CookieValue; \n} \n\n// delete the cookie \nfunction unsetCookie (name) { \n    document.cookie = name + \"=; expires =\" + new Date (0); \n}\nTalk about the three-way handshake TCP transport policy\n\nIn order to reach the target accurately at the data, TCP uses a three-way handshake protocol strategy. After using the TCP protocol to send out packets, TCP will not ignore the situation after transfer, it will be delivered to the other party to confirm the success. Handshake using TCP flags: SYN and ACK. \nData with the sender first sends a SYN packet to the other flag. After the receiver receives, SYN / ACK packet backhaul flags to show communicate with a confirmation message. Packet, representing the last, the sender return pass with ACK flag \"handshake\" End \nIf at some stage during the handshake inexplicably interrupted, TCP protocol will be in the same order to send the same packet again.\nTalk about your understanding of the Promise\n\nIn accordance with Promise / A + defined, Promise has four states:\n\npending: the initial state, the non-fulfilled or rejected. \nFulfilled: the success of the operation. \nrejected: the failed operation. \nsettled: Promise has been fulfilled or rejected, and not pending\nIn addition, Fulfilled and rejected together collectively settled .\n\nPromise objects used for delayed (deferred) and asynchronous (asynchronous) calculations.\n\nPromise of constructor\nConstruct a Promise , the most basic usage is as follows:\n\nvar = new Promise Promise (function (resolve, reject) { \n    if (...) {// Succeed \n        resolve (result); \n    } else {// fails \n        reject (Error (errMessage)); \n    } \n});\nPromise instance has then method (with a then object method, commonly referred to thenable ). Its use is as follows:\n\npromise.then (onFulfilled, onRejected)\nReceives two function as an argument, one fulfilled is called when one rejected when they were called, received parameter is the future, onFulfilled correspond resolve , onRejected correspond to reject .\n\nJavascript garbage collection method\n\nClear mark (mark and sweep)\n\nThis is the JavaScript garbage collection the most common way, when the variable into the execution environment, such as a function to declare a variable, the garbage collector will be marked as \"into the environment\", when leaving the environment variables (ending function execution) to labeled \"leave the environment.\"\n\nGarbage collector to run when all variables are stored in memory plus mark, and then remove the environment variables and variables (closures) is referenced by an environment variable, there are still marked after this is done is to delete variables\n\nReference count (reference counting)\n\nIn the low version IE memory leaks occur frequently, many times, because it uses reference counting for garbage collection. Policy reference count is the number used by the track record of each value, when you declare a variable number of citations and a reference type assigned to the variable when this value is increased by one, if the value of the variable into another is worth quoting this number by 1, when citations this value becomes zero, no variables described in use, this value can not be accessed, so its footprint can be recovered, so the garbage collector in Running time to clean out the reference number of the space occupied by a value of 0.\n\nIn IE though JavaScript objects marked clearing the way for garbage collection, but the BOM and DOM objects is through reference counting garbage, that is as far as BOM and DOM circular reference problem occurs.\n\nTalk about performance optimization problem\n\nCode level: Avoid using css expression, avoid the use of advanced selectors, wildcard selector. Cache use: Cache Ajax, use CDN, use external js and css file to the cache, add the Expires header, the server configuration Etag, reducing the number of requests and other DNS lookup: merge styles and scripts, using css image sprites, beyond the initial first screen Image resource demand loading, lazy loading static resources. Request Bandwidth: compressed file, open GZIP,\n\nMobile end performance optimization\n\nTry to use css3 animation, open hardware acceleration. Appropriate use of touch event instead of click event. Avoid using css3 gradient shading effects. Use as few box-shadow and Gradients . box-shadow and gradients are often performance killer page\nWhat is Etag?\n\nBrowser download components when they will be stored in the browser cache. If you need to get the same components, the browser cache time again check the components, if already expired, the browser sends a conditional GET request to the server, the server determines the cache still valid, it sends a 304 response, telling the browser can be reused cache component.\n\nThen the server is based on what the judge cache is still valid? The answer is, there are two ways, one is ETag mentioned earlier, another is based on the Last-Modified\n\nExpires and Cache-Control\n\nExpires requires the client and server strict clock synchronization. HTTP1.1 introduction of Cache-Control to overcome the limitations of Expires header. If the max-age and Expires simultaneously, the max-age have a higher priority.\n\nCache-Control: no-cache, Private, max-age = 0 \nETag: abcde \nExpires: Thu, 15 Apr 2014 20:00:00 GMT \nPragma: Private \nLast-Modified: // now $ RFC1123 format\nThe difference between stacks and queues?\n\nStack insert and delete operations are carried out at one end, and queue operation is carried out at both ends. \nFIFO queue, stack advanced out after. \nStack only allowed in the tail end of the insert and delete, and queue only allowed in the tail end of the insert, delete the header end\nThe difference between stack and heap?\n\nStack area (stack) - assigned automatically by the compiler release, storage function parameters, local variables and so on. \nHeap (heap) - general distribution release by the programmer, if the programmer does not release, may be recovered by the OS when the program ends. \nHeap (data structures): heap can be seen as a tree, such as: heap sort; \nstack (data structures): An advanced after the data structure.\nHow much do you know about Http 2.0?\n\nHTTP / 2 introduced a \"server push (serverpush)\" concept, which allows the server before the client needs the data to take the initiative to send data to the client cache, thereby improving performance. HTTP / 2 encryption to provide more support for HTTP / 2 using a multiplexing technology that allows multiple messages simultaneously on a cross connection. It adds header compression (header compression), so even very small requests, which request and response header will only occupy a small percentage of bandwidth.\nStatus API Training Shop Blog About Pricing\n© 2015 GitHub , Inc. Terms Privacy Security Contact Help';\n?>\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/Session.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 2.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\t\tAndrey Andreev\n * @link\t\thttp://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session {\n\n\t/**\n\t * Userdata array\n\t *\n\t * Just a reference to $_SESSION, for BC purposes.\n\t */\n\tpublic $userdata;\n\n\tprotected $_driver = 'files';\n\tprotected $_config;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(array $params = array())\n\t{\n\t\t// No sessions under CLI\n\t\tif (is_cli())\n\t\t{\n\t\t\tlog_message('debug', 'Session: Initialization under CLI aborted.');\n\t\t\treturn;\n\t\t}\n\t\telseif ((bool) ini_get('session.auto_start'))\n\t\t{\n\t\t\tlog_message('error', 'Session: session.auto_start is enabled in php.ini. Aborting.');\n\t\t\treturn;\n\t\t}\n\t\telseif ( ! empty($params['driver']))\n\t\t{\n\t\t\t$this->_driver = $params['driver'];\n\t\t\tunset($params['driver']);\n\t\t}\n\t\telseif ($driver = config_item('sess_driver'))\n\t\t{\n\t\t\t$this->_driver = $driver;\n\t\t}\n\t\t// Note: BC workaround\n\t\telseif (config_item('sess_use_database'))\n\t\t{\n\t\t\t$this->_driver = 'database';\n\t\t}\n\n\t\t$class = $this->_ci_load_classes($this->_driver);\n\n\t\t// Configuration ...\n\t\t$this->_configure($params);\n\n\t\t$class = new $class($this->_config);\n\t\tif ($class instanceof SessionHandlerInterface)\n\t\t{\n\t\t\tif (is_php('5.4'))\n\t\t\t{\n\t\t\t\tsession_set_save_handler($class, TRUE);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsession_set_save_handler(\n\t\t\t\t\tarray($class, 'open'),\n\t\t\t\t\tarray($class, 'close'),\n\t\t\t\t\tarray($class, 'read'),\n\t\t\t\t\tarray($class, 'write'),\n\t\t\t\t\tarray($class, 'destroy'),\n\t\t\t\t\tarray($class, 'gc')\n\t\t\t\t);\n\n\t\t\t\tregister_shutdown_function('session_write_close');\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', \"Session: Driver '\".$this->_driver.\"' doesn't implement SessionHandlerInterface. Aborting.\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Sanitize the cookie, because apparently PHP doesn't do that for userspace handlers\n\t\tif (isset($_COOKIE[$this->_config['cookie_name']])\n\t\t\t&& (\n\t\t\t\t! is_string($_COOKIE[$this->_config['cookie_name']])\n\t\t\t\tOR ! preg_match('/^[0-9a-f]{40}$/', $_COOKIE[$this->_config['cookie_name']])\n\t\t\t)\n\t\t)\n\t\t{\n\t\t\tunset($_COOKIE[$this->_config['cookie_name']]);\n\t\t}\n\n\t\tsession_start();\n\n\t\t// Is session ID auto-regeneration configured? (ignoring ajax requests)\n\t\tif ((empty($_SERVER['HTTP_X_REQUESTED_WITH']) OR strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest')\n\t\t\t&& ($regenerate_time = config_item('sess_time_to_update')) > 0\n\t\t)\n\t\t{\n\t\t\tif ( ! isset($_SESSION['__ci_last_regenerate']))\n\t\t\t{\n\t\t\t\t$_SESSION['__ci_last_regenerate'] = time();\n\t\t\t}\n\t\t\telseif ($_SESSION['__ci_last_regenerate'] < (time() - $regenerate_time))\n\t\t\t{\n\t\t\t\t$this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));\n\t\t\t}\n\t\t}\n\t\t// Another work-around ... PHP doesn't seem to send the session cookie\n\t\t// unless it is being currently created or regenerated\n\t\telseif (isset($_COOKIE[$this->_config['cookie_name']]) && $_COOKIE[$this->_config['cookie_name']] === session_id())\n\t\t{\n\t\t\tsetcookie(\n\t\t\t\t$this->_config['cookie_name'],\n\t\t\t\tsession_id(),\n\t\t\t\t(empty($this->_config['cookie_lifetime']) ? 0 : time() + $this->_config['cookie_lifetime']),\n\t\t\t\t$this->_config['cookie_path'],\n\t\t\t\t$this->_config['cookie_domain'],\n\t\t\t\t$this->_config['cookie_secure'],\n\t\t\t\tTRUE\n\t\t\t);\n\t\t}\n\n\t\t$this->_ci_init_vars();\n\n\t\tlog_message('info', \"Session: Class initialized using '\".$this->_driver.\"' driver.\");\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * CI Load Classes\n\t *\n\t * An internal method to load all possible dependency and extension\n\t * classes. It kind of emulates the CI_Driver library, but is\n\t * self-sufficient.\n\t *\n\t * @param\tstring\t$driver\tDriver name\n\t * @return\tstring\tDriver class name\n\t */\n\tprotected function _ci_load_classes($driver)\n\t{\n\t\t// PHP 5.4 compatibility\n\t\tinterface_exists('SessionHandlerInterface', FALSE) OR require_once(BASEPATH.'libraries/Session/SessionHandlerInterface.php');\n\n\t\t$prefix = config_item('subclass_prefix');\n\n\t\tif ( ! class_exists('CI_Session_driver', FALSE))\n\t\t{\n\t\t\trequire_once(\n\t\t\t\tfile_exists(APPPATH.'libraries/Session/Session_driver.php')\n\t\t\t\t\t? APPPATH.'libraries/Session/Session_driver.php'\n\t\t\t\t\t: BASEPATH.'libraries/Session/Session_driver.php'\n\t\t\t);\n\n\t\t\tif (file_exists($file_path = APPPATH.'libraries/Session/'.$prefix.'Session_driver.php'))\n\t\t\t{\n\t\t\t\trequire_once($file_path);\n\t\t\t}\n\t\t}\n\n\t\t$class = 'Session_'.$driver.'_driver';\n\n\t\t// Allow custom drivers without the CI_ or MY_ prefix\n\t\tif ( ! class_exists($class, FALSE) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$class.'.php'))\n\t\t{\n\t\t\trequire_once($file_path);\n\t\t\tif (class_exists($class, FALSE))\n\t\t\t{\n\t\t\t\treturn $class;\n\t\t\t}\n\t\t}\n\n\t\tif ( ! class_exists('CI_'.$class, FALSE))\n\t\t{\n\t\t\tif (file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$class.'.php') OR file_exists($file_path = BASEPATH.'libraries/Session/drivers/'.$class.'.php'))\n\t\t\t{\n\t\t\t\trequire_once($file_path);\n\t\t\t}\n\n\t\t\tif ( ! class_exists('CI_'.$class, FALSE) && ! class_exists($class, FALSE))\n\t\t\t{\n\t\t\t\tthrow new UnexpectedValueException(\"Session: Configured driver '\".$driver.\"' was not found. Aborting.\");\n\t\t\t}\n\t\t}\n\n\t\tif ( ! class_exists($prefix.$class) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$prefix.$class.'.php'))\n\t\t{\n\t\t\trequire_once($file_path);\n\t\t\tif (class_exists($prefix.$class, FALSE))\n\t\t\t{\n\t\t\t\treturn $prefix.$class;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Session: '.$prefix.$class.\".php found but it doesn't declare class \".$prefix.$class.'.');\n\t\t\t}\n\t\t}\n\n\t\treturn 'CI_'.$class;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Configuration\n\t *\n\t * Handle input parameters and configuration defaults\n\t *\n\t * @param\tarray\t&$params\tInput parameters\n\t * @return\tvoid\n\t */\n\tprotected function _configure(&$params)\n\t{\n\t\t$expiration = config_item('sess_expiration');\n\n\t\tif (isset($params['cookie_lifetime']))\n\t\t{\n\t\t\t$params['cookie_lifetime'] = (int) $params['cookie_lifetime'];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$params['cookie_lifetime'] = ( ! isset($expiration) && config_item('sess_expire_on_close'))\n\t\t\t\t? 0 : (int) $expiration;\n\t\t}\n\n\t\tisset($params['cookie_name']) OR $params['cookie_name'] = config_item('sess_cookie_name');\n\t\tif (empty($params['cookie_name']))\n\t\t{\n\t\t\t$params['cookie_name'] = ini_get('session.name');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tini_set('session.name', $params['cookie_name']);\n\t\t}\n\n\t\tisset($params['cookie_path']) OR $params['cookie_path'] = config_item('cookie_path');\n\t\tisset($params['cookie_domain']) OR $params['cookie_domain'] = config_item('cookie_domain');\n\t\tisset($params['cookie_secure']) OR $params['cookie_secure'] = (bool) config_item('cookie_secure');\n\n\t\tsession_set_cookie_params(\n\t\t\t$params['cookie_lifetime'],\n\t\t\t$params['cookie_path'],\n\t\t\t$params['cookie_domain'],\n\t\t\t$params['cookie_secure'],\n\t\t\tTRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons\n\t\t);\n\n\t\tif (empty($expiration))\n\t\t{\n\t\t\t$params['expiration'] = (int) ini_get('session.gc_maxlifetime');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$params['expiration'] = (int) $expiration;\n\t\t\tini_set('session.gc_maxlifetime', $expiration);\n\t\t}\n\n\t\t$params['match_ip'] = (bool) (isset($params['match_ip']) ? $params['match_ip'] : config_item('sess_match_ip'));\n\n\t\tisset($params['save_path']) OR $params['save_path'] = config_item('sess_save_path');\n\n\t\t$this->_config = $params;\n\n\t\t// Security is king\n\t\tini_set('session.use_trans_sid', 0);\n\t\tini_set('session.use_strict_mode', 1);\n\t\tini_set('session.use_cookies', 1);\n\t\tini_set('session.use_only_cookies', 1);\n\t\tini_set('session.hash_function', 1);\n\t\tini_set('session.hash_bits_per_character', 4);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Handle temporary variables\n\t *\n\t * Clears old \"flash\" data, marks the new one for deletion and handles\n\t * \"temp\" data deletion.\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _ci_init_vars()\n\t{\n\t\tif ( ! empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\t$current_time = time();\n\n\t\t\tforeach ($_SESSION['__ci_vars'] as $key => &$value)\n\t\t\t{\n\t\t\t\tif ($value === 'new')\n\t\t\t\t{\n\t\t\t\t\t$_SESSION['__ci_vars'][$key] = 'old';\n\t\t\t\t}\n\t\t\t\t// Hacky, but 'old' will (implicitly) always be less than time() ;)\n\t\t\t\t// DO NOT move this above the 'new' check!\n\t\t\t\telseif ($value < $current_time)\n\t\t\t\t{\n\t\t\t\t\tunset($_SESSION[$key], $_SESSION['__ci_vars'][$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (empty($_SESSION['__ci_vars']))\n\t\t\t{\n\t\t\t\tunset($_SESSION['__ci_vars']);\n\t\t\t}\n\t\t}\n\n\t\t$this->userdata =& $_SESSION;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Mark as flash\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tbool\n\t */\n\tpublic function mark_as_flash($key)\n\t{\n\t\tif (is_array($key))\n\t\t{\n\t\t\tfor ($i = 0, $c = count($key); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ( ! isset($_SESSION[$key[$i]]))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$new = array_fill_keys($key, 'new');\n\n\t\t\t$_SESSION['__ci_vars'] = isset($_SESSION['__ci_vars'])\n\t\t\t\t? array_merge($_SESSION['__ci_vars'], $new)\n\t\t\t\t: $new;\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ( ! isset($_SESSION[$key]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$_SESSION['__ci_vars'][$key] = 'new';\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get flash keys\n\t *\n\t * @return\tarray\n\t */\n\tpublic function get_flash_keys()\n\t{\n\t\tif ( ! isset($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\t$keys = array();\n\t\tforeach (array_keys($_SESSION['__ci_vars']) as $key)\n\t\t{\n\t\t\tis_int($_SESSION['__ci_vars'][$key]) OR $keys[] = $key;\n\t\t}\n\n\t\treturn $keys;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unmark flash\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unmark_flash($key)\n\t{\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tis_array($key) OR $key = array($key);\n\n\t\tforeach ($key as $k)\n\t\t{\n\t\t\tif (isset($_SESSION['__ci_vars'][$k]) && ! is_int($_SESSION['__ci_vars'][$k]))\n\t\t\t{\n\t\t\t\tunset($_SESSION['__ci_vars'][$k]);\n\t\t\t}\n\t\t}\n\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tunset($_SESSION['__ci_vars']);\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Mark as temp\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @param\tint\t$ttl\tTime-to-live in seconds\n\t * @return\tbool\n\t */\n\tpublic function mark_as_temp($key, $ttl = 300)\n\t{\n\t\t$ttl += time();\n\n\t\tif (is_array($key))\n\t\t{\n\t\t\t$temp = array();\n\n\t\t\tforeach ($key as $k => $v)\n\t\t\t{\n\t\t\t\t// Do we have a key => ttl pair, or just a key?\n\t\t\t\tif (is_int($k))\n\t\t\t\t{\n\t\t\t\t\t$k = $v;\n\t\t\t\t\t$v = $ttl;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$v += time();\n\t\t\t\t}\n\n\t\t\t\tif ( ! isset($_SESSION[$k]))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\t$temp[$k] = $v;\n\t\t\t}\n\n\t\t\t$_SESSION['__ci_vars'] = isset($_SESSION['__ci_vars'])\n\t\t\t\t? array_merge($_SESSION['__ci_vars'], $temp)\n\t\t\t\t: $temp;\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ( ! isset($_SESSION[$key]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$_SESSION['__ci_vars'][$key] = $ttl;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get temp keys\n\t *\n\t * @return\tarray\n\t */\n\tpublic function get_temp_keys()\n\t{\n\t\tif ( ! isset($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\t$keys = array();\n\t\tforeach (array_keys($_SESSION['__ci_vars']) as $key)\n\t\t{\n\t\t\tis_int($_SESSION['__ci_vars'][$key]) && $keys[] = $key;\n\t\t}\n\n\t\treturn $keys;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unmark flash\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unmark_temp($key)\n\t{\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tis_array($key) OR $key = array($key);\n\n\t\tforeach ($key as $k)\n\t\t{\n\t\t\tif (isset($_SESSION['__ci_vars'][$k]) && is_int($_SESSION['__ci_vars'][$k]))\n\t\t\t{\n\t\t\t\tunset($_SESSION['__ci_vars'][$k]);\n\t\t\t}\n\t\t}\n\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tunset($_SESSION['__ci_vars']);\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * __get()\n\t *\n\t * @param\tstring\t$key\t'session_id' or a session data key\n\t * @return\tmixed\n\t */\n\tpublic function __get($key)\n\t{\n\t\t// Note: Keep this order the same, just in case somebody wants to\n\t\t//       use 'session_id' as a session data key, for whatever reason\n\t\tif (isset($_SESSION[$key]))\n\t\t{\n\t\t\treturn $_SESSION[$key];\n\t\t}\n\t\telseif ($key === 'session_id')\n\t\t{\n\t\t\treturn session_id();\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * __set()\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @param\tmixed\t$value\tSession data value\n\t * @return\tvoid\n\t */\n\tpublic function __set($key, $value)\n\t{\n\t\t$_SESSION[$key] = $value;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Session destroy\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function sess_destroy()\n\t{\n\t\tsession_destroy();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Session regenerate\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tbool\t$destroy\tDestroy old session data flag\n\t * @return\tvoid\n\t */\n\tpublic function sess_regenerate($destroy = FALSE)\n\t{\n\t\t$_SESSION['__ci_last_regenerate'] = time();\n\t\tsession_regenerate_id($destroy);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get userdata reference\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @returns\tarray\n\t */\n\tpublic function &get_userdata()\n\t{\n\t\treturn $_SESSION;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Userdata (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tmixed\tSession data value or NULL if not found\n\t */\n\tpublic function userdata($key = NULL)\n\t{\n\t\tif (isset($key))\n\t\t{\n\t\t\treturn isset($_SESSION[$key]) ? $_SESSION[$key] : NULL;\n\t\t}\n\t\telseif (empty($_SESSION))\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\t$userdata = array();\n\t\t$_exclude = array_merge(\n\t\t\tarray('__ci_vars'),\n\t\t\t$this->get_flash_keys(),\n\t\t\t$this->get_temp_keys()\n\t\t);\n\n\t\tforeach (array_keys($_SESSION) as $key)\n\t\t{\n\t\t\tif ( ! in_array($key, $_exclude, TRUE))\n\t\t\t{\n\t\t\t\t$userdata[$key] = $_SESSION[$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $userdata;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Set userdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key or an associative array\n\t * @param\tmixed\t$value\tValue to store\n\t * @return\tvoid\n\t */\n\tpublic function set_userdata($data, $value = NULL)\n\t{\n\t\tif (is_array($data))\n\t\t{\n\t\t\tforeach ($data as $key => &$value)\n\t\t\t{\n\t\t\t\t$_SESSION[$key] = $value;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t$_SESSION[$data] = $value;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unset userdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unset_userdata($key)\n\t{\n\t\tif (is_array($key))\n\t\t{\n\t\t\tforeach ($key as $k)\n\t\t\t{\n\t\t\t\tunset($_SESSION[$k]);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tunset($_SESSION[$key]);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * All userdata (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @return\tarray\t$_SESSION, excluding flash data items\n\t */\n\tpublic function all_userdata()\n\t{\n\t\treturn $this->userdata();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Has userdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tbool\n\t */\n\tpublic function has_userdata($key)\n\t{\n\t\treturn isset($_SESSION[$key]);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Flashdata (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tmixed\tSession data value or NULL if not found\n\t */\n\tpublic function flashdata($key = NULL)\n\t{\n\t\tif (isset($key))\n\t\t{\n\t\t\treturn (isset($_SESSION['__ci_vars'], $_SESSION['__ci_vars'][$key], $_SESSION[$key]) && ! is_int($_SESSION['__ci_vars'][$key]))\n\t\t\t\t? $_SESSION[$key]\n\t\t\t\t: NULL;\n\t\t}\n\n\t\t$flashdata = array();\n\n\t\tif ( ! empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tforeach ($_SESSION['__ci_vars'] as $key => &$value)\n\t\t\t{\n\t\t\t\tis_int($value) OR $flashdata[$key] = $_SESSION[$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $flashdata;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Set flashdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key or an associative array\n\t * @param\tmixed\t$value\tValue to store\n\t * @return\tvoid\n\t */\n\tpublic function set_flashdata($data, $value = NULL)\n\t{\n\t\t$this->set_userdata($data, $value);\n\t\t$this->mark_as_flash(is_array($data) ? array_keys($data) : $data);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Keep flashdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function keep_flashdata($key)\n\t{\n\t\t$this->mark_as_flash($key);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Temp data (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tmixed\tSession data value or NULL if not found\n\t */\n\tpublic function tempdata($key = NULL)\n\t{\n\t\tif (isset($key))\n\t\t{\n\t\t\treturn (isset($_SESSION['__ci_vars'], $_SESSION['__ci_vars'][$key], $_SESSION[$key]) && is_int($_SESSION['__ci_vars'][$key]))\n\t\t\t\t? $_SESSION[$key]\n\t\t\t\t: NULL;\n\t\t}\n\n\t\t$tempdata = array();\n\n\t\tif ( ! empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tforeach ($_SESSION['__ci_vars'] as $key => &$value)\n\t\t\t{\n\t\t\t\tis_int($value) && $tempdata[$key] = $_SESSION[$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $tempdata;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Set tempdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key or an associative array of items\n\t * @param\tmixed\t$value\tValue to store\n\t * @param\tint\t$ttl\tTime-to-live in seconds\n\t * @return\tvoid\n\t */\n\tpublic function set_tempdata($data, $value = NULL, $ttl = 300)\n\t{\n\t\t$this->set_userdata($data, $value);\n\t\t$this->mark_as_temp(is_array($data) ? array_keys($data) : $data, $ttl);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unset tempdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unset_tempdata($key)\n\t{\n\t\t$this->unmark_temp($key);\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/SessionHandlerInterface.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SessionHandlerInterface\n *\n * PHP 5.4 compatibility interface\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttp://codeigniter.com/user_guide/libraries/sessions.html\n */\ninterface SessionHandlerInterface {\n\n\tpublic function open($save_path, $name);\n\tpublic function close();\n\tpublic function read($session_id);\n\tpublic function write($session_id, $session_data);\n\tpublic function destroy($session_id);\n\tpublic function gc($maxlifetime);\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/Session_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Driver Class\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttp://codeigniter.com/user_guide/libraries/sessions.html\n */\nabstract class CI_Session_driver implements SessionHandlerInterface {\n\n\tprotected $_config;\n\n\t/**\n\t * Data fingerprint\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_fingerprint;\n\n\t/**\n\t * Lock placeholder\n\t *\n\t * @var\tmixed\n\t */\n\tprotected $_lock = FALSE;\n\n\t/**\n\t * Read session ID\n\t *\n\t * Used to detect session_regenerate_id() calls because PHP only calls\n\t * write() after regenerating the ID.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_session_id;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\t$this->_config =& $params;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cookie destroy\n\t *\n\t * Internal method to force removal of a cookie by the client\n\t * when session_destroy() is called.\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _cookie_destroy()\n\t{\n\t\treturn setcookie(\n\t\t\t$this->_config['cookie_name'],\n\t\t\tNULL,\n\t\t\t1,\n\t\t\t$this->_config['cookie_path'],\n\t\t\t$this->_config['cookie_domain'],\n\t\t\t$this->_config['cookie_secure'],\n\t\t\tTRUE\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * A dummy method allowing drivers with no locking functionality\n\t * (databases other than PostgreSQL and MySQL) to act as if they\n\t * do acquire a lock.\n\t *\n\t * @param\tstring\t$session_id\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\t$this->_lock = TRUE;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif ($this->_lock)\n\t\t{\n\t\t\t$this->_lock = FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/drivers/Session_database_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Database Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttp://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_database_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * DB object\n\t *\n\t * @var\tobject\n\t */\n\tprotected $_db;\n\n\t/**\n\t * Row exists flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_row_exists = FALSE;\n\n\t/**\n\t * Lock \"driver\" flag\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_platform;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\t$CI =& get_instance();\n\t\tisset($CI->db) OR $CI->load->database();\n\t\t$this->_db = $CI->db;\n\n\t\tif ( ! $this->_db instanceof CI_DB_query_builder)\n\t\t{\n\t\t\tthrow new Exception('Query Builder not enabled for the configured database. Aborting.');\n\t\t}\n\t\telseif ($this->_db->pconnect)\n\t\t{\n\t\t\tthrow new Exception('Configured database connection is persistent. Aborting.');\n\t\t}\n\t\telseif ($this->_db->cache_on)\n\t\t{\n\t\t\tthrow new Exception('Configured database connection has cache enabled. Aborting.');\n\t\t}\n\n\t\t$db_driver = $this->_db->dbdriver.(empty($this->_db->subdriver) ? '' : '_'.$this->_db->subdriver);\n\t\tif (strpos($db_driver, 'mysql') !== FALSE)\n\t\t{\n\t\t\t$this->_platform = 'mysql';\n\t\t}\n\t\telseif (in_array($db_driver, array('postgre', 'pdo_pgsql'), TRUE))\n\t\t{\n\t\t\t$this->_platform = 'postgre';\n\t\t}\n\n\t\t// Note: BC work-around for the old 'sess_table_name' setting, should be removed in the future.\n\t\tisset($this->_config['save_path']) OR $this->_config['save_path'] = config_item('sess_table_name');\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Initializes the database connection\n\t *\n\t * @param\tstring\t$save_path\tTable name\n\t * @param\tstring\t$name\t\tSession cookie name, unused\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\treturn empty($this->_db->conn_id)\n\t\t\t? (bool) $this->_db->db_connect()\n\t\t\t: TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\tif ($this->_get_lock($session_id) !== FALSE)\n\t\t{\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\t$this->_db\n\t\t\t\t->select('data')\n\t\t\t\t->from($this->_config['save_path'])\n\t\t\t\t->where('id', $session_id);\n\n\t\t\tif ($this->_config['match_ip'])\n\t\t\t{\n\t\t\t\t$this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);\n\t\t\t}\n\n\t\t\tif (($result = $this->_db->get()->row()) === NULL)\n\t\t\t{\n\t\t\t\t$this->_fingerprint = md5('');\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\t// PostgreSQL's variant of a BLOB datatype is Bytea, which is a\n\t\t\t// PITA to work with, so we use base64-encoded data in a TEXT\n\t\t\t// field instead.\n\t\t\t$result = ($this->_platform === 'postgre')\n\t\t\t\t? base64_decode(rtrim($result->data))\n\t\t\t\t: $result->data;\n\n\t\t\t$this->_fingerprint = md5($result);\n\t\t\t$this->_row_exists = TRUE;\n\t\t\treturn $result;\n\t\t}\n\n\t\t$this->_fingerprint = md5('');\n\t\treturn '';\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\t// Was the ID regenerated?\n\t\tif ($session_id !== $this->_session_id)\n\t\t{\n\t\t\tif ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_row_exists = FALSE;\n\t\t\t$this->_session_id = $session_id;\n\t\t}\n\t\telseif ($this->_lock === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->_row_exists === FALSE)\n\t\t{\n\t\t\t$insert_data = array(\n\t\t\t\t'id' => $session_id,\n\t\t\t\t'ip_address' => $_SERVER['REMOTE_ADDR'],\n\t\t\t\t'timestamp' => time(),\n\t\t\t\t'data' => ($this->_platform === 'postgre' ? base64_encode($session_data) : $session_data)\n\t\t\t);\n\n\t\t\tif ($this->_db->insert($this->_config['save_path'], $insert_data))\n\t\t\t{\n\t\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\t\treturn $this->_row_exists = TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_db->where('id', $session_id);\n\t\tif ($this->_config['match_ip'])\n\t\t{\n\t\t\t$this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);\n\t\t}\n\n\t\t$update_data = array('timestamp' => time());\n\t\tif ($this->_fingerprint !== md5($session_data))\n\t\t{\n\t\t\t$update_data['data'] = ($this->_platform === 'postgre')\n\t\t\t\t? base64_encode($session_data)\n\t\t\t\t: $session_data;\n\t\t}\n\n\t\tif ($this->_db->update($this->_config['save_path'], $update_data))\n\t\t{\n\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\treturn ($this->_lock)\n\t\t\t? $this->_release_lock()\n\t\t\t: TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif ($this->_lock)\n\t\t{\n\t\t\t$this->_db->where('id', $session_id);\n\t\t\tif ($this->_config['match_ip'])\n\t\t\t{\n\t\t\t\t$this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);\n\t\t\t}\n\n\t\t\treturn $this->_db->delete($this->_config['save_path'])\n\t\t\t\t? ($this->close() && $this->_cookie_destroy())\n\t\t\t\t: FALSE;\n\t\t}\n\n\t\treturn ($this->close() && $this->_cookie_destroy());\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\treturn $this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime));\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * Acquires a lock, depending on the underlying platform.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\tif ($this->_platform === 'mysql')\n\t\t{\n\t\t\t$arg = $session_id.($this->_config['match_ip'] ? '_'.$_SERVER['REMOTE_ADDR'] : '');\n\t\t\tif ($this->_db->query(\"SELECT GET_LOCK('\".$arg.\"', 300) AS ci_session_lock\")->row()->ci_session_lock)\n\t\t\t{\n\t\t\t\t$this->_lock = $arg;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($this->_platform === 'postgre')\n\t\t{\n\t\t\t$arg = \"hashtext('\".$session_id.\"')\".($this->_config['match_ip'] ? \", hashtext('\".$_SERVER['REMOTE_ADDR'].\"')\" : '');\n\t\t\tif ($this->_db->simple_query('SELECT pg_advisory_lock('.$arg.')'))\n\t\t\t{\n\t\t\t\t$this->_lock = $arg;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::_get_lock($session_id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * Releases a previously acquired lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif ( ! $this->_lock)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ($this->_platform === 'mysql')\n\t\t{\n\t\t\tif ($this->_db->query(\"SELECT RELEASE_LOCK('\".$this->_lock.\"') AS ci_session_lock\")->row()->ci_session_lock)\n\t\t\t{\n\t\t\t\t$this->_lock = FALSE;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($this->_platform === 'postgre')\n\t\t{\n\t\t\tif ($this->_db->simple_query('SELECT pg_advisory_unlock('.$this->_lock.')'))\n\t\t\t{\n\t\t\t\t$this->_lock = FALSE;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::_release_lock();\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/drivers/Session_files_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n*/\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Files Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttp://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_files_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * Save path\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_save_path;\n\n\t/**\n\t * File handle\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_file_handle;\n\n\t/**\n\t * File name\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_file_path;\n\n\t/**\n\t * File new flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_file_new;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (isset($this->_config['save_path']))\n\t\t{\n\t\t\t$this->_config['save_path'] = rtrim($this->_config['save_path'], '/\\\\');\n\t\t\tini_set('session.save_path', $this->_config['save_path']);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_config['save_path'] = rtrim(ini_get('session.save_path'), '/\\\\');\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Sanitizes the save_path directory.\n\t *\n\t * @param\tstring\t$save_path\tPath to session files' directory\n\t * @param\tstring\t$name\t\tSession cookie name\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\tif ( ! is_dir($save_path))\n\t\t{\n\t\t\tif ( ! mkdir($save_path, 0700, TRUE))\n\t\t\t{\n\t\t\t\tthrow new Exception(\"Session: Configured save path '\".$this->_config['save_path'].\"' is not a directory, doesn't exist or cannot be created.\");\n\t\t\t}\n\t\t}\n\t\telseif ( ! is_writable($save_path))\n\t\t{\n\t\t\tthrow new Exception(\"Session: Configured save path '\".$this->_config['save_path'].\"' is not writable by the PHP process.\");\n\t\t}\n\n\t\t$this->_config['save_path'] = $save_path;\n\t\t$this->_file_path = $this->_config['save_path'].DIRECTORY_SEPARATOR\n\t\t\t.$name // we'll use the session cookie name as a prefix to avoid collisions\n\t\t\t.($this->_config['match_ip'] ? md5($_SERVER['REMOTE_ADDR']) : '');\n\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\t// This might seem weird, but PHP 5.6 introduces session_reset(),\n\t\t// which re-reads session data\n\t\tif ($this->_file_handle === NULL)\n\t\t{\n\t\t\t// Just using fopen() with 'c+b' mode would be perfect, but it is only\n\t\t\t// available since PHP 5.2.6 and we have to set permissions for new files,\n\t\t\t// so we'd have to hack around this ...\n\t\t\tif (($this->_file_new = ! file_exists($this->_file_path.$session_id)) === TRUE)\n\t\t\t{\n\t\t\t\tif (($this->_file_handle = fopen($this->_file_path.$session_id, 'w+b')) === FALSE)\n\t\t\t\t{\n\t\t\t\t\tlog_message('error', \"Session: File '\".$this->_file_path.$session_id.\"' doesn't exist and cannot be created.\");\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (($this->_file_handle = fopen($this->_file_path.$session_id, 'r+b')) === FALSE)\n\t\t\t{\n\t\t\t\tlog_message('error', \"Session: Unable to open file '\".$this->_file_path.$session_id.\"'.\");\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (flock($this->_file_handle, LOCK_EX) === FALSE)\n\t\t\t{\n\t\t\t\tlog_message('error', \"Session: Unable to obtain lock for file '\".$this->_file_path.$session_id.\"'.\");\n\t\t\t\tfclose($this->_file_handle);\n\t\t\t\t$this->_file_handle = NULL;\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\tif ($this->_file_new)\n\t\t\t{\n\t\t\t\tchmod($this->_file_path.$session_id, 0600);\n\t\t\t\t$this->_fingerprint = md5('');\n\t\t\t\treturn '';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\trewind($this->_file_handle);\n\t\t}\n\n\t\t$session_data = '';\n\t\tfor ($read = 0, $length = filesize($this->_file_path.$session_id); $read < $length; $read += strlen($buffer))\n\t\t{\n\t\t\tif (($buffer = fread($this->_file_handle, $length - $read)) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$session_data .= $buffer;\n\t\t}\n\n\t\t$this->_fingerprint = md5($session_data);\n\t\treturn $session_data;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\t// If the two IDs don't match, we have a session_regenerate_id() call\n\t\t// and we need to close the old handle and open a new one\n\t\tif ($session_id !== $this->_session_id && ( ! $this->close() OR $this->read($session_id) === FALSE))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! is_resource($this->_file_handle))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($this->_fingerprint === md5($session_data))\n\t\t{\n\t\t\treturn ($this->_file_new)\n\t\t\t\t? TRUE\n\t\t\t\t: touch($this->_file_path.$session_id);\n\t\t}\n\n\t\tif ( ! $this->_file_new)\n\t\t{\n\t\t\tftruncate($this->_file_handle, 0);\n\t\t\trewind($this->_file_handle);\n\t\t}\n\n\t\tif (($length = strlen($session_data)) > 0)\n\t\t{\n\t\t\tfor ($written = 0; $written < $length; $written += $result)\n\t\t\t{\n\t\t\t\tif (($result = fwrite($this->_file_handle, substr($session_data, $written))) === FALSE)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( ! is_int($result))\n\t\t\t{\n\t\t\t\t$this->_fingerprint = md5(substr($session_data, 0, $written));\n\t\t\t\tlog_message('error', 'Session: Unable to write data.');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t$this->_fingerprint = md5($session_data);\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks and closes file descriptor.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\tif (is_resource($this->_file_handle))\n\t\t{\n\t\t\tflock($this->_file_handle, LOCK_UN);\n\t\t\tfclose($this->_file_handle);\n\n\t\t\t$this->_file_handle = $this->_file_new = $this->_session_id = NULL;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif ($this->close())\n\t\t{\n\t\t\treturn file_exists($this->_file_path.$session_id)\n\t\t\t\t? (unlink($this->_file_path.$session_id) && $this->_cookie_destroy())\n\t\t\t\t: TRUE;\n\t\t}\n\t\telseif ($this->_file_path !== NULL)\n\t\t{\n\t\t\tclearstatcache();\n\t\t\treturn file_exists($this->_file_path.$session_id)\n\t\t\t\t? (unlink($this->_file_path.$session_id) && $this->_cookie_destroy())\n\t\t\t\t: TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\tif ( ! is_dir($this->_config['save_path']) OR ($directory = opendir($this->_config['save_path'])) === FALSE)\n\t\t{\n\t\t\tlog_message('debug', \"Session: Garbage collector couldn't list files under directory '\".$this->_config['save_path'].\"'.\");\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$ts = time() - $maxlifetime;\n\n\t\t$pattern = sprintf(\n\t\t\t'/^%s[0-9a-f]{%d}$/',\n\t\t\tpreg_quote($this->_config['cookie_name'], '/'),\n\t\t\t($this->_config['match_ip'] === TRUE ? 72 : 40)\n\t\t);\n\n\t\twhile (($file = readdir($directory)) !== FALSE)\n\t\t{\n\t\t\t// If the filename doesn't match this pattern, it's either not a session file or is not ours\n\t\t\tif ( ! preg_match($pattern, $file)\n\t\t\t\tOR ! is_file($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)\n\t\t\t\tOR ($mtime = filemtime($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)) === FALSE\n\t\t\t\tOR $mtime > $ts)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tunlink($this->_config['save_path'].DIRECTORY_SEPARATOR.$file);\n\t\t}\n\n\t\tclosedir($directory);\n\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/drivers/Session_memcached_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Memcached Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttp://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_memcached_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * Memcached instance\n\t *\n\t * @var\tMemcached\n\t */\n\tprotected $_memcached;\n\n\t/**\n\t * Key prefix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_key_prefix = 'ci_session:';\n\n\t/**\n\t * Lock key\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_lock_key;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->_config['save_path']))\n\t\t{\n\t\t\tlog_message('error', 'Session: No Memcached save path configured.');\n\t\t}\n\n\t\tif ($this->_config['match_ip'] === TRUE)\n\t\t{\n\t\t\t$this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Sanitizes save_path and initializes connections.\n\t *\n\t * @param\tstring\t$save_path\tServer path(s)\n\t * @param\tstring\t$name\t\tSession cookie name, unused\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\t$this->_memcached = new Memcached();\n\t\t$this->_memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, TRUE); // required for touch() usage\n\t\t$server_list = array();\n\t\tforeach ($this->_memcached->getServerList() as $server)\n\t\t{\n\t\t\t$server_list[] = $server['host'].':'.$server['port'];\n\t\t}\n\n\t\tif ( ! preg_match_all('#,?([^,:]+)\\:(\\d{1,5})(?:\\:(\\d+))?#', $this->_config['save_path'], $matches, PREG_SET_ORDER))\n\t\t{\n\t\t\t$this->_memcached = NULL;\n\t\t\tlog_message('error', 'Session: Invalid Memcached save path format: '.$this->_config['save_path']);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tforeach ($matches as $match)\n\t\t{\n\t\t\t// If Memcached already has this server (or if the port is invalid), skip it\n\t\t\tif (in_array($match[1].':'.$match[2], $server_list, TRUE))\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Session: Memcached server pool already has '.$match[1].':'.$match[2]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ! $this->_memcached->addServer($match[1], $match[2], isset($match[3]) ? $match[3] : 0))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Could not add '.$match[1].':'.$match[2].' to Memcached server pool.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$server_list[] = $match[1].':'.$match[2];\n\t\t\t}\n\t\t}\n\n\t\tif (empty($server_list))\n\t\t{\n\t\t\tlog_message('error', 'Session: Memcached server pool is empty.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\tif (isset($this->_memcached) && $this->_get_lock($session_id))\n\t\t{\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\t$session_data = (string) $this->_memcached->get($this->_key_prefix.$session_id);\n\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\treturn $session_data;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\tif ( ! isset($this->_memcached))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t// Was the ID regenerated?\n\t\telseif ($session_id !== $this->_session_id)\n\t\t{\n\t\t\tif ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_fingerprint = md5('');\n\t\t\t$this->_session_id = $session_id;\n\t\t}\n\n\t\tif (isset($this->_lock_key))\n\t\t{\n\t\t\t$this->_memcached->replace($this->_lock_key, time(), 300);\n\t\t\tif ($this->_fingerprint !== ($fingerprint = md5($session_data)))\n\t\t\t{\n\t\t\t\tif ($this->_memcached->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))\n\t\t\t\t{\n\t\t\t\t\t$this->_fingerprint = $fingerprint;\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\treturn $this->_memcached->touch($this->_key_prefix.$session_id, $this->_config['expiration']);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks and closes connection.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\tif (isset($this->_memcached))\n\t\t{\n\t\t\tisset($this->_lock_key) && $this->_memcached->delete($this->_lock_key);\n\t\t\tif ( ! $this->_memcached->quit())\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_memcached = NULL;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif (isset($this->_memcached, $this->_lock_key))\n\t\t{\n\t\t\t$this->_memcached->delete($this->_key_prefix.$session_id);\n\t\t\treturn $this->_cookie_destroy();\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\t// Not necessary, Memcached takes care of that.\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * Acquires an (emulated) lock.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\tif (isset($this->_lock_key))\n\t\t{\n\t\t\treturn $this->_memcached->replace($this->_lock_key, time(), 300);\n\t\t}\n\n\t\t// 30 attempts to obtain a lock, in case another request already has it\n\t\t$lock_key = $this->_key_prefix.$session_id.':lock';\n\t\t$attempt = 0;\n\t\tdo\n\t\t{\n\t\t\tif ($this->_memcached->get($lock_key))\n\t\t\t{\n\t\t\t\tsleep(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ! $this->_memcached->set($lock_key, time(), 300))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = $lock_key;\n\t\t\tbreak;\n\t\t}\n\t\twhile (++$attempt < 30);\n\n\t\tif ($attempt === 30)\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_lock = TRUE;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * Releases a previously acquired lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif (isset($this->_memcached, $this->_lock_key) && $this->_lock)\n\t\t{\n\t\t\tif ( ! $this->_memcached->delete($this->_lock_key) && $this->_memcached->getResultCode() !== Memcached::RES_NOTFOUND)\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = NULL;\n\t\t\t$this->_lock = FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/drivers/Session_redis_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Redis Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttp://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_redis_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * phpRedis instance\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_redis;\n\n\t/**\n\t * Key prefix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_key_prefix = 'ci_session:';\n\n\t/**\n\t * Lock key\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_lock_key;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->_config['save_path']))\n\t\t{\n\t\t\tlog_message('error', 'Session: No Redis save path configured.');\n\t\t}\n\t\telseif (preg_match('#(?:tcp://)?([^:?]+)(?:\\:(\\d+))?(\\?.+)?#', $this->_config['save_path'], $matches))\n\t\t{\n\t\t\tisset($matches[3]) OR $matches[3] = ''; // Just to avoid undefined index notices below\n\t\t\t$this->_config['save_path'] = array(\n\t\t\t\t'host' => $matches[1],\n\t\t\t\t'port' => empty($matches[2]) ? NULL : $matches[2],\n\t\t\t\t'password' => preg_match('#auth=([^\\s&]+)#', $matches[3], $match) ? $match[1] : NULL,\n\t\t\t\t'database' => preg_match('#database=(\\d+)#', $matches[3], $match) ? (int) $match[1] : NULL,\n\t\t\t\t'timeout' => preg_match('#timeout=(\\d+\\.\\d+)#', $matches[3], $match) ? (float) $match[1] : NULL\n\t\t\t);\n\n\t\t\tpreg_match('#prefix=([^\\s&]+)#', $matches[3], $match) && $this->_key_prefix = $match[1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', 'Session: Invalid Redis save path format: '.$this->_config['save_path']);\n\t\t}\n\n\t\tif ($this->_config['match_ip'] === TRUE)\n\t\t{\n\t\t\t$this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Sanitizes save_path and initializes connection.\n\t *\n\t * @param\tstring\t$save_path\tServer path\n\t * @param\tstring\t$name\t\tSession cookie name, unused\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\tif (empty($this->_config['save_path']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$redis = new Redis();\n\t\tif ( ! $redis->connect($this->_config['save_path']['host'], $this->_config['save_path']['port'], $this->_config['save_path']['timeout']))\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to connect to Redis with the configured settings.');\n\t\t}\n\t\telseif (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password']))\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to authenticate to Redis instance.');\n\t\t}\n\t\telseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database']))\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_redis = $redis;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\tif (isset($this->_redis) && $this->_get_lock($session_id))\n\t\t{\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\t$session_data = (string) $this->_redis->get($this->_key_prefix.$session_id);\n\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\treturn $session_data;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\tif ( ! isset($this->_redis))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t// Was the ID regenerated?\n\t\telseif ($session_id !== $this->_session_id)\n\t\t{\n\t\t\tif ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_fingerprint = md5('');\n\t\t\t$this->_session_id = $session_id;\n\t\t}\n\n\t\tif (isset($this->_lock_key))\n\t\t{\n\t\t\t$this->_redis->setTimeout($this->_lock_key, 300);\n\t\t\tif ($this->_fingerprint !== ($fingerprint = md5($session_data)))\n\t\t\t{\n\t\t\t\tif ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))\n\t\t\t\t{\n\t\t\t\t\t$this->_fingerprint = $fingerprint;\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\treturn $this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration']);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks and closes connection.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\tif (isset($this->_redis))\n\t\t{\n\t\t\ttry {\n\t\t\t\tif ($this->_redis->ping() === '+PONG')\n\t\t\t\t{\n\t\t\t\t\tisset($this->_lock_key) && $this->_redis->delete($this->_lock_key);\n\t\t\t\t\tif ( ! $this->_redis->close())\n\t\t\t\t\t{\n\t\t\t\t\t\treturn FALSE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (RedisException $e)\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Got RedisException on close(): '.$e->getMessage());\n\t\t\t}\n\n\t\t\t$this->_redis = NULL;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif (isset($this->_redis, $this->_lock_key))\n\t\t{\n\t\t\tif (($result = $this->_redis->delete($this->_key_prefix.$session_id)) !== 1)\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Session: Redis::delete() expected to return 1, got '.var_export($result, TRUE).' instead.');\n\t\t\t}\n\n\t\t\treturn $this->_cookie_destroy();\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\t// Not necessary, Redis takes care of that.\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * Acquires an (emulated) lock.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\tif (isset($this->_lock_key))\n\t\t{\n\t\t\treturn $this->_redis->setTimeout($this->_lock_key, 300);\n\t\t}\n\n\t\t// 30 attempts to obtain a lock, in case another request already has it\n\t\t$lock_key = $this->_key_prefix.$session_id.':lock';\n\t\t$attempt = 0;\n\t\tdo\n\t\t{\n\t\t\tif (($ttl = $this->_redis->ttl($lock_key)) > 0)\n\t\t\t{\n\t\t\t\tsleep(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ! $this->_redis->setex($lock_key, 300, time()))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = $lock_key;\n\t\t\tbreak;\n\t\t}\n\t\twhile (++$attempt < 30);\n\n\t\tif ($attempt === 30)\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.');\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($ttl === -1)\n\t\t{\n\t\t\tlog_message('debug', 'Session: Lock for '.$this->_key_prefix.$session_id.' had no TTL, overriding.');\n\t\t}\n\n\t\t$this->_lock = TRUE;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * Releases a previously acquired lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif (isset($this->_redis, $this->_lock_key) && $this->_lock)\n\t\t{\n\t\t\tif ( ! $this->_redis->delete($this->_lock_key))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = NULL;\n\t\t\t$this->_lock = FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/drivers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Session/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Table.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.3.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * HTML Table Generating Class\n *\n * Lets you create tables manually or from database result objects, or arrays.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tHTML Tables\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/table.html\n */\nclass CI_Table {\n\n\t/**\n\t * Data for table rows\n\t *\n\t * @var array\n\t */\n\tpublic $rows\t\t= array();\n\n\t/**\n\t * Data for table heading\n\t *\n\t * @var array\n\t */\n\tpublic $heading\t\t= array();\n\n\t/**\n\t * Whether or not to automatically create the table header\n\t *\n\t * @var bool\n\t */\n\tpublic $auto_heading\t= TRUE;\n\n\t/**\n\t * Table caption\n\t *\n\t * @var string\n\t */\n\tpublic $caption\t\t= NULL;\n\n\t/**\n\t * Table layout template\n\t *\n\t * @var array\n\t */\n\tpublic $template\t= NULL;\n\n\t/**\n\t * Newline setting\n\t *\n\t * @var string\n\t */\n\tpublic $newline\t\t= \"\\n\";\n\n\t/**\n\t * Contents of empty cells\n\t *\n\t * @var string\n\t */\n\tpublic $empty_cells\t= '';\n\n\t/**\n\t * Callback for custom table layout\n\t *\n\t * @var function\n\t */\n\tpublic $function\t= NULL;\n\n\t/**\n\t * Set the template from the table config file if it exists\n\t *\n\t * @param\tarray\t$config\t(default: array())\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t// initialize config\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\t$this->template[$key] = $val;\n\t\t}\n\n\t\tlog_message('info', 'Table Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the template\n\t *\n\t * @param\tarray\t$template\n\t * @return\tbool\n\t */\n\tpublic function set_template($template)\n\t{\n\t\tif ( ! is_array($template))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->template = $template;\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the table heading\n\t *\n\t * Can be passed as an array or discreet params\n\t *\n\t * @param\tmixed\n\t * @return\tCI_Table\n\t */\n\tpublic function set_heading($args = array())\n\t{\n\t\t$this->heading = $this->_prep_args(func_get_args());\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set columns. Takes a one-dimensional array as input and creates\n\t * a multi-dimensional array with a depth equal to the number of\n\t * columns. This allows a single array with many elements to be\n\t * displayed in a table that has a fixed column count.\n\t *\n\t * @param\tarray\t$array\n\t * @param\tint\t$col_limit\n\t * @return\tarray\n\t */\n\tpublic function make_columns($array = array(), $col_limit = 0)\n\t{\n\t\tif ( ! is_array($array) OR count($array) === 0 OR ! is_int($col_limit))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Turn off the auto-heading feature since it's doubtful we\n\t\t// will want headings from a one-dimensional array\n\t\t$this->auto_heading = FALSE;\n\n\t\tif ($col_limit === 0)\n\t\t{\n\t\t\treturn $array;\n\t\t}\n\n\t\t$new = array();\n\t\tdo\n\t\t{\n\t\t\t$temp = array_splice($array, 0, $col_limit);\n\n\t\t\tif (count($temp) < $col_limit)\n\t\t\t{\n\t\t\t\tfor ($i = count($temp); $i < $col_limit; $i++)\n\t\t\t\t{\n\t\t\t\t\t$temp[] = '&nbsp;';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$new[] = $temp;\n\t\t}\n\t\twhile (count($array) > 0);\n\n\t\treturn $new;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set \"empty\" cells\n\t *\n\t * Can be passed as an array or discreet params\n\t *\n\t * @param\tmixed\t$value\n\t * @return\tCI_Table\n\t */\n\tpublic function set_empty($value)\n\t{\n\t\t$this->empty_cells = $value;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add a table row\n\t *\n\t * Can be passed as an array or discreet params\n\t *\n\t * @param\tmixed\n\t * @return\tCI_Table\n\t */\n\tpublic function add_row($args = array())\n\t{\n\t\t$this->rows[] = $this->_prep_args(func_get_args());\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Args\n\t *\n\t * Ensures a standard associative array format for all cell data\n\t *\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tprotected function _prep_args($args)\n\t{\n\t\t// If there is no $args[0], skip this and treat as an associative array\n\t\t// This can happen if there is only a single key, for example this is passed to table->generate\n\t\t// array(array('foo'=>'bar'))\n\t\tif (isset($args[0]) && count($args) === 1 && is_array($args[0]) && ! isset($args[0]['data']))\n\t\t{\n\t\t\t$args = $args[0];\n\t\t}\n\n\t\tforeach ($args as $key => $val)\n\t\t{\n\t\t\tis_array($val) OR $args[$key] = array('data' => $val);\n\t\t}\n\n\t\treturn $args;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add a table caption\n\t *\n\t * @param\tstring\t$caption\n\t * @return\tCI_Table\n\t */\n\tpublic function set_caption($caption)\n\t{\n\t\t$this->caption = $caption;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate the table\n\t *\n\t * @param\tmixed\t$table_data\n\t * @return\tstring\n\t */\n\tpublic function generate($table_data = NULL)\n\t{\n\t\t// The table data can optionally be passed to this function\n\t\t// either as a database result object or an array\n\t\tif ( ! empty($table_data))\n\t\t{\n\t\t\tif ($table_data instanceof CI_DB_result)\n\t\t\t{\n\t\t\t\t$this->_set_from_db_result($table_data);\n\t\t\t}\n\t\t\telseif (is_array($table_data))\n\t\t\t{\n\t\t\t\t$this->_set_from_array($table_data);\n\t\t\t}\n\t\t}\n\n\t\t// Is there anything to display? No? Smite them!\n\t\tif (empty($this->heading) && empty($this->rows))\n\t\t{\n\t\t\treturn 'Undefined table data';\n\t\t}\n\n\t\t// Compile and validate the template date\n\t\t$this->_compile_template();\n\n\t\t// Validate a possibly existing custom cell manipulation function\n\t\tif (isset($this->function) && ! is_callable($this->function))\n\t\t{\n\t\t\t$this->function = NULL;\n\t\t}\n\n\t\t// Build the table!\n\n\t\t$out = $this->template['table_open'].$this->newline;\n\n\t\t// Add any caption here\n\t\tif ($this->caption)\n\t\t{\n\t\t\t$out .= '<caption>'.$this->caption.'</caption>'.$this->newline;\n\t\t}\n\n\t\t// Is there a table heading to display?\n\t\tif ( ! empty($this->heading))\n\t\t{\n\t\t\t$out .= $this->template['thead_open'].$this->newline.$this->template['heading_row_start'].$this->newline;\n\n\t\t\tforeach ($this->heading as $heading)\n\t\t\t{\n\t\t\t\t$temp = $this->template['heading_cell_start'];\n\n\t\t\t\tforeach ($heading as $key => $val)\n\t\t\t\t{\n\t\t\t\t\tif ($key !== 'data')\n\t\t\t\t\t{\n\t\t\t\t\t\t$temp = str_replace('<th', '<th '.$key.'=\"'.$val.'\"', $temp);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$out .= $temp.(isset($heading['data']) ? $heading['data'] : '').$this->template['heading_cell_end'];\n\t\t\t}\n\n\t\t\t$out .= $this->template['heading_row_end'].$this->newline.$this->template['thead_close'].$this->newline;\n\t\t}\n\n\t\t// Build the table rows\n\t\tif ( ! empty($this->rows))\n\t\t{\n\t\t\t$out .= $this->template['tbody_open'].$this->newline;\n\n\t\t\t$i = 1;\n\t\t\tforeach ($this->rows as $row)\n\t\t\t{\n\t\t\t\tif ( ! is_array($row))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// We use modulus to alternate the row colors\n\t\t\t\t$name = fmod($i++, 2) ? '' : 'alt_';\n\n\t\t\t\t$out .= $this->template['row_'.$name.'start'].$this->newline;\n\n\t\t\t\tforeach ($row as $cell)\n\t\t\t\t{\n\t\t\t\t\t$temp = $this->template['cell_'.$name.'start'];\n\n\t\t\t\t\tforeach ($cell as $key => $val)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ($key !== 'data')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$temp = str_replace('<td', '<td '.$key.'=\"'.$val.'\"', $temp);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t$cell = isset($cell['data']) ? $cell['data'] : '';\n\t\t\t\t\t$out .= $temp;\n\n\t\t\t\t\tif ($cell === '' OR $cell === NULL)\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= $this->empty_cells;\n\t\t\t\t\t}\n\t\t\t\t\telseif (isset($this->function))\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= call_user_func($this->function, $cell);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= $cell;\n\t\t\t\t\t}\n\n\t\t\t\t\t$out .= $this->template['cell_'.$name.'end'];\n\t\t\t\t}\n\n\t\t\t\t$out .= $this->template['row_'.$name.'end'].$this->newline;\n\t\t\t}\n\n\t\t\t$out .= $this->template['tbody_close'].$this->newline;\n\t\t}\n\n\t\t$out .= $this->template['table_close'];\n\n\t\t// Clear table class properties before generating the table\n\t\t$this->clear();\n\n\t\treturn $out;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clears the table arrays.  Useful if multiple tables are being generated\n\t *\n\t * @return\tCI_Table\n\t */\n\tpublic function clear()\n\t{\n\t\t$this->rows = array();\n\t\t$this->heading = array();\n\t\t$this->auto_heading = TRUE;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set table data from a database result object\n\t *\n\t * @param\tCI_DB_result\t$db_result\tDatabase result object\n\t * @return\tvoid\n\t */\n\tprotected function _set_from_db_result($object)\n\t{\n\t\t// First generate the headings from the table column names\n\t\tif ($this->auto_heading === TRUE && empty($this->heading))\n\t\t{\n\t\t\t$this->heading = $this->_prep_args($object->list_fields());\n\t\t}\n\n\t\tforeach ($object->result_array() as $row)\n\t\t{\n\t\t\t$this->rows[] = $this->_prep_args($row);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set table data from an array\n\t *\n\t * @param\tarray\t$data\n\t * @return\tvoid\n\t */\n\tprotected function _set_from_array($data)\n\t{\n\t\tif ($this->auto_heading === TRUE && empty($this->heading))\n\t\t{\n\t\t\t$this->heading = $this->_prep_args(array_shift($data));\n\t\t}\n\n\t\tforeach ($data as &$row)\n\t\t{\n\t\t\t$this->rows[] = $this->_prep_args($row);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile Template\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _compile_template()\n\t{\n\t\tif ($this->template === NULL)\n\t\t{\n\t\t\t$this->template = $this->_default_template();\n\t\t\treturn;\n\t\t}\n\n\t\t$this->temp = $this->_default_template();\n\t\tforeach (array('table_open', 'thead_open', 'thead_close', 'heading_row_start', 'heading_row_end', 'heading_cell_start', 'heading_cell_end', 'tbody_open', 'tbody_close', 'row_start', 'row_end', 'cell_start', 'cell_end', 'row_alt_start', 'row_alt_end', 'cell_alt_start', 'cell_alt_end', 'table_close') as $val)\n\t\t{\n\t\t\tif ( ! isset($this->template[$val]))\n\t\t\t{\n\t\t\t\t$this->template[$val] = $this->temp[$val];\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Default Template\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _default_template()\n\t{\n\t\treturn array(\n\t\t\t'table_open'\t\t=> '<table border=\"0\" cellpadding=\"4\" cellspacing=\"0\">',\n\n\t\t\t'thead_open'\t\t=> '<thead>',\n\t\t\t'thead_close'\t\t=> '</thead>',\n\n\t\t\t'heading_row_start'\t=> '<tr>',\n\t\t\t'heading_row_end'\t=> '</tr>',\n\t\t\t'heading_cell_start'\t=> '<th>',\n\t\t\t'heading_cell_end'\t=> '</th>',\n\n\t\t\t'tbody_open'\t\t=> '<tbody>',\n\t\t\t'tbody_close'\t\t=> '</tbody>',\n\n\t\t\t'row_start'\t\t=> '<tr>',\n\t\t\t'row_end'\t\t=> '</tr>',\n\t\t\t'cell_start'\t\t=> '<td>',\n\t\t\t'cell_end'\t\t=> '</td>',\n\n\t\t\t'row_alt_start'\t\t=> '<tr>',\n\t\t\t'row_alt_end'\t\t=> '</tr>',\n\t\t\t'cell_alt_start'\t=> '<td>',\n\t\t\t'cell_alt_end'\t\t=> '</td>',\n\n\t\t\t'table_close'\t\t=> '</table>'\n\t\t);\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Trackback.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Trackback Class\n *\n * Trackback Sending/Receiving Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tTrackbacks\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/trackback.html\n */\nclass CI_Trackback {\n\n\t/**\n\t * Character set\n\t *\n\t * @var\tstring\n\t */\n\tpublic $charset = 'UTF-8';\n\n\t/**\n\t * Trackback data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $data = array(\n\t\t'url' => '',\n\t\t'title' => '',\n\t\t'excerpt' => '',\n\t\t'blog_name' => '',\n\t\t'charset' => ''\n\t);\n\n\t/**\n\t * Convert ASCII flag\n\t *\n\t * Whether to convert high-ASCII and MS Word\n\t * characters to HTML entities.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $convert_ascii = TRUE;\n\n\t/**\n\t * Response\n\t *\n\t * @var\tstring\n\t */\n\tpublic $response = '';\n\n\t/**\n\t * Error messages list\n\t *\n\t * @var\tstring[]\n\t */\n\tpublic $error_msg = array();\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tlog_message('info', 'Trackback Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Trackback\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function send($tb_data)\n\t{\n\t\tif ( ! is_array($tb_data))\n\t\t{\n\t\t\t$this->set_error('The send() method must be passed an array');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Pre-process the Trackback Data\n\t\tforeach (array('url', 'title', 'excerpt', 'blog_name', 'ping_url') as $item)\n\t\t{\n\t\t\tif ( ! isset($tb_data[$item]))\n\t\t\t{\n\t\t\t\t$this->set_error('Required item missing: '.$item);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tswitch ($item)\n\t\t\t{\n\t\t\t\tcase 'ping_url':\n\t\t\t\t\t$$item = $this->extract_urls($tb_data[$item]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'excerpt':\n\t\t\t\t\t$$item = $this->limit_characters($this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'url':\n\t\t\t\t\t$$item = str_replace('&#45;', '-', $this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t$$item = $this->convert_xml(strip_tags(stripslashes($tb_data[$item])));\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Convert High ASCII Characters\n\t\t\tif ($this->convert_ascii === TRUE && in_array($item, array('excerpt', 'title', 'blog_name'), TRUE))\n\t\t\t{\n\t\t\t\t$$item = $this->convert_ascii($$item);\n\t\t\t}\n\t\t}\n\n\t\t// Build the Trackback data string\n\t\t$charset = isset($tb_data['charset']) ? $tb_data['charset'] : $this->charset;\n\n\t\t$data = 'url='.rawurlencode($url).'&title='.rawurlencode($title).'&blog_name='.rawurlencode($blog_name)\n\t\t\t.'&excerpt='.rawurlencode($excerpt).'&charset='.rawurlencode($charset);\n\n\t\t// Send Trackback(s)\n\t\t$return = TRUE;\n\t\tif (count($ping_url) > 0)\n\t\t{\n\t\t\tforeach ($ping_url as $url)\n\t\t\t{\n\t\t\t\tif ($this->process($url, $data) === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$return = FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $return;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Receive Trackback  Data\n\t *\n\t * This function simply validates the incoming TB data.\n\t * It returns FALSE on failure and TRUE on success.\n\t * If the data is valid it is set to the $this->data array\n\t * so that it can be inserted into a database.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function receive()\n\t{\n\t\tforeach (array('url', 'title', 'blog_name', 'excerpt') as $val)\n\t\t{\n\t\t\tif (empty($_POST[$val]))\n\t\t\t{\n\t\t\t\t$this->set_error('The following required POST variable is missing: '.$val);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->data['charset'] = isset($_POST['charset']) ? strtoupper(trim($_POST['charset'])) : 'auto';\n\n\t\t\tif ($val !== 'url' && MB_ENABLED === TRUE)\n\t\t\t{\n\t\t\t\tif (MB_ENABLED === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$_POST[$val] = mb_convert_encoding($_POST[$val], $this->charset, $this->data['charset']);\n\t\t\t\t}\n\t\t\t\telseif (ICONV_ENABLED === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$_POST[$val] = @iconv($this->data['charset'], $this->charset.'//IGNORE', $_POST[$val]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$_POST[$val] = ($val !== 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]);\n\n\t\t\tif ($val === 'excerpt')\n\t\t\t{\n\t\t\t\t$_POST['excerpt'] = $this->limit_characters($_POST['excerpt']);\n\t\t\t}\n\n\t\t\t$this->data[$val] = $_POST[$val];\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Trackback Error Message\n\t *\n\t * Allows custom errors to be set. By default it\n\t * sends the \"incomplete information\" error, as that's\n\t * the most common one.\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function send_error($message = 'Incomplete Information')\n\t{\n\t\texit('<?xml version=\"1.0\" encoding=\"utf-8\"?'.\">\\n<response>\\n<error>1</error>\\n<message>\".$message.\"</message>\\n</response>\");\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Trackback Success Message\n\t *\n\t * This should be called when a trackback has been\n\t * successfully received and inserted.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function send_success()\n\t{\n\t\texit('<?xml version=\"1.0\" encoding=\"utf-8\"?'.\">\\n<response>\\n<error>0</error>\\n</response>\");\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch a particular item\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function data($item)\n\t{\n\t\treturn isset($this->data[$item]) ? $this->data[$item] : '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process Trackback\n\t *\n\t * Opens a socket connection and passes the data to\n\t * the server. Returns TRUE on success, FALSE on failure\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function process($url, $data)\n\t{\n\t\t$target = parse_url($url);\n\n\t\t// Open the socket\n\t\tif ( ! $fp = @fsockopen($target['host'], 80))\n\t\t{\n\t\t\t$this->set_error('Invalid Connection: '.$url);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Build the path\n\t\t$path = isset($target['path']) ? $target['path'] : $url;\n\t\tempty($target['query']) OR $path .= '?'.$target['query'];\n\n\t\t// Add the Trackback ID to the data string\n\t\tif ($id = $this->get_id($url))\n\t\t{\n\t\t\t$data = 'tb_id='.$id.'&'.$data;\n\t\t}\n\n\t\t// Transfer the data\n\t\tfputs($fp, 'POST '.$path.\" HTTP/1.0\\r\\n\");\n\t\tfputs($fp, 'Host: '.$target['host'].\"\\r\\n\");\n\t\tfputs($fp, \"Content-type: application/x-www-form-urlencoded\\r\\n\");\n\t\tfputs($fp, 'Content-length: '.strlen($data).\"\\r\\n\");\n\t\tfputs($fp, \"Connection: close\\r\\n\\r\\n\");\n\t\tfputs($fp, $data);\n\n\t\t// Was it successful?\n\n\t\t$this->response = '';\n\t\twhile ( ! feof($fp))\n\t\t{\n\t\t\t$this->response .= fgets($fp, 128);\n\t\t}\n\t\t@fclose($fp);\n\n\t\tif (stripos($this->response, '<error>0</error>') === FALSE)\n\t\t{\n\t\t\t$message = preg_match('/<message>(.*?)<\\/message>/is', $this->response, $match)\n\t\t\t\t? trim($match[1])\n\t\t\t\t: 'An unknown error was encountered';\n\t\t\t$this->set_error($message);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extract Trackback URLs\n\t *\n\t * This function lets multiple trackbacks be sent.\n\t * It takes a string of URLs (separated by comma or\n\t * space) and puts each URL into an array\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function extract_urls($urls)\n\t{\n\t\t// Remove the pesky white space and replace with a comma, then replace doubles.\n\t\t$urls = str_replace(',,', ',', preg_replace('/\\s*(\\S+)\\s*/', '\\\\1,', $urls));\n\n\t\t// Break into an array via commas and remove duplicates\n\t\t$urls = array_unique(preg_split('/[,]/', rtrim($urls, ',')));\n\n\t\tarray_walk($urls, array($this, 'validate_url'));\n\t\treturn $urls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate URL\n\t *\n\t * Simply adds \"http://\" if missing\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function validate_url(&$url)\n\t{\n\t\t$url = trim($url);\n\n\t\tif (strpos($url, 'http') !== 0)\n\t\t{\n\t\t\t$url = 'http://'.$url;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Find the Trackback URL's ID\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function get_id($url)\n\t{\n\t\t$tb_id = '';\n\n\t\tif (strpos($url, '?') !== FALSE)\n\t\t{\n\t\t\t$tb_array = explode('/', $url);\n\t\t\t$tb_end   = $tb_array[count($tb_array)-1];\n\n\t\t\tif ( ! is_numeric($tb_end))\n\t\t\t{\n\t\t\t\t$tb_end  = $tb_array[count($tb_array)-2];\n\t\t\t}\n\n\t\t\t$tb_array = explode('=', $tb_end);\n\t\t\t$tb_id\t= $tb_array[count($tb_array)-1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$url = rtrim($url, '/');\n\n\t\t\t$tb_array = explode('/', $url);\n\t\t\t$tb_id\t= $tb_array[count($tb_array)-1];\n\n\t\t\tif ( ! is_numeric($tb_id))\n\t\t\t{\n\t\t\t\t$tb_id = $tb_array[count($tb_array)-2];\n\t\t\t}\n\t\t}\n\n\t\treturn ctype_digit((string) $tb_id) ? $tb_id : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert Reserved XML characters to Entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function convert_xml($str)\n\t{\n\t\t$temp = '__TEMP_AMPERSANDS__';\n\n\t\t$str = preg_replace(array('/&#(\\d+);/', '/&(\\w+);/'), $temp.'\\\\1;', $str);\n\n\t\t$str = str_replace(array('&', '<', '>', '\"', \"'\", '-'),\n\t\t\t\t\tarray('&amp;', '&lt;', '&gt;', '&quot;', '&#39;', '&#45;'),\n\t\t\t\t\t$str);\n\n\t\treturn preg_replace(array('/'.$temp.'(\\d+);/', '/'.$temp.'(\\w+);/'), array('&#\\\\1;', '&\\\\1;'), $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Character limiter\n\t *\n\t * Limits the string based on the character count. Will preserve complete words.\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function limit_characters($str, $n = 500, $end_char = '&#8230;')\n\t{\n\t\tif (strlen($str) < $n)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t$str = preg_replace('/\\s+/', ' ', str_replace(array(\"\\r\\n\", \"\\r\", \"\\n\"), ' ', $str));\n\n\t\tif (strlen($str) <= $n)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t$out = '';\n\t\tforeach (explode(' ', trim($str)) as $val)\n\t\t{\n\t\t\t$out .= $val.' ';\n\t\t\tif (strlen($out) >= $n)\n\t\t\t{\n\t\t\t\treturn rtrim($out).$end_char;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * High ASCII to Entities\n\t *\n\t * Converts Hight ascii text and MS Word special chars\n\t * to character entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function convert_ascii($str)\n\t{\n\t\t$count\t= 1;\n\t\t$out\t= '';\n\t\t$temp\t= array();\n\n\t\tfor ($i = 0, $s = strlen($str); $i < $s; $i++)\n\t\t{\n\t\t\t$ordinal = ord($str[$i]);\n\n\t\t\tif ($ordinal < 128)\n\t\t\t{\n\t\t\t\t$out .= $str[$i];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (count($temp) === 0)\n\t\t\t\t{\n\t\t\t\t\t$count = ($ordinal < 224) ? 2 : 3;\n\t\t\t\t}\n\n\t\t\t\t$temp[] = $ordinal;\n\n\t\t\t\tif (count($temp) === $count)\n\t\t\t\t{\n\t\t\t\t\t$number = ($count === 3)\n\t\t\t\t\t\t? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64)\n\t\t\t\t\t\t: (($temp[0] % 32) * 64) + ($temp[1] % 64);\n\n\t\t\t\t\t$out .= '&#'.$number.';';\n\t\t\t\t\t$count = 1;\n\t\t\t\t\t$temp = array();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $out;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set error message\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_error($msg)\n\t{\n\t\tlog_message('error', $msg);\n\t\t$this->error_msg[] = $msg;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show error messages\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function display_errors($open = '<p>', $close = '</p>')\n\t{\n\t\treturn (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Typography.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Typography Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/typography.html\n */\nclass CI_Typography {\n\n\t/**\n\t * Block level elements that should not be wrapped inside <p> tags\n\t *\n\t * @var string\n\t */\n\tpublic $block_elements = 'address|blockquote|div|dl|fieldset|form|h\\d|hr|noscript|object|ol|p|pre|script|table|ul';\n\n\t/**\n\t * Elements that should not have <p> and <br /> tags within them.\n\t *\n\t * @var string\n\t */\n\tpublic $skip_elements\t= 'p|pre|ol|ul|dl|object|table|h\\d';\n\n\t/**\n\t * Tags we want the parser to completely ignore when splitting the string.\n\t *\n\t * @var string\n\t */\n\tpublic $inline_elements = 'a|abbr|acronym|b|bdo|big|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|q|samp|select|small|span|strong|sub|sup|textarea|tt|var';\n\n\t/**\n\t * array of block level elements that require inner content to be within another block level element\n\t *\n\t * @var array\n\t */\n\tpublic $inner_block_required = array('blockquote');\n\n\t/**\n\t * the last block element parsed\n\t *\n\t * @var string\n\t */\n\tpublic $last_block_element = '';\n\n\t/**\n\t * whether or not to protect quotes within { curly braces }\n\t *\n\t * @var bool\n\t */\n\tpublic $protect_braced_quotes = FALSE;\n\n\t/**\n\t * Auto Typography\n\t *\n\t * This function converts text, making it typographically correct:\n\t *\t- Converts double spaces into paragraphs.\n\t *\t- Converts single line breaks into <br /> tags\n\t *\t- Converts single and double quotes into correctly facing curly quote entities.\n\t *\t- Converts three dots into ellipsis.\n\t *\t- Converts double dashes into em-dashes.\n\t *  - Converts two spaces into entities\n\t *\n\t * @param\tstring\n\t * @param\tbool\twhether to reduce more then two consecutive newlines to two\n\t * @return\tstring\n\t */\n\tpublic function auto_typography($str, $reduce_linebreaks = FALSE)\n\t{\n\t\tif ($str === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t// Standardize Newlines to make matching easier\n\t\tif (strpos($str, \"\\r\") !== FALSE)\n\t\t{\n\t\t\t$str = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\n\t\t}\n\n\t\t// Reduce line breaks.  If there are more than two consecutive linebreaks\n\t\t// we'll compress them down to a maximum of two since there's no benefit to more.\n\t\tif ($reduce_linebreaks === TRUE)\n\t\t{\n\t\t\t$str = preg_replace(\"/\\n\\n+/\", \"\\n\\n\", $str);\n\t\t}\n\n\t\t// HTML comment tags don't conform to patterns of normal tags, so pull them out separately, only if needed\n\t\t$html_comments = array();\n\t\tif (strpos($str, '<!--') !== FALSE && preg_match_all('#(<!\\-\\-.*?\\-\\->)#s', $str, $matches))\n\t\t{\n\t\t\tfor ($i = 0, $total = count($matches[0]); $i < $total; $i++)\n\t\t\t{\n\t\t\t\t$html_comments[] = $matches[0][$i];\n\t\t\t\t$str = str_replace($matches[0][$i], '{@HC'.$i.'}', $str);\n\t\t\t}\n\t\t}\n\n\t\t// match and yank <pre> tags if they exist.  It's cheaper to do this separately since most content will\n\t\t// not contain <pre> tags, and it keeps the PCRE patterns below simpler and faster\n\t\tif (strpos($str, '<pre') !== FALSE)\n\t\t{\n\t\t\t$str = preg_replace_callback('#<pre.*?>.*?</pre>#si', array($this, '_protect_characters'), $str);\n\t\t}\n\n\t\t// Convert quotes within tags to temporary markers.\n\t\t$str = preg_replace_callback('#<.+?>#si', array($this, '_protect_characters'), $str);\n\n\t\t// Do the same with braces if necessary\n\t\tif ($this->protect_braced_quotes === TRUE)\n\t\t{\n\t\t\t$str = preg_replace_callback('#\\{.+?\\}#si', array($this, '_protect_characters'), $str);\n\t\t}\n\n\t\t// Convert \"ignore\" tags to temporary marker.  The parser splits out the string at every tag\n\t\t// it encounters.  Certain inline tags, like image tags, links, span tags, etc. will be\n\t\t// adversely affected if they are split out so we'll convert the opening bracket < temporarily to: {@TAG}\n\t\t$str = preg_replace('#<(/*)('.$this->inline_elements.')([ >])#i', '{@TAG}\\\\1\\\\2\\\\3', $str);\n\n\t\t/* Split the string at every tag. This expression creates an array with this prototype:\n\t\t *\n\t\t *\t[array]\n\t\t *\t{\n\t\t *\t\t[0] = <opening tag>\n\t\t *\t\t[1] = Content...\n\t\t *\t\t[2] = <closing tag>\n\t\t *\t\tEtc...\n\t\t *\t}\n\t\t */\n\t\t$chunks = preg_split('/(<(?:[^<>]+(?:\"[^\"]*\"|\\'[^\\']*\\')?)+>)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);\n\n\t\t// Build our finalized string.  We cycle through the array, skipping tags, and processing the contained text\n\t\t$str = '';\n\t\t$process = TRUE;\n\n\t\tfor ($i = 0, $c = count($chunks) - 1; $i <= $c; $i++)\n\t\t{\n\t\t\t// Are we dealing with a tag? If so, we'll skip the processing for this cycle.\n\t\t\t// Well also set the \"process\" flag which allows us to skip <pre> tags and a few other things.\n\t\t\tif (preg_match('#<(/*)('.$this->block_elements.').*?>#', $chunks[$i], $match))\n\t\t\t{\n\t\t\t\tif (preg_match('#'.$this->skip_elements.'#', $match[2]))\n\t\t\t\t{\n\t\t\t\t\t$process = ($match[1] === '/');\n\t\t\t\t}\n\n\t\t\t\tif ($match[1] === '')\n\t\t\t\t{\n\t\t\t\t\t$this->last_block_element = $match[2];\n\t\t\t\t}\n\n\t\t\t\t$str .= $chunks[$i];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ($process === FALSE)\n\t\t\t{\n\t\t\t\t$str .= $chunks[$i];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//  Force a newline to make sure end tags get processed by _format_newlines()\n\t\t\tif ($i === $c)\n\t\t\t{\n\t\t\t\t$chunks[$i] .= \"\\n\";\n\t\t\t}\n\n\t\t\t//  Convert Newlines into <p> and <br /> tags\n\t\t\t$str .= $this->_format_newlines($chunks[$i]);\n\t\t}\n\n\t\t// No opening block level tag? Add it if needed.\n\t\tif ( ! preg_match('/^\\s*<(?:'.$this->block_elements.')/i', $str))\n\t\t{\n\t\t\t$str = preg_replace('/^(.*?)<('.$this->block_elements.')/i', '<p>$1</p><$2', $str);\n\t\t}\n\n\t\t// Convert quotes, elipsis, em-dashes, non-breaking spaces, and ampersands\n\t\t$str = $this->format_characters($str);\n\n\t\t// restore HTML comments\n\t\tfor ($i = 0, $total = count($html_comments); $i < $total; $i++)\n\t\t{\n\t\t\t// remove surrounding paragraph tags, but only if there's an opening paragraph tag\n\t\t\t// otherwise HTML comments at the ends of paragraphs will have the closing tag removed\n\t\t\t// if '<p>{@HC1}' then replace <p>{@HC1}</p> with the comment, else replace only {@HC1} with the comment\n\t\t\t$str = preg_replace('#(?(?=<p>\\{@HC'.$i.'\\})<p>\\{@HC'.$i.'\\}(\\s*</p>)|\\{@HC'.$i.'\\})#s', $html_comments[$i], $str);\n\t\t}\n\n\t\t// Final clean up\n\t\t$table = array(\n\n\t\t\t\t\t\t// If the user submitted their own paragraph tags within the text\n\t\t\t\t\t\t// we will retain them instead of using our tags.\n\t\t\t\t\t\t'/(<p[^>*?]>)<p>/'\t=> '$1', // <?php BBEdit syntax coloring bug fix\n\n\t\t\t\t\t\t// Reduce multiple instances of opening/closing paragraph tags to a single one\n\t\t\t\t\t\t'#(</p>)+#'\t\t\t=> '</p>',\n\t\t\t\t\t\t'/(<p>\\W*<p>)+/'\t=> '<p>',\n\n\t\t\t\t\t\t// Clean up stray paragraph tags that appear before block level elements\n\t\t\t\t\t\t'#<p></p><('.$this->block_elements.')#'\t=> '<$1',\n\n\t\t\t\t\t\t// Clean up stray non-breaking spaces preceeding block elements\n\t\t\t\t\t\t'#(&nbsp;\\s*)+<('.$this->block_elements.')#'\t=> '  <$2',\n\n\t\t\t\t\t\t// Replace the temporary markers we added earlier\n\t\t\t\t\t\t'/\\{@TAG\\}/'\t\t=> '<',\n\t\t\t\t\t\t'/\\{@DQ\\}/'\t\t\t=> '\"',\n\t\t\t\t\t\t'/\\{@SQ\\}/'\t\t\t=> \"'\",\n\t\t\t\t\t\t'/\\{@DD\\}/'\t\t\t=> '--',\n\t\t\t\t\t\t'/\\{@NBS\\}/'\t\t=> '  ',\n\n\t\t\t\t\t\t// An unintended consequence of the _format_newlines function is that\n\t\t\t\t\t\t// some of the newlines get truncated, resulting in <p> tags\n\t\t\t\t\t\t// starting immediately after <block> tags on the same line.\n\t\t\t\t\t\t// This forces a newline after such occurrences, which looks much nicer.\n\t\t\t\t\t\t\"/><p>\\n/\"\t\t\t=> \">\\n<p>\",\n\n\t\t\t\t\t\t// Similarly, there might be cases where a closing </block> will follow\n\t\t\t\t\t\t// a closing </p> tag, so we'll correct it by adding a newline in between\n\t\t\t\t\t\t'#</p></#'\t\t\t=> \"</p>\\n</\"\n\t\t\t\t\t\t);\n\n\t\t// Do we need to reduce empty lines?\n\t\tif ($reduce_linebreaks === TRUE)\n\t\t{\n\t\t\t$table['#<p>\\n*</p>#'] = '';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// If we have empty paragraph tags we add a non-breaking space\n\t\t\t// otherwise most browsers won't treat them as true paragraphs\n\t\t\t$table['#<p></p>#'] = '<p>&nbsp;</p>';\n\t\t}\n\n\t\treturn preg_replace(array_keys($table), $table, $str);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Format Characters\n\t *\n\t * This function mainly converts double and single quotes\n\t * to curly entities, but it also converts em-dashes,\n\t * double spaces, and ampersands\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function format_characters($str)\n\t{\n\t\tstatic $table;\n\n\t\tif ( ! isset($table))\n\t\t{\n\t\t\t$table = array(\n\t\t\t\t\t\t\t// nested smart quotes, opening and closing\n\t\t\t\t\t\t\t// note that rules for grammar (English) allow only for two levels deep\n\t\t\t\t\t\t\t// and that single quotes are _supposed_ to always be on the outside\n\t\t\t\t\t\t\t// but we'll accommodate both\n\t\t\t\t\t\t\t// Note that in all cases, whitespace is the primary determining factor\n\t\t\t\t\t\t\t// on which direction to curl, with non-word characters like punctuation\n\t\t\t\t\t\t\t// being a secondary factor only after whitespace is addressed.\n\t\t\t\t\t\t\t'/\\'\"(\\s|$)/'\t\t\t\t\t=> '&#8217;&#8221;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\\'\"/'\t\t\t\t=> '$1&#8216;&#8220;',\n\t\t\t\t\t\t\t'/\\'\"(\\W)/'\t\t\t\t\t\t=> '&#8217;&#8221;$1',\n\t\t\t\t\t\t\t'/(\\W)\\'\"/'\t\t\t\t\t\t=> '$1&#8216;&#8220;',\n\t\t\t\t\t\t\t'/\"\\'(\\s|$)/'\t\t\t\t\t=> '&#8221;&#8217;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\"\\'/'\t\t\t\t=> '$1&#8220;&#8216;',\n\t\t\t\t\t\t\t'/\"\\'(\\W)/'\t\t\t\t\t\t=> '&#8221;&#8217;$1',\n\t\t\t\t\t\t\t'/(\\W)\"\\'/'\t\t\t\t\t\t=> '$1&#8220;&#8216;',\n\n\t\t\t\t\t\t\t// single quote smart quotes\n\t\t\t\t\t\t\t'/\\'(\\s|$)/'\t\t\t\t\t=> '&#8217;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\\'/'\t\t\t\t=> '$1&#8216;',\n\t\t\t\t\t\t\t'/\\'(\\W)/'\t\t\t\t\t\t=> '&#8217;$1',\n\t\t\t\t\t\t\t'/(\\W)\\'/'\t\t\t\t\t\t=> '$1&#8216;',\n\n\t\t\t\t\t\t\t// double quote smart quotes\n\t\t\t\t\t\t\t'/\"(\\s|$)/'\t\t\t\t\t\t=> '&#8221;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\"/'\t\t\t\t\t=> '$1&#8220;',\n\t\t\t\t\t\t\t'/\"(\\W)/'\t\t\t\t\t\t=> '&#8221;$1',\n\t\t\t\t\t\t\t'/(\\W)\"/'\t\t\t\t\t\t=> '$1&#8220;',\n\n\t\t\t\t\t\t\t// apostrophes\n\t\t\t\t\t\t\t\"/(\\w)'(\\w)/\"\t\t\t\t\t=> '$1&#8217;$2',\n\n\t\t\t\t\t\t\t// Em dash and ellipses dots\n\t\t\t\t\t\t\t'/\\s?\\-\\-\\s?/'\t\t\t\t\t=> '&#8212;',\n\t\t\t\t\t\t\t'/(\\w)\\.{3}/'\t\t\t\t\t=> '$1&#8230;',\n\n\t\t\t\t\t\t\t// double space after sentences\n\t\t\t\t\t\t\t'/(\\W)  /'\t\t\t\t\t\t=> '$1&nbsp; ',\n\n\t\t\t\t\t\t\t// ampersands, if not a character entity\n\t\t\t\t\t\t\t'/&(?!#?[a-zA-Z0-9]{2,};)/'\t\t=> '&amp;'\n\t\t\t\t\t\t);\n\t\t}\n\n\t\treturn preg_replace(array_keys($table), $table, $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Format Newlines\n\t *\n\t * Converts newline characters into either <p> tags or <br />\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _format_newlines($str)\n\t{\n\t\tif ($str === '' OR (strpos($str, \"\\n\") === FALSE && ! in_array($this->last_block_element, $this->inner_block_required)))\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t// Convert two consecutive newlines to paragraphs\n\t\t$str = str_replace(\"\\n\\n\", \"</p>\\n\\n<p>\", $str);\n\n\t\t// Convert single spaces to <br /> tags\n\t\t$str = preg_replace(\"/([^\\n])(\\n)([^\\n])/\", '\\\\1<br />\\\\2\\\\3', $str);\n\n\t\t// Wrap the whole enchilada in enclosing paragraphs\n\t\tif ($str !== \"\\n\")\n\t\t{\n\t\t\t// We trim off the right-side new line so that the closing </p> tag\n\t\t\t// will be positioned immediately following the string, matching\n\t\t\t// the behavior of the opening <p> tag\n\t\t\t$str =  '<p>'.rtrim($str).'</p>';\n\t\t}\n\n\t\t// Remove empty paragraphs if they are on the first line, as this\n\t\t// is a potential unintended consequence of the previous code\n\t\treturn preg_replace('/<p><\\/p>(.*)/', '\\\\1', $str, 1);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Protect Characters\n\t *\n\t * Protects special characters from being formatted later\n\t * We don't want quotes converted within tags so we'll temporarily convert them to {@DQ} and {@SQ}\n\t * and we don't want double dashes converted to emdash entities, so they are marked with {@DD}\n\t * likewise double spaces are converted to {@NBS} to prevent entity conversion\n\t *\n\t * @param\tarray\n\t * @return\tstring\n\t */\n\tprotected function _protect_characters($match)\n\t{\n\t\treturn str_replace(array(\"'\",'\"','--','  '), array('{@SQ}', '{@DQ}', '{@DD}', '{@NBS}'), $match[0]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert newlines to HTML line breaks except within PRE tags\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function nl2br_except_pre($str)\n\t{\n\t\t$newstr = '';\n\t\tfor ($ex = explode('pre>', $str), $ct = count($ex), $i = 0; $i < $ct; $i++)\n\t\t{\n\t\t\t$newstr .= (($i % 2) === 0) ? nl2br($ex[$i]) : $ex[$i];\n\t\t\tif ($ct - 1 !== $i)\n\t\t\t{\n\t\t\t\t$newstr .= 'pre>';\n\t\t\t}\n\t\t}\n\n\t\treturn $newstr;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Unit_test.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.3.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Unit Testing Class\n *\n * Simple testing class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tUnitTesting\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/unit_testing.html\n */\nclass CI_Unit_test {\n\n\t/**\n\t * Active flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $active = TRUE;\n\n\t/**\n\t * Test results\n\t *\n\t * @var\tarray\n\t */\n\tpublic $results = array();\n\n\t/**\n\t * Strict comparison flag\n\t *\n\t * Whether to use === or == when comparing\n\t *\n\t * @var\tbool\n\t */\n\tpublic $strict = FALSE;\n\n\t/**\n\t * Template\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_template = NULL;\n\n\t/**\n\t * Template rows\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_template_rows = NULL;\n\n\t/**\n\t * List of visible test items\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_test_items_visible\t= array(\n\t\t'test_name',\n\t\t'test_datatype',\n\t\t'res_datatype',\n\t\t'result',\n\t\t'file',\n\t\t'line',\n\t\t'notes'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tlog_message('info', 'Unit Testing Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the tests\n\t *\n\t * Runs the supplied tests\n\t *\n\t * @param\tarray\t$items\n\t * @return\tvoid\n\t */\n\tpublic function set_test_items($items)\n\t{\n\t\tif ( ! empty($items) && is_array($items))\n\t\t{\n\t\t\t$this->_test_items_visible = $items;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the tests\n\t *\n\t * Runs the supplied tests\n\t *\n\t * @param\tmixed\t$test\n\t * @param\tmixed\t$expected\n\t * @param\tstring\t$test_name\n\t * @param\tstring\t$notes\n\t * @return\tstring\n\t */\n\tpublic function run($test, $expected = TRUE, $test_name = 'undefined', $notes = '')\n\t{\n\t\tif ($this->active === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (in_array($expected, array('is_object', 'is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null', 'is_resource'), TRUE))\n\t\t{\n\t\t\t$expected = str_replace('is_double', 'is_float', $expected);\n\t\t\t$result = $expected($test);\n\t\t\t$extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$result = ($this->strict === TRUE) ? ($test === $expected) : ($test == $expected);\n\t\t\t$extype = gettype($expected);\n\t\t}\n\n\t\t$back = $this->_backtrace();\n\n\t\t$report = array (\n\t\t\t'test_name'     => $test_name,\n\t\t\t'test_datatype' => gettype($test),\n\t\t\t'res_datatype'  => $extype,\n\t\t\t'result'        => ($result === TRUE) ? 'passed' : 'failed',\n\t\t\t'file'          => $back['file'],\n\t\t\t'line'          => $back['line'],\n\t\t\t'notes'         => $notes\n\t\t);\n\n\t\t$this->results[] = $report;\n\n\t\treturn $this->report($this->result(array($report)));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate a report\n\t *\n\t * Displays a table with the test data\n\t *\n\t * @param\tarray\t $result\n\t * @return\tstring\n\t */\n\tpublic function report($result = array())\n\t{\n\t\tif (count($result) === 0)\n\t\t{\n\t\t\t$result = $this->result();\n\t\t}\n\n\t\t$CI =& get_instance();\n\t\t$CI->load->language('unit_test');\n\n\t\t$this->_parse_template();\n\n\t\t$r = '';\n\t\tforeach ($result as $res)\n\t\t{\n\t\t\t$table = '';\n\n\t\t\tforeach ($res as $key => $val)\n\t\t\t{\n\t\t\t\tif ($key === $CI->lang->line('ut_result'))\n\t\t\t\t{\n\t\t\t\t\tif ($val === $CI->lang->line('ut_passed'))\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = '<span style=\"color: #0C0;\">'.$val.'</span>';\n\t\t\t\t\t}\n\t\t\t\t\telseif ($val === $CI->lang->line('ut_failed'))\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = '<span style=\"color: #C00;\">'.$val.'</span>';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$table .= str_replace(array('{item}', '{result}'), array($key, $val), $this->_template_rows);\n\t\t\t}\n\n\t\t\t$r .= str_replace('{rows}', $table, $this->_template);\n\t\t}\n\n\t\treturn $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Use strict comparison\n\t *\n\t * Causes the evaluation to use === rather than ==\n\t *\n\t * @param\tbool\t$state\n\t * @return\tvoid\n\t */\n\tpublic function use_strict($state = TRUE)\n\t{\n\t\t$this->strict = (bool) $state;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Make Unit testing active\n\t *\n\t * Enables/disables unit testing\n\t *\n\t * @param\tbool\n\t * @return\tvoid\n\t */\n\tpublic function active($state = TRUE)\n\t{\n\t\t$this->active = (bool) $state;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result Array\n\t *\n\t * Returns the raw result data\n\t *\n\t * @param\tarray\t$results\n\t * @return\tarray\n\t */\n\tpublic function result($results = array())\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->load->language('unit_test');\n\n\t\tif (count($results) === 0)\n\t\t{\n\t\t\t$results = $this->results;\n\t\t}\n\n\t\t$retval = array();\n\t\tforeach ($results as $result)\n\t\t{\n\t\t\t$temp = array();\n\t\t\tforeach ($result as $key => $val)\n\t\t\t{\n\t\t\t\tif ( ! in_array($key, $this->_test_items_visible))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telseif (in_array($key, array('test_name', 'test_datatype', 'test_res_datatype', 'result'), TRUE))\n\t\t\t\t{\n\t\t\t\t\tif (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = $line;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;\n\t\t\t}\n\n\t\t\t$retval[] = $temp;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the template\n\t *\n\t * This lets us set the template to be used to display results\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_template($template)\n\t{\n\t\t$this->_template = $template;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate a backtrace\n\t *\n\t * This lets us show file names and line numbers\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _backtrace()\n\t{\n\t\t$back = debug_backtrace();\n\t\treturn array(\n\t\t\t'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),\n\t\t\t'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Default Template\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _default_template()\n\t{\n\t\t$this->_template = \"\\n\".'<table style=\"width:100%; font-size:small; margin:10px 0; border-collapse:collapse; border:1px solid #CCC;\">{rows}'.\"\\n</table>\";\n\n\t\t$this->_template_rows = \"\\n\\t<tr>\\n\\t\\t\".'<th style=\"text-align: left; border-bottom:1px solid #CCC;\">{item}</th>'\n\t\t\t\t\t.\"\\n\\t\\t\".'<td style=\"border-bottom:1px solid #CCC;\">{result}</td>'.\"\\n\\t</tr>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse Template\n\t *\n\t * Harvests the data within the template {pseudo-variables}\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _parse_template()\n\t{\n\t\tif ($this->_template_rows !== NULL)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif ($this->_template === NULL OR ! preg_match('/\\{rows\\}(.*?)\\{\\/rows\\}/si', $this->_template, $match))\n\t\t{\n\t\t\t$this->_default_template();\n\t\t\treturn;\n\t\t}\n\n\t\t$this->_template_rows = $match[1];\n\t\t$this->_template = str_replace($match[0], '{rows}', $this->_template);\n\t}\n\n}\n\n/**\n * Helper function to test boolean TRUE\n *\n * @param\tmixed\t$test\n * @return\tbool\n */\nfunction is_true($test)\n{\n\treturn ($test === TRUE);\n}\n\n/**\n * Helper function to test boolean FALSE\n *\n * @param\tmixed\t$test\n * @return\tbool\n */\nfunction is_false($test)\n{\n\treturn ($test === FALSE);\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Upload.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * File Uploading Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tUploads\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/file_uploading.html\n */\nclass CI_Upload {\n\n\t/**\n\t * Maximum file size\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_size = 0;\n\n\t/**\n\t * Maximum image width\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_width = 0;\n\n\t/**\n\t * Maximum image height\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_height = 0;\n\n\t/**\n\t * Minimum image width\n\t *\n\t * @var\tint\n\t */\n\tpublic $min_width = 0;\n\n\t/**\n\t * Minimum image height\n\t *\n\t * @var\tint\n\t */\n\tpublic $min_height = 0;\n\n\t/**\n\t * Maximum filename length\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_filename = 0;\n\n\t/**\n\t * Maximum duplicate filename increment ID\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_filename_increment = 100;\n\n\t/**\n\t * Allowed file types\n\t *\n\t * @var\tstring\n\t */\n\tpublic $allowed_types = '';\n\n\t/**\n\t * Temporary filename\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_temp = '';\n\n\t/**\n\t * Filename\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_name = '';\n\n\t/**\n\t * Original filename\n\t *\n\t * @var\tstring\n\t */\n\tpublic $orig_name = '';\n\n\t/**\n\t * File type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_type = '';\n\n\t/**\n\t * File size\n\t *\n\t * @var\tint\n\t */\n\tpublic $file_size = NULL;\n\n\t/**\n\t * Filename extension\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_ext = '';\n\n\t/**\n\t * Force filename extension to lowercase\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_ext_tolower = FALSE;\n\n\t/**\n\t * Upload path\n\t *\n\t * @var\tstring\n\t */\n\tpublic $upload_path = '';\n\n\t/**\n\t * Overwrite flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $overwrite = FALSE;\n\n\t/**\n\t * Obfuscate filename flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $encrypt_name = FALSE;\n\n\t/**\n\t * Is image flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $is_image = FALSE;\n\n\t/**\n\t * Image width\n\t *\n\t * @var\tint\n\t */\n\tpublic $image_width = NULL;\n\n\t/**\n\t * Image height\n\t *\n\t * @var\tint\n\t */\n\tpublic $image_height = NULL;\n\n\t/**\n\t * Image type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $image_type = '';\n\n\t/**\n\t * Image size string\n\t *\n\t * @var\tstring\n\t */\n\tpublic $image_size_str = '';\n\n\t/**\n\t * Error messages list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $error_msg = array();\n\n\t/**\n\t * Remove spaces flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $remove_spaces = TRUE;\n\n\t/**\n\t * MIME detection flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $detect_mime = TRUE;\n\n\t/**\n\t * XSS filter flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $xss_clean = FALSE;\n\n\t/**\n\t * Apache mod_mime fix flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $mod_mime_fix = TRUE;\n\n\t/**\n\t * Temporary filename prefix\n\t *\n\t * @var\tstring\n\t */\n\tpublic $temp_prefix = 'temp_file_';\n\n\t/**\n\t * Filename sent by the client\n\t *\n\t * @var\tbool\n\t */\n\tpublic $client_name = '';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Filename override\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_file_name_override = '';\n\n\t/**\n\t * MIME types list\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_mimes = array();\n\n\t/**\n\t * CI Singleton\n\t *\n\t * @var\tobject\n\t */\n\tprotected $_CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$props\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tempty($config) OR $this->initialize($config, FALSE);\n\n\t\t$this->_mimes =& get_mimes();\n\t\t$this->_CI =& get_instance();\n\n\t\tlog_message('info', 'Upload Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize preferences\n\t *\n\t * @param\tarray\t$config\n\t * @param\tbool\t$reset\n\t * @return\tCI_Upload\n\t */\n\tpublic function initialize(array $config = array(), $reset = TRUE)\n\t{\n\t\t$reflection = new ReflectionClass($this);\n\n\t\tif ($reset === TRUE)\n\t\t{\n\t\t\t$defaults = $reflection->getDefaultProperties();\n\t\t\tforeach (array_keys($defaults) as $key)\n\t\t\t{\n\t\t\t\tif ($key[0] === '_')\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (isset($config[$key]))\n\t\t\t\t{\n\t\t\t\t\tif ($reflection->hasMethod('set_'.$key))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->{'set_'.$key}($config[$key]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->$key = $config[$key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->$key = $defaults[$key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($config as $key => &$value)\n\t\t\t{\n\t\t\t\tif ($key[0] !== '_' && $reflection->hasProperty($key))\n\t\t\t\t{\n\t\t\t\t\tif ($reflection->hasMethod('set_'.$key))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->{'set_'.$key}($value);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->$key = $value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if a file_name was provided in the config, use it instead of the user input\n\t\t// supplied file name for all uploads until initialized again\n\t\t$this->_file_name_override = $this->file_name;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Perform the file upload\n\t *\n\t * @param\tstring\t$field\n\t * @return\tbool\n\t */\n\tpublic function do_upload($field = 'userfile')\n\t{\n\t\t// Is $_FILES[$field] set? If not, no reason to continue.\n\t\tif (isset($_FILES[$field]))\n\t\t{\n\t\t\t$_file = $_FILES[$field];\n\t\t}\n\t\t// Does the field name contain array notation?\n\t\telseif (($c = preg_match_all('/(?:^[^\\[]+)|\\[[^]]*\\]/', $field, $matches)) > 1)\n\t\t{\n\t\t\t$_file = $_FILES;\n\t\t\tfor ($i = 0; $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// We can't track numeric iterations, only full field names are accepted\n\t\t\t\tif (($field = trim($matches[0][$i], '[]')) === '' OR ! isset($_file[$field]))\n\t\t\t\t{\n\t\t\t\t\t$_file = NULL;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t$_file = $_file[$field];\n\t\t\t}\n\t\t}\n\n\t\tif ( ! isset($_file))\n\t\t{\n\t\t\t$this->set_error('upload_no_file_selected', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Is the upload path valid?\n\t\tif ( ! $this->validate_upload_path())\n\t\t{\n\t\t\t// errors will already be set by validate_upload_path() so just return FALSE\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Was the file able to be uploaded? If not, determine the reason why.\n\t\tif ( ! is_uploaded_file($_file['tmp_name']))\n\t\t{\n\t\t\t$error = isset($_file['error']) ? $_file['error'] : 4;\n\n\t\t\tswitch ($error)\n\t\t\t{\n\t\t\t\tcase UPLOAD_ERR_INI_SIZE:\n\t\t\t\t\t$this->set_error('upload_file_exceeds_limit', 'info');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_FORM_SIZE:\n\t\t\t\t\t$this->set_error('upload_file_exceeds_form_limit', 'info');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_PARTIAL:\n\t\t\t\t\t$this->set_error('upload_file_partial', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_NO_FILE:\n\t\t\t\t\t$this->set_error('upload_no_file_selected', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_NO_TMP_DIR:\n\t\t\t\t\t$this->set_error('upload_no_temp_directory', 'error');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_CANT_WRITE:\n\t\t\t\t\t$this->set_error('upload_unable_to_write_file', 'error');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_EXTENSION:\n\t\t\t\t\t$this->set_error('upload_stopped_by_extension', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t$this->set_error('upload_no_file_selected', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the uploaded data as class variables\n\t\t$this->file_temp = $_file['tmp_name'];\n\t\t$this->file_size = $_file['size'];\n\n\t\t// Skip MIME type detection?\n\t\tif ($this->detect_mime !== FALSE)\n\t\t{\n\t\t\t$this->_file_mime_type($_file);\n\t\t}\n\n\t\t$this->file_type = preg_replace('/^(.+?);.*$/', '\\\\1', $this->file_type);\n\t\t$this->file_type = strtolower(trim(stripslashes($this->file_type), '\"'));\n\t\t$this->file_name = $this->_prep_filename($_file['name']);\n\t\t$this->file_ext\t = $this->get_extension($this->file_name);\n\t\t$this->client_name = $this->file_name;\n\n\t\t// Is the file type allowed to be uploaded?\n\t\tif ( ! $this->is_allowed_filetype())\n\t\t{\n\t\t\t$this->set_error('upload_invalid_filetype', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// if we're overriding, let's now make sure the new name and type is allowed\n\t\tif ($this->_file_name_override !== '')\n\t\t{\n\t\t\t$this->file_name = $this->_prep_filename($this->_file_name_override);\n\n\t\t\t// If no extension was provided in the file_name config item, use the uploaded one\n\t\t\tif (strpos($this->_file_name_override, '.') === FALSE)\n\t\t\t{\n\t\t\t\t$this->file_name .= $this->file_ext;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// An extension was provided, let's have it!\n\t\t\t\t$this->file_ext\t= $this->get_extension($this->_file_name_override);\n\t\t\t}\n\n\t\t\tif ( ! $this->is_allowed_filetype(TRUE))\n\t\t\t{\n\t\t\t\t$this->set_error('upload_invalid_filetype', 'debug');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// Convert the file size to kilobytes\n\t\tif ($this->file_size > 0)\n\t\t{\n\t\t\t$this->file_size = round($this->file_size/1024, 2);\n\t\t}\n\n\t\t// Is the file size within the allowed maximum?\n\t\tif ( ! $this->is_allowed_filesize())\n\t\t{\n\t\t\t$this->set_error('upload_invalid_filesize', 'info');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Are the image dimensions within the allowed size?\n\t\t// Note: This can fail if the server has an open_basedir restriction.\n\t\tif ( ! $this->is_allowed_dimensions())\n\t\t{\n\t\t\t$this->set_error('upload_invalid_dimensions', 'info');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Sanitize the file name for security\n\t\t$this->file_name = $this->_CI->security->sanitize_filename($this->file_name);\n\n\t\t// Truncate the file name if it's too long\n\t\tif ($this->max_filename > 0)\n\t\t{\n\t\t\t$this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);\n\t\t}\n\n\t\t// Remove white spaces in the name\n\t\tif ($this->remove_spaces === TRUE)\n\t\t{\n\t\t\t$this->file_name = preg_replace('/\\s+/', '_', $this->file_name);\n\t\t}\n\n\t\t/*\n\t\t * Validate the file name\n\t\t * This function appends an number onto the end of\n\t\t * the file if one with the same name already exists.\n\t\t * If it returns false there was a problem.\n\t\t */\n\t\t$this->orig_name = $this->file_name;\n\t\tif (FALSE === ($this->file_name = $this->set_filename($this->upload_path, $this->file_name)))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/*\n\t\t * Run the file through the XSS hacking filter\n\t\t * This helps prevent malicious code from being\n\t\t * embedded within a file. Scripts can easily\n\t\t * be disguised as images or other file types.\n\t\t */\n\t\tif ($this->xss_clean && $this->do_xss_clean() === FALSE)\n\t\t{\n\t\t\t$this->set_error('upload_unable_to_write_file', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/*\n\t\t * Move the file to the final destination\n\t\t * To deal with different server configurations\n\t\t * we'll attempt to use copy() first. If that fails\n\t\t * we'll use move_uploaded_file(). One of the two should\n\t\t * reliably work in most environments\n\t\t */\n\t\tif ( ! @copy($this->file_temp, $this->upload_path.$this->file_name))\n\t\t{\n\t\t\tif ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name))\n\t\t\t{\n\t\t\t\t$this->set_error('upload_destination_error', 'error');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * Set the finalized image dimensions\n\t\t * This sets the image width/height (assuming the\n\t\t * file was an image). We use this information\n\t\t * in the \"data\" function.\n\t\t */\n\t\t$this->set_image_properties($this->upload_path.$this->file_name);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Finalized Data Array\n\t *\n\t * Returns an associative array containing all of the information\n\t * related to the upload, allowing the developer easy access in one array.\n\t *\n\t * @param\tstring\t$index\n\t * @return\tmixed\n\t */\n\tpublic function data($index = NULL)\n\t{\n\t\t$data = array(\n\t\t\t\t'file_name'\t\t=> $this->file_name,\n\t\t\t\t'file_type'\t\t=> $this->file_type,\n\t\t\t\t'file_path'\t\t=> $this->upload_path,\n\t\t\t\t'full_path'\t\t=> $this->upload_path.$this->file_name,\n\t\t\t\t'raw_name'\t\t=> str_replace($this->file_ext, '', $this->file_name),\n\t\t\t\t'orig_name'\t\t=> $this->orig_name,\n\t\t\t\t'client_name'\t\t=> $this->client_name,\n\t\t\t\t'file_ext'\t\t=> $this->file_ext,\n\t\t\t\t'file_size'\t\t=> $this->file_size,\n\t\t\t\t'is_image'\t\t=> $this->is_image(),\n\t\t\t\t'image_width'\t\t=> $this->image_width,\n\t\t\t\t'image_height'\t\t=> $this->image_height,\n\t\t\t\t'image_type'\t\t=> $this->image_type,\n\t\t\t\t'image_size_str'\t=> $this->image_size_str,\n\t\t\t);\n\n\t\tif ( ! empty($index))\n\t\t{\n\t\t\treturn isset($data[$index]) ? $data[$index] : NULL;\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Upload Path\n\t *\n\t * @param\tstring\t$path\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_upload_path($path)\n\t{\n\t\t// Make sure it has a trailing slash\n\t\t$this->upload_path = rtrim($path, '/').'/';\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the file name\n\t *\n\t * This function takes a filename/path as input and looks for the\n\t * existence of a file with the same name. If found, it will append a\n\t * number to the end of the filename to avoid overwriting a pre-existing file.\n\t *\n\t * @param\tstring\t$path\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tpublic function set_filename($path, $filename)\n\t{\n\t\tif ($this->encrypt_name === TRUE)\n\t\t{\n\t\t\t$filename = md5(uniqid(mt_rand())).$this->file_ext;\n\t\t}\n\n\t\tif ($this->overwrite === TRUE OR ! file_exists($path.$filename))\n\t\t{\n\t\t\treturn $filename;\n\t\t}\n\n\t\t$filename = str_replace($this->file_ext, '', $filename);\n\n\t\t$new_filename = '';\n\t\tfor ($i = 1; $i < $this->max_filename_increment; $i++)\n\t\t{\n\t\t\tif ( ! file_exists($path.$filename.$i.$this->file_ext))\n\t\t\t{\n\t\t\t\t$new_filename = $filename.$i.$this->file_ext;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ($new_filename === '')\n\t\t{\n\t\t\t$this->set_error('upload_bad_filename', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $new_filename;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum File Size\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_filesize($n)\n\t{\n\t\t$this->max_size = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum File Size\n\t *\n\t * An internal alias to set_max_filesize() to help with configuration\n\t * as initialize() will look for a set_<property_name>() method ...\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tprotected function set_max_size($n)\n\t{\n\t\treturn $this->set_max_filesize($n);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum File Name Length\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_filename($n)\n\t{\n\t\t$this->max_filename = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum Image Width\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_width($n)\n\t{\n\t\t$this->max_width = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum Image Height\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_height($n)\n\t{\n\t\t$this->max_height = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set minimum image width\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_min_width($n)\n\t{\n\t\t$this->min_width = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set minimum image height\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_min_height($n)\n\t{\n\t\t$this->min_height = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Allowed File Types\n\t *\n\t * @param\tmixed\t$types\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_allowed_types($types)\n\t{\n\t\t$this->allowed_types = (is_array($types) OR $types === '*')\n\t\t\t? $types\n\t\t\t: explode('|', $types);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Image Properties\n\t *\n\t * Uses GD to determine the width/height/type of image\n\t *\n\t * @param\tstring\t$path\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_image_properties($path = '')\n\t{\n\t\tif ($this->is_image() && function_exists('getimagesize'))\n\t\t{\n\t\t\tif (FALSE !== ($D = @getimagesize($path)))\n\t\t\t{\n\t\t\t\t$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');\n\n\t\t\t\t$this->image_width\t= $D[0];\n\t\t\t\t$this->image_height\t= $D[1];\n\t\t\t\t$this->image_type\t= isset($types[$D[2]]) ? $types[$D[2]] : 'unknown';\n\t\t\t\t$this->image_size_str\t= $D[3]; // string containing height and width\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set XSS Clean\n\t *\n\t * Enables the XSS flag so that the file that was uploaded\n\t * will be run through the XSS filter.\n\t *\n\t * @param\tbool\t$flag\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_xss_clean($flag = FALSE)\n\t{\n\t\t$this->xss_clean = ($flag === TRUE);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate the image\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_image()\n\t{\n\t\t// IE will sometimes return odd mime-types during upload, so here we just standardize all\n\t\t// jpegs or pngs to the same file type.\n\n\t\t$png_mimes  = array('image/x-png');\n\t\t$jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');\n\n\t\tif (in_array($this->file_type, $png_mimes))\n\t\t{\n\t\t\t$this->file_type = 'image/png';\n\t\t}\n\t\telseif (in_array($this->file_type, $jpeg_mimes))\n\t\t{\n\t\t\t$this->file_type = 'image/jpeg';\n\t\t}\n\n\t\t$img_mimes = array('image/gif',\t'image/jpeg', 'image/png');\n\n\t\treturn in_array($this->file_type, $img_mimes, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Verify that the filetype is allowed\n\t *\n\t * @param\tbool\t$ignore_mime\n\t * @return\tbool\n\t */\n\tpublic function is_allowed_filetype($ignore_mime = FALSE)\n\t{\n\t\tif ($this->allowed_types === '*')\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif (empty($this->allowed_types) OR ! is_array($this->allowed_types))\n\t\t{\n\t\t\t$this->set_error('upload_no_file_types', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$ext = strtolower(ltrim($this->file_ext, '.'));\n\n\t\tif ( ! in_array($ext, $this->allowed_types, TRUE))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Images get some additional checks\n\t\tif (in_array($ext, array('gif', 'jpg', 'jpeg', 'jpe', 'png'), TRUE) && @getimagesize($this->file_temp) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($ignore_mime === TRUE)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif (isset($this->_mimes[$ext]))\n\t\t{\n\t\t\treturn is_array($this->_mimes[$ext])\n\t\t\t\t? in_array($this->file_type, $this->_mimes[$ext], TRUE)\n\t\t\t\t: ($this->_mimes[$ext] === $this->file_type);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Verify that the file is within the allowed size\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_allowed_filesize()\n\t{\n\t\treturn ($this->max_size === 0 OR $this->max_size > $this->file_size);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Verify that the image is within the allowed width/height\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_allowed_dimensions()\n\t{\n\t\tif ( ! $this->is_image())\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif (function_exists('getimagesize'))\n\t\t{\n\t\t\t$D = @getimagesize($this->file_temp);\n\n\t\t\tif ($this->max_width > 0 && $D[0] > $this->max_width)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ($this->max_height > 0 && $D[1] > $this->max_height)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ($this->min_width > 0 && $D[0] < $this->min_width)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ($this->min_height > 0 && $D[1] < $this->min_height)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Upload Path\n\t *\n\t * Verifies that it is a valid upload path with proper permissions.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function validate_upload_path()\n\t{\n\t\tif ($this->upload_path === '')\n\t\t{\n\t\t\t$this->set_error('upload_no_filepath', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (realpath($this->upload_path) !== FALSE)\n\t\t{\n\t\t\t$this->upload_path = str_replace('\\\\', '/', realpath($this->upload_path));\n\t\t}\n\n\t\tif ( ! is_dir($this->upload_path))\n\t\t{\n\t\t\t$this->set_error('upload_no_filepath', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! is_really_writable($this->upload_path))\n\t\t{\n\t\t\t$this->set_error('upload_not_writable', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->upload_path = preg_replace('/(.+?)\\/*$/', '\\\\1/',  $this->upload_path);\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extract the file extension\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tpublic function get_extension($filename)\n\t{\n\t\t$x = explode('.', $filename);\n\n\t\tif (count($x) === 1)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t$ext = ($this->file_ext_tolower) ? strtolower(end($x)) : end($x);\n\t\treturn '.'.$ext;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Limit the File Name Length\n\t *\n\t * @param\tstring\t$filename\n\t * @param\tint\t$length\n\t * @return\tstring\n\t */\n\tpublic function limit_filename_length($filename, $length)\n\t{\n\t\tif (strlen($filename) < $length)\n\t\t{\n\t\t\treturn $filename;\n\t\t}\n\n\t\t$ext = '';\n\t\tif (strpos($filename, '.') !== FALSE)\n\t\t{\n\t\t\t$parts\t\t= explode('.', $filename);\n\t\t\t$ext\t\t= '.'.array_pop($parts);\n\t\t\t$filename\t= implode('.', $parts);\n\t\t}\n\n\t\treturn substr($filename, 0, ($length - strlen($ext))).$ext;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Runs the file through the XSS clean function\n\t *\n\t * This prevents people from embedding malicious code in their files.\n\t * I'm not sure that it won't negatively affect certain files in unexpected ways,\n\t * but so far I haven't found that it causes trouble.\n\t *\n\t * @return\tstring\n\t */\n\tpublic function do_xss_clean()\n\t{\n\t\t$file = $this->file_temp;\n\n\t\tif (filesize($file) == 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (memory_get_usage() && ($memory_limit = ini_get('memory_limit')))\n\t\t{\n\t\t\t$memory_limit *= 1024 * 1024;\n\n\t\t\t// There was a bug/behavioural change in PHP 5.2, where numbers over one million get output\n\t\t\t// into scientific notation. number_format() ensures this number is an integer\n\t\t\t// http://bugs.php.net/bug.php?id=43053\n\n\t\t\t$memory_limit = number_format(ceil(filesize($file) + $memory_limit), 0, '.', '');\n\n\t\t\tini_set('memory_limit', $memory_limit); // When an integer is used, the value is measured in bytes. - PHP.net\n\t\t}\n\n\t\t// If the file being uploaded is an image, then we should have no problem with XSS attacks (in theory), but\n\t\t// IE can be fooled into mime-type detecting a malformed image as an html file, thus executing an XSS attack on anyone\n\t\t// using IE who looks at the image. It does this by inspecting the first 255 bytes of an image. To get around this\n\t\t// CI will itself look at the first 255 bytes of an image to determine its relative safety. This can save a lot of\n\t\t// processor power and time if it is actually a clean image, as it will be in nearly all instances _except_ an\n\t\t// attempted XSS attack.\n\n\t\tif (function_exists('getimagesize') && @getimagesize($file) !== FALSE)\n\t\t{\n\t\t\tif (($file = @fopen($file, 'rb')) === FALSE) // \"b\" to force binary\n\t\t\t{\n\t\t\t\treturn FALSE; // Couldn't open the file, return FALSE\n\t\t\t}\n\n\t\t\t$opening_bytes = fread($file, 256);\n\t\t\tfclose($file);\n\n\t\t\t// These are known to throw IE into mime-type detection chaos\n\t\t\t// <a, <body, <head, <html, <img, <plaintext, <pre, <script, <table, <title\n\t\t\t// title is basically just in SVG, but we filter it anyhow\n\n\t\t\t// if it's an image or no \"triggers\" detected in the first 256 bytes - we're good\n\t\t\treturn ! preg_match('/<(a|body|head|html|img|plaintext|pre|script|table|title)[\\s>]/i', $opening_bytes);\n\t\t}\n\n\t\tif (($data = @file_get_contents($file)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->_CI->security->xss_clean($data, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set an error message\n\t *\n\t * @param\tstring\t$msg\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_error($msg, $log_level = 'error')\n\t{\n\t\t$this->_CI->lang->load('upload');\n\n\t\tis_array($msg) OR $msg = array($msg);\n\t\tforeach ($msg as $val)\n\t\t{\n\t\t\t$msg = ($this->_CI->lang->line($val) === FALSE) ? $val : $this->_CI->lang->line($val);\n\t\t\t$this->error_msg[] = $msg;\n\t\t\tlog_message($log_level, $msg);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Display the error message\n\t *\n\t * @param\tstring\t$open\n\t * @param\tstring\t$close\n\t * @return\tstring\n\t */\n\tpublic function display_errors($open = '<p>', $close = '</p>')\n\t{\n\t\treturn (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Filename\n\t *\n\t * Prevents possible script execution from Apache's handling\n\t * of files' multiple extensions.\n\t *\n\t * @link\thttp://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tprotected function _prep_filename($filename)\n\t{\n\t\tif ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR ($ext_pos = strrpos($filename, '.')) === FALSE)\n\t\t{\n\t\t\treturn $filename;\n\t\t}\n\n\t\t$ext = substr($filename, $ext_pos);\n\t\t$filename = substr($filename, 0, $ext_pos);\n\t\treturn str_replace('.', '_', $filename).$ext;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * File MIME type\n\t *\n\t * Detects the (actual) MIME type of the uploaded file, if possible.\n\t * The input array is expected to be $_FILES[$field]\n\t *\n\t * @param\tarray\t$file\n\t * @return\tvoid\n\t */\n\tprotected function _file_mime_type($file)\n\t{\n\t\t// We'll need this to validate the MIME info string (e.g. text/plain; charset=us-ascii)\n\t\t$regexp = '/^([a-z\\-]+\\/[a-z0-9\\-\\.\\+]+)(;\\s.+)?$/';\n\n\t\t/* Fileinfo extension - most reliable method\n\t\t *\n\t\t * Unfortunately, prior to PHP 5.3 - it's only available as a PECL extension and the\n\t\t * more convenient FILEINFO_MIME_TYPE flag doesn't exist.\n\t\t */\n\t\tif (function_exists('finfo_file'))\n\t\t{\n\t\t\t$finfo = @finfo_open(FILEINFO_MIME);\n\t\t\tif (is_resource($finfo)) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system\n\t\t\t{\n\t\t\t\t$mime = @finfo_file($finfo, $file['tmp_name']);\n\t\t\t\tfinfo_close($finfo);\n\n\t\t\t\t/* According to the comments section of the PHP manual page,\n\t\t\t\t * it is possible that this function returns an empty string\n\t\t\t\t * for some files (e.g. if they don't exist in the magic MIME database)\n\t\t\t\t */\n\t\t\t\tif (is_string($mime) && preg_match($regexp, $mime, $matches))\n\t\t\t\t{\n\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* This is an ugly hack, but UNIX-type systems provide a \"native\" way to detect the file type,\n\t\t * which is still more secure than depending on the value of $_FILES[$field]['type'], and as it\n\t\t * was reported in issue #750 (https://github.com/EllisLab/CodeIgniter/issues/750) - it's better\n\t\t * than mime_content_type() as well, hence the attempts to try calling the command line with\n\t\t * three different functions.\n\t\t *\n\t\t * Notes:\n\t\t *\t- the DIRECTORY_SEPARATOR comparison ensures that we're not on a Windows system\n\t\t *\t- many system admins would disable the exec(), shell_exec(), popen() and similar functions\n\t\t *\t  due to security concerns, hence the function_usable() checks\n\t\t */\n\t\tif (DIRECTORY_SEPARATOR !== '\\\\')\n\t\t{\n\t\t\t$cmd = function_exists('escapeshellarg')\n\t\t\t\t? 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1'\n\t\t\t\t: 'file --brief --mime '.$file['tmp_name'].' 2>&1';\n\n\t\t\tif (function_usable('exec'))\n\t\t\t{\n\t\t\t\t/* This might look confusing, as $mime is being populated with all of the output when set in the second parameter.\n\t\t\t\t * However, we only need the last line, which is the actual return value of exec(), and as such - it overwrites\n\t\t\t\t * anything that could already be set for $mime previously. This effectively makes the second parameter a dummy\n\t\t\t\t * value, which is only put to allow us to get the return status code.\n\t\t\t\t */\n\t\t\t\t$mime = @exec($cmd, $mime, $return_status);\n\t\t\t\tif ($return_status === 0 && is_string($mime) && preg_match($regexp, $mime, $matches))\n\t\t\t\t{\n\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( ! ini_get('safe_mode') && function_usable('shell_exec'))\n\t\t\t{\n\t\t\t\t$mime = @shell_exec($cmd);\n\t\t\t\tif (strlen($mime) > 0)\n\t\t\t\t{\n\t\t\t\t\t$mime = explode(\"\\n\", trim($mime));\n\t\t\t\t\tif (preg_match($regexp, $mime[(count($mime) - 1)], $matches))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (function_usable('popen'))\n\t\t\t{\n\t\t\t\t$proc = @popen($cmd, 'r');\n\t\t\t\tif (is_resource($proc))\n\t\t\t\t{\n\t\t\t\t\t$mime = @fread($proc, 512);\n\t\t\t\t\t@pclose($proc);\n\t\t\t\t\tif ($mime !== FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$mime = explode(\"\\n\", trim($mime));\n\t\t\t\t\t\tif (preg_match($regexp, $mime[(count($mime) - 1)], $matches))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to the deprecated mime_content_type(), if available (still better than $_FILES[$field]['type'])\n\t\tif (function_exists('mime_content_type'))\n\t\t{\n\t\t\t$this->file_type = @mime_content_type($file['tmp_name']);\n\t\t\tif (strlen($this->file_type) > 0) // It's possible that mime_content_type() returns FALSE or an empty string\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t$this->file_type = $file['type'];\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/User_agent.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * User Agent Class\n *\n * Identifies the platform, browser, robot, or mobile device of the browsing agent\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tUser Agent\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/user_agent.html\n */\nclass CI_User_agent {\n\n\t/**\n\t * Current user-agent\n\t *\n\t * @var string\n\t */\n\tpublic $agent = NULL;\n\n\t/**\n\t * Flag for if the user-agent belongs to a browser\n\t *\n\t * @var bool\n\t */\n\tpublic $is_browser = FALSE;\n\n\t/**\n\t * Flag for if the user-agent is a robot\n\t *\n\t * @var bool\n\t */\n\tpublic $is_robot = FALSE;\n\n\t/**\n\t * Flag for if the user-agent is a mobile browser\n\t *\n\t * @var bool\n\t */\n\tpublic $is_mobile = FALSE;\n\n\t/**\n\t * Languages accepted by the current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $languages = array();\n\n\t/**\n\t * Character sets accepted by the current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $charsets = array();\n\n\t/**\n\t * List of platforms to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $platforms = array();\n\n\t/**\n\t * List of browsers to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $browsers = array();\n\n\t/**\n\t * List of mobile browsers to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $mobiles = array();\n\n\t/**\n\t * List of robots to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $robots = array();\n\n\t/**\n\t * Current user-agent platform\n\t *\n\t * @var string\n\t */\n\tpublic $platform = '';\n\n\t/**\n\t * Current user-agent browser\n\t *\n\t * @var string\n\t */\n\tpublic $browser = '';\n\n\t/**\n\t * Current user-agent version\n\t *\n\t * @var string\n\t */\n\tpublic $version = '';\n\n\t/**\n\t * Current user-agent mobile name\n\t *\n\t * @var string\n\t */\n\tpublic $mobile = '';\n\n\t/**\n\t * Current user-agent robot name\n\t *\n\t * @var string\n\t */\n\tpublic $robot = '';\n\n\t/**\n\t * HTTP Referer\n\t *\n\t * @var\tmixed\n\t */\n\tpublic $referer;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * Sets the User Agent and runs the compilation routine\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tif (isset($_SERVER['HTTP_USER_AGENT']))\n\t\t{\n\t\t\t$this->agent = trim($_SERVER['HTTP_USER_AGENT']);\n\t\t}\n\n\t\tif ($this->agent !== NULL && $this->_load_agent_file())\n\t\t{\n\t\t\t$this->_compile_data();\n\t\t}\n\n\t\tlog_message('info', 'User Agent Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile the User Agent Data\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _load_agent_file()\n\t{\n\t\tif (($found = file_exists(APPPATH.'config/user_agents.php')))\n\t\t{\n\t\t\tinclude(APPPATH.'config/user_agents.php');\n\t\t}\n\n\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php');\n\t\t\t$found = TRUE;\n\t\t}\n\n\t\tif ($found !== TRUE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$return = FALSE;\n\n\t\tif (isset($platforms))\n\t\t{\n\t\t\t$this->platforms = $platforms;\n\t\t\tunset($platforms);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\tif (isset($browsers))\n\t\t{\n\t\t\t$this->browsers = $browsers;\n\t\t\tunset($browsers);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\tif (isset($mobiles))\n\t\t{\n\t\t\t$this->mobiles = $mobiles;\n\t\t\tunset($mobiles);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\tif (isset($robots))\n\t\t{\n\t\t\t$this->robots = $robots;\n\t\t\tunset($robots);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\treturn $return;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile the User Agent Data\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _compile_data()\n\t{\n\t\t$this->_set_platform();\n\n\t\tforeach (array('_set_robot', '_set_browser', '_set_mobile') as $function)\n\t\t{\n\t\t\tif ($this->$function() === TRUE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Platform\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_platform()\n\t{\n\t\tif (is_array($this->platforms) && count($this->platforms) > 0)\n\t\t{\n\t\t\tforeach ($this->platforms as $key => $val)\n\t\t\t{\n\t\t\t\tif (preg_match('|'.preg_quote($key).'|i', $this->agent))\n\t\t\t\t{\n\t\t\t\t\t$this->platform = $val;\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$this->platform = 'Unknown Platform';\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Browser\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_browser()\n\t{\n\t\tif (is_array($this->browsers) && count($this->browsers) > 0)\n\t\t{\n\t\t\tforeach ($this->browsers as $key => $val)\n\t\t\t{\n\t\t\t\tif (preg_match('|'.$key.'.*?([0-9\\.]+)|i', $this->agent, $match))\n\t\t\t\t{\n\t\t\t\t\t$this->is_browser = TRUE;\n\t\t\t\t\t$this->version = $match[1];\n\t\t\t\t\t$this->browser = $val;\n\t\t\t\t\t$this->_set_mobile();\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Robot\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_robot()\n\t{\n\t\tif (is_array($this->robots) && count($this->robots) > 0)\n\t\t{\n\t\t\tforeach ($this->robots as $key => $val)\n\t\t\t{\n\t\t\t\tif (preg_match('|'.preg_quote($key).'|i', $this->agent))\n\t\t\t\t{\n\t\t\t\t\t$this->is_robot = TRUE;\n\t\t\t\t\t$this->robot = $val;\n\t\t\t\t\t$this->_set_mobile();\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Mobile Device\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_mobile()\n\t{\n\t\tif (is_array($this->mobiles) && count($this->mobiles) > 0)\n\t\t{\n\t\t\tforeach ($this->mobiles as $key => $val)\n\t\t\t{\n\t\t\t\tif (FALSE !== (stripos($this->agent, $key)))\n\t\t\t\t{\n\t\t\t\t\t$this->is_mobile = TRUE;\n\t\t\t\t\t$this->mobile = $val;\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the accepted languages\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _set_languages()\n\t{\n\t\tif ((count($this->languages) === 0) && ! empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))\n\t\t{\n\t\t\t$this->languages = explode(',', preg_replace('/(;\\s?q=[0-9\\.]+)|\\s/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_LANGUAGE']))));\n\t\t}\n\n\t\tif (count($this->languages) === 0)\n\t\t{\n\t\t\t$this->languages = array('Undefined');\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the accepted character sets\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _set_charsets()\n\t{\n\t\tif ((count($this->charsets) === 0) && ! empty($_SERVER['HTTP_ACCEPT_CHARSET']))\n\t\t{\n\t\t\t$this->charsets = explode(',', preg_replace('/(;\\s?q=.+)|\\s/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_CHARSET']))));\n\t\t}\n\n\t\tif (count($this->charsets) === 0)\n\t\t{\n\t\t\t$this->charsets = array('Undefined');\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Browser\n\t *\n\t * @param\tstring\t$key\n\t * @return\tbool\n\t */\n\tpublic function is_browser($key = NULL)\n\t{\n\t\tif ( ! $this->is_browser)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// No need to be specific, it's a browser\n\t\tif ($key === NULL)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Check for a specific browser\n\t\treturn (isset($this->browsers[$key]) && $this->browser === $this->browsers[$key]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Robot\n\t *\n\t * @param\tstring\t$key\n\t * @return\tbool\n\t */\n\tpublic function is_robot($key = NULL)\n\t{\n\t\tif ( ! $this->is_robot)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// No need to be specific, it's a robot\n\t\tif ($key === NULL)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Check for a specific robot\n\t\treturn (isset($this->robots[$key]) && $this->robot === $this->robots[$key]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Mobile\n\t *\n\t * @param\tstring\t$key\n\t * @return\tbool\n\t */\n\tpublic function is_mobile($key = NULL)\n\t{\n\t\tif ( ! $this->is_mobile)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// No need to be specific, it's a mobile\n\t\tif ($key === NULL)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Check for a specific robot\n\t\treturn (isset($this->mobiles[$key]) && $this->mobile === $this->mobiles[$key]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is this a referral from another site?\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_referral()\n\t{\n\t\tif ( ! isset($this->referer))\n\t\t{\n\t\t\tif (empty($_SERVER['HTTP_REFERER']))\n\t\t\t{\n\t\t\t\t$this->referer = FALSE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$referer_host = @parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);\n\t\t\t\t$own_host = parse_url(config_item('base_url'), PHP_URL_HOST);\n\n\t\t\t\t$this->referer = ($referer_host && $referer_host !== $own_host);\n\t\t\t}\n\t\t}\n\n\t\treturn $this->referer;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Agent String\n\t *\n\t * @return\tstring\n\t */\n\tpublic function agent_string()\n\t{\n\t\treturn $this->agent;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Platform\n\t *\n\t * @return\tstring\n\t */\n\tpublic function platform()\n\t{\n\t\treturn $this->platform;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Browser Name\n\t *\n\t * @return\tstring\n\t */\n\tpublic function browser()\n\t{\n\t\treturn $this->browser;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Browser Version\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\treturn $this->version;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get The Robot Name\n\t *\n\t * @return\tstring\n\t */\n\tpublic function robot()\n\t{\n\t\treturn $this->robot;\n\t}\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Mobile Device\n\t *\n\t * @return\tstring\n\t */\n\tpublic function mobile()\n\t{\n\t\treturn $this->mobile;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the referrer\n\t *\n\t * @return\tbool\n\t */\n\tpublic function referrer()\n\t{\n\t\treturn empty($_SERVER['HTTP_REFERER']) ? '' : trim($_SERVER['HTTP_REFERER']);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the accepted languages\n\t *\n\t * @return\tarray\n\t */\n\tpublic function languages()\n\t{\n\t\tif (count($this->languages) === 0)\n\t\t{\n\t\t\t$this->_set_languages();\n\t\t}\n\n\t\treturn $this->languages;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the accepted Character Sets\n\t *\n\t * @return\tarray\n\t */\n\tpublic function charsets()\n\t{\n\t\tif (count($this->charsets) === 0)\n\t\t{\n\t\t\t$this->_set_charsets();\n\t\t}\n\n\t\treturn $this->charsets;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Test for a particular language\n\t *\n\t * @param\tstring\t$lang\n\t * @return\tbool\n\t */\n\tpublic function accept_lang($lang = 'en')\n\t{\n\t\treturn in_array(strtolower($lang), $this->languages(), TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Test for a particular character set\n\t *\n\t * @param\tstring\t$charset\n\t * @return\tbool\n\t */\n\tpublic function accept_charset($charset = 'utf-8')\n\t{\n\t\treturn in_array(strtolower($charset), $this->charsets(), TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a custom user-agent string\n\t *\n\t * @param\tstring\t$string\n\t * @return\tvoid\n\t */\n\tpublic function parse($string)\n\t{\n\t\t// Reset values\n\t\t$this->is_browser = FALSE;\n\t\t$this->is_robot = FALSE;\n\t\t$this->is_mobile = FALSE;\n\t\t$this->browser = '';\n\t\t$this->version = '';\n\t\t$this->mobile = '';\n\t\t$this->robot = '';\n\n\t\t// Set the new user-agent string and parse it, unless empty\n\t\t$this->agent = $string;\n\n\t\tif ( ! empty($string))\n\t\t{\n\t\t\t$this->_compile_data();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Xmlrpc.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nif ( ! function_exists('xml_parser_create'))\n{\n\tshow_error('Your PHP installation does not support XML');\n}\n\n// ------------------------------------------------------------------------\n\n/**\n * XML-RPC request handler class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass CI_Xmlrpc {\n\n\t/**\n\t * Debug flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $debug\t\t= FALSE;\n\n\t/**\n\t * I4 data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcI4\t= 'i4';\n\n\t/**\n\t * Integer data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcInt\t= 'int';\n\n\t/**\n\t * Boolean data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcBoolean\t= 'boolean';\n\n\t/**\n\t * Double data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcDouble\t= 'double';\n\n\t/**\n\t * String data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcString\t= 'string';\n\n\t/**\n\t * DateTime format\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcDateTime\t= 'dateTime.iso8601';\n\n\t/**\n\t * Base64 data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcBase64\t= 'base64';\n\n\t/**\n\t * Array data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcArray\t= 'array';\n\n\t/**\n\t * Struct data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcStruct\t= 'struct';\n\n\t/**\n\t * Data types list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $xmlrpcTypes\t= array();\n\n\t/**\n\t * Valid parents list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $valid_parents\t= array();\n\n\t/**\n\t * Response error numbers list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $xmlrpcerr\t\t= array();\n\n\t/**\n\t * Response error messages list\n\t *\n\t * @var\tstring[]\n\t */\n\tpublic $xmlrpcstr\t\t= array();\n\n\t/**\n\t * Encoding charset\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpc_defencoding\t= 'UTF-8';\n\n\t/**\n\t * XML-RPC client name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcName\t\t= 'XML-RPC for CodeIgniter';\n\n\t/**\n\t * XML-RPC version\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcVersion\t\t= '1.1';\n\n\t/**\n\t * Start of user errors\n\t *\n\t * @var\tint\n\t */\n\tpublic $xmlrpcerruser\t\t= 800;\n\n\t/**\n\t * Start of XML parse errors\n\t *\n\t * @var\tint\n\t */\n\tpublic $xmlrpcerrxml\t\t= 100;\n\n\t/**\n\t * Backslash replacement value\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpc_backslash\t= '';\n\n\t/**\n\t * XML-RPC Client object\n\t *\n\t * @var\tobject\n\t */\n\tpublic $client;\n\n\t/**\n\t * XML-RPC Method name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $method;\n\n\t/**\n\t * XML-RPC Data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $data;\n\n\t/**\n\t * XML-RPC Message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $message\t\t\t= '';\n\n\t/**\n\t * Request error message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $error\t\t\t= '';\n\n\t/**\n\t * XML-RPC result object\n\t *\n\t * @var\tobject\n\t */\n\tpublic $result;\n\n\t/**\n\t * XML-RPC Reponse\n\t *\n\t * @var\tarray\n\t */\n\tpublic $response\t\t= array(); // Response from remote server\n\n\t/**\n\t * XSS Filter flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $xss_clean\t\t= TRUE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * Initializes property default values\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t$this->xmlrpc_backslash = chr(92).chr(92);\n\n\t\t// Types for info sent back and forth\n\t\t$this->xmlrpcTypes = array(\n\t\t\t$this->xmlrpcI4\t \t\t=> '1',\n\t\t\t$this->xmlrpcInt\t\t=> '1',\n\t\t\t$this->xmlrpcBoolean\t=> '1',\n\t\t\t$this->xmlrpcString\t\t=> '1',\n\t\t\t$this->xmlrpcDouble\t\t=> '1',\n\t\t\t$this->xmlrpcDateTime\t=> '1',\n\t\t\t$this->xmlrpcBase64\t\t=> '1',\n\t\t\t$this->xmlrpcArray\t\t=> '2',\n\t\t\t$this->xmlrpcStruct\t\t=> '3'\n\t\t);\n\n\t\t// Array of Valid Parents for Various XML-RPC elements\n\t\t$this->valid_parents = array('BOOLEAN' => array('VALUE'),\n\t\t\t'I4'\t\t\t\t=> array('VALUE'),\n\t\t\t'INT'\t\t\t\t=> array('VALUE'),\n\t\t\t'STRING'\t\t\t=> array('VALUE'),\n\t\t\t'DOUBLE'\t\t\t=> array('VALUE'),\n\t\t\t'DATETIME.ISO8601'\t=> array('VALUE'),\n\t\t\t'BASE64'\t\t\t=> array('VALUE'),\n\t\t\t'ARRAY'\t\t\t=> array('VALUE'),\n\t\t\t'STRUCT'\t\t\t=> array('VALUE'),\n\t\t\t'PARAM'\t\t\t=> array('PARAMS'),\n\t\t\t'METHODNAME'\t\t=> array('METHODCALL'),\n\t\t\t'PARAMS'\t\t\t=> array('METHODCALL', 'METHODRESPONSE'),\n\t\t\t'MEMBER'\t\t\t=> array('STRUCT'),\n\t\t\t'NAME'\t\t\t\t=> array('MEMBER'),\n\t\t\t'DATA'\t\t\t\t=> array('ARRAY'),\n\t\t\t'FAULT'\t\t\t=> array('METHODRESPONSE'),\n\t\t\t'VALUE'\t\t\t=> array('MEMBER', 'DATA', 'PARAM', 'FAULT')\n\t\t);\n\n\t\t// XML-RPC Responses\n\t\t$this->xmlrpcerr['unknown_method'] = '1';\n\t\t$this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';\n\t\t$this->xmlrpcerr['invalid_return'] = '2';\n\t\t$this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.';\n\t\t$this->xmlrpcerr['incorrect_params'] = '3';\n\t\t$this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';\n\t\t$this->xmlrpcerr['introspect_unknown'] = '4';\n\t\t$this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';\n\t\t$this->xmlrpcerr['http_error'] = '5';\n\t\t$this->xmlrpcstr['http_error'] = \"Did not receive a '200 OK' response from remote server.\";\n\t\t$this->xmlrpcerr['no_data'] = '6';\n\t\t$this->xmlrpcstr['no_data'] = 'No data received from server.';\n\n\t\t$this->initialize($config);\n\n\t\tlog_message('info', 'XML-RPC Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tif (count($config) > 0)\n\t\t{\n\t\t\tforeach ($config as $key => $val)\n\t\t\t{\n\t\t\t\tif (isset($this->$key))\n\t\t\t\t{\n\t\t\t\t\t$this->$key = $val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse server URL\n\t *\n\t * @param\tstring\t$url\n\t * @param\tint\t$port\n\t * @param\tstring\t$proxy\n\t * @param\tint\t$proxy_port\n\t * @return\tvoid\n\t */\n\tpublic function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)\n\t{\n\t\tif (strpos($url, 'http') !== 0)\n\t\t{\n\t\t\t$url = 'http://'.$url;\n\t\t}\n\n\t\t$parts = parse_url($url);\n\n\t\tif (isset($parts['user'], $parts['pass']))\n\t\t{\n\t\t\t$parts['host'] = $parts['user'].':'.$parts['pass'].'@'.$parts['host'];\n\t\t}\n\n\t\t$path = isset($parts['path']) ? $parts['path'] : '/';\n\n\t\tif ( ! empty($parts['query']))\n\t\t{\n\t\t\t$path .= '?'.$parts['query'];\n\t\t}\n\n\t\t$this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Timeout\n\t *\n\t * @param\tint\t$seconds\n\t * @return\tvoid\n\t */\n\tpublic function timeout($seconds = 5)\n\t{\n\t\tif ($this->client !== NULL && is_int($seconds))\n\t\t{\n\t\t\t$this->client->timeout = $seconds;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Methods\n\t *\n\t * @param\tstring\t$function\tMethod name\n\t * @return\tvoid\n\t */\n\tpublic function method($function)\n\t{\n\t\t$this->method = $function;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Take Array of Data and Create Objects\n\t *\n\t * @param\tarray\t$incoming\n\t * @return\tvoid\n\t */\n\tpublic function request($incoming)\n\t{\n\t\tif ( ! is_array($incoming))\n\t\t{\n\t\t\t// Send Error\n\t\t\treturn;\n\t\t}\n\n\t\t$this->data = array();\n\n\t\tforeach ($incoming as $key => $value)\n\t\t{\n\t\t\t$this->data[$key] = $this->values_parsing($value);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Debug\n\t *\n\t * @param\tbool\t$flag\n\t * @return\tvoid\n\t */\n\tpublic function set_debug($flag = TRUE)\n\t{\n\t\t$this->debug = ($flag === TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Values Parsing\n\t *\n\t * @param\tmixed\t$value\n\t * @return\tobject\n\t */\n\tpublic function values_parsing($value)\n\t{\n\t\tif (is_array($value) && array_key_exists(0, $value))\n\t\t{\n\t\t\tif ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))\n\t\t\t{\n\t\t\t\t$temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))\n\t\t\t\t{\n\t\t\t\t\twhile (list($k) = each($value[0]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$value[0][$k] = $this->values_parsing($value[0][$k]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$temp = new XML_RPC_Values($value[0], $value[1]);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$temp = new XML_RPC_Values($value, 'string');\n\t\t}\n\n\t\treturn $temp;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sends XML-RPC Request\n\t *\n\t * @return\tbool\n\t */\n\tpublic function send_request()\n\t{\n\t\t$this->message = new XML_RPC_Message($this->method, $this->data);\n\t\t$this->message->debug = $this->debug;\n\n\t\tif ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))\n\t\t{\n\t\t\t$this->error = $this->result->errstr;\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->response = $this->result->decode();\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns Error\n\t *\n\t * @return\tstring\n\t */\n\tpublic function display_error()\n\t{\n\t\treturn $this->error;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns Remote Server Response\n\t *\n\t * @return\tstring\n\t */\n\tpublic function display_response()\n\t{\n\t\treturn $this->response;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sends an Error Message for Server Request\n\t *\n\t * @param\tint\t$number\n\t * @param\tstring\t$message\n\t * @return\tobject\n\t */\n\tpublic function send_error_message($number, $message)\n\t{\n\t\treturn new XML_RPC_Response(0, $number, $message);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Response for Server Request\n\t *\n\t * @param\tarray\t$response\n\t * @return\tobject\n\t */\n\tpublic function send_response($response)\n\t{\n\t\t// $response should be array of values, which will be parsed\n\t\t// based on their data and type into a valid group of XML-RPC values\n\t\treturn new XML_RPC_Response($this->values_parsing($response));\n\t}\n\n} // END XML_RPC Class\n\n/**\n * XML-RPC Client class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Client extends CI_Xmlrpc\n{\n\t/**\n\t * Path\n\t *\n\t * @var\tstring\n\t */\n\tpublic $path\t\t\t= '';\n\n\t/**\n\t * Server hostname\n\t *\n\t * @var\tstring\n\t */\n\tpublic $server\t\t\t= '';\n\n\t/**\n\t * Server port\n\t *\n\t * @var\tint\n\t */\n\tpublic $port\t\t\t= 80;\n\n\t/**\n\t *\n\t * Server username\n\t *\n\t * @var\tstring\n\t */\n\tpublic $username;\n\n\t/**\n\t * Server password\n\t *\n\t * @var\tstring\n\t */\n\tpublic $password;\n\n\t/**\n\t * Proxy hostname\n\t *\n\t * @var\tstring\n\t */\n\tpublic $proxy\t\t\t= FALSE;\n\n\t/**\n\t * Proxy port\n\t *\n\t * @var\tint\n\t */\n\tpublic $proxy_port\t\t= 8080;\n\n\t/**\n\t * Error number\n\t *\n\t * @var\tstring\n\t */\n\tpublic $errno\t\t\t= '';\n\n\t/**\n\t * Error message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $errstring\t\t= '';\n\n\t/**\n\t * Timeout in seconds\n\t *\n\t * @var\tint\n\t */\n\tpublic $timeout\t\t= 5;\n\n\t/**\n\t * No Multicall flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $no_multicall\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tstring\t$path\n\t * @param\tobject\t$server\n\t * @param\tint\t$port\n\t * @param\tstring\t$proxy\n\t * @param\tint\t$proxy_port\n\t * @return\tvoid\n\t */\n\tpublic function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)\n\t{\n\t\tparent::__construct();\n\n\t\t$url = parse_url('http://'.$server);\n\n\t\tif (isset($url['user'], $url['pass']))\n\t\t{\n\t\t\t$this->username = $url['user'];\n\t\t\t$this->password = $url['pass'];\n\t\t}\n\n\t\t$this->port = $port;\n\t\t$this->server = $url['host'];\n\t\t$this->path = $path;\n\t\t$this->proxy = $proxy;\n\t\t$this->proxy_port = $proxy_port;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send message\n\t *\n\t * @param\tmixed\t$msg\n\t * @return\tobject\n\t */\n\tpublic function send($msg)\n\t{\n\t\tif (is_array($msg))\n\t\t{\n\t\t\t// Multi-call disabled\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);\n\t\t}\n\n\t\treturn $this->sendPayload($msg);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send payload\n\t *\n\t * @param\tobject\t$msg\n\t * @return\tobject\n\t */\n\tpublic function sendPayload($msg)\n\t{\n\t\tif ($this->proxy === FALSE)\n\t\t{\n\t\t\t$server = $this->server;\n\t\t\t$port = $this->port;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$server = $this->proxy;\n\t\t\t$port = $this->proxy_port;\n\t\t}\n\n\t\t$fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);\n\n\t\tif ( ! is_resource($fp))\n\t\t{\n\t\t\terror_log($this->xmlrpcstr['http_error']);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);\n\t\t}\n\n\t\tif (empty($msg->payload))\n\t\t{\n\t\t\t// $msg = XML_RPC_Messages\n\t\t\t$msg->createPayload();\n\t\t}\n\n\t\t$r = \"\\r\\n\";\n\t\t$op = 'POST '.$this->path.' HTTP/1.0'.$r\n\t\t\t.'Host: '.$this->server.$r\n\t\t\t.'Content-Type: text/xml'.$r\n\t\t\t.(isset($this->username, $this->password) ? 'Authorization: Basic '.base64_encode($this->username.':'.$this->password).$r : '')\n\t\t\t.'User-Agent: '.$this->xmlrpcName.$r\n\t\t\t.'Content-Length: '.strlen($msg->payload).$r.$r\n\t\t\t.$msg->payload;\n\n\t\tfor ($written = $timestamp = 0, $length = strlen($op); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($fp, substr($op, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951\n\t\t\telseif ($result === 0)\n\t\t\t{\n\t\t\t\tif ($timestamp === 0)\n\t\t\t\t{\n\t\t\t\t\t$timestamp = time();\n\t\t\t\t}\n\t\t\t\telseif ($timestamp < (time() - $this->timeout))\n\t\t\t\t{\n\t\t\t\t\t$result = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tusleep(250000);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$timestamp = 0;\n\t\t\t}\n\t\t}\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\terror_log($this->xmlrpcstr['http_error']);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);\n\t\t}\n\n\t\t$resp = $msg->parseResponse($fp);\n\t\tfclose($fp);\n\t\treturn $resp;\n\t}\n\n} // END XML_RPC_Client Class\n\n/**\n * XML-RPC Response class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Response\n{\n\n\t/**\n\t * Value\n\t *\n\t * @var\tmixed\n\t */\n\tpublic $val\t\t= 0;\n\n\t/**\n\t * Error number\n\t *\n\t * @var\tint\n\t */\n\tpublic $errno\t\t= 0;\n\n\t/**\n\t * Error message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $errstr\t\t= '';\n\n\t/**\n\t * Headers list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $headers\t\t= array();\n\n\t/**\n\t * XSS Filter flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $xss_clean\t= TRUE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tmixed\t$val\n\t * @param\tint\t$code\n\t * @param\tstring\t$fstr\n\t * @return\tvoid\n\t */\n\tpublic function __construct($val, $code = 0, $fstr = '')\n\t{\n\t\tif ($code !== 0)\n\t\t{\n\t\t\t// error\n\t\t\t$this->errno = $code;\n\t\t\t$this->errstr = htmlspecialchars($fstr,\n\t\t\t\t\t\t\t(is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),\n\t\t\t\t\t\t\t'UTF-8');\n\t\t}\n\t\telseif ( ! is_object($val))\n\t\t{\n\t\t\t// programmer error, not an object\n\t\t\terror_log(\"Invalid type '\".gettype($val).\"' (value: \".$val.') passed to XML_RPC_Response. Defaulting to empty value.');\n\t\t\t$this->val = new XML_RPC_Values();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->val = $val;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fault code\n\t *\n\t * @return\tint\n\t */\n\tpublic function faultCode()\n\t{\n\t\treturn $this->errno;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fault string\n\t *\n\t * @return\tstring\n\t */\n\tpublic function faultString()\n\t{\n\t\treturn $this->errstr;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Value\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function value()\n\t{\n\t\treturn $this->val;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prepare response\n\t *\n\t * @return\tstring\txml\n\t */\n\tpublic function prepare_response()\n\t{\n\t\treturn \"<methodResponse>\\n\"\n\t\t\t.($this->errno\n\t\t\t\t? '<fault>\n\t<value>\n\t\t<struct>\n\t\t\t<member>\n\t\t\t\t<name>faultCode</name>\n\t\t\t\t<value><int>'.$this->errno.'</int></value>\n\t\t\t</member>\n\t\t\t<member>\n\t\t\t\t<name>faultString</name>\n\t\t\t\t<value><string>'.$this->errstr.'</string></value>\n\t\t\t</member>\n\t\t</struct>\n\t</value>\n</fault>'\n\t\t\t\t: \"<params>\\n<param>\\n\".$this->val->serialize_class().\"</param>\\n</params>\")\n\t\t\t.\"\\n</methodResponse>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decode\n\t *\n\t * @param\tmixed\t$array\n\t * @return\tarray\n\t */\n\tpublic function decode($array = NULL)\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif (is_array($array))\n\t\t{\n\t\t\twhile (list($key) = each($array))\n\t\t\t{\n\t\t\t\tif (is_array($array[$key]))\n\t\t\t\t{\n\t\t\t\t\t$array[$key] = $this->decode($array[$key]);\n\t\t\t\t}\n\t\t\t\telseif ($this->xss_clean)\n\t\t\t\t{\n\t\t\t\t\t$array[$key] = $CI->security->xss_clean($array[$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $array;\n\t\t}\n\n\t\t$result = $this->xmlrpc_decoder($this->val);\n\n\t\tif (is_array($result))\n\t\t{\n\t\t\t$result = $this->decode($result);\n\t\t}\n\t\telseif ($this->xss_clean)\n\t\t{\n\t\t\t$result = $CI->security->xss_clean($result);\n\t\t}\n\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XML-RPC Object to PHP Types\n\t *\n\t * @param\tobject\n\t * @return\tarray\n\t */\n\tpublic function xmlrpc_decoder($xmlrpc_val)\n\t{\n\t\t$kind = $xmlrpc_val->kindOf();\n\n\t\tif ($kind === 'scalar')\n\t\t{\n\t\t\treturn $xmlrpc_val->scalarval();\n\t\t}\n\t\telseif ($kind === 'array')\n\t\t{\n\t\t\treset($xmlrpc_val->me);\n\t\t\t$b = current($xmlrpc_val->me);\n\t\t\t$arr = array();\n\n\t\t\tfor ($i = 0, $size = count($b); $i < $size; $i++)\n\t\t\t{\n\t\t\t\t$arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);\n\t\t\t}\n\t\t\treturn $arr;\n\t\t}\n\t\telseif ($kind === 'struct')\n\t\t{\n\t\t\treset($xmlrpc_val->me['struct']);\n\t\t\t$arr = array();\n\n\t\t\twhile (list($key,$value) = each($xmlrpc_val->me['struct']))\n\t\t\t{\n\t\t\t\t$arr[$key] = $this->xmlrpc_decoder($value);\n\t\t\t}\n\t\t\treturn $arr;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ISO-8601 time to server or UTC time\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tint\tunix timestamp\n\t */\n\tpublic function iso8601_decode($time, $utc = FALSE)\n\t{\n\t\t// Return a time in the localtime, or UTC\n\t\t$t = 0;\n\t\tif (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))\n\t\t{\n\t\t\t$fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';\n\t\t\t$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);\n\t\t}\n\t\treturn $t;\n\t}\n\n} // END XML_RPC_Response Class\n\n/**\n * XML-RPC Message class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Message extends CI_Xmlrpc\n{\n\n\t/**\n\t * Payload\n\t *\n\t * @var\tstring\n\t */\n\tpublic $payload;\n\n\t/**\n\t * Method name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $method_name;\n\n\t/**\n\t * Parameter list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $params\t\t= array();\n\n\t/**\n\t * XH?\n\t *\n\t * @var\tarray\n\t */\n\tpublic $xh\t\t= array();\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tstring\t$method\n\t * @param\tarray\t$pars\n\t * @return\tvoid\n\t */\n\tpublic function __construct($method, $pars = FALSE)\n\t{\n\t\tparent::__construct();\n\n\t\t$this->method_name = $method;\n\t\tif (is_array($pars) && count($pars) > 0)\n\t\t{\n\t\t\tfor ($i = 0, $c = count($pars); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// $pars[$i] = XML_RPC_Values\n\t\t\t\t$this->params[] = $pars[$i];\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Payload to Send\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function createPayload()\n\t{\n\t\t$this->payload = '<?xml version=\"1.0\"?'.\">\\r\\n<methodCall>\\r\\n\"\n\t\t\t\t.'<methodName>'.$this->method_name.\"</methodName>\\r\\n\"\n\t\t\t\t.\"<params>\\r\\n\";\n\n\t\tfor ($i = 0, $c = count($this->params); $i < $c; $i++)\n\t\t{\n\t\t\t// $p = XML_RPC_Values\n\t\t\t$p = $this->params[$i];\n\t\t\t$this->payload .= \"<param>\\r\\n\".$p->serialize_class().\"</param>\\r\\n\";\n\t\t}\n\n\t\t$this->payload .= \"</params>\\r\\n</methodCall>\\r\\n\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse External XML-RPC Server's Response\n\t *\n\t * @param\tresource\n\t * @return\tobject\n\t */\n\tpublic function parseResponse($fp)\n\t{\n\t\t$data = '';\n\n\t\twhile ($datum = fread($fp, 4096))\n\t\t{\n\t\t\t$data .= $datum;\n\t\t}\n\n\t\t// Display HTTP content for debugging\n\t\tif ($this->debug === TRUE)\n\t\t{\n\t\t\techo \"<pre>---DATA---\\n\".htmlspecialchars($data).\"\\n---END DATA---\\n\\n</pre>\";\n\t\t}\n\n\t\t// Check for data\n\t\tif ($data === '')\n\t\t{\n\t\t\terror_log($this->xmlrpcstr['no_data']);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);\n\t\t}\n\n\t\t// Check for HTTP 200 Response\n\t\tif (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\\/[0-9\\.]+ 200 /', $data))\n\t\t{\n\t\t\t$errstr = substr($data, 0, strpos($data, \"\\n\")-1);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Create and Set Up XML Parser\n\t\t//-------------------------------------\n\n\t\t$parser = xml_parser_create($this->xmlrpc_defencoding);\n\t\t$pname = (string) $parser;\n\t\t$this->xh[$pname] = array(\n\t\t\t'isf'\t\t=> 0,\n\t\t\t'ac'\t\t=> '',\n\t\t\t'headers'\t=> array(),\n\t\t\t'stack'\t\t=> array(),\n\t\t\t'valuestack'\t=> array(),\n\t\t\t'isf_reason'\t=> 0\n\t\t);\n\n\t\txml_set_object($parser, $this);\n\t\txml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);\n\t\txml_set_element_handler($parser, 'open_tag', 'closing_tag');\n\t\txml_set_character_data_handler($parser, 'character_data');\n\t\t//xml_set_default_handler($parser, 'default_handler');\n\n\t\t// Get headers\n\t\t$lines = explode(\"\\r\\n\", $data);\n\t\twhile (($line = array_shift($lines)))\n\t\t{\n\t\t\tif (strlen($line) < 1)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t$this->xh[$pname]['headers'][] = $line;\n\t\t}\n\t\t$data = implode(\"\\r\\n\", $lines);\n\n\t\t// Parse XML data\n\t\tif ( ! xml_parse($parser, $data, count($data)))\n\t\t{\n\t\t\t$errstr = sprintf('XML error: %s at line %d',\n\t\t\t\t\t\txml_error_string(xml_get_error_code($parser)),\n\t\t\t\t\t\txml_get_current_line_number($parser));\n\n\t\t\t$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);\n\t\t\txml_parser_free($parser);\n\t\t\treturn $r;\n\t\t}\n\t\txml_parser_free($parser);\n\n\t\t// Got ourselves some badness, it seems\n\t\tif ($this->xh[$pname]['isf'] > 1)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\techo \"---Invalid Return---\\n\".$this->xh[$pname]['isf_reason'].\"---Invalid Return---\\n\\n\";\n\t\t\t}\n\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);\n\t\t}\n\t\telseif ( ! is_object($this->xh[$pname]['value']))\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);\n\t\t}\n\n\t\t// Display XML content for debugging\n\t\tif ($this->debug === TRUE)\n\t\t{\n\t\t\techo '<pre>';\n\n\t\t\tif (count($this->xh[$pname]['headers'] > 0))\n\t\t\t{\n\t\t\t\techo \"---HEADERS---\\n\";\n\t\t\t\tforeach ($this->xh[$pname]['headers'] as $header)\n\t\t\t\t{\n\t\t\t\t\techo $header.\"\\n\";\n\t\t\t\t}\n\t\t\t\techo \"---END HEADERS---\\n\\n\";\n\t\t\t}\n\n\t\t\techo \"---DATA---\\n\".htmlspecialchars($data).\"\\n---END DATA---\\n\\n---PARSED---\\n\";\n\t\t\tvar_dump($this->xh[$pname]['value']);\n\t\t\techo \"\\n---END PARSED---</pre>\";\n\t\t}\n\n\t\t// Send response\n\t\t$v = $this->xh[$pname]['value'];\n\t\tif ($this->xh[$pname]['isf'])\n\t\t{\n\t\t\t$errno_v = $v->me['struct']['faultCode'];\n\t\t\t$errstr_v = $v->me['struct']['faultString'];\n\t\t\t$errno = $errno_v->scalarval();\n\n\t\t\tif ($errno === 0)\n\t\t\t{\n\t\t\t\t// FAULT returned, errno needs to reflect that\n\t\t\t\t$errno = -1;\n\t\t\t}\n\n\t\t\t$r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$r = new XML_RPC_Response($v);\n\t\t}\n\n\t\t$r->headers = $this->xh[$pname]['headers'];\n\t\treturn $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t// ------------------------------------\n\t//  Begin Return Message Parsing section\n\t// ------------------------------------\n\n\t// quick explanation of components:\n\t//   ac - used to accumulate values\n\t//   isf - used to indicate a fault\n\t//   lv - used to indicate \"looking for a value\": implements\n\t//\t\tthe logic to allow values with no types to be strings\n\t//   params - used to store parameters in method calls\n\t//   method - used to store method name\n\t//\t stack - array with parent tree of the xml element,\n\t//\t\t\t used to validate the nesting of elements\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Start Element Handler\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function open_tag($the_parser, $name)\n\t{\n\t\t$the_parser = (string) $the_parser;\n\n\t\t// If invalid nesting, then return\n\t\tif ($this->xh[$the_parser]['isf'] > 1) return;\n\n\t\t// Evaluate and check for correct nesting of XML elements\n\t\tif (count($this->xh[$the_parser]['stack']) === 0)\n\t\t{\n\t\t\tif ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')\n\t\t\t{\n\t\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t\t$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// not top level element: see if parent is OK\n\t\telseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))\n\t\t{\n\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t$this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0];\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ($name)\n\t\t{\n\t\t\tcase 'STRUCT':\n\t\t\tcase 'ARRAY':\n\t\t\t\t// Creates array for child elements\n\t\t\t\t$cur_val = array('value' => array(), 'type' => $name);\n\t\t\t\tarray_unshift($this->xh[$the_parser]['valuestack'], $cur_val);\n\t\t\t\tbreak;\n\t\t\tcase 'METHODNAME':\n\t\t\tcase 'NAME':\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\tbreak;\n\t\t\tcase 'FAULT':\n\t\t\t\t$this->xh[$the_parser]['isf'] = 1;\n\t\t\t\tbreak;\n\t\t\tcase 'PARAM':\n\t\t\t\t$this->xh[$the_parser]['value'] = NULL;\n\t\t\t\tbreak;\n\t\t\tcase 'VALUE':\n\t\t\t\t$this->xh[$the_parser]['vt'] = 'value';\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\t$this->xh[$the_parser]['lv'] = 1;\n\t\t\t\tbreak;\n\t\t\tcase 'I4':\n\t\t\tcase 'INT':\n\t\t\tcase 'STRING':\n\t\t\tcase 'BOOLEAN':\n\t\t\tcase 'DOUBLE':\n\t\t\tcase 'DATETIME.ISO8601':\n\t\t\tcase 'BASE64':\n\t\t\t\tif ($this->xh[$the_parser]['vt'] !== 'value')\n\t\t\t\t{\n\t\t\t\t\t//two data elements inside a value: an error occurred!\n\t\t\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t\t\t$this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '\n\t\t\t\t\t\t\t\t\t\t.$this->xh[$the_parser]['vt'].' element inside a single value';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\tbreak;\n\t\t\tcase 'MEMBER':\n\t\t\t\t// Set name of <member> to nothing to prevent errors later if no <name> is found\n\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['name'] = '';\n\n\t\t\t\t// Set NULL value to check to see if value passed for this param/member\n\t\t\t\t$this->xh[$the_parser]['value'] = NULL;\n\t\t\t\tbreak;\n\t\t\tcase 'DATA':\n\t\t\tcase 'METHODCALL':\n\t\t\tcase 'METHODRESPONSE':\n\t\t\tcase 'PARAMS':\n\t\t\t\t// valid elements that add little to processing\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t/// An Invalid Element is Found, so we have trouble\n\t\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t\t$this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Add current element name to stack, to allow validation of nesting\n\t\tarray_unshift($this->xh[$the_parser]['stack'], $name);\n\n\t\t$name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * End Element Handler\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function closing_tag($the_parser, $name)\n\t{\n\t\t$the_parser = (string) $the_parser;\n\n\t\tif ($this->xh[$the_parser]['isf'] > 1) return;\n\n\t\t// Remove current element from stack and set variable\n\t\t// NOTE: If the XML validates, then we do not have to worry about\n\t\t// the opening and closing of elements. Nesting is checked on the opening\n\t\t// tag so we be safe there as well.\n\n\t\t$curr_elem = array_shift($this->xh[$the_parser]['stack']);\n\n\t\tswitch ($name)\n\t\t{\n\t\t\tcase 'STRUCT':\n\t\t\tcase 'ARRAY':\n\t\t\t\t$cur_val = array_shift($this->xh[$the_parser]['valuestack']);\n\t\t\t\t$this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();\n\t\t\t\t$this->xh[$the_parser]['vt']\t= strtolower($name);\n\t\t\t\tbreak;\n\t\t\tcase 'NAME':\n\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];\n\t\t\t\tbreak;\n\t\t\tcase 'BOOLEAN':\n\t\t\tcase 'I4':\n\t\t\tcase 'INT':\n\t\t\tcase 'STRING':\n\t\t\tcase 'DOUBLE':\n\t\t\tcase 'DATETIME.ISO8601':\n\t\t\tcase 'BASE64':\n\t\t\t\t$this->xh[$the_parser]['vt'] = strtolower($name);\n\n\t\t\t\tif ($name === 'STRING')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];\n\t\t\t\t}\n\t\t\t\telseif ($name === 'DATETIME.ISO8601')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['vt']\t= $this->xmlrpcDateTime;\n\t\t\t\t\t$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];\n\t\t\t\t}\n\t\t\t\telseif ($name === 'BASE64')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);\n\t\t\t\t}\n\t\t\t\telseif ($name === 'BOOLEAN')\n\t\t\t\t{\n\t\t\t\t\t// Translated BOOLEAN values to TRUE AND FALSE\n\t\t\t\t\t$this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];\n\t\t\t\t}\n\t\t\t\telseif ($name=='DOUBLE')\n\t\t\t\t{\n\t\t\t\t\t// we have a DOUBLE\n\t\t\t\t\t// we must check that only 0123456789-.<space> are characters here\n\t\t\t\t\t$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\\t \\.]+$/', $this->xh[$the_parser]['ac'])\n\t\t\t\t\t\t\t\t\t\t? (float) $this->xh[$the_parser]['ac']\n\t\t\t\t\t\t\t\t\t\t: 'ERROR_NON_NUMERIC_FOUND';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// we have an I4/INT\n\t\t\t\t\t// we must check that only 0123456789-<space> are characters here\n\t\t\t\t\t$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\\t ]+$/', $this->xh[$the_parser]['ac'])\n\t\t\t\t\t\t\t\t\t\t? (int) $this->xh[$the_parser]['ac']\n\t\t\t\t\t\t\t\t\t\t: 'ERROR_NON_NUMERIC_FOUND';\n\t\t\t\t}\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\t$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value\n\t\t\t\tbreak;\n\t\t\tcase 'VALUE':\n\t\t\t\t// This if() detects if no scalar was inside <VALUE></VALUE>\n\t\t\t\tif ($this->xh[$the_parser]['vt'] == 'value')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['value']\t= $this->xh[$the_parser]['ac'];\n\t\t\t\t\t$this->xh[$the_parser]['vt']\t= $this->xmlrpcString;\n\t\t\t\t}\n\n\t\t\t\t// build the XML-RPC value out of the data received, and substitute it\n\t\t\t\t$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);\n\n\t\t\t\tif (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')\n\t\t\t\t{\n\t\t\t\t\t// Array\n\t\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Struct\n\t\t\t\t\t$this->xh[$the_parser]['value'] = $temp;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'MEMBER':\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\n\t\t\t\t// If value add to array in the stack for the last element built\n\t\t\t\tif ($this->xh[$the_parser]['value'])\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'DATA':\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\tbreak;\n\t\t\tcase 'PARAM':\n\t\t\t\tif ($this->xh[$the_parser]['value'])\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'METHODNAME':\n\t\t\t\t$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);\n\t\t\t\tbreak;\n\t\t\tcase 'PARAMS':\n\t\t\tcase 'FAULT':\n\t\t\tcase 'METHODCALL':\n\t\t\tcase 'METHORESPONSE':\n\t\t\t\t// We're all good kids with nuthin' to do\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// End of an Invalid Element. Taken care of during the opening tag though\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse character data\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function character_data($the_parser, $data)\n\t{\n\t\t$the_parser = (string) $the_parser;\n\n\t\tif ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already\n\n\t\t// If a value has not been found\n\t\tif ($this->xh[$the_parser]['lv'] !== 3)\n\t\t{\n\t\t\tif ($this->xh[$the_parser]['lv'] === 1)\n\t\t\t{\n\t\t\t\t$this->xh[$the_parser]['lv'] = 2; // Found a value\n\t\t\t}\n\n\t\t\tif ( ! isset($this->xh[$the_parser]['ac']))\n\t\t\t{\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t}\n\n\t\t\t$this->xh[$the_parser]['ac'] .= $data;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add parameter\n\t *\n\t * @param\tmixed\n\t * @return\tvoid\n\t */\n\tpublic function addParam($par)\n\t{\n\t\t$this->params[] = $par;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Output parameters\n\t *\n\t * @param\tarray\t$array\n\t * @return\tarray\n\t */\n\tpublic function output_parameters(array $array = array())\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif ( ! empty($array))\n\t\t{\n\t\t\twhile (list($key) = each($array))\n\t\t\t{\n\t\t\t\tif (is_array($array[$key]))\n\t\t\t\t{\n\t\t\t\t\t$array[$key] = $this->output_parameters($array[$key]);\n\t\t\t\t}\n\t\t\t\telseif ($key !== 'bits' && $this->xss_clean)\n\t\t\t\t{\n\t\t\t\t\t// 'bits' is for the MetaWeblog API image bits\n\t\t\t\t\t// @todo - this needs to be made more general purpose\n\t\t\t\t\t$array[$key] = $CI->security->xss_clean($array[$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $array;\n\t\t}\n\n\t\t$parameters = array();\n\n\t\tfor ($i = 0, $c = count($this->params); $i < $c; $i++)\n\t\t{\n\t\t\t$a_param = $this->decode_message($this->params[$i]);\n\n\t\t\tif (is_array($a_param))\n\t\t\t{\n\t\t\t\t$parameters[] = $this->output_parameters($a_param);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;\n\t\t\t}\n\t\t}\n\n\t\treturn $parameters;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decode message\n\t *\n\t * @param\tobject\n\t * @return\tmixed\n\t */\n\tpublic function decode_message($param)\n\t{\n\t\t$kind = $param->kindOf();\n\n\t\tif ($kind === 'scalar')\n\t\t{\n\t\t\treturn $param->scalarval();\n\t\t}\n\t\telseif ($kind === 'array')\n\t\t{\n\t\t\treset($param->me);\n\t\t\t$b = current($param->me);\n\t\t\t$arr = array();\n\n\t\t\tfor ($i = 0, $c = count($b); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$arr[] = $this->decode_message($param->me['array'][$i]);\n\t\t\t}\n\n\t\t\treturn $arr;\n\t\t}\n\t\telseif ($kind === 'struct')\n\t\t{\n\t\t\treset($param->me['struct']);\n\t\t\t$arr = array();\n\n\t\t\twhile (list($key,$value) = each($param->me['struct']))\n\t\t\t{\n\t\t\t\t$arr[$key] = $this->decode_message($value);\n\t\t\t}\n\n\t\t\treturn $arr;\n\t\t}\n\t}\n\n} // END XML_RPC_Message Class\n\n/**\n * XML-RPC Values class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Values extends CI_Xmlrpc\n{\n\t/**\n\t * Value data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $me\t= array();\n\n\t/**\n\t * Value type\n\t *\n\t * @var\tint\n\t */\n\tpublic $mytype\t= 0;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tmixed\t$val\n\t * @param\tstring\t$type\n\t * @return\tvoid\n\t */\n\tpublic function __construct($val = -1, $type = '')\n\t{\n\t\tparent::__construct();\n\n\t\tif ($val !== -1 OR $type !== '')\n\t\t{\n\t\t\t$type = $type === '' ? 'string' : $type;\n\n\t\t\tif ($this->xmlrpcTypes[$type] == 1)\n\t\t\t{\n\t\t\t\t$this->addScalar($val, $type);\n\t\t\t}\n\t\t\telseif ($this->xmlrpcTypes[$type] == 2)\n\t\t\t{\n\t\t\t\t$this->addArray($val);\n\t\t\t}\n\t\t\telseif ($this->xmlrpcTypes[$type] == 3)\n\t\t\t{\n\t\t\t\t$this->addStruct($val);\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add scalar value\n\t *\n\t * @param\tscalar\n\t * @param\tstring\n\t * @return\tint\n\t */\n\tpublic function addScalar($val, $type = 'string')\n\t{\n\t\t$typeof = $this->xmlrpcTypes[$type];\n\n\t\tif ($this->mytype === 1)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ($typeof != 1)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ($type === $this->xmlrpcBoolean)\n\t\t{\n\t\t\t$val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));\n\t\t}\n\n\t\tif ($this->mytype === 2)\n\t\t{\n\t\t\t// adding to an array here\n\t\t\t$ar = $this->me['array'];\n\t\t\t$ar[] = new XML_RPC_Values($val, $type);\n\t\t\t$this->me['array'] = $ar;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// a scalar, so set the value and remember we're scalar\n\t\t\t$this->me[$type] = $val;\n\t\t\t$this->mytype = $typeof;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add array value\n\t *\n\t * @param\tarray\n\t * @return\tint\n\t */\n\tpublic function addArray($vals)\n\t{\n\t\tif ($this->mytype !== 0)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';\n\t\t\treturn 0;\n\t\t}\n\n\t\t$this->mytype = $this->xmlrpcTypes['array'];\n\t\t$this->me['array'] = $vals;\n\t\treturn 1;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add struct value\n\t *\n\t * @param\tobject\n\t * @return\tint\n\t */\n\tpublic function addStruct($vals)\n\t{\n\t\tif ($this->mytype !== 0)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';\n\t\t\treturn 0;\n\t\t}\n\t\t$this->mytype = $this->xmlrpcTypes['struct'];\n\t\t$this->me['struct'] = $vals;\n\t\treturn 1;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get value type\n\t *\n\t * @return\tstring\n\t */\n\tpublic function kindOf()\n\t{\n\t\tswitch ($this->mytype)\n\t\t{\n\t\t\tcase 3: return 'struct';\n\t\t\tcase 2: return 'array';\n\t\t\tcase 1: return 'scalar';\n\t\t\tdefault: return 'undef';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Serialize data\n\t *\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tpublic function serializedata($typ, $val)\n\t{\n\t\t$rs = '';\n\n\t\tswitch ($this->xmlrpcTypes[$typ])\n\t\t{\n\t\t\tcase 3:\n\t\t\t\t// struct\n\t\t\t\t$rs .= \"<struct>\\n\";\n\t\t\t\treset($val);\n\t\t\t\twhile (list($key2, $val2) = each($val))\n\t\t\t\t{\n\t\t\t\t\t$rs .= \"<member>\\n<name>{$key2}</name>\\n\".$this->serializeval($val2).\"</member>\\n\";\n\t\t\t\t}\n\t\t\t\t$rs .= '</struct>';\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t// array\n\t\t\t\t$rs .= \"<array>\\n<data>\\n\";\n\t\t\t\tfor ($i = 0, $c = count($val); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$rs .= $this->serializeval($val[$i]);\n\t\t\t\t}\n\t\t\t\t$rs .= \"</data>\\n</array>\\n\";\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\t// others\n\t\t\t\tswitch ($typ)\n\t\t\t\t{\n\t\t\t\t\tcase $this->xmlrpcBase64:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $this->xmlrpcBoolean:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $this->xmlrpcString:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.$val.'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn $rs;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Serialize class\n\t *\n\t * @return\tstring\n\t */\n\tpublic function serialize_class()\n\t{\n\t\treturn $this->serializeval($this);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Serialize value\n\t *\n\t * @param\tobject\n\t * @return\tstring\n\t */\n\tpublic function serializeval($o)\n\t{\n\t\t$ar = $o->me;\n\t\treset($ar);\n\n\t\tlist($typ, $val) = each($ar);\n\t\treturn \"<value>\\n\".$this->serializedata($typ, $val).\"</value>\\n\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Scalar value\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function scalarval()\n\t{\n\t\treset($this->me);\n\t\treturn current($this->me);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encode time in ISO-8601 form.\n\t * Useful for sending time in XML-RPC\n\t *\n\t * @param\tint\tunix timestamp\n\t * @param\tbool\n\t * @return\tstring\n\t*/\n\tpublic function iso8601_encode($time, $utc = FALSE)\n\t{\n\t\treturn ($utc) ? strftime('%Y%m%dT%H:%i:%s', $time) : gmstrftime('%Y%m%dT%H:%i:%s', $time);\n\t}\n\n} // END XML_RPC_Values Class\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Xmlrpcs.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nif ( ! function_exists('xml_parser_create'))\n{\n\tshow_error('Your PHP installation does not support XML');\n}\n\nif ( ! class_exists('CI_Xmlrpc', FALSE))\n{\n\tshow_error('You must load the Xmlrpc class before loading the Xmlrpcs class in order to create a server.');\n}\n\n// ------------------------------------------------------------------------\n\n/**\n * XML-RPC server class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass CI_Xmlrpcs extends CI_Xmlrpc {\n\n\t/**\n\t * Array of methods mapped to function names and signatures\n\t *\n\t * @var array\n\t */\n\tpublic $methods = array();\n\n\t/**\n\t * Debug Message\n\t *\n\t * @var string\n\t */\n\tpublic $debug_msg = '';\n\n\t/**\n\t * XML RPC Server methods\n\t *\n\t * @var array\n\t */\n\tpublic $system_methods\t= array();\n\n\t/**\n\t * Configuration object\n\t *\n\t * @var object\n\t */\n\tpublic $object = FALSE;\n\n\t/**\n\t * Initialize XMLRPC class\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tparent::__construct();\n\t\t$this->set_system_methods();\n\n\t\tif (isset($config['functions']) && is_array($config['functions']))\n\t\t{\n\t\t\t$this->methods = array_merge($this->methods, $config['functions']);\n\t\t}\n\n\t\tlog_message('info', 'XML-RPC Server Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize Prefs and Serve\n\t *\n\t * @param\tmixed\n\t * @return\tvoid\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tif (isset($config['functions']) && is_array($config['functions']))\n\t\t{\n\t\t\t$this->methods = array_merge($this->methods, $config['functions']);\n\t\t}\n\n\t\tif (isset($config['debug']))\n\t\t{\n\t\t\t$this->debug = $config['debug'];\n\t\t}\n\n\t\tif (isset($config['object']) && is_object($config['object']))\n\t\t{\n\t\t\t$this->object = $config['object'];\n\t\t}\n\n\t\tif (isset($config['xss_clean']))\n\t\t{\n\t\t\t$this->xss_clean = $config['xss_clean'];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Setting of System Methods\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function set_system_methods()\n\t{\n\t\t$this->methods = array(\n\t\t\t\t\t'system.listMethods'\t => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.listMethods',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString), array($this->xmlrpcArray)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Returns an array of available methods on this server'),\n\t\t\t\t\t'system.methodHelp'\t => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.methodHelp',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcString, $this->xmlrpcString)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Returns a documentation string for the specified method'),\n\t\t\t\t\t'system.methodSignature' => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.methodSignature',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Returns an array describing the return type and required parameters of a method'),\n\t\t\t\t\t'system.multicall'\t => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.multicall',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcArray, $this->xmlrpcArray)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Combine multiple RPC calls in one request. See http://www.xmlrpc.com/discuss/msgReader$1208 for details')\n\t\t\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Main Server Function\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function serve()\n\t{\n\t\t$r = $this->parseRequest();\n\t\t$payload = '<?xml version=\"1.0\" encoding=\"'.$this->xmlrpc_defencoding.'\"?'.'>'.\"\\n\".$this->debug_msg.$r->prepare_response();\n\n\t\theader('Content-Type: text/xml');\n\t\theader('Content-Length: '.strlen($payload));\n\t\texit($payload);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Method to Class\n\t *\n\t * @param\tstring\tmethod name\n\t * @param\tstring\tfunction\n\t * @param\tstring\tsignature\n\t * @param\tstring\tdocstring\n\t * @return\tvoid\n\t */\n\tpublic function add_to_map($methodname, $function, $sig, $doc)\n\t{\n\t\t$this->methods[$methodname] = array(\n\t\t\t'function'\t=> $function,\n\t\t\t'signature'\t=> $sig,\n\t\t\t'docstring'\t=> $doc\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse Server Request\n\t *\n\t * @param\tstring\tdata\n\t * @return\tobject\txmlrpc response\n\t */\n\tpublic function parseRequest($data = '')\n\t{\n\t\t//-------------------------------------\n\t\t//  Get Data\n\t\t//-------------------------------------\n\n\t\tif ($data === '')\n\t\t{\n\t\t\t$CI =& get_instance();\n\t\t\tif ($CI->input->method() === 'post')\n\t\t\t{\n\t\t\t\t$data = $CI->input->raw_input_stream;\n\t\t\t}\n\t\t}\n\n\t\t//-------------------------------------\n\t\t//  Set up XML Parser\n\t\t//-------------------------------------\n\n\t\t$parser = xml_parser_create($this->xmlrpc_defencoding);\n\t\t$parser_object = new XML_RPC_Message('filler');\n\t\t$pname = (string) $parser;\n\n\t\t$parser_object->xh[$pname] = array(\n\t\t\t'isf' => 0,\n\t\t\t'isf_reason' => '',\n\t\t\t'params' => array(),\n\t\t\t'stack' => array(),\n\t\t\t'valuestack' => array(),\n\t\t\t'method' => ''\n\t\t);\n\n\t\txml_set_object($parser, $parser_object);\n\t\txml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);\n\t\txml_set_element_handler($parser, 'open_tag', 'closing_tag');\n\t\txml_set_character_data_handler($parser, 'character_data');\n\t\t//xml_set_default_handler($parser, 'default_handler');\n\n\t\t//-------------------------------------\n\t\t// PARSE + PROCESS XML DATA\n\t\t//-------------------------------------\n\n\t\tif ( ! xml_parse($parser, $data, 1))\n\t\t{\n\t\t\t// Return XML error as a faultCode\n\t\t\t$r = new XML_RPC_Response(0,\n\t\t\t\t$this->xmlrpcerrxml + xml_get_error_code($parser),\n\t\t\t\tsprintf('XML error: %s at line %d',\n\t\t\t\txml_error_string(xml_get_error_code($parser)),\n\t\t\t\txml_get_current_line_number($parser)));\n\t\t\txml_parser_free($parser);\n\t\t}\n\t\telseif ($parser_object->xh[$pname]['isf'])\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);\n\t\t}\n\t\telse\n\t\t{\n\t\t\txml_parser_free($parser);\n\n\t\t\t$m = new XML_RPC_Message($parser_object->xh[$pname]['method']);\n\t\t\t$plist = '';\n\n\t\t\tfor ($i = 0, $c = count($parser_object->xh[$pname]['params']); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ($this->debug === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$plist .= $i.' - '.print_r(get_object_vars($parser_object->xh[$pname]['params'][$i]), TRUE).\";\\n\";\n\t\t\t\t}\n\n\t\t\t\t$m->addParam($parser_object->xh[$pname]['params'][$i]);\n\t\t\t}\n\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\techo \"<pre>---PLIST---\\n\".$plist.\"\\n---PLIST END---\\n\\n</pre>\";\n\t\t\t}\n\n\t\t\t$r = $this->_execute($m);\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// SET DEBUGGING MESSAGE\n\t\t//-------------------------------------\n\n\t\tif ($this->debug === TRUE)\n\t\t{\n\t\t\t$this->debug_msg = \"<!-- DEBUG INFO:\\n\\n\".$plist.\"\\n END DEBUG-->\\n\";\n\t\t}\n\n\t\treturn $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Executes the Method\n\t *\n\t * @param\tobject\n\t * @return\tmixed\n\t */\n\tprotected function _execute($m)\n\t{\n\t\t$methName = $m->method_name;\n\n\t\t// Check to see if it is a system call\n\t\t$system_call = (strpos($methName, 'system') === 0);\n\n\t\tif ($this->xss_clean === FALSE)\n\t\t{\n\t\t\t$m->xss_clean = FALSE;\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Valid Method\n\t\t//-------------------------------------\n\n\t\tif ( ! isset($this->methods[$methName]['function']))\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Check for Method (and Object)\n\t\t//-------------------------------------\n\n\t\t$method_parts = explode('.', $this->methods[$methName]['function']);\n\t\t$objectCall = (isset($method_parts[1]) && $method_parts[1] !== '');\n\n\t\tif ($system_call === TRUE)\n\t\t{\n\t\t\tif ( ! is_callable(array($this,$method_parts[1])))\n\t\t\t{\n\t\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\t\t\t}\n\t\t}\n\t\telseif (($objectCall && ! is_callable(array($method_parts[0], $method_parts[1])))\n\t\t\tOR ( ! $objectCall && ! is_callable($this->methods[$methName]['function']))\n\t\t)\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Checking Methods Signature\n\t\t//-------------------------------------\n\n\t\tif (isset($this->methods[$methName]['signature']))\n\t\t{\n\t\t\t$sig = $this->methods[$methName]['signature'];\n\t\t\tfor ($i = 0, $c = count($sig); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$current_sig = $sig[$i];\n\n\t\t\t\tif (count($current_sig) === count($m->params)+1)\n\t\t\t\t{\n\t\t\t\t\tfor ($n = 0, $mc = count($m->params); $n < $mc; $n++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$p = $m->params[$n];\n\t\t\t\t\t\t$pt = ($p->kindOf() === 'scalar') ? $p->scalarval() : $p->kindOf();\n\n\t\t\t\t\t\tif ($pt !== $current_sig[$n+1])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$pno = $n+1;\n\t\t\t\t\t\t\t$wanted = $current_sig[$n+1];\n\n\t\t\t\t\t\t\treturn new XML_RPC_Response(0,\n\t\t\t\t\t\t\t\t$this->xmlrpcerr['incorrect_params'],\n\t\t\t\t\t\t\t\t$this->xmlrpcstr['incorrect_params'] .\n\t\t\t\t\t\t\t\t': Wanted '.$wanted.', got '.$pt.' at param '.$pno.')');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Calls the Function\n\t\t//-------------------------------------\n\n\t\tif ($objectCall === TRUE)\n\t\t{\n\t\t\tif ($method_parts[0] === 'this' && $system_call === TRUE)\n\t\t\t{\n\t\t\t\treturn call_user_func(array($this, $method_parts[1]), $m);\n\t\t\t}\n\t\t\telseif ($this->object === FALSE)\n\t\t\t{\n\t\t\t\treturn get_instance()->$method_parts[1]($m);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $this->object->$method_parts[1]($m);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn call_user_func($this->methods[$methName]['function'], $m);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: List Methods\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function listMethods($m)\n\t{\n\t\t$v = new XML_RPC_Values();\n\t\t$output = array();\n\n\t\tforeach ($this->methods as $key => $value)\n\t\t{\n\t\t\t$output[] = new XML_RPC_Values($key, 'string');\n\t\t}\n\n\t\tforeach ($this->system_methods as $key => $value)\n\t\t{\n\t\t\t$output[] = new XML_RPC_Values($key, 'string');\n\t\t}\n\n\t\t$v->addArray($output);\n\t\treturn new XML_RPC_Response($v);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: Return Signature for Method\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function methodSignature($m)\n\t{\n\t\t$parameters = $m->output_parameters();\n\t\t$method_name = $parameters[0];\n\n\t\tif (isset($this->methods[$method_name]))\n\t\t{\n\t\t\tif ($this->methods[$method_name]['signature'])\n\t\t\t{\n\t\t\t\t$sigs = array();\n\t\t\t\t$signature = $this->methods[$method_name]['signature'];\n\n\t\t\t\tfor ($i = 0, $c = count($signature); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$cursig = array();\n\t\t\t\t\t$inSig = $signature[$i];\n\t\t\t\t\tfor ($j = 0, $jc = count($inSig); $j < $jc; $j++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$cursig[]= new XML_RPC_Values($inSig[$j], 'string');\n\t\t\t\t\t}\n\t\t\t\t\t$sigs[] = new XML_RPC_Values($cursig, 'array');\n\t\t\t\t}\n\n\t\t\t\treturn new XML_RPC_Response(new XML_RPC_Values($sigs, 'array'));\n\t\t\t}\n\n\t\t\treturn new XML_RPC_Response(new XML_RPC_Values('undef', 'string'));\n\t\t}\n\n\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: Doc String for Method\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function methodHelp($m)\n\t{\n\t\t$parameters = $m->output_parameters();\n\t\t$method_name = $parameters[0];\n\n\t\tif (isset($this->methods[$method_name]))\n\t\t{\n\t\t\t$docstring = isset($this->methods[$method_name]['docstring']) ? $this->methods[$method_name]['docstring'] : '';\n\n\t\t\treturn new XML_RPC_Response(new XML_RPC_Values($docstring, 'string'));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: Multi-call\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function multicall($m)\n\t{\n\t\t// Disabled\n\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\n\t\t$parameters = $m->output_parameters();\n\t\t$calls = $parameters[0];\n\n\t\t$result = array();\n\n\t\tforeach ($calls as $value)\n\t\t{\n\t\t\t$m = new XML_RPC_Message($value[0]);\n\t\t\t$plist = '';\n\n\t\t\tfor ($i = 0, $c = count($value[1]); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$m->addParam(new XML_RPC_Values($value[1][$i], 'string'));\n\t\t\t}\n\n\t\t\t$attempt = $this->_execute($m);\n\n\t\t\tif ($attempt->faultCode() !== 0)\n\t\t\t{\n\t\t\t\treturn $attempt;\n\t\t\t}\n\n\t\t\t$result[] = new XML_RPC_Values(array($attempt->value()), 'array');\n\t\t}\n\n\t\treturn new XML_RPC_Response(new XML_RPC_Values($result, 'array'));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Multi-call Function: Error Handling\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function multicall_error($err)\n\t{\n\t\t$str = is_string($err) ? $this->xmlrpcstr[\"multicall_${err}\"] : $err->faultString();\n\t\t$code = is_string($err) ? $this->xmlrpcerr[\"multicall_${err}\"] : $err->faultCode();\n\n\t\t$struct['faultCode'] = new XML_RPC_Values($code, 'int');\n\t\t$struct['faultString'] = new XML_RPC_Values($str, 'string');\n\n\t\treturn new XML_RPC_Values($struct, 'struct');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Multi-call Function: Processes method\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function do_multicall($call)\n\t{\n\t\tif ($call->kindOf() !== 'struct')\n\t\t{\n\t\t\treturn $this->multicall_error('notstruct');\n\t\t}\n\t\telseif ( ! $methName = $call->me['struct']['methodName'])\n\t\t{\n\t\t\treturn $this->multicall_error('nomethod');\n\t\t}\n\n\t\tlist($scalar_type, $scalar_value) = each($methName->me);\n\t\t$scalar_type = $scalar_type === $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type;\n\n\t\tif ($methName->kindOf() !== 'scalar' OR $scalar_type !== 'string')\n\t\t{\n\t\t\treturn $this->multicall_error('notstring');\n\t\t}\n\t\telseif ($scalar_value === 'system.multicall')\n\t\t{\n\t\t\treturn $this->multicall_error('recursion');\n\t\t}\n\t\telseif ( ! $params = $call->me['struct']['params'])\n\t\t{\n\t\t\treturn $this->multicall_error('noparams');\n\t\t}\n\t\telseif ($params->kindOf() !== 'array')\n\t\t{\n\t\t\treturn $this->multicall_error('notarray');\n\t\t}\n\n\t\tlist($a, $b) = each($params->me);\n\n\t\t$msg = new XML_RPC_Message($scalar_value);\n\t\tfor ($i = 0, $numParams = count($b); $i < $numParams; $i++)\n\t\t{\n\t\t\t$msg->params[] = $params->me['array'][$i];\n\t\t}\n\n\t\t$result = $this->_execute($msg);\n\n\t\tif ($result->faultCode() !== 0)\n\t\t{\n\t\t\treturn $this->multicall_error($result);\n\t\t}\n\n\t\treturn new XML_RPC_Values(array($result->value()), 'array');\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/Zip.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2015, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttp://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Zip Compression Class\n *\n * This class is based on a library I found at Zend:\n * http://www.zend.com/codex.php?id=696&single=1\n *\n * The original library is a little rough around the edges so I\n * refactored it and added several additional methods -- Rick Ellis\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tEncryption\n * @author\t\tEllisLab Dev Team\n * @link\t\thttp://codeigniter.com/user_guide/libraries/zip.html\n */\nclass CI_Zip {\n\n\t/**\n\t * Zip data in string form\n\t *\n\t * @var string\n\t */\n\tpublic $zipdata = '';\n\n\t/**\n\t * Zip data for a directory in string form\n\t *\n\t * @var string\n\t */\n\tpublic $directory = '';\n\n\t/**\n\t * Number of files/folder in zip file\n\t *\n\t * @var int\n\t */\n\tpublic $entries = 0;\n\n\t/**\n\t * Number of files in zip\n\t *\n\t * @var int\n\t */\n\tpublic $file_num = 0;\n\n\t/**\n\t * relative offset of local header\n\t *\n\t * @var int\n\t */\n\tpublic $offset = 0;\n\n\t/**\n\t * Reference to time at init\n\t *\n\t * @var int\n\t */\n\tpublic $now;\n\n\t/**\n\t * The level of compression\n\t *\n\t * Ranges from 0 to 9, with 9 being the highest level.\n\t *\n\t * @var\tint\n\t */\n\tpublic $compression_level = 2;\n\n\t/**\n\t * Initialize zip compression class\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->now = time();\n\t\tlog_message('info', 'Zip Compression Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Directory\n\t *\n\t * Lets you add a virtual directory into which you can place files.\n\t *\n\t * @param\tmixed\t$directory\tthe directory name. Can be string or array\n\t * @return\tvoid\n\t */\n\tpublic function add_dir($directory)\n\t{\n\t\tforeach ((array) $directory as $dir)\n\t\t{\n\t\t\tif ( ! preg_match('|.+/$|', $dir))\n\t\t\t{\n\t\t\t\t$dir .= '/';\n\t\t\t}\n\n\t\t\t$dir_time = $this->_get_mod_time($dir);\n\t\t\t$this->_add_dir($dir, $dir_time['file_mtime'], $dir_time['file_mdate']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get file/directory modification time\n\t *\n\t * If this is a newly created file/dir, we will set the time to 'now'\n\t *\n\t * @param\tstring\t$dir\tpath to file\n\t * @return\tarray\tfilemtime/filemdate\n\t */\n\tprotected function _get_mod_time($dir)\n\t{\n\t\t// filemtime() may return false, but raises an error for non-existing files\n\t\t$date = file_exists($dir) ? getdate(filemtime($dir)) : getdate($this->now);\n\n\t\treturn array(\n\t\t\t'file_mtime' => ($date['hours'] << 11) + ($date['minutes'] << 5) + $date['seconds'] / 2,\n\t\t\t'file_mdate' => (($date['year'] - 1980) << 9) + ($date['mon'] << 5) + $date['mday']\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Directory\n\t *\n\t * @param\tstring\t$dir\tthe directory name\n\t * @param\tint\t$file_mtime\n\t * @param\tint\t$file_mdate\n\t * @return\tvoid\n\t */\n\tprotected function _add_dir($dir, $file_mtime, $file_mdate)\n\t{\n\t\t$dir = str_replace('\\\\', '/', $dir);\n\n\t\t$this->zipdata .=\n\t\t\t\"\\x50\\x4b\\x03\\x04\\x0a\\x00\\x00\\x00\\x00\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V', 0) // crc32\n\t\t\t.pack('V', 0) // compressed filesize\n\t\t\t.pack('V', 0) // uncompressed filesize\n\t\t\t.pack('v', strlen($dir)) // length of pathname\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.$dir\n\t\t\t// below is \"data descriptor\" segment\n\t\t\t.pack('V', 0) // crc32\n\t\t\t.pack('V', 0) // compressed filesize\n\t\t\t.pack('V', 0); // uncompressed filesize\n\n\t\t$this->directory .=\n\t\t\t\"\\x50\\x4b\\x01\\x02\\x00\\x00\\x0a\\x00\\x00\\x00\\x00\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V',0) // crc32\n\t\t\t.pack('V',0) // compressed filesize\n\t\t\t.pack('V',0) // uncompressed filesize\n\t\t\t.pack('v', strlen($dir)) // length of pathname\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.pack('v', 0) // file comment length\n\t\t\t.pack('v', 0) // disk number start\n\t\t\t.pack('v', 0) // internal file attributes\n\t\t\t.pack('V', 16) // external file attributes - 'directory' bit set\n\t\t\t.pack('V', $this->offset) // relative offset of local header\n\t\t\t.$dir;\n\n\t\t$this->offset = strlen($this->zipdata);\n\t\t$this->entries++;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Data to Zip\n\t *\n\t * Lets you add files to the archive. If the path is included\n\t * in the filename it will be placed within a directory. Make\n\t * sure you use add_dir() first to create the folder.\n\t *\n\t * @param\tmixed\t$filepath\tA single filepath or an array of file => data pairs\n\t * @param\tstring\t$data\t\tSingle file contents\n\t * @return\tvoid\n\t */\n\tpublic function add_data($filepath, $data = NULL)\n\t{\n\t\tif (is_array($filepath))\n\t\t{\n\t\t\tforeach ($filepath as $path => $data)\n\t\t\t{\n\t\t\t\t$file_data = $this->_get_mod_time($path);\n\t\t\t\t$this->_add_data($path, $data, $file_data['file_mtime'], $file_data['file_mdate']);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$file_data = $this->_get_mod_time($filepath);\n\t\t\t$this->_add_data($filepath, $data, $file_data['file_mtime'], $file_data['file_mdate']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Data to Zip\n\t *\n\t * @param\tstring\t$filepath\tthe file name/path\n\t * @param\tstring\t$data\tthe data to be encoded\n\t * @param\tint\t$file_mtime\n\t * @param\tint\t$file_mdate\n\t * @return\tvoid\n\t */\n\tprotected function _add_data($filepath, $data, $file_mtime, $file_mdate)\n\t{\n\t\t$filepath = str_replace('\\\\', '/', $filepath);\n\n\t\t$uncompressed_size = strlen($data);\n\t\t$crc32  = crc32($data);\n\t\t$gzdata = substr(gzcompress($data, $this->compression_level), 2, -4);\n\t\t$compressed_size = strlen($gzdata);\n\n\t\t$this->zipdata .=\n\t\t\t\"\\x50\\x4b\\x03\\x04\\x14\\x00\\x00\\x00\\x08\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V', $crc32)\n\t\t\t.pack('V', $compressed_size)\n\t\t\t.pack('V', $uncompressed_size)\n\t\t\t.pack('v', strlen($filepath)) // length of filename\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.$filepath\n\t\t\t.$gzdata; // \"file data\" segment\n\n\t\t$this->directory .=\n\t\t\t\"\\x50\\x4b\\x01\\x02\\x00\\x00\\x14\\x00\\x00\\x00\\x08\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V', $crc32)\n\t\t\t.pack('V', $compressed_size)\n\t\t\t.pack('V', $uncompressed_size)\n\t\t\t.pack('v', strlen($filepath)) // length of filename\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.pack('v', 0) // file comment length\n\t\t\t.pack('v', 0) // disk number start\n\t\t\t.pack('v', 0) // internal file attributes\n\t\t\t.pack('V', 32) // external file attributes - 'archive' bit set\n\t\t\t.pack('V', $this->offset) // relative offset of local header\n\t\t\t.$filepath;\n\n\t\t$this->offset = strlen($this->zipdata);\n\t\t$this->entries++;\n\t\t$this->file_num++;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Read the contents of a file and add it to the zip\n\t *\n\t * @param\tstring\t$path\n\t * @param\tbool\t$archive_filepath\n\t * @return\tbool\n\t */\n\tpublic function read_file($path, $archive_filepath = FALSE)\n\t{\n\t\tif (file_exists($path) && FALSE !== ($data = file_get_contents($path)))\n\t\t{\n\t\t\tif (is_string($archive_filepath))\n\t\t\t{\n\t\t\t\t$name = str_replace('\\\\', '/', $archive_filepath);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$name = str_replace('\\\\', '/', $path);\n\n\t\t\t\tif ($archive_filepath === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$name = preg_replace('|.*/(.+)|', '\\\\1', $name);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->add_data($name, $data);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read a directory and add it to the zip.\n\t *\n\t * This function recursively reads a folder and everything it contains (including\n\t * sub-folders) and creates a zip based on it. Whatever directory structure\n\t * is in the original file path will be recreated in the zip file.\n\t *\n\t * @param\tstring\t$path\tpath to source directory\n\t * @param\tbool\t$preserve_filepath\n\t * @param\tstring\t$root_path\n\t * @return\tbool\n\t */\n\tpublic function read_dir($path, $preserve_filepath = TRUE, $root_path = NULL)\n\t{\n\t\t$path = rtrim($path, '/\\\\').DIRECTORY_SEPARATOR;\n\t\tif ( ! $fp = @opendir($path))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the original directory root for child dir's to use as relative\n\t\tif ($root_path === NULL)\n\t\t{\n\t\t\t$root_path = str_replace(array('\\\\', '/'), DIRECTORY_SEPARATOR, dirname($path)).DIRECTORY_SEPARATOR;\n\t\t}\n\n\t\twhile (FALSE !== ($file = readdir($fp)))\n\t\t{\n\t\t\tif ($file[0] === '.')\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (is_dir($path.$file))\n\t\t\t{\n\t\t\t\t$this->read_dir($path.$file.DIRECTORY_SEPARATOR, $preserve_filepath, $root_path);\n\t\t\t}\n\t\t\telseif (FALSE !== ($data = file_get_contents($path.$file)))\n\t\t\t{\n\t\t\t\t$name = str_replace(array('\\\\', '/'), DIRECTORY_SEPARATOR, $path);\n\t\t\t\tif ($preserve_filepath === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$name = str_replace($root_path, '', $name);\n\t\t\t\t}\n\n\t\t\t\t$this->add_data($name.$file, $data);\n\t\t\t}\n\t\t}\n\n\t\tclosedir($fp);\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Zip file\n\t *\n\t * @return\tstring\t(binary encoded)\n\t */\n\tpublic function get_zip()\n\t{\n\t\t// Is there any data to return?\n\t\tif ($this->entries === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->zipdata\n\t\t\t.$this->directory.\"\\x50\\x4b\\x05\\x06\\x00\\x00\\x00\\x00\"\n\t\t\t.pack('v', $this->entries) // total # of entries \"on this disk\"\n\t\t\t.pack('v', $this->entries) // total # of entries overall\n\t\t\t.pack('V', strlen($this->directory)) // size of central dir\n\t\t\t.pack('V', strlen($this->zipdata)) // offset to start of central dir\n\t\t\t.\"\\x00\\x00\"; // .zip file comment length\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write File to the specified directory\n\t *\n\t * Lets you write a file\n\t *\n\t * @param\tstring\t$filepath\tthe file name\n\t * @return\tbool\n\t */\n\tpublic function archive($filepath)\n\t{\n\t\tif ( ! ($fp = @fopen($filepath, 'w+b')))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tflock($fp, LOCK_EX);\n\n\t\tfor ($result = $written = 0, $data = $this->get_zip(), $length = strlen($data); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($fp, substr($data, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tflock($fp, LOCK_UN);\n\t\tfclose($fp);\n\n\t\treturn is_int($result);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Download\n\t *\n\t * @param\tstring\t$filename\tthe file name\n\t * @return\tvoid\n\t */\n\tpublic function download($filename = 'backup.zip')\n\t{\n\t\tif ( ! preg_match('|.+?\\.zip$|', $filename))\n\t\t{\n\t\t\t$filename .= '.zip';\n\t\t}\n\n\t\tget_instance()->load->helper('download');\n\t\t$get_zip = $this->get_zip();\n\t\t$zip_content =& $get_zip;\n\n\t\tforce_download($filename, $zip_content);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize Data\n\t *\n\t * Lets you clear current zip data. Useful if you need to create\n\t * multiple zips with different data.\n\t *\n\t * @return\tCI_Zip\n\t */\n\tpublic function clear_data()\n\t{\n\t\t$this->zipdata = '';\n\t\t$this->directory = '';\n\t\t$this->entries = 0;\n\t\t$this->file_num = 0;\n\t\t$this->offset = 0;\n\t\treturn $this;\n\t}\n\n}\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README.md",
    "content": ">**微注**：在继续学习 & 积累，并率先于[这里](http://www.jeffjade.com/2016/03/30/104-front-end-tutorial/ )持续更新。\n\n## __综合类__\n\n综合类 | 地址\n:----:|:----:\n前端知识体系|http://www.cnblogs.com/sb19871023/p/3894452.html\n前端知识结构|https://github.com/JacksonTian/fks\nWeb前端开发大系概览|https://github.com/unruledboy/WebFrontEndStack\nWeb前端开发大系概览-中文版|http://www.cnblogs.com/unruledboy/p/WebFrontEndStack.html\nWeb Front-end Stack v2.2| [Web Front-end Stack v2.2](https://raw.githubusercontent.com/unruledboy/WebFrontEndStack/master/Web%20Front%20End%20Stack.png)\n免费的编程中文书籍索引|https://github.com/justjavac/free-programming-books-zh_CN\n前端书籍|https://github.com/dypsilon/frontend-dev-bookmarks\n前端免费书籍大全|https://github.com/vhf/free-programming-books\n前端知识体系|http://www.cnblogs.com/sb19871023/p/3894452.html\n免费的编程中文书籍索引|https://github.com/justjavac/free-programming-books-zh_CN\n智能社 - 精通JavaScript开发|http://study.163.com/course/introduction/224014.htm\n重新介绍 JavaScript（JS 教程）|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript\n麻省理工学院公开课：计算机科学及编程导论|http://v.163.com/special/opencourse/bianchengdaolun.html\nJavaScript中的this陷阱的最全收集--没有之一|http://segmentfault.com/a/1190000002640298\nJS函数式编程指南|https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch1.html\nJavaScript Promise迷你书（中文版）|http://liubin.github.io/promises-book\n腾讯移动Web前端知识库|https://github.com/AlloyTeam/Mars\nFront-End-Develop-Guide 前端开发指南|https://github.com/Front-End-Developers-Hunan/Front-End-Develop-Guide\n前端开发笔记本|https://li-xinyang.gitbooks.io/frontend-notebook/content\n大前端工具集 - 聂微东|https://github.com/nieweidong/fetool\n前端开发者手册|https://dwqs.gitbooks.io/frontenddevhandbook/content\n\n## __入门类__\n\n入门类 | 地址\n:----:|:----: \n前端入门教程|http://www.cnblogs.com/jikey/p/3613082.html\n瘳雪峰的Javascript教程|http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000\njQuery基础教程|http://www.imooc.com/view/11\n前端工程师必备的PS技能——切图篇|http://www.imooc.com/view/506\n结合个人经历总结的前端入门方法|https://github.com/qiu-deqing/FE-learning\n    \n## __工具类__\n\n工具类| 地址\n:----:|:----: \n__前端人的俱乐部__| http://f2er.club/ 真可以解放你的收藏夹\n如何优雅地使用Sublime Text|http://www.jeffjade.com/2015/12/15/2015-04-17-toss-sublime-text/#\n新编码神器Atom使用纪要|http://www.jeffjade.com/2016/03/03/2016-03-02-how-to-use-atom/\ncss sprite 雪碧图制作|http://www.imooc.com/learn/93\n版本控制入门 – 搬进 Github|http://www.imooc.com/learn/390\nGrunt-beginner前端自动化工具|http://www.imooc.com/learn/30\nIntelliJ IDEA 简体中文专题教程|https://github.com/judasn/IntelliJ-IDEA-Tutorial\nWebstorm,InterllIdea,Phpstorm|http://t.cn/8kZZ1Uy\nSublimeText|https://github.com/jikeytang/sublime-text\nAtom|https://atom.io\nvisual studio code|https://code.visualstudio.com\n\n## __综合效果搜索平台__\n\n综合效果搜索平台 | 地址\n:----:|:----: \n**JavaScript 资源大全中文版**|https://github.com/jobbole/awesome-javascript-cn\n**100+ 超全的web开发工具和资源**|https://xituqu.com/170.html\nzoommyapp.com|http://zoommyapp.com/ 高质量图库\nunsplash.com|https://unsplash.com/ 高质量图库\nwww.pinterest.com|https://www.pinterest.com/ 图库\nNew Old Stock|http://nos.twnsnd.co 复古风图库\n效果网|http://www.jq22.com\n花瓣网|http://huaban.com/\n优美图|http://www.topit.me/\ncodepen|http://codepen.io/\n摄图网|http://699pic.com/\n常用的JavaScript代码片段|http://microjs.com\n\n## __团队Blog|周报类__\n\n周报类| 地址\n:----:|:----: \n__奇舞周刊__ | http://old.75team.com/weekly/\n码农周刊|http://weekly.manong.io\nWEB前端开发|http://www.css88.com\nA JS tip per day! |http://www.jstips.co\n腾讯全端 AlloyTeam |http://www.alloyteam.com/webdevelop/\n平安科技移动开发二队技术周报|https://github.com/PaicHyperionDev/MobileDevWeekly\n\n## __开发中心__\n\n开发中心| 地址\n:----:|:----: \nmozilla js参考|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript\nchrome开发中心（chrome的内核已转向blink）|https://developer.chrome.com/extensions/api_index.html\nsafari开发中心|https://developer.apple.com/library/safari/navigation\nmicrosoft js参考|https://msdn.microsoft.com/zh-cn/library/d1et7k7c(v=vs.94.aspx\njs秘密花园|http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html\njs秘密花园|http://bonsaiden.github.io/JavaScript-Garden/zh\nw3help|http://www.w3help.org 综合Bug集合网站\n\n## __Nodejs__\n\nNodejs  | 地址\n:----:|:----:  \nnodejs 篇幅比较巨大|http://liuqing.pw\nNode.js 包教不包会|https://github.com/alsotang/node-lessons\n篇幅比较少|http://www.rainweb.cn/article/category/Nodejs\nnode express 入门教程|http://www.w3cfuns.com/article-5598538-1-1.html\nnodejs定时任务|http://my.oschina.net/u/568264/blog/193773\n一个nodejs博客|http://60sky.com\n【NodeJS 学习笔记04】新闻发布系统|http://www.cnblogs.com/yexiaochai/p/3536547.html\n过年7天乐，学nodejs 也快乐|http://www.cnblogs.com/qqloving/p/3541099.html\n七天学会NodeJS|https://github.com/nqdeng/7-days-nodejs\nNodejs学习笔记（二）--- 事件模块|http://www.cnblogs.com/zhongweiv/p/nodejs_events.html\nnodejs入门|http://www.cnblogs.com/liusuqi/p/3735491.html\nangularjs nodejs|https://github.com/zensh/jsgen\n从零开始nodejs系列文章|http://blog.fens.me/series-nodejs\n理解nodejs|http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb\nnodejs事件轮询|http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop\nnode入门|http://www.nodebeginner.org/index-zh-cn.html\nnodejs cms|http://ourjs.com/detail/53e1f281c5910a9806000001\nNode初学者入门，一本全面的NodeJS教程|http://ourjs.com/detail/529ca5950cb6498814000005\nNodeJS的代码调试和性能调优|http://www.barretlee.com/blog/2015/10/07/debug-nodejs-in-command-line\n\n## __综合API__\n\n综合API| 地址\n:----:|:----:\njavascripting|http://www.javascripting.com\n各种流行库搜索|http://microjs.com    \nrunoob.com-包含各种API集合|http://www.runoob.com\n开源中国在线API文档合集|http://tool.oschina.net/apidocs\ndevdocs|http://devdocs.io 英文综合API网站\n\n## __Ecmascript__\n\nEcmascript| 地址\n:----:|:----:    \nUnderstanding ECMAScript 6 - Nicholas C. Zakas|https://leanpub.com/understandinges6/read\nexploring-es6|https://leanpub.com/exploring-es6/read\nexploring-es6翻译|https://github.com/es6-org/exploring-es6\nexploring-es6翻译后预览|http://es6-org.github.io/exploring-es6\n阮一峰 es6|http://es6.ruanyifeng.com\n阮一峰 Javascript|http://javascript.ruanyifeng.com\nECMA-262，第 5 版|http://yanhaijing.com/es5\nes5|http://es5.github.io\n\n## __Js template__\n\nJs template| 地址\n:----:|:----:    \ntemplate-chooser|http://garann.github.io/template-chooser\nartTemplate|https://github.com/aui/artTemplate\ntomdjs|https://github.com/aui/tmodjs/blob/master/README.md\n淘宝模板juicer模板|http://juicer.name/docs/docs_zh_cn.html\nFxtpl v1.0 繁星前端模板引擎|http://koen301.github.io/fxtpl\nlaytpl|http://laytpl.layui.com\nmozilla - nunjucks|https://github.com/mozilla/nunjucks\nJuicer|https://github.com/PaulGuo/Juicer\ndustjs|http://akdubya.github.io/dustjs\netpl|http://ecomfe.github.io/etpl\n\n## **HTML5(HTML)**\nHTML(HTML5) | 地址\n:----:|:----: \n深入理解HTML5标签|https://segmentfault.com/a/1190000002695791\n如何写出高效率的HTML|https://segmentfault.com/a/1190000002680822\nHTML meta标签总结与属性使用介绍|https://segmentfault.com/a/1190000004279791\n戏说HTML5|http://www.cnblogs.com/dojo-lzz/p/5059316.html\n\n## __CSS3(CSS)__\n\nCSS| 地址\n:----:|:----:    \nCSS 语法参考|http://tympanus.net/codrops/css_reference\n**如何编写可维护的CSS**|https://github.com/chadluo/CSS-Guidelines/blob/master/README.md\nCSS3动画手册|http://isux.tencent.com/css3/index.html\n腾讯css3动画制作工具|http://isux.tencent.com/css3/tools.html\n志爷css小工具集合|http://linxz.github.io/tianyizone\ncss3 js 移动大杂烩|http://www.note12.com/category/blog/2014-6-5/538fe0a9f786f1b7019a4dfb\nbouncejs 触摸库|http://bouncejs.com\ncss3 按钮动画|http://fian.my.id/Waves\nanimate.css|http://daneden.github.io/animate.css\n全局CSS的终结(狗带 [译]|http://www.alloyteam.com/2015/10/8536\nbrowserhacks|http://browserhacks.com\n\n## __Angularjs__\n\nAngularjs| 地址\n:----:|:----:    \nAngular.js 的一些学习资源|https://github.com/dolymood/AngularLearning\nangularjs中文社区|http://angularjs.cn\nAngularjs源码学习|http://www.cnblogs.com/xuwenmin888/p/3739096.html\nAngularjs源码学习|http://www.ifeenan.com/?c=AngularJS\nangular对bootstrap的封装|http://angular-ui.github.io/bootstrap\nangularjs + nodejs|https://cnodejs.org/topic/51404e0f069911196d2e3923\n吕大豹 Angularjs|http://www.cnblogs.com/lvdabao/tag/AngularJs\nAngularJS 最佳实践|http://www.infoq.com/cn/news/2013/02/angular-web-app\nAngular的一些扩展指令|http://www.lovelucy.info/angularjs-best-practices.html\nAngular数据绑定原理|https://github.com/Pasvaz/bindonce\n一些扩展Angular UI组件|https://github.com/angular-ui\nEmber和AngularJS的性能测试|http://voidcanvas.com/emberjs-vs-angularjs-performance-testing\n带你走近AngularJS - 基本功能介绍|http://www.cnblogs.com/powertoolsteam/p/angularjs-introdection.html\nAngularjs开发指南|http://angular.duapp.com/docs/guide\nAngularjs学习|http://www.cnblogs.com/amosli/p/3710648.html\n不要带着jQuery的思维去学习AngularJS|http://www.rainweb.cn/article/angularjs-jquery.html\nangularjs 学习笔记|http://wangjiatao.diandian.com/?tag=angularjs\nangularjs 开发指南|http://www.angularjs.cn/T008\nangularjs 英文资料|https://github.com/jmcunningham/AngularJS-Learning\nangular bootstrap|http://angular-ui.github.io/bootstrap\nangular jq mobile|https://github.com/opitzconsulting/jquery-mobile-angular-adapter\nangular ui|http://mgcrea.github.io/angular-strap\n整合jQuery Mobile+AngularJS经验谈|http://www.tuicool.com/articles/7ZZVr2\n有jQuery背景，该如何用AngularJS编程思想|http://blog.jobbole.com/46589/ \nAngularJS在线教程|http://each.sinaapp.com/angular\nangular学习笔记|http://www.zouyesheng.com/angular.html\n\n\n## __React__\n\nReact| 地址\n:----:|:----:    \nreact.js 中文论坛|http://www.react-china.org\nreact.js 官方网址|https://facebook.github.io/react/index.html\nreact.js 官方文档|https://facebook.github.io/react/docs/getting-started.html\nreact.js material UI|http://material-ui.com/#\nreact.js TouchstoneJS UI|http://touchstonejs.io\nreact.js amazeui UI|http://amazeui.org/react\nReact 入门实例教程 - 阮一峰|http://www.ruanyifeng.com/blog/2015/03/react.html\nReact Native 中文版|http://wiki.jikexueyuan.com/project/react-native\nWebpack 和 React 小书 - 前端乱炖|http://www.html-js.com/article/Fakefish%203053\nWebpack 和 React 小书 - gitbook|https://fakefish.github.io/react-webpack-cookbook\nwebpack|https://github.com/webpack/webpack\nWebpack，101入门体验|http://html-js.com/article/3009\nwebpack入门教程|http://html-js.com/article/3113\n基于webpack搭建前端工程解决方案探索|http://segmentfault.com/a/1190000003499526\nReact原创实战视频教程|http://www.piliyu.com\n\n## __vue__\n\nvue| 地址\n:----:|:----: \nVue|http://cn.vuejs.org\nVue 论坛|http://forum.vuejs.org\nVue 入门指南|http://www.cnblogs.com/aaronjs/p/3660102.html\nVue 的一些资源索引|http://segmentfault.com/a/1190000000411057\nawesome-vue|https://github.com/vuejs/awesome-vue\n\n## __移动端API__\n\n移动端API| 地址\n:----:|:----: \n99移动端知识集合|https://github.com/jtyjty99999/mobileTech\n移动端前端开发知识库|https://github.com/AlloyTeam/Mars\n移动前端的一些坑和解决方法（外观表现）|http://caibaojian.com/mobile-web-bug.html\n【原】移动web资源整理|http://www.cnblogs.com/PeunZhang/p/3407453.html\nzepto 1.0 中文手册|http://mweb.baidu.com/zeptoapi\nzepto 1.0 中文手册|http://www.html-5.cn/Manual/Zepto\nzepto 1.1.2|http://www.css88.com/doc/zeptojs_api\nzepto 中文注释|http://www.cnblogs.com/sky000/archive/2013/03/29/2988952.html\njqmobile 手册|http://app-framework-software.intel.com/api.php\n移动浏览器开发集合|https://github.com/maxzhang/maxzhang.github.com/issues\n移动开发大杂烩|https://github.com/hoosin/mobile-web-favorites\n\n## __jQuery__\n\njQuery| 地址\n:----:|:----:    \njQuery API 中文文档|http://www.jquery123.com\nhemin 在线版|http://hemin.cn/jq\ncss88 jq api|http://www.css88.com/jqapi-1.9/on\ncss88 jqui api|http://www.css88.com/jquery-ui-api\n学习jquery|http://learn.jquery.com\njquery 源码查找|http://james.padolsey.com/jquery\nWeb前端资源汇总(jQuery,Js,Css3等)|http://www.cnblogs.com/jihua/p/webfront.html\n\n## __D3__\n\nD3| 地址\n:----:|:----: \nd3 Tutorials|https://github.com/mbostock/d3/wiki/Tutorials\nGallery|https://github.com/mbostock/d3/wiki/Gallery\nlofter|http://datavisual.lofter.com/post/40cf3a_188e535\niteye|http://alanland.iteye.com/blog/1878595\nruanyifeng|http://javascript.ruanyifeng.com/library/d3.html\n\n## __Requriejs__\n\nRequriejs| 地址\n:----:|:----: \nJavascript模块化编程（一）：模块的写法 |http://www.ruanyifeng.com/blog/2012/10/javascript_module.html\nJavascript模块化编程（二）：AMD规范|http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html\nJavascript模块化编程（三）：require.js的用法|http://www.ruanyifeng.com/blog/2012/11/require_js.html\nRequireJS入门（一）|http://www.cnblogs.com/snandy/archive/2012/05/22/2513652.html\nRequireJS入门（二）|http://www.cnblogs.com/snandy/archive/2012/05/23/2513712.html\nRequireJS进阶（三）|http://www.cnblogs.com/snandy/archive/2012/06/08/2538001.html\nrequrie源码学习|http://www.cnblogs.com/yexiaochai/p/3632580.html \nrequrie 入门指南|http://www.oschina.net/translate/getting-started-with-the-requirejs-library \nrequrieJS 学习笔记|http://www.cnblogs.com/yexiaochai/p/3214926.html \nrequriejs 其一 |http://cyj.me/why-seajs/requirejs/ \nrequire backbone结合|http://www.cnblogs.com/yexiaochai/p/3221081.html \n\n## __Seajs__\n\nSeajs| 地址\n:----:|:----: \nseajs|http://seajs.org\nseajs 中文手册|http://cyj.me/why-seajs/zh\n\n## __Less,sass__\n\nLess,sass| 地址\n:----:|:----: \nsass|http://www.w3cplus.com/sassguide\nsass教程-sass中国|http://www.sass.hk\nSass 中文文档|http://sass.bootcss.com\nless|http://less.bootcss.com\n\n## __Markdown__\n\nMarkdown| 地址\n:----:|:----: \nMarkdown 语法说明 (简体中文版|http://wowubuntu.com/markdown\nmarkdown入门参考|https://github.com/LearnShare/Learning-Markdown/blob/master/README.md\ngitbook|https://www.gitbook.com 国外的在线markdown可编辑成书\nmdeditor|https://www.zybuluo.com/mdeditor  一款国内的在线markdown编辑器\nstackedit|https://stackedit.io 国外的在线markdown编辑器，功能强大，同步云盘\nmditor|http://bh-lay.github.io/mditor 一款轻量级的markdown编辑器\nlepture-editor|https://github.com/lepture/editor\nmarkdown-editor|https://github.com/jbt/markdown-editor\n作业部落|https://www.zybuluo.com 功能强大，速度流畅，全平台同步\n\n## __兼容性__\n\n兼容性| 地址\n:----:|:----: \nesma 兼容列表|http://kangax.github.io/compat-table/es6\nW3C CSS验证服务|http://jigsaw.w3.org/css-validator/validator.html.zh-cn\ncaniuse|http://caniuse.com/#index \ncsscreator|http://csscreator.com/properties\nmicrosoft|https://msdn.microsoft.com/zh-cn/library/cc351024(v=vs.85.aspx\n在线测兼容-移动端|http://www.responsinator.com\nemulators|https://www.manymo.com/emulators\n\n## __UI相关__\n\nUI相关| 地址\n:----:|:----: \nbootcss|http://v3.bootcss.com\nMetroUICSS|http://www.w3cplus.com/MetroUICSS\nsemantic|http://semantic-ui.com\nButtons|http://alexwolfe.github.io/Buttons\nkitecss|http://hiloki.github.io/kitecss\npintuer|http://www.pintuer.com\namazeui|http://amazeui.org\nworldhello|http://www.worldhello.net/gotgithub/index.html\nlinuxtoy|http://igit.linuxtoy.org/contents.html\ngitmagic|http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn\nrogerdudler|http://rogerdudler.github.io/git-guide/index.zh.html\ngitref|http://gitref.justjavac.com\nbook|http://git-scm.com/book/zh\ngogojimmy|http://gogojimmy.net/2012/01/17/how-to-use-git-1-git-basic\n\n## __其它API__\n\n其它API| 地址\n:----:|:----: \nHTTP API 设计指南|http://segmentfault.com/bookmark/1230000002521721\njavascript流行库汇总|javascriptoo\n验证api|http://niceue.com/validator/demo/index.php\nunderscore 中文手册|http://www.css88.com/doc/underscore\nunderscore源码分析|http://www.html-js.com/article/Underscorejs-source-code-analysis-of-underscorejs-source-code-analysis%203031\nunderscore源码分析-亚里士朱德的博客|http://yalishizhude.github.io/tags/underscore\nunderscrejs en api|http://underscorejs.org\nlodash - underscore的代替品|https://lodash.com\next4api|http://extjs-doc-cn.github.io/ext4api\nbackbone 中文手册|http://www.csser.com/tools/backbone/backbone.js.html\nqwrap手册|http://dev.qwrap.com/resource/js/_docs/_youa/#/qw/base/loadJs_.htm\n缓动函数|http://easings.net/zh-cn\nsvg 中文参考|http://www.w3school.com.cn/svg/svg_reference.asp\nsvg mdn参考|https://developer.mozilla.org/en-US/docs/Web/SVG\nsvg 导出 canvas|https://github.com/gabelerner/canvg\nsvg 导出 png|https://github.com/exupero/saveSvgAsPng\nai-to-svg|http://www.zamzar.com/convert/ai-to-svg\nlocalStorage 库|https://github.com/machao/localStorage\n\n## __图表类__\n\n图表类| 地址\n:----:|:----: \nHighcharts 中文API|http://www.hcharts.cn/api/index.php\nHighcharts 英文API|http://api.highcharts.com/highcharts\nECharts 百度的图表软件|http://echarts.baidu.com/ \n高德地图|http://lbs.amap.com/api\n开源的矢量图脚本框架|http://paperjs.org\nsvg 地图|http://jvectormap.com\n\n## __正则__\n\n正则| 地址\n:----:|:----: \nJS正则表达式元字符|http://segmentfault.com/a/1190000002471140\n正则表达式30分钟入门教程|http://deerchao.net/tutorials/regex/regex.htm\nMDN-正则表达式|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions\nruanyifeng - RegExp对象|http://javascript.ruanyifeng.com/stdlib/regexp.html\n小胡子哥 - 进阶正则表达式|http://div.io/topic/764?page=1\nis.js|https://github.com/Cedriking/is.js/blob/master/is.js\n正则在线测试|http://regexper.com\n\n## __前端规范__\n\n前端规范| 地址\n:----:|:----: \n通过分析github代码库总结出来的工程师代码书写习惯|http://alloyteam.github.io/CodeGuide\nHTML&CSS编码规范 by @mdo|http://codeguide.bootcss.com\n团队合作的css命名规范-腾讯AlloyTeam前端团队|http://www.alloyteam.com/2011/10/css-on-team-naming/\n前端编码规范之js - by yuwenhui|http://yuwenhui.github.io\n前端编码规范之js - by 李靖|http://www.cnblogs.com/hustskyking/p/javascript-spec.html\n前端开发规范手册|http://zhibimo.com/read/Ashu/front-end-style-guide\nAirbnb JavaScript 编码规范（简体中文版）|https://github.com/yuche/javascript#table-of-contents\nAMD与CMD规范的区别|http://www.zhihu.com/question/20351507\nAMD与CMD规范的区别|http://www.cnblogs.com/tugenhua0707/p/3507957.html\nKISSY 源码规范|http://docs.kissyui.com/1.4/docs/html/tutorials/style-guide/kissy-source-style.html\nbt编码规范|http://codeguide.bootcss.com\n规范加强版|https://github.com/Suxiaogang/Code_Guide\n前端代码规范 及 最佳实践|http://blog.jobbole.com/79075\n百度前端规范|http://coderlmn.github.io/code-standards\n百度前端规范|http://isobar-idev.github.io/code-standards\n百度前端规范|http://zhuanlan.zhihu.com/fuyun/19884834\nECMAScript6 编码规范--广发证券前端团队|https://github.com/gf-rd/es6-coding-style\nJavaScript 风格指南/编码规范（Airbnb公司版）|http://blog.jobbole.com/79484\n网易前端开发规范|http://nec.netease.com/standard\ncss模块|http://www.75team.com/archives/1049\n前端规范资源列表|https://github.com/ecomfe/spec\n\n## __PHP__\n\nPHP| 地址\n:----:|:----: \n最流行的PHP 代码规范|http://segmentfault.com/a/1190000000443795\n最流行的PHP 代码规范|https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-2-coding-style-guide.md\n\n## __各大公司开源项目__\n\n各大公司开源项目| 地址\n:----:|:----: \nFacebook Projects|https://code.facebook.com/projects/web\n百度web前端研发部|http://fex.baidu.com\n百度EFE|http://efe.baidu.com\n百度github|https://github.com/fex-team\nalloyteam|http://www.alloyteam.com\nalloyteam-github|http://alloyteam.github.io\nalloyteam-AlloyGameEngine|https://github.com/AlloyTeam/AlloyGameEngine\nAlloyDesigner|http://alloyteam.github.io/AlloyDesigner 即时修改，即时保存，设计稿较正，其它开发辅助工具\nH5交互页编辑器AEditor介绍|http://www.alloyteam.com/2015/06/h5-jiao-hu-ye-bian-ji-qi-aeditor-jie-shao H5动画交互页开发的工具介绍\nAEditor|http://aeditor.alloyteam.com H5动画交互页开发的工具\nmaka|http://forum.maka.im/wordpress\n值得订阅的weekly|https://github.com/fenbility/weekly-feed\n腾讯html5|http://cube.qq.com\n奇舞团开源项目|http://75team.github.io\nQunar UED|http://ued.qunar.com\nScrat|http://scrat.io\n\n## __常用__\n\n常用 |地址\n:----:|:----: \nieBetter.js-让IE6-IE8拥有IE9+,Chrome等浏览器特性|http://www.zhangxinxu.com/wordpress/2013/12/iebetter-js-make-ie6-ie8-like-modern-browser-ie9-chrome\n模拟键盘|http://mottie.github.io/Keyboard\n拼音|https://github.com/hotoo/pinyin\n中国个人身份证号验证|https://github.com/mc-zone/IDValidator\n\n## __算法__\n\n算法 | 地址\n:----:|:----: \n数据结构与算法 JavaScript 描述. 章节练习|https://github.com/Ralph-Wang/algorithm.in.js\n常见排序算法（JS版）|https://github.com/twobin/twobinSort\n经典排序|https://github.com/luofei2011/jsAgm/blob/master/js/sort.js\n常见排序算法-js版本|https://github.com/hechangmin/jssort\nJavaScript 算法与数据结构 精华集|https://github.com/lightningtgc/JavaScript-Algorithms\n面试常考算法题精讲|http://www.nowcoder.com/live/courses\n\n## __移动端__\n\n移动端 | 地址\n:----:|:----: \nfastclick|https://github.com/ftlabs/fastclick\nno-click-delay|https://github.com/mmastrac/jquery-noclickdelay\n【敏捷开发】Android团队开发规范|http://www.cnblogs.com/lcw/p/3619181.html\nAndroid 开发规范与应用|http://www.jianshu.com/p/4390f4fe19b3\n**ionic** | https://github.com/ychow/ionic-guide\n\n\n## __JSON__\n\nJSON | 地址\n:----:|:----: \n模拟生成JSON数据|http://beta.json-generator.com\n返回跨域JSONAPI|http://jsonp.afeld.me\n\n## __焦点图__\n\n焦点图 | 地址\n:----:|:----: \nmyfocus|https://github.com/koen301/myfocus\nmyfocus-官方演示站|http://www.chhua.com/myfocus\nSuperSlidev2.1 -- 大话主席|http://www.superslide2.com\nsoChange|http://www.bujichong.com/sojs/soChange/index.html\n\n## __Ext, EasyUI, J-UI 及其它各种UI方案__\n\nExt, EasyUI, J-UI 及其它各种UI方案 | 地址\n:----:|:----:\nextjs|https://www.sencha.com/products/extjs\next4英文api|http://docs.sencha.com/extjs/4.0.7\next4中文api|http://extjs-doc-cn.github.io/ext4api\njquery easyui 未压缩源代码|http://jquery-easyui.googlecode.com/svn/trunk/src\nJ-UI|http://jui.org\nMUI-最接近原生APP体验的高性能前端框架|http://dcloudio.github.io/mui\nAmaze UI | 中国首个开源 HTML5 跨屏前端框架|http://amazeui.org\n淘宝 HTML5 前端框架|http://m.sui.taobao.org\nKISSY - 阿里前端JavaScript库|http://docs.kissyui.com\n网易Nej - Nice Easy Javascript|http://nej.netease.com\nKendo UI MVVM Demo|http://demos.telerik.com/kendo-ui/mvvm/index\nBootstrap|http://www.bootcss.com\nSmart UI|http://smartui.chinamzz.com\n雅虎UI - CSS UI|http://developer.yahoo.com/yui/grids\n\n## __页面 社会化 分享功能__\n\n页面 社会化 分享功能 | 地址\n:----:|:----: \n百度分享|http://share.baidu.com pc端\nJiaThis|http://jiathis.com pc端\n社会化分享组件|http://developer.baidu.com/soc/share 移动端\nShareSDK 轻松实现社会化功能|http://www.mob.com/#/index 移动端\n友盟分享|http://dev.umeng.com/social/android/quick-integration 移动端\n\n## __富文本编辑器__\n\n富文本编辑器 | 地址\n:----:|:----: \n功能齐全 tinymce|https://www.tinymce.com\n百度 ueditor|http://ueditor.baidu.com/website\n经典的ckeditor|http://ckeditor.com\n经典的kindeditor|http://kindeditor.net\nwysiwyg|http://www.bootcss.com/p/bootstrap-wysiwyg\n一个有情怀的编辑器。Bach's Editor|http://integ.github.io/BachEditor\ntower用的编辑器|https://github.com/mycolorway/simditor\nsummernote 编辑器|https://github.com/summernote/summernote\nhtml5编辑器|http://neilj.github.io/Squire\nQuilljs编辑器 | http://quilljs.com\nXEditor|http://lab.hustlzp.com/XEditor\nwangEditor|https://github.com/wangfupeng1988/wangEditor \n\n## __前端概述__\n\n前端概述 | 地址\n:----:|:----: \n前端工具大全|http://www.awesomes.cn\n什么是前端工程化|https://github.com/fouber/blog/issues/10?from=timeline&isappinstalled=0#\n[译] 前端攻略-从路人甲到英雄无敌|https://segmentfault.com/a/1190000005174755\n\n## __Gulp__\n\nGulp  | 地址\n:----:|:----:  \nGulp官网|http://gulpjs.com\nGulp中文网|http://www.gulpjs.com.cn\ngulp资料收集|https://github.com/Platform-CUF/use-gulp\nGulp：任务自动管理工具 - ruanyifeng|http://javascript.ruanyifeng.com/tool/gulp.html\nGulp插件|http://gulpjs.com/plugins\nGulp探究折腾之路(I)|http://www.jeffjade.com/2015/11/25/2015-11-25-toss-gulp/\nGulp折腾之路(II)|http://www.jeffjade.com/2016/01/19/2016-01-19-toss-gulp/\nGulp不完全入门教程|http://www.ido321.com/1622.html\n为什么使用gulp?|https://github.com/hjzheng/CUF_meeting_knowledge_share/issues/33\nGulp安装及配合组件构建前端开发一体化|http://www.dbpoo.com/getting-started-with-gulp\nGulp 入门指南|https://github.com/nimojs/gulp-book\nGulp 入门指南 - nimojs|https://github.com/nimojs/blog/issues/19\nGulp in Action|http://www.imooc.com/video/5692\nGulp开发教程（翻译）|http://www.w3ctech.com/topic/134\n前端构建工具gulpjs的使用介绍及技巧|http://www.cnblogs.com/2050/p/4198792.html\n\n## __Grunt__\n\nGrunt  | 地址\n:----:|:----:  \ngruntjs|http://gruntjs.com\nGrunt中文网|http://www.gruntjs.net\n\n## __Fis__\n\nFis  | 地址\n:----:|:----:  \nfis 官网|http://fex-team.github.io/fis-site/index.html\nfis|http://fis.baidu.com\n\n## __pc图轮__\n\npc图轮  | 地址\n:----:|:----:  \n单屏轮播sochange|http://www.jsfoot.com/jquery/demo/2011-09-20/192.html\n左右按钮多图切换|http://bxslider.com/examples/carousel-demystified\nfullpage全屏轮播|https://github.com/alvarotrigo/fullPage.js\n\n## __移动端图轮__\n\n移动端图轮  | 地址\n:----:|:----:  \n无缝切换|http://www.swipejs.com\n滑屏效果|http://www.idangero.us/swiper\n全屏fullpage|https://github.com/peunzhang/fullpage\n单个图片切换|https://github.com/qiqiboy/touchslider\n单个全屏切换|https://github.com/peunzhang/slip.js\n百度的切换库|http://touch.code.baidu.com/examples.html?qq-pf-to=pcqq.group\n单个全屏切换|https://github.com/peunzhang/iSlider\n滑屏效果|https://github.com/saw/touch-interfaces\n旋转拖动设置|http://baijs.com/tinycircleslider\n类似于swipe切换|http://touchslider.com\n支持多种形式的触摸滑动|http://www.swiper.com.cn/demo/index.html\n滑屏效果|https://github.com/joker-ye/main/blob/master/wap/index.html\n大话主席pc移动图片轮换|http://www.superslide2.com\n滑屏效果|https://github.com/hahnzhu/parallax.js\n基于zepto的fullpage|https://github.com/yanhaijing/zepto.fullpage\n[WebApp]定宽网页设计下，固定宽度布局开发WebApp并实现多终端下WebApp布局自适应|http://www.cnblogs.com/plums/archive/2013/01/10/WebApp-fixed-width-layout-of-multi-terminal-adapter-since.html\n判断微信客户端的那些坑|http://loo2k.com/blog/detecting-wechat-client\n可以通过javascript直接调用原生分享的工具|https://github.com/JefferyWang/nativeShare.js\nJiaThis 分享到微信代码|http://www.jiathis.com/help/html/weixin-share-code\n聊聊移动端跨平台开发的各种技术|http://fex.baidu.com/blog/2015/05/cross-mobile\n前端自动化测试|http://www.zhihu.com/question/29922082\n多种轮换图片|http://ajccom.github.io/niceslider\n滑动侧边栏|https://mango.github.io/slideout\n\n## __文件上传__\n\n文件上传  | 地址\n:----:|:----:  \n百度上传组件|http://fex.baidu.com/webuploader\n上传|https://blueimp.github.io/jQuery-File-Upload\nflash 头像上传|http://www.hdfu.net\n图片上传预览|http://www.dropzonejs.com\n图片裁剪|http://elemefe.github.io/image-cropper\n图片裁剪-shearphoto|http://www.shearphoto.com\njQuery图片处理|http://www.oschina.net/project/tag/284/jquery-image-tools?lang=0&os=0&sort=view&p=2\n\n## __模拟select__\n\n模拟select  | 地址\n:----:|:----:  \n糖饼 select|http://aui.github.io/popupjs/doc/selectbox.html\nflexselect|https://github.com/rmm5t/jquery-flexselect\n双select|http://loudev.com\nselect2|http://select2.github.io\n\n## __取色插件__\n\n取色插件  | 地址\n:----:|:----:  \n类似 Photoshop 的界面取色插件|http://www.jq22.com/plugin/367\njquery color|https://github.com/jquery/jquery-color\n取色插件集合|http://www.oschina.net/project/tag/287/color-picker\nfarbtastic 圆环＋正方形|https://github.com/mattfarina/farbtastic\n\n## __城市联动__\n\n城市联动  | 地址\n:----:|:----:  \njquery.cityselect.js基于jQuery+JSON的省市或自定义联动效果|http://www.ijquery.cn/?p=360\n\n## __剪贴板__\n\n剪贴板  | 地址\n:----:|:----:  \n剪贴板|https://github.com/zeroclipboard/zeroclipboard\nclipboard 最新的剪切方案|http://zenorocha.github.io/clipboard.js\n不是Flash的剪贴板|https://github.com/zenorocha/clipboard.js\n\n## __简繁转换__\n\n简繁转换  | 地址\n:----:|:----:  \n简繁转换|https://github.com/BYVoid/OpenCC\n\n## __表格 Grid__\n\n表格 Grid  | 地址\n:----:|:----:  \nfacebook表格|http://facebook.github.io/fixed-data-table\n类似于Excel编辑表格-handsontable|http://handsontable.com\nbootstrap-table插件|http://bootstrap-table.wenzhixin.net.cn\ndatatables|https://www.datatables.net\n\n## __在线演示__\n\n在线演示  | 地址\n:----:|:----:  \njs 在线编辑 - runjs|http://runjs.cn\njs 在线编辑 - jsbin|http://jsbin.com\njs 在线编辑 - codepen|http://codepen.io\njs 在线编辑 - jsfiddle|http://jsfiddle.net\njava 在线编辑 - runjs|http://ideone.com\njs 在线编辑 - hcharts|http://code.hcharts.cn\njs 在线编辑 - jsdm|http://jsdm.com\nsql 在线编辑 - sqlfiddle|http://sqlfiddle.com\nmozilla 在线编辑器|https://thimble.mozilla.org\n\n## __常规优化__\n\n常规优化|地址\n:----:|:----:\nJavascript高性能动画与页面渲染|http://www.infoq.com/cn/articles/javascript-high-performance-animation-and-page-rendering\n移动H5前端性能优化指南|http://isux.tencent.com/h5-performance.html\n5173首页前端性能优化实践|http://ued.5173.com/?p=1731\n给网页设计师和前端开发者看的前端性能优化|http://www.uisdc.com/front-end-performance-for-web-designers-and-front-end-developers\n复杂应用的 CSS 性能分析和优化建议|http://www.orzpoint.com/profiling-css-and-optimization-notes\n张鑫旭——前端性能| [张鑫旭——前端性能](http://www.zhangxinxu.com/wordpress/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD)\n前端性能监控总结|http://www.xiaoqiang.org/javascript/font-end-performance-monitor.html\n网站性能优化之CSS无图片技术| [网站性能优化之CSS无图片技术](http://udc.weibo.com/2013/05/%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8Bcss%E6%97%A0%E5%9B%BE%E7%89%87%E6%8A%80%E6%9C%AF)\nweb前端性能优化进阶路| [web前端性能优化进阶路](http://www.aliued.cn/2013/01/20/web%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E8%BF%9B%E9%98%B6%E8%B7%AF.html)\n前端技术：网站性能优化之CSS无图片技术|http://my.eoe.cn/tuwandou/archive/4544.html\n浏览器的加载与页面性能优化|http://www.baiduux.com/blog/2011/02/15/browser-loading\n页面加载中的图片性能优化|http://www.w3ctech.com/p/1503\nHey——前端性能| [Hey——前端性能](http://www.feelcss.com/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD)\nhtml优化| [html优化](http://www.baiduux.com/blog/2010/03/15/html%E4%BC%98%E5%8C%96-2)\n99css——性能| [99css——性能](http://www.99css.com/tag/%e6%80%a7%e8%83%bd)\nYslow——性能优化|http://www.yslow.net/category.php?cid=20\nYSLOW中文介绍|http://www.cnblogs.com/yslow\n转一篇Yahoo关于网站性能优化的文章，兼谈本站要做的优化|http://www.360ito.com/article/40.html\nYahoo!团队实践分享：网站性能|http://www.360doc.com/content/10/0928/09/2588264_56971287.shtml\n网站性能优化指南：什么使我们的网站变慢？|http://blog.jiasule.com/i/153\n网站性能优化实践，减少加载时间，提高用户体验|http://www.powereasy.net/helpyou/knowledge/ecommerce/9593.html\n浅谈网站性能优化 前端篇|http://www.umtry.com/archives/747.html\n前端重构实践之如何对网站性能优化？|http://www.adinnet.cn/blog/designview/2012-7-12/678.html\n前端性能优化：使用媒体查询加载指定大小的背景图片|http://www.gbin1.com/technology/javascript/20130708-front-end-performance-optimization-9\n网站性能系列博文|http://www.mykuer.com/post/factors-that-affect-the-speed-of-web-site-open.html\n加载，不只是少一点点|http://tgideas.qq.com/webplat/info/news_version3/804/808/811/m579/201109/41355.shtml\n前端性能的测试与优化|http://mzhou.me/article/95310\n分享网页加载速度优化的一些技巧？|http://www.gbin1.com/technology/html/20130217-tips-for-speed-up-page-loading\n页面加载中的图片性能优化|http://www.f2es.com/images-bytes-opt\nweb前端优化(基于Yslow|http://www.tcreator.info/webSchool/website/Front-end-Opt-Yslow.html\n网站性能优化工具大全|https://www.qianduan.net/website-performance-optimization-tool.html\n【高性能前端1】高性能HTML|http://www.alloyteam.com/2012/10/high-performance-html\n【高性能前端2】高性能CSS|http://www.alloyteam.com/2012/10/high-performance-css\n由12306谈谈网站前端性能和后端性能优化|http://coolshell.cn/articles/6470.html\nAlloyTeam——前端优化| [AlloyTeam——前端优化](http://www.alloyteam.com/webfrontend/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96)\n毫秒必争，前端网页性能最佳实践|http://www.cnblogs.com/developersupport/p/3248695.html\n网站性能工具Yslow的使用方法|http://blog.sina.com.cn/s/blog_6e9d2e0701017kvu.html\n前端工程与性能优化（上）：静态资源版本更新与缓存|http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part1\n前端工程与性能优化（下）：静态资源管理与模板框架|http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part2\nHTTPS连接的前几毫秒发生了什么|http://blog.jobbole.com/48369\nYslow|http://uicss.cn/yslow/#more-12319\nEssential Web Performance Metrics — A Primer, Part 1|http://blog.smartbear.com/web-performance/essential-web-performance-metrics-a-primer-part-1\nEssential Web Performance Metrics — Part 2|http://blog.smartbear.com/performance/essential-web-performance-metrics-part-2\nYUISlide,针对移动设备的动画性能优化|http://jayli.github.io/blog/data/2011/12/23/yuislide.html\nImproving Site Performance|http://joelglovier.com/improving-site-performance\n让网站提速的最佳前端实践|http://segmentfault.com/a/1190000000367899\nWhy Website Speed is Important|http://sixrevisions.com/web-development/why-website-speed-is-important\nNeed for Speed – How to Improve your Website Performance|https://www.devbridge.com/articles/need-for-speed-how-to-improve-your-website-performance\n阿里无线前端性能优化指南 (Pt.1 加载期优化 |https://github.com/amfe/article/issues/1\n\n## __优化工具__\n\n优化工具|地址\n:----:|:----:\nJavaScript 性能分析新工具 OneProfile|http://www.html-js.com/article/3083\nJavaScript 堆内存分析新工具 OneHeap|http://www.html-js.com/article/3091\n\n## __在线工具__\n\n在线工具|地址\n:----:|:----:\ngoogle在线工具|https://developers.google.com/speed/pagespeed/insights\n阿里测|http://www.alibench.com\n阿里-免费测试服务|http://itest.aliyun.com\n阿里-F2etest多浏览器兼容性测试解决方案|https://github.com/alibaba/f2etest\njs性能测试|http://jsperf.com\n\n## __前端架构__\n\n前端架构|地址\n:----:|:----:\n技术架构|http://www.zhihu.com/topic/19612641\n前端架构|http://saito.im/note/The-Architecture-of-F2E\n如何成为前端架构师|http://www.zhihu.com/question/24092572\n关于前端架构-张克军|http://hikejun.com/sharing/2010webrebuild/?file=fe-infrastructure.html\n百度腾讯offer比较（腾讯游戏VS百度基础架构）|http://www.zhihu.com/question/25583350\n\n## __推荐作品__\n\n推荐作品|地址\n:----:|:----:\nwinter代码片段需要翻墙|https://gist.github.com/wintercn\nfgm|http://www.fgm.cc/learn\n岑安作品集|https://github.com/hongru/hongru.github.com\n当耐特demo集合|http://kmdjs.github.io\n米空格 js作品|http://www.laoshu133.com/Lab\nmyFocus|http://koen301.github.io\nSeaJS组件库|http://panxuepeng.github.io/seajslib\n颜海镜作品|http://yanhaijing.com/myProject\n脚儿网作品|http://jo2.org/category/myworks\njavascript个人作品|http://www.cnitblog.com/yemoo/category/3107.html\n妙味的雷东升游戏作品|http://bbs.miaov.com/forum.php?mod=viewthread&tid=7790\njavascript作品集|http://bbs.csdn.net/topics/380227212\n云五笔，灰度产生生成工具|https://github.com/TooBug/works\n项目主页|http://koen301.github.io\n个性的作品主页|http://zaole.net\n播放器|http://static.tingall.com/v2/player\nucren js demos 集|http://ucren.com/blog/demos\n智能社|http://www.zhinengshe.com/works_list.html\n实例陈列架|http://demos.shizuwu.cn\nzoye demo|http://zoye.sinaapp.com/demo\n王员外|http://lab.yuanwai.wang\n平凡|http://pingfan1990.sinaapp.com\njyg 游戏案例|http://www.lovewebgames.com\n很多jquery插件|http://www.helloweba.com/list.html\n不羁虫 - soJs 作品系列|http://www.bujichong.com/sojs/api/index.html\nfrozenui|http://frozenui.github.io/case.html\n黑白棋|http://js-game.github.io/othello\nfromone|http://yansm.github.io/fromone/index.html\npazguille|http://pazguille.me\n**Html5 VideoPlayer**|https://github.com/zmmbreeze/DeadSimpleVideoPlayer\n**Proton 烟花**|http://a-jie.github.io/Proton/#example\n\n## __简历模板__\n\n简历模板|地址\n:----:|:----:\n简历|http://hcy2367.github.io/resume\n张伦|http://ncuey.sinaapp.com/CrispElite/ \n简历|https://github.com/hacke2/ResumeSample\n马斯特|http://pinkyjie.com/resume\n张秋怡|https://joyeecheung.github.io/resume/\n翁天信|http://blog.dandyweng.com/2013/07/how-my-website-was-created\n动画方式的简历|http://www.webhek.com/misc/interactive-resume\n组件丰富简历|http://www.linqing07.com/resume.html\nhaorooms博客|http://www.haorooms.com/about\n\n## __面试题__\n\n面试题|地址\n:----:|:----:\n那几个月在找工作（百度，网易游戏）|http://www.nowcoder.com/discuss/3196\n2014最新面试题|http://www.html-js.com/article/1743\n2016校招内推 -- 阿里巴巴前端 -- 三面面试经历 |http://www.cnblogs.com/imwtr/p/4685546.html\n年后跳槽那点事：乐视+金山+360面试之行|http://www.cnblogs.com/lvdabao/p/3660707.html\nInterviewing a front-end developer| http://blog.sourcing.io/interview-questions\n拉勾网js面试题|http://www.cnblogs.com/52cik/p/js-question-lg.html\n前端面试|http://www.cnblogs.com/allenxing/p/3724382.html\nWeb开发笔试面试题 大全|http://mianshiti.diandian.com\n前端开发面试题|http://segmentfault.com/a/1190000000465431\n2014最新前端面试题|https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions\n百度面试|https://github.com/fex-team/interview-questions\n面试题|http://www.w3cfuns.com/forum.php?mod=forumdisplay&fid=51&filter=typeid&typeid=177\n前端工作面试问题|https://github.com/darcyclarke/Front-end-Developer-Interview-Questions/tree/master/Chinese\n前端开发面试题|http://segmentfault.com/a/1190000000465431\n5个经典的前端面试问题| [5个经典的前端面试问题](http://ourjs.com/detail/5%E4%B8%AA%E7%BB%8F%E5%85%B8%E7%9A%84%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98)\n最全前端面试问题及答案总结 |http://segmentfault.com/a/1190000002562454\n如何面试一名前端开发工程师？|http://www.html-js.com/article/Large-search-front-team-column%202961\n史上最全 前端开发面试问题及答案整理|https://github.com/hawx1993/Front-end-Interview-questions\n前端实习生面试总结 |http://www.cnblogs.com/xiaoruo/p/4665163.html\n史上最全 前端开发面试问题及答案整理|https://github.com/hawx1993/Front-end-Interview-questions\nBAT及各大互联网公司2014前端笔试面试题：JavaScript篇|http://blog.jobbole.com/78738\n前端开发面试题大收集|https://github.com/paddingme/Front-end-Web-Development-Interview-Question\n收集的前端面试题和答案|https://github.com/qiu-deqing/FE-interview\n如何面试前端工程师|http://www.zhihu.com/question/19568008\n前端开发面试题|https://github.com/markyun/My-blog/blob/master/Front-end-Developer-Questions/Questions-and-Answers/README.md\n牛客网-笔试面经|http://www.nowcoder.com/discuss?type=2\n\n## __iconfont__\n\niconfont|地址\n:----:|:----:\n中文字体|http://www.zhihu.com/question/21253343\n淘宝字库|http://iconfont.cn\n字体|http://mux.alimama.com/fonts\n制作教程|http://iconfont.cn/help/platform.html\nzhangxinxu-icommon|http://www.zhangxinxu.com/wordpress/?s=icomoon\nicommon|https://icomoon.io/app\n用字体在网页中画ICON图标(推荐教程|http://imooc.com/learn/243\n字体压缩工具|http://font-spider.org\n\n## __Fiddler__\n\nFiddler|地址\n:----:|:----:\nFiddler调式使用知多少(一深入研究|http://www.cnblogs.com/tugenhua0707/p/4623317.html\n微信fiddle|http://www.cnblogs.com/strick/p/4570006.html\n微信fiddle|http://gaoboy.com/article/26.html\n\n## __Chrome__\n\nChrome|地址\n:----:|:----:\nGoogle Chrome 官方|https://developer.chrome.com/devtools\nChrome - 基础|http://www.cnblogs.com/constantince/p/4565261.html\nChrome - 进阶|http://www.cnblogs.com/constantince/p/4579121.html\nChrome - 性能|http://www.cnblogs.com/constantince/p/4585983.html\nChrome - 性能进阶|http://www.cnblogs.com/constantince/p/4607497.html\nChrome - 移动|http://www.cnblogs.com/constantince/p/4624241.html\nChrome - 使用技巧|http://www.cnblogs.com/liyunhua/p/4544738.html\nChrome - Console控制台不完全指南|http://www.cnblogs.com/Wayou/p/chrome-console-tips-and-tricks.html\nChrome - Workspace使浏览器变成IDE|http://c7sky.com/chrome-devtools-workspace.html\nnetwork面板|http://www.html-js.com/article/Nothing-blind%202975\nchrome开发工具快捷键|http://anti-code.com/devtools-cheatsheet\nchrome调试工具常用功能整理|http://www.html-js.com/article/2327\nChrome 开发工具 Workspace 使用|http://www.iinterest.net/2014/05/09/chrome-dev-tool-workspace\nChrome神器Vimium快捷键学习记录 |http://www.cppblog.com/deercoder/archive/2011/10/22/158886.html\nsass调试-w3cplus|http://www.w3cplus.com/sassguide/debug.html\n如何更专业的使用Chrome开发者工具-w3cplus|http://www.w3cplus.com/tools/how-to-use-chrome-devtools-like-a-pro.html\nchrome调试canvas|http://sentsin.com/web/253.html\nchrome profiles1|https://developer.chrome.com/devtools/index\nchrome profiles2|http://h5dev.uc.cn/article-25-1.html\nchrome profiles3|http://www.oschina.net/translate/performance-optimisation-with-timeline-profiles\nchrome移动版调试|https://developer.chrome.com/devtools/docs/mobile-emulation\nchrome调试|http://ued.taobao.org/blog/2012/06/debug-with-chrome-dev-tool\nchrome的调试|http://www.cnblogs.com/QLeelulu/archive/2011/08/28/2156402.html\nchrome console 命令详解|https://developer.chrome.com/devtools/docs/commandline-api\n查看事件绑定1|http://www.cnblogs.com/leonkao/p/3809655.html\n查看事件绑定2|http://www.cnblogs.com/xiaoyao2011/p/3447421.html\n神器——Chrome开发者工具(一|http://segmentfault.com/a/1190000000683599\n奇趣百科性能优化(Chrome DevTools 中的 Timeline Profils 等工具使用介绍|https://xinranliu.me/2015-05-22-qiqu-performance\nchrome 开发者工具的 15 个小技巧|http://frontenddev.org/link/15-tips-of-chrome-developer-tools.html\nChrome开发者工具不完全指南|http://1ke.co/course/361\nChrome 开发者工具使用技巧|http://segmentfault.com/a/1190000003882567\n\n## __Firebug__\n\nFirebug|地址\n:----:|:----:\nfirebug视频教程|http://www.imooc.com/learn/137\nfirefox 模拟器|https://developer.mozilla.org/zh-CN/docs/Tools/WebIDE\nconsole.log 命令详解|http://www.cnblogs.com/ctriphire/p/4116207.html\nFirebug入门指南|http://www.ruanyifeng.com/blog/2008/06/firebug_tutorial.html\nFirebug控制台详解|http://www.ruanyifeng.com/blog/2011/03/firebug_console_tutorial.html\n\n## __移动,微信调试__\n\n移动,微信调试|地址\n:----:|:----:\n浏览器端调试安卓|https://openstf.github.io\n移动端前端开发调试|http://yujiangshui.com/multidevice-frontend-debug\n使用 Chrome 远程调试 Android 设备|https://github.com/yujiangshui/CN-Chrome-DevTools/blob/remote-debugging/md/Use-Tools/remote-debugging.md\nmac移动端调试|http://plus.uc.cn/document/webapp/doc5.html\nmac移动端调试|http://www.mihtool.com\n无线调试攻略|http://thx.github.io/mobile/debugging-in-mobile\n无线调试攻略|http://yanhaijing.com/mobile/2014/12/17/web-debug-for-mobile\n屌爆了,完美调试 微信webview(x5|http://www.jianshu.com/p/ccf124f1f74b\n微信调试的那些事| [微信调试的那些事](http://liyaodong.com/2015/07/06/%E5%BE%AE%E4%BF%A1%E8%B0%83%E8%AF%95%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B)\n远程console|http://jsconsole.com\n微信调试工具|http://blog.qqbrowser.cc\n各种真机远程调试方法汇总|https://github.com/jieyou/remote_inspect_web_on_real_device\n\n## __iOS Simulator__\n\niOS Simulator|地址\n:----:|:----:\nSimulator| [iOS_Simulator_Guide-Introduction](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html)\niOS Simulator的介绍和使用心得|http://www.crifan.com/intro_ios_simulator_in_xcode_and_usage_summary\n\n## __Image__\n\nimg|地址\n:----:|:----:\nloading img|http://preloaders.net/en/circular\n智图-图片优化平台|http://zhitu.isux.us\n在线png优化|https://tinypng.com\nSM.MS(图床工具～简易好用)|https://sm.ms/\nyutuku：极简图床|http://yotuku.cn/\nQchan图床|http://tuchuang.org/\n\n## __浏览器同步__\n\n浏览器同步|地址\n:----:|:----:\npuer|https://github.com/leeluolee/puer\nliveReload|http://livereload.com\nf5|http://getf5.com\nFile Watchers|http://geek100.com/2608\n\n## __在线PPT制作__\n\n在线PPT制作|地址\n:----:|:----:\nnodePPT| [nodePPT](http://js8.in/2013/11/16/%E6%8E%A8%E8%8D%90nodeppt%EF%BC%9A%E4%BD%BF%E7%94%A8markdown%E8%AF%AD%E6%B3%95%E6%9D%A5%E5%86%99%E7%BD%91%E9%A1%B5ppt)\n**Cleaver快速制作网页PPT**|http://www.jeffjade.com/2015/10/15/2015-10-16-cleaver-make-ppt/\n**impress.js** | http://www.cnblogs.com/Darren_code/archive/2013/01/04/impressjs.html\nPPT|https://github.com/ksky521/nodePPT\n**reveal**|https://github.com/hakimel/reveal.js\nbespoke-fx|https://github.com/ebow/bespoke-fx\nslippy|https://github.com/Seldaek/slippy\n\n## __前端导航网站__\n\n前端导航网站|地址\n:----:|:----:\n界面清爽的前端导航|http://uxbees.com/index.html\n前端导航|http://whycss.com\n前端网址导航|http://www.daqianduan.com/nav\n前端名录|http://sentsin.com/daohang\n前端导航|http://123.jser.us\n前端开发资源|http://www.css88.com/nav\n网址导航|http://www.haourl.cn\n前端开发仓库 - 众多效果的收集地|http://code.ciaoca.com \n前端资源导航|https://github.com/jnoodle/f2e-collect\nF2E 前端导航|http://f2e.im/static/pages/nav/index.html\n\n## __常用CDN__\n\n常用CDN|地址\n:----:|:----:\n新浪CDN|http://lib.sinaapp.com\n百度静态资源公共库|http://cdn.code.baidu.com\n360网站卫士常用前端公共库CDN服务|http://libs.useso.com\nBootstrap中文网开源项目免费 CDN 服务|http://www.bootcdn.cn\n开放静态文件 CDN - 七牛|http://staticfile.org\nCDN加速 - jq22|http://www.jq22.com/cdn\njQuery CDN|http://code.jquery.com\nGoogle jQuery CDN|http://www.google-jquery-cdn.com\n微软CDN|http://www.asp.net/ajax/cdn\n\n## __Git__\n\nGit|地址\n:----:|:----:\ngit-scm|http://git-scm.com\n廖雪峰-Git教程| [廖雪峰-Git教程](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)\ngit-for-windows|https://git-for-windows.github.io\nGitHub 添加 SSH keys|http://daemon369.github.io/git/2015/03/10/add-ssh-keys-for-github\ngogithub|http://www.worldhello.net/gotgithub/index.html\ngit常规命令练习|http://pcottle.github.io/learnGitBranching\ngit的资料整理|https://github.com/xirong/my-git\n我所记录的git命令（非常实用）|http://www.cnblogs.com/fanfan259/p/4810517.html\n企业开发git工作流模式探索部分休整|https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md\nGitHub 漫游指南|https://github.com/phodal/github-roam\nGitHub秘籍|https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md\n使用git和github进行协同开发流程|http://livoras.com/post/28\n动画方式练习git|http://onlywei.github.io/explain-git-with-d3\n\n## __各种日期日历__\n\n各种日期日历 | 地址\n:----:|:----: \n经典my97|http://www.my97.net/dp/demo/index.htm\n强大的独立日期选择器|http://www.cnblogs.com/gbin1/archive/2012/04/16/2452105.html\nfullcalendar|http://fullcalendar.io\nfullcalendar日历控件知识点集合 |http://blog.csdn.net/francislaw/article/details/7740630\n中文api|http://blog.sina.com.cn/s/blog_9475b1c101012c5f.html\n农历日历|https://github.com/zzyss86/LunarCalendar\n超酷的仿百度带节日日历老黄历控件|http://www.sucaisj.com/jiaoben/date/201509/16856.html\n日期格式化|http://momentjs.com\n大牛日历控件|https://github.com/Johnqing/QPAYCalendar\n我群某管理作品|https://github.com/Iamlars/dateMarker\ninput按位替换-官网|http://digitalbush.com/projects/masked-input-plugin\ninput按位替换-github|https://github.com/digitalBush/jquery.maskedinput/tree/1.2.2\nbootstrap-daterangepicker|https://github.com/dangrossman/bootstrap-daterangepicker\n国外30个插件集合|http://www.vandelaydesign.com/30-best-free-jquery-plugins\nJavaScript datepicker|http://dbushell.com/2012/10/09/pikaday-javascript-datepicker\nDatepair.js|http://jonthornton.github.io/Datepair.js\n一个风格多样的日历|https://github.com/glad/glDatePicker\n弹出层式的全日历|http://amsul.ca/pickadate.js/date\njquery双日历|http://www.daterangepicker.com\n大气实用jQuery手机移动端日历日期选择插件|http://www.frankdemo.cn/index.php?c=content&a=show&id=115\njQuery Mobile 移动开发中的日期插件Mobiscroll |https://mobiscroll.com\n\n## __Date library__\n\nDate library | 地址\n:----:|:----: \nDatejs|https://github.com/datejs/Datejs\nsugarjs|http://sugarjs.com/api/Date\n\n## __其它__\n\n其它| 地址\n:----:|:----: \nMock.js 是一款模拟数据生成器|http://mockjs.com\n特色的HTML框架可以创建精美的iOS应用|http://framework7.taobao.org\n淘宝SUI|http://m.sui.taobao.org\navalonjs|http://avalonjs.github.io\nAvalon新一代UI库： OniUI|http://ued.qunar.com/oniui/index.html\navalon.oniui-基于avalon的组件库|https://github.com/RubyLouvre/avalon.oniui\n生成二维码(草料)|http://cli.im\n\n## __效果类__\n\n效果类 | 地址\n:----:|:----: \n弹出层|http://www.imooc.com/learn/58\n焦点图轮播特效|http://www.imooc.com/learn/18\n**HTML5 有哪些让你惊艳的 demo？** |http://www.zhihu.com/question/24398907\n\n## __弹出层__\n\n弹出层| 地址\n:----:|:----:    \nartDialog 最新版|https://github.com/aui/artDialog\nartDialog 文档|http://aui.github.io/artDialog/doc/index.html\ngoogle code 下载地址|https://code.google.com/p/artdialog/downloads/list\n贤心弹出层|http://layer.layui.com\n响应式用户交互组件库|https://github.com/bh-lay/UI\nsweetalert-有css3动画弹出层|http://t4t5.github.io/sweetalert\n\n## __优秀JavaScript项目__\n\n优秀JavaScript项目 | 地址\n:----:|:----: \nAngular和Webpack种子文件|https://github.com/AngularClass/angular2-webpack-starter\nFis3面向前端的工程构建系统|https://github.com/fex-team/fis3\nFis3 DEMO|https://github.com/fex-team/fis3-demo\n前端JQuery系列:源码剖析|https://github.com/JsAaron/jQuery\navalon框架|https://github.com/RubyLouvre/avalon\nMicrosoft ChakraCore 微软的Chakra引擎|https://github.com/Microsoft/ChakraCore\nQuintus HTML游戏引擎|https://github.com/cykod/Quintus\n一个用node.js搭建的有趣博客|https://github.com/STRML/strml.net\nWeb前端助手--FeHelper（Chrome扩展）|https://github.com/zxlie/FeHelper\n百度前端技术学院|https://github.com/baidu-ife/ife\nCheerio（node.js中的jQuery）|https://github.com/cheeriojs/cheerio\nnodejs的一个聊天软件 类似微信|https://github.com/BryanYang/freechat\n使用html5和node.js构建的网易云音乐|https://github.com/stkevintan/Cube\nbabel ES6转换为ES5|https://github.com/babel/babel\n一个JS富文本编辑器|https://github.com/fex-team/ueditor\n一个JS脑图可视化工具|https://github.com/fex-team/kityminder-core\n一个JS写的Flappy Bird Game|https://github.com/ellisonleao/clumsy-bird\n一个JS写的GBA模拟器|https://github.com/taisel/IodineGBA\nSegmentFault写的Markdown解析器|https://github.com/SegmentFault/HyperDown.js\n基于node.js的Ghost博客|https://github.com/TryGhost/Ghost\n学习react的demos|https://github.com/ruanyf/react-demos\n\n\n>转载请保留原链接：[http://www.jeffjade.com/2016/03/30/104-front-end-tutorial/](http://www.jeffjade.com/2016/03/30/104-front-end-tutorial/)\n"
  },
  {
    "path": "04-Front-end-tutorial-master/README_old.md",
    "content": "1. 综合类\n\n    - [前端知识体系](http://www.cnblogs.com/sb19871023/p/3894452.html)\n    - [前端知识结构](https://github.com/JacksonTian/fks)\n    - [Web前端开发大系概览](https://github.com/unruledboy/WebFrontEndStack)\n    - [Web前端开发大系概览-中文版](http://www.cnblogs.com/unruledboy/p/WebFrontEndStack.html)\n    - [Web Front-end Stack v2.2](https://raw.githubusercontent.com/unruledboy/WebFrontEndStack/master/Web%20Front%20End%20Stack.png)\n    - [免费的编程中文书籍索引](https://github.com/justjavac/free-programming-books-zh_CN)\n    - [前端书籍](https://github.com/dypsilon/frontend-dev-bookmarks)\n    - [前端免费书籍大全](https://github.com/vhf/free-programming-books)\n    - [前端知识体系](http://www.cnblogs.com/sb19871023/p/3894452.html)\n    - [免费的编程中文书籍索引](https://github.com/justjavac/free-programming-books-zh_CN)\n    - [智能社 - 精通JavaScript开发](http://study.163.com/course/introduction/224014.htm)\n    - [重新介绍 JavaScript（JS 教程）](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript)\n    - [麻省理工学院公开课：计算机科学及编程导论](http://v.163.com/special/opencourse/bianchengdaolun.html)\n    - [JavaScript中的this陷阱的最全收集--没有之一](http://segmentfault.com/a/1190000002640298)\n    - [JS函数式编程指南](https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch1.html)\n    - [JavaScript Promise迷你书（中文版）](http://liubin.github.io/promises-book/)\n    - [腾讯移动Web前端知识库](https://github.com/AlloyTeam/Mars)\n    - [Front-End-Develop-Guide 前端开发指南](https://github.com/Front-End-Developers-Hunan/Front-End-Develop-Guide)\n    - [前端开发笔记本](https://li-xinyang.gitbooks.io/frontend-notebook/content/)\n    - [大前端工具集 - 聂微东](https://github.com/nieweidong/fetool)\n    - [前端开发者手册](https://dwqs.gitbooks.io/frontenddevhandbook/content/)\n\n2. 入门类\n\n    - [前端入门教程](http://www.cnblogs.com/jikey/p/3613082.html)\n    - [瘳雪峰的Javascript教程](http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000)\n    - [jQuery基础教程](http://www.imooc.com/view/11)\n    - [前端工程师必备的PS技能——切图篇](http://www.imooc.com/view/506)\n    - [结合个人经历总结的前端入门方法](https://github.com/qiu-deqing/FE-learning)\n\n3. 效果类\n\n    - [弹出层](http://www.imooc.com/learn/58)\n    - [焦点图轮播特效](http://www.imooc.com/learn/18)\n    \n4. 工具类\n\n    - [css sprite 雪碧图制作](http://www.imooc.com/learn/93)\n    - [版本控制入门 – 搬进 Github](http://www.imooc.com/learn/390)\n    - [Grunt-beginner前端自动化工具](http://www.imooc.com/learn/30)\n\n5. 慕课专题\n\n    - [张鑫旭 - 慕课系列](http://www.imooc.com/space/teacher/id/197450)\n    - [lyn - 慕课系列](http://www.imooc.com/space/teacher/id/104593)\n    - [艾伦 - 慕课系列](http://www.imooc.com/space/teacher/id/290139)\n    - [碧仔 - Hello，移动WEB](http://www.imooc.com/view/494)\n\n6. 周报类\n\n    - [平安科技移动开发二队技术周报](https://github.com/PaicHyperionDev/MobileDevWeekly)\n\n###六. API:\n\n####1. 总目录\n\n1. 开发中心\n\n    - [mozilla js参考](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)\n    - [chrome开发中心（chrome的内核已转向blink）](https://developer.chrome.com/extensions/api_index.html)\n    - [safari开发中心](https://developer.apple.com/library/safari/navigation)\n    - [microsoft js参考](https://msdn.microsoft.com/zh-cn/library/d1et7k7c(v=vs.94).aspx)\n    - [js秘密花园](http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html)\n    - [js秘密花园](http://bonsaiden.github.io/JavaScript-Garden/zh/)\n    - [w3help](http://www.w3help.org/) 综合Bug集合网站\n\n2. 综合搜索\n\n    - [javascripting](http://www.javascripting.com/)\n    - [各种流行库搜索](http://microjs.com/)\n\n3. 综合API\n    \n    - [runoob.com-包含各种API集合](http://www.runoob.com/)\n    - [开源中国在线API文档合集](http://tool.oschina.net/apidocs)\n    - [devdocs](http://devdocs.io/) 英文综合API网站\n\n####2. jQuery\n\n* [jQuery API 中文文档](http://www.jquery123.com/)\n* [hemin 在线版](http://hemin.cn/jq/)\n* [css88 jq api](http://www.css88.com/jqapi-1.9/on/)\n* [css88 jqui api](http://www.css88.com/jquery-ui-api/)\n* [学习jquery](http://learn.jquery.com/)\n* [jquery 源码查找](http://james.padolsey.com/jquery/)\n\n####3. Ecmascript\n\n- [Understanding ECMAScript 6 - Nicholas C. Zakas](https://leanpub.com/understandinges6/read)\n- [exploring-es6](https://leanpub.com/exploring-es6/read)\n- [exploring-es6翻译](https://github.com/es6-org/exploring-es6)\n- [exploring-es6翻译后预览](http://es6-org.github.io/exploring-es6/)\n- [阮一峰 es6](http://es6.ruanyifeng.com/)\n- [阮一峰 Javascript](http://javascript.ruanyifeng.com/)\n- [ECMA-262，第 5 版](http://yanhaijing.com/es5/)\n- [es5](http://es5.github.io/)\n\n####4. Js template\n\n- [template-chooser](http://garann.github.io/template-chooser/)\n- [artTemplate](https://github.com/aui/artTemplate)\n- [tomdjs](https://github.com/aui/tmodjs/blob/master/README.md)\n- [淘宝模板juicer模板](http://juicer.name/docs/docs_zh_cn.html)\n- [Fxtpl v1.0 繁星前端模板引擎](http://koen301.github.io/fxtpl/)\n- [laytpl](http://laytpl.layui.com/)\n- [mozilla - nunjucks](https://github.com/mozilla/nunjucks)\n- [Juicer](https://github.com/PaulGuo/Juicer)\n- [dustjs](http://akdubya.github.io/dustjs/)\n- [etpl](http://ecomfe.github.io/etpl/)\n\n####5. 弹出层\n\n- [artDialog 最新版](https://github.com/aui/artDialog)\n- [artDialog 文档](http://aui.github.io/artDialog/doc/index.html)\n- [google code 下载地址](https://code.google.com/p/artdialog/downloads/list)\n- [贤心弹出层](http://layer.layui.com/)\n- [响应式用户交互组件库](https://github.com/bh-lay/UI)\n- [sweetalert-有css3动画弹出层](http://t4t5.github.io/sweetalert/)\n\n####6. CSS\n\n- [CSS 语法参考](http://tympanus.net/codrops/css_reference/)\n- [CSS3动画手册](http://isux.tencent.com/css3/index.html)\n- [腾讯css3动画制作工具](http://isux.tencent.com/css3/tools.html)\n- [志爷css小工具集合](http://linxz.github.io/tianyizone/)\n- [css3 js 移动大杂烩](http://www.note12.com/category/blog/2014-6-5/538fe0a9f786f1b7019a4dfb)\n- [bouncejs 触摸库](http://bouncejs.com/)\n- [css3 按钮动画](http://fian.my.id/Waves/)\n- [animate.css](http://daneden.github.io/animate.css/)\n- [全局CSS的终结(狗带) [译]](http://www.alloyteam.com/2015/10/8536/)\n\n####7. Angularjs\n\n- [Angular.js 的一些学习资源](https://github.com/dolymood/AngularLearning)\n- [angularjs中文社区](http://angularjs.cn/)\n- [Angularjs源码学习](http://www.cnblogs.com/xuwenmin888/p/3739096.html)\n- [Angularjs源码学习](http://www.ifeenan.com/?c=AngularJS)\n- [angular对bootstrap的封装](http://angular-ui.github.io/bootstrap/)\n- [angularjs + nodejs](https://cnodejs.org/topic/51404e0f069911196d2e3923)\n- [吕大豹 Angularjs](http://www.cnblogs.com/lvdabao/tag/AngularJs/)\n- [AngularJS 最佳实践](http://www.infoq.com/cn/news/2013/02/angular-web-app)\n- [Angular的一些扩展指令](http://www.lovelucy.info/angularjs-best-practices.html)\n- [Angular数据绑定原理](https://github.com/Pasvaz/bindonce)\n- [一些扩展Angular UI组件](https://github.com/angular-ui/)\n- [Ember和AngularJS的性能测试](http://voidcanvas.com/emberjs-vs-angularjs-performance-testing/)\n- [带你走近AngularJS - 基本功能介绍](http://www.cnblogs.com/powertoolsteam/p/angularjs-introdection.html)\n- [Angularjs开发指南](http://angular.duapp.com/docs/guide)\n- [Angularjs学习](http://www.cnblogs.com/amosli/p/3710648.html)\n- [不要带着jQuery的思维去学习AngularJS](http://www.rainweb.cn/article/angularjs-jquery.html)\n- [angularjs 学习笔记](http://wangjiatao.diandian.com/?tag=angularjs)\n- [angularjs 开发指南](http://www.angularjs.cn/T008)\n- [angularjs 英文资料](https://github.com/jmcunningham/AngularJS-Learning)\n- [angular bootstrap](http://angular-ui.github.io/bootstrap/)\n- [angular jq mobile](https://github.com/opitzconsulting/jquery-mobile-angular-adapter)\n- [angular ui](http://mgcrea.github.io/angular-strap/)\n- [整合jQuery Mobile+AngularJS经验谈](http://www.tuicool.com/articles/7ZZVr2)\n- [有jQuery背景，该如何用AngularJS编程思想](http://blog.jobbole.com/46589/ )\n- [AngularJS在线教程](http://each.sinaapp.com/angular/)\n- [angular学习笔记](http://www.zouyesheng.com/angular.html)\n\n####8. React\n- [react.js 中文论坛](http://www.react-china.org/)\n- [react.js 官方网址](https://facebook.github.io/react/index.html)\n- [react.js 官方文档](https://facebook.github.io/react/docs/getting-started.html)\n- [react.js material UI](http://material-ui.com/#/)\n- [react.js TouchstoneJS UI](http://touchstonejs.io/)\n- [react.js amazeui UI](http://amazeui.org/react/)\n- [React 入门实例教程 - 阮一峰](http://www.ruanyifeng.com/blog/2015/03/react.html)\n- [React Native 中文版](http://wiki.jikexueyuan.com/project/react-native/)\n- [Webpack 和 React 小书 - 前端乱炖](http://www.html-js.com/article/Fakefish%203053)\n- [Webpack 和 React 小书 - gitbook](https://fakefish.github.io/react-webpack-cookbook/)\n- [webpack](https://github.com/webpack/webpack)\n- [Webpack，101入门体验](http://html-js.com/article/3009)\n- [webpack入门教程](http://html-js.com/article/3113)\n- [基于webpack搭建前端工程解决方案探索](http://segmentfault.com/a/1190000003499526)\n- [React原创实战视频教程](http://www.piliyu.com/)\n\n####9. 移动端API\n\n1. API    \n    - [99移动端知识集合](https://github.com/jtyjty99999/mobileTech)\n    - [移动端前端开发知识库](https://github.com/AlloyTeam/Mars)\n    - [移动前端的一些坑和解决方法（外观表现）](http://caibaojian.com/mobile-web-bug.html)\n    - [【原】移动web资源整理](http://www.cnblogs.com/PeunZhang/p/3407453.html)\n    - [zepto 1.0 中文手册](http://mweb.baidu.com/zeptoapi/)\n    - [zepto 1.0 中文手册](http://www.html-5.cn/Manual/Zepto/)\n    - [zepto 1.1.2](http://www.css88.com/doc/zeptojs_api/)\n    - [zepto 中文注释](http://www.cnblogs.com/sky000/archive/2013/03/29/2988952.html)\n    - [jqmobile 手册](http://app-framework-software.intel.com/api.php)\n    - [移动浏览器开发集合](https://github.com/maxzhang/maxzhang.github.com/issues)\n    - [移动开发大杂烩](https://github.com/hoosin/mobile-web-favorites)\n    - [微信webview中的一些问题](http://lin-chao.github.io/2014/11/14/%E5%BE%AE%E4%BF%A1webview%E4%B8%AD%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98/)\n2. 框架    \n    - [特色的HTML框架可以创建精美的iOS应用](http://framework7.taobao.org/)\n    - [淘宝SUI](http://m.sui.taobao.org/)\n\n####10. avalon\n\n- [avalonjs](http://avalonjs.github.io/)\n- [Avalon新一代UI库： OniUI](http://ued.qunar.com/oniui/index.html)\n- [avalon.oniui-基于avalon的组件库](https://github.com/RubyLouvre/avalon.oniui)\n- []()\n\n####11. Requriejs\n\n- [Javascript模块化编程（一）：模块的写法 ](http://www.ruanyifeng.com/blog/2012/10/javascript_module.html)\n- [Javascript模块化编程（二）：AMD规范](http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html)\n- [Javascript模块化编程（三）：require.js的用法](http://www.ruanyifeng.com/blog/2012/11/require_js.html)\n- [RequireJS入门（一）](http://www.cnblogs.com/snandy/archive/2012/05/22/2513652.html)\n- [RequireJS入门（二）](http://www.cnblogs.com/snandy/archive/2012/05/23/2513712.html)\n- [RequireJS进阶（三）](http://www.cnblogs.com/snandy/archive/2012/06/08/2538001.html)\n- [requrie源码学习](http://www.cnblogs.com/yexiaochai/p/3632580.html )\n- [requrie 入门指南](http://www.oschina.net/translate/getting-started-with-the-requirejs-library )\n- [requrieJS 学习笔记](http://www.cnblogs.com/yexiaochai/p/3214926.html )\n- [requriejs 其一 ](http://cyj.me/why-seajs/requirejs/ )\n- [require backbone结合](http://www.cnblogs.com/yexiaochai/p/3221081.html )\n\n####12. Seajs\n\n- [seajs](http://seajs.org/)\n- [seajs 中文手册](http://cyj.me/why-seajs/zh/)\n\n####13. Less,sass\n\n- [sass](http://www.w3cplus.com/sassguide/)\n- [sass教程-sass中国](http://www.sass.hk/)\n- [Sass 中文文档](http://sass.bootcss.com/)\n- [less](http://less.bootcss.com/)\n\n####14. Markdown\n        \n- [Markdown 语法说明 (简体中文版)](http://wowubuntu.com/markdown/)\n- [markdown入门参考](https://github.com/LearnShare/Learning-Markdown/blob/master/README.md)\n- [gitbook](https://www.gitbook.com/) 国外的在线markdown可编辑成书\n- [mdeditor](https://www.zybuluo.com/mdeditor)  一款国内的在线markdown编辑器\n- [stackedit](https://stackedit.io) 国外的在线markdown编辑器，功能强大，同步云盘\n- [mditor](http://bh-lay.github.io/mditor/) 一款轻量级的markdown编辑器\n- [lepture-editor](https://github.com/lepture/editor)\n- [markdown-editor](https://github.com/jbt/markdown-editor)\n\n####15. D3\n\n- [d3 Tutorials](https://github.com/mbostock/d3/wiki/Tutorials)\n- [Gallery](https://github.com/mbostock/d3/wiki/Gallery)\n- [lofter](http://datavisual.lofter.com/post/40cf3a_188e535)\n- [iteye](http://alanland.iteye.com/blog/1878595)\n- [ruanyifeng](http://javascript.ruanyifeng.com/library/d3.html)\n\n####16. 兼容性\n\n- [esma 兼容列表](http://kangax.github.io/compat-table/es6/)\n- [W3C CSS验证服务](http://jigsaw.w3.org/css-validator/validator.html.zh-cn)\n- [caniuse](http://caniuse.com/#index )\n- [csscreator](http://csscreator.com/properties)\n- [microsoft](https://msdn.microsoft.com/zh-cn/library/cc351024(v=vs.85).aspx)\n- [在线测兼容-移动端](http://www.responsinator.com/)\n- [emulators](https://www.manymo.com/emulators)\n\n####17. UI相关\n\n- [bootcss](http://v3.bootcss.com/)\n- [MetroUICSS](http://www.w3cplus.com/MetroUICSS/)\n- [semantic](http://semantic-ui.com/)\n- [Buttons](http://alexwolfe.github.io/Buttons/)\n- [kitecss](http://hiloki.github.io/kitecss/)\n- [pintuer](http://www.pintuer.com/)\n- [amazeui](http://amazeui.org/)\n- [worldhello](http://www.worldhello.net/gotgithub/index.html)\n- [linuxtoy](http://igit.linuxtoy.org/contents.html)\n- [gitmagic](http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/)\n- [rogerdudler](http://rogerdudler.github.io/git-guide/index.zh.html)\n- [gitref](http://gitref.justjavac.com/)\n- [book](http://git-scm.com/book/zh)\n- [gogojimmy](http://gogojimmy.net/2012/01/17/how-to-use-git-1-git-basic/)\n\n####18. HTTP\n\n- [HTTP API 设计指南](http://segmentfault.com/bookmark/1230000002521721)\n\n####19. 其它API\n\n- [javascript流行库汇总](javascriptoo)\n- [验证api](http://niceue.com/validator/demo/index.php)\n- [underscore 中文手册](http://www.css88.com/doc/underscore/)\n- [underscore源码分析](http://www.html-js.com/article/Underscorejs-source-code-analysis-of-underscorejs-source-code-analysis%203031)\n- [underscore源码分析-亚里士朱德的博客](http://yalishizhude.github.io/tags/underscore/)\n- [underscrejs en api](http://underscorejs.org/)\n- [lodash - underscore的代替品](https://lodash.com/)\n- [ext4api](http://extjs-doc-cn.github.io/ext4api/)\n- [backbone 中文手册](http://www.csser.com/tools/backbone/backbone.js.html)\n- [qwrap手册](http://dev.qwrap.com/resource/js/_docs/_youa/#/qw/base/loadJs_.htm)\n- [缓动函数](http://easings.net/zh-cn)\n- [svg 中文参考](http://www.w3school.com.cn/svg/svg_reference.asp)\n- [svg mdn参考](https://developer.mozilla.org/en-US/docs/Web/SVG)\n- [svg 导出 canvas](https://github.com/gabelerner/canvg)\n- [svg 导出 png](https://github.com/exupero/saveSvgAsPng)\n- [ai-to-svg](http://www.zamzar.com/convert/ai-to-svg/)\n- [localStorage 库](https://github.com/machao/localStorage)\n\n####20. 图表类\n\n- [Highcharts 中文API](http://www.hcharts.cn/api/index.php)\n- [Highcharts 英文API](http://api.highcharts.com/highcharts)\n- [ECharts 百度的图表软件](http://echarts.baidu.com/ )\n- [高德地图](http://lbs.amap.com/api/)\n- [开源的矢量图脚本框架](http://paperjs.org/)\n- [svg 地图](http://jvectormap.com/)\n\n####21. vue\n\n- [Vue](http://cn.vuejs.org/)\n- [Vue 论坛](http://forum.vuejs.org/)\n- [Vue 入门指南](http://www.cnblogs.com/aaronjs/p/3660102.html)\n- [Vue 的一些资源索引](http://segmentfault.com/a/1190000000411057)\n- [awesome-vue](https://github.com/vuejs/awesome-vue)\n\n####21. 正则\n\n- [JS正则表达式元字符](http://segmentfault.com/a/1190000002471140)\n- [正则表达式30分钟入门教程](http://deerchao.net/tutorials/regex/regex.htm)\n- [MDN-正则表达式](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions)\n- [ruanyifeng - RegExp对象](http://javascript.ruanyifeng.com/stdlib/regexp.html)\n- [小胡子哥 - 进阶正则表达式](http://div.io/topic/764?page=1)\n- [is.js](https://github.com/Cedriking/is.js/blob/master/is.js)\n- [正则在线测试](http://regexper.com/)\n- []()\n\n####22. ionic\n\n- [ionic](https://github.com/ychow/ionic-guide)\n\n####23. 其它\n\n- [Mock.js 是一款模拟数据生成器](http://mockjs.com/)\n\n###七. 开发规范\n\n1. 前端\n    - [通过分析github代码库总结出来的工程师代码书写习惯](http://alloyteam.github.io/CodeGuide)\n    - [HTML&CSS编码规范 by @mdo](http://codeguide.bootcss.com/)\n    - [团队合作的css命名规范-腾讯AlloyTeam前端团队](http://www.alloyteam.com/2011/10/107/)\n    - [前端编码规范之js - by yuwenhui](http://yuwenhui.github.io/)\n    - [前端编码规范之js - by 李靖](http://www.cnblogs.com/hustskyking/p/javascript-spec.html)\n    - [前端开发规范手册](http://zhibimo.com/read/Ashu/front-end-style-guide/)\n    - [Airbnb JavaScript 编码规范（简体中文版）](https://github.com/yuche/javascript#table-of-contents)\n    - [AMD与CMD规范的区别](http://www.zhihu.com/question/20351507)\n    - [AMD与CMD规范的区别](http://www.cnblogs.com/tugenhua0707/p/3507957.html)\n    - [KISSY 源码规范](http://docs.kissyui.com/1.4/docs/html/tutorials/style-guide/kissy-source-style.html)\n    - [bt编码规范](http://codeguide.bootcss.com/)\n    - [规范加强版](https://github.com/Suxiaogang/Code_Guide)\n    - [前端代码规范 及 最佳实践](http://blog.jobbole.com/79075/)\n    - [百度前端规范](http://coderlmn.github.io/code-standards/)\n    - [百度前端规范](http://isobar-idev.github.io/code-standards/)\n    - [百度前端规范](http://zhuanlan.zhihu.com/fuyun/19884834)\n    - [ECMAScript6 编码规范--广发证券前端团队](https://github.com/gf-rd/es6-coding-style)\n    - [JavaScript 风格指南/编码规范（Airbnb公司版）](http://blog.jobbole.com/79484/)\n    - [网易前端开发规范](http://nec.netease.com/standard)\n    - [css模块](http://www.75team.com/archives/1049)\n    - [前端规范资源列表](https://github.com/ecomfe/spec)\n\n2. PHP\n\n    - [最流行的PHP 代码规范](http://segmentfault.com/a/1190000000443795)\n    - [最流行的PHP 代码规范](https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-2-coding-style-guide.md)\n        \n3. Android\n\n    - [【敏捷开发】Android团队开发规范](http://www.cnblogs.com/lcw/p/3619181.html)\n    - [Android 开发规范与应用](http://www.jianshu.com/p/4390f4fe19b3)\n\n###八. 其它收集\n\n####1. 各大公司开源项目\n\n- [Facebook Projects](https://code.facebook.com/projects/web/)\n- [百度web前端研发部](http://fex.baidu.com/)\n- [百度EFE](http://efe.baidu.com/)\n- [百度github](https://github.com/fex-team/)\n- [alloyteam](http://www.alloyteam.com/)\n- [alloyteam-github](http://alloyteam.github.io/)\n- [alloyteam-AlloyGameEngine](https://github.com/AlloyTeam/AlloyGameEngine)\n- [AlloyDesigner](http://alloyteam.github.io/AlloyDesigner/) 即时修改，即时保存，设计稿较正，其它开发辅助工具\n- [H5交互页编辑器AEditor介绍](http://www.alloyteam.com/2015/06/h5-jiao-hu-ye-bian-ji-qi-aeditor-jie-shao/) H5动画交互页开发的工具介绍\n- [AEditor](http://aeditor.alloyteam.com/) H5动画交互页开发的工具\n- [maka](http://forum.maka.im/wordpress/)\n- [值得订阅的weekly](https://github.com/fenbility/weekly-feed)\n- [腾讯html5](http://cube.qq.com/)\n- [奇舞团开源项目](http://75team.github.io/)\n- [Qunar UED](http://ued.qunar.com/)\n- [Scrat](http://scrat.io)\n\n####2. Javascript\n\n1. 常用    \n\n    - [ieBetter.js-让IE6-IE8拥有IE9+,Chrome等浏览器特性](http://www.zhangxinxu.com/wordpress/2013/12/iebetter-js-make-ie6-ie8-like-modern-browser-ie9-chrome/)\n    - [模拟键盘](http://mottie.github.io/Keyboard/)\n    - [拼音](https://github.com/hotoo/pinyin)\n    - [中国个人身份证号验证](https://github.com/mc-zone/IDValidator)\n\n2. 算法\n\n    - [数据结构与算法 JavaScript 描述. 章节练习](https://github.com/Ralph-Wang/algorithm.in.js)\n    - [常见排序算法（JS版）](https://github.com/twobin/twobinSort)\n    - [经典排序](https://github.com/luofei2011/jsAgm/blob/master/js/sort.js)\n    - [常见排序算法-js版本](https://github.com/hechangmin/jssort)\n    - [JavaScript 算法与数据结构 精华集](https://github.com/lightningtgc/JavaScript-Algorithms)\n    - [面试常考算法题精讲](http://www.nowcoder.com/live/courses)\n    - []()\n\n3. 移动端\n    \n    - [fastclick](https://github.com/ftlabs/fastclick)\n    - [no-click-delay](https://github.com/mmastrac/jquery-noclickdelay)\n\n4. JSON\n \n    - [模拟生成JSON数据](http://beta.json-generator.com/)\n    - [返回跨域JSONAPI](http://jsonp.afeld.me/)\n\n####3. Html5\n- [HTML5 有哪些让你惊艳的 demo？](http://www.zhihu.com/question/24398907)\n\n####4. CSS\n- [browserhacks](http://browserhacks.com/)\n- []()\n\n####5. jQuery\n\n1. 焦点图\n    \n    - [myfocus](https://github.com/koen301/myfocus)\n    - [myfocus-官方演示站](http://www.chhua.com/myfocus/)\n    - [SuperSlidev2.1 -- 大话主席](http://www.superslide2.com/)\n    - [soChange](http://www.bujichong.com/sojs/soChange/index.html)\n\n####6. Ext, EasyUI, J-UI 及其它各种UI方案\n\n1. Ext\n\n    - [extjs](https://www.sencha.com/products/extjs/)\n    - [ext4英文api](http://docs.sencha.com/extjs/4.0.7/)\n    - [ext4中文api](http://extjs-doc-cn.github.io/ext4api/)\n    - []()\n    \n2. EasyUI\n\n    - [jquery easyui 未压缩源代码](http://jquery-easyui.googlecode.com/svn/trunk/src/)\n\n3. J-UI\n\n    - [J-UI](http://jui.org/)\n   \n4. Other\n\n    - [MUI-最接近原生APP体验的高性能前端框架](http://dcloudio.github.io/mui/)\n    - [Amaze UI | 中国首个开源 HTML5 跨屏前端框架](http://amazeui.org/)\n    - [淘宝 HTML5 前端框架](http://m.sui.taobao.org/)\n    - [KISSY - 阿里前端JavaScript库](http://docs.kissyui.com/)\n    - [网易Nej - Nice Easy Javascript](http://nej.netease.com/)\n    - [Kendo UI MVVM Demo](http://demos.telerik.com/kendo-ui/mvvm/index)\n    - [Bootstrap](http://www.bootcss.com/)\n    - [Smart UI](http://smartui.chinamzz.com/)\n    - [雅虎UI - CSS UI](http://developer.yahoo.com/yui/grids/)\n\n####7. 页面 社会化 分享功能\n\n- [百度分享](http://share.baidu.com/) pc端\n- [JiaThis](http://jiathis.com/) pc端\n- [社会化分享组件](http://developer.baidu.com/soc/share) 移动端\n- [ShareSDK 轻松实现社会化功能](http://www.mob.com/#/index) 移动端\n- [友盟分享](http://dev.umeng.com/social/android/quick-integration) 移动端\n\n####8. 富文本编辑器\n\n- [功能齐全 tinymce](https://www.tinymce.com/)\n- [百度 ueditor](http://ueditor.baidu.com/website/)\n- [经典的ckeditor](http://ckeditor.com/)\n- [经典的kindeditor](http://kindeditor.net/)\n- [wysiwyg](http://www.bootcss.com/p/bootstrap-wysiwyg/)\n- [一个有情怀的编辑器。Bach's Editor](http://integ.github.io/BachEditor/)\n- [tower用的编辑器](https://github.com/mycolorway/simditor)\n- [summernote 编辑器](https://github.com/summernote/summernote)\n- [html5编辑器](http://neilj.github.io/Squire/)\n- [XEditor](http://lab.hustlzp.com/XEditor/)\n- [wangEditor](https://github.com/wangfupeng1988/wangEditor )\n\n####9. 日历\n\n1. PC\n\n    - [经典my97](http://www.my97.net/dp/demo/index.htm)\n    - [强大的独立日期选择器](http://www.cnblogs.com/gbin1/archive/2012/04/16/2452105.html)\n    - [fullcalendar](http://fullcalendar.io/)\n    - [fullcalendar日历控件知识点集合 ](http://blog.csdn.net/francislaw/article/details/7740630)\n    - [中文api](http://blog.sina.com.cn/s/blog_9475b1c101012c5f.html)\n    - [农历日历](https://github.com/zzyss86/LunarCalendar)\n    - [超酷的仿百度带节日日历老黄历控件](http://www.sucaisj.com/jiaoben/date/201509/16856.html)\n    - [日期格式化](http://momentjs.com/)\n    - [大牛日历控件](https://github.com/Johnqing/QPAYCalendar/)\n    - [我群某管理作品](https://github.com/Iamlars/dateMarker)\n    - [input按位替换-官网](http://digitalbush.com/projects/masked-input-plugin/)\n    - [input按位替换-github](https://github.com/digitalBush/jquery.maskedinput/tree/1.2.2)\n    - [bootstrap-daterangepicker](https://github.com/dangrossman/bootstrap-daterangepicker)\n    - [国外30个插件集合](http://www.vandelaydesign.com/30-best-free-jquery-plugins/)\n    - [JavaScript datepicker](http://dbushell.com/2012/10/09/pikaday-javascript-datepicker/)\n    - [Datepair.js](http://jonthornton.github.io/Datepair.js/)\n    - [一个风格多样的日历](https://github.com/glad/glDatePicker)\n    - [弹出层式的全日历](http://amsul.ca/pickadate.js/date/)\n    - [jquery双日历](http://www.daterangepicker.com/)\n\n2. 移动\n\n    - [大气实用jQuery手机移动端日历日期选择插件](http://www.frankdemo.cn/index.php?c=content&a=show&id=115)\n    - [jQuery Mobile 移动开发中的日期插件Mobiscroll ](https://mobiscroll.com/)\n\n\n3. Date library\n\n    - [Datejs](https://github.com/datejs/Datejs)\n    - [sugarjs](http://sugarjs.com/api/Date)\n\n####10. 综合效果搜索平台\n\n- [效果网](http://www.jq22.com)\n- [17素材](http://www.17sucai.com/)\n- [常用的JavaScript代码片段](http://microjs.com/)\n\n####11. 前端工程化\n\n1. 概述\n\n    - [前端工具大全](http://www.awesomes.cn/)\n    - [什么是前端工程化](https://github.com/fouber/blog/issues/10?from=timeline&isappinstalled=0#)\n\n2. Gulp \n    \n    - [Gulp官网](http://gulpjs.com/)\n    - [Gulp中文网](http://www.gulpjs.com.cn/)\n    - [gulp资料收集](https://github.com/Platform-CUF/use-gulp)\n    - [Gulp：任务自动管理工具 - ruanyifeng](http://javascript.ruanyifeng.com/tool/gulp.html)\n    - [Gulp插件](http://gulpjs.com/plugins/)\n    - [Gulp不完全入门教程](http://www.ido321.com/1622.html)\n    - [为什么使用gulp?](https://github.com/hjzheng/CUF_meeting_knowledge_share/issues/33)\n    - [Gulp安装及配合组件构建前端开发一体化](http://www.dbpoo.com/getting-started-with-gulp/)\n    - [Gulp 入门指南](https://github.com/nimojs/gulp-book)\n    - [Gulp 入门指南 - nimojs](https://github.com/nimojs/blog/issues/19)\n    - [Gulp入门教程](http://markpop.github.io/2014/09/17/Gulp%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B/)\n    - [Gulp in Action](http://www.imooc.com/video/5692)\n    - [Gulp开发教程（翻译）](http://www.w3ctech.com/topic/134)\n    - [前端构建工具gulpjs的使用介绍及技巧](http://www.cnblogs.com/2050/p/4198792.html)\n\n3. Grunt\n\n    - [gruntjs](http://gruntjs.com/)\n    - [Grunt中文网](http://www.gruntjs.net/)\n\n4. Fis\n\n    - [fis 官网](http://fex-team.github.io/fis-site/index.html)\n    - [fis](http://fis.baidu.com/)\n\n####12. 轮播图\n\n1. pc图轮\n\n    - [单屏轮播sochange](http://www.jsfoot.com/jquery/demo/2011-09-20/192.html)\n    - [左右按钮多图切换](http://bxslider.com/examples/carousel-demystified)\n    - [fullpage全屏轮播](https://github.com/alvarotrigo/fullPage.js/)\n\n2. 移动端\n\n    - [无缝切换](http://www.swipejs.com/)\n    - [滑屏效果](http://www.idangero.us/swiper/)\n    - [全屏fullpage](https://github.com/peunzhang/fullpage)\n    - [单个图片切换](https://github.com/qiqiboy/touchslider)\n    - [单个全屏切换](https://github.com/peunzhang/slip.js)\n    - [百度的切换库](http://touch.code.baidu.com/examples.html?qq-pf-to=pcqq.group)\n    - [单个全屏切换](https://github.com/peunzhang/iSlider)\n    - [滑屏效果](https://github.com/saw/touch-interfaces)\n    - [旋转拖动设置](http://baijs.com/tinycircleslider/)\n    - [类似于swipe切换](http://touchslider.com/)\n    - [支持多种形式的触摸滑动](http://www.swiper.com.cn/demo/index.html)\n    - [滑屏效果](https://github.com/joker-ye/main/blob/master/wap/index.html)\n    - [大话主席pc移动图片轮换](http://www.superslide2.com/)\n    - [滑屏效果](https://github.com/hahnzhu/parallax.js)\n    - [基于zepto的fullpage](https://github.com/yanhaijing/zepto.fullpage)\n    - [[WebApp]定宽网页设计下，固定宽度布局开发WebApp并实现多终端下WebApp布局自适应](http://www.cnblogs.com/plums/archive/2013/01/10/WebApp-fixed-width-layout-of-multi-terminal-adapter-since.html)\n    - [判断微信客户端的那些坑](http://loo2k.com/blog/detecting-wechat-client/)\n    - [可以通过javascript直接调用原生分享的工具](https://github.com/JefferyWang/nativeShare.js)\n    - [JiaThis 分享到微信代码](http://www.jiathis.com/help/html/weixin-share-code)\n    - [聊聊移动端跨平台开发的各种技术](http://fex.baidu.com/blog/2015/05/cross-mobile/)\n    - [前端自动化测试](http://www.zhihu.com/question/29922082)\n    - [多种轮换图片](http://ajccom.github.io/niceslider/)\n    - [滑动侧边栏](https://mango.github.io/slideout/)\n\n####13. 文件上传\n\n- [百度上传组件](http://fex.baidu.com/webuploader/)\n- [上传](https://blueimp.github.io/jQuery-File-Upload/)\n- [flash 头像上传](http://www.hdfu.net/)\n- [图片上传预览](http://www.dropzonejs.com/)\n- [图片裁剪](http://elemefe.github.io/image-cropper/)\n- [图片裁剪-shearphoto](http://www.shearphoto.com/)\n- [jQuery图片处理](http://www.oschina.net/project/tag/284/jquery-image-tools?lang=0&os=0&sort=view&p=2)\n- []()\n\n####14. 模拟select\n\n- [糖饼 select](http://aui.github.io/popupjs/doc/selectbox.html)\n- [flexselect](https://github.com/rmm5t/jquery-flexselect)\n- [双select](http://loudev.com/)\n- [select2](http://select2.github.io/)\n- []()\n\n####15. 取色插件\n\n- [类似 Photoshop 的界面取色插件](http://www.jq22.com/plugin/367)\n- [jquery color](https://github.com/jquery/jquery-color/)\n- [取色插件集合](http://www.oschina.net/project/tag/287/color-picker)\n- [farbtastic 圆环＋正方形](https://github.com/mattfarina/farbtastic)\n- []()\n\n####16. 城市联动\n\n- [jquery.cityselect.js基于jQuery+JSON的省市或自定义联动效果](http://www.ijquery.cn/?p=360)\n- []()\n\n####17. 剪贴板\n\n- [剪贴板](https://github.com/zeroclipboard/zeroclipboard)\n- [clipboard 最新的剪切方案](http://zenorocha.github.io/clipboard.js/)\n- [不是Flash的剪贴板](https://github.com/zenorocha/clipboard.js)\n\n####18. 简繁转换\n\n- [简繁转换](https://github.com/BYVoid/OpenCC)\n\n####19. 表格 Grid\n\n- [facebook表格](http://facebook.github.io/fixed-data-table/)\n- [类似于Excel编辑表格-handsontable](http://handsontable.com/)\n- [bootstrap-table插件](http://bootstrap-table.wenzhixin.net.cn/)\n- [datatables](https://www.datatables.net/)\n\n####20. 在线演示\n\n- [js 在线编辑 - runjs](http://runjs.cn/)\n- [js 在线编辑 - jsbin](http://jsbin.com/)\n- [js 在线编辑 - codepen](http://codepen.io/)\n- [js 在线编辑 - jsfiddle](http://jsfiddle.net/)\n- [java 在线编辑 - runjs](http://ideone.com/)\n- [js 在线编辑 - hcharts](http://code.hcharts.cn/)\n- [js 在线编辑 - jsdm](http://jsdm.com/)\n- [sql 在线编辑 - sqlfiddle](http://sqlfiddle.com/)\n- [mozilla 在线编辑器](https://thimble.mozilla.org)\n\n####21. 播放器\n\n- [Html5 VideoPlayer](https://github.com/zmmbreeze/DeadSimpleVideoPlayer)\n\n####22. 粒子动画\n\n- [Proton 烟花](http://a-jie.github.io/Proton/#example)\n\n###九. Nodejs\n\n- [nodejs 篇幅比较巨大](http://liuqing.pw/)\n- [Node.js 包教不包会](https://github.com/alsotang/node-lessons)\n- [篇幅比较少](http://www.rainweb.cn/article/category/Nodejs)\n- [node express 入门教程](http://www.w3cfuns.com/article-5598538-1-1.html)\n- [nodejs定时任务](http://my.oschina.net/u/568264/blog/193773)\n- [一个nodejs博客](http://60sky.com/)\n- [【NodeJS 学习笔记04】新闻发布系统](http://www.cnblogs.com/yexiaochai/p/3536547.html)\n- [过年7天乐，学nodejs 也快乐](http://www.cnblogs.com/qqloving/p/3541099.html)\n- [七天学会NodeJS](https://github.com/nqdeng/7-days-nodejs)\n- [Nodejs学习笔记（二）--- 事件模块](http://www.cnblogs.com/zhongweiv/p/nodejs_events.html)\n- [nodejs入门](http://www.cnblogs.com/liusuqi/p/3735491.html)\n- [angularjs nodejs](https://github.com/zensh/jsgen)\n- [从零开始nodejs系列文章](http://blog.fens.me/series-nodejs/)\n- [理解nodejs](http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb)\n- [nodejs事件轮询](http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/)\n- [node入门](http://www.nodebeginner.org/index-zh-cn.html)\n- [nodejs cms](http://ourjs.com/detail/53e1f281c5910a9806000001)\n- [Node初学者入门，一本全面的NodeJS教程](http://ourjs.com/detail/529ca5950cb6498814000005)\n- [NodeJS的代码调试和性能调优](http://www.barretlee.com/blog/2015/10/07/debug-nodejs-in-command-line/)\n\n###十. 性能优化\n\n1. 常规优化\n\n    - [Javascript高性能动画与页面渲染](http://www.infoq.com/cn/articles/javascript-high-performance-animation-and-page-rendering)\n    - [移动H5前端性能优化指南](http://isux.tencent.com/h5-performance.html)\n    - [5173首页前端性能优化实践](http://ued.5173.com/?p=1731)\n    - [给网页设计师和前端开发者看的前端性能优化](http://www.uisdc.com/front-end-performance-for-web-designers-and-front-end-developers)\n    - [复杂应用的 CSS 性能分析和优化建议](http://www.orzpoint.com/profiling-css-and-optimization-notes/)\n    - [张鑫旭——前端性能](http://www.zhangxinxu.com/wordpress/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD/)\n    - [前端性能监控总结](http://www.xiaoqiang.org/javascript/font-end-performance-monitor.html)\n    - [网站性能优化之CSS无图片技术](http://udc.weibo.com/2013/05/%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8Bcss%E6%97%A0%E5%9B%BE%E7%89%87%E6%8A%80%E6%9C%AF/)\n    - [web前端性能优化进阶路](http://www.aliued.cn/2013/01/20/web%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E8%BF%9B%E9%98%B6%E8%B7%AF.html)\n    - [前端技术：网站性能优化之CSS无图片技术](http://my.eoe.cn/tuwandou/archive/4544.html)\n    - [浏览器的加载与页面性能优化](http://www.baiduux.com/blog/2011/02/15/browser-loading/)\n    - [页面加载中的图片性能优化](http://www.w3ctech.com/p/1503)\n    - [Hey——前端性能](http://www.feelcss.com/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD)\n    - [html优化](http://www.baiduux.com/blog/2010/03/15/html%E4%BC%98%E5%8C%96-2/)\n    - [99css——性能](http://www.99css.com/tag/%e6%80%a7%e8%83%bd)\n    - [Yslow——性能优化](http://www.yslow.net/category.php?cid=20)\n    - [YSLOW中文介绍](http://www.cnblogs.com/yslow/)\n    - [转一篇Yahoo关于网站性能优化的文章，兼谈本站要做的优化](http://www.360ito.com/article/40.html)\n    - [Yahoo!团队实践分享：网站性能](http://www.360doc.com/content/10/0928/09/2588264_56971287.shtml)\n    - [网站性能优化指南：什么使我们的网站变慢？](http://blog.jiasule.com/i/153)\n    - [网站性能优化实践，减少加载时间，提高用户体验](http://www.powereasy.net/helpyou/knowledge/ecommerce/9593.html)\n    - [浅谈网站性能优化 前端篇](http://www.umtry.com/archives/747.html)\n    - [前端重构实践之如何对网站性能优化？](http://www.adinnet.cn/blog/designview/2012-7-12/678.html)\n    - [前端性能优化：使用媒体查询加载指定大小的背景图片](http://www.gbin1.com/technology/javascript/20130708-front-end-performance-optimization-9/)\n    - [网站性能系列博文](http://www.mykuer.com/post/factors-that-affect-the-speed-of-web-site-open.html)\n    - [加载，不只是少一点点](http://tgideas.qq.com/webplat/info/news_version3/804/808/811/m579/201109/41355.shtml)\n    - [前端性能的测试与优化](http://mzhou.me/article/95310/)\n    - [分享网页加载速度优化的一些技巧？](http://www.gbin1.com/technology/html/20130217-tips-for-speed-up-page-loading/)\n    - [页面加载中的图片性能优化](http://www.f2es.com/images-bytes-opt/)\n    - [web前端优化(基于Yslow)](http://www.tcreator.info/webSchool/website/Front-end-Opt-Yslow.html)\n    - [网站性能优化工具大全](https://www.qianduan.net/website-performance-optimization-tool.html)\n    - [【高性能前端1】高性能HTML](http://www.alloyteam.com/2012/10/high-performance-html/)\n    - [【高性能前端2】高性能CSS](http://www.alloyteam.com/2012/10/high-performance-css/)\n    - [由12306谈谈网站前端性能和后端性能优化](http://coolshell.cn/articles/6470.html)\n    - [AlloyTeam——前端优化](http://www.alloyteam.com/webfrontend/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/)\n    - [毫秒必争，前端网页性能最佳实践](http://www.cnblogs.com/developersupport/p/3248695.html)\n    - [网站性能工具Yslow的使用方法](http://blog.sina.com.cn/s/blog_6e9d2e0701017kvu.html)\n    - [前端工程与性能优化（上）：静态资源版本更新与缓存](http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part1)\n    - [前端工程与性能优化（下）：静态资源管理与模板框架](http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part2)\n    - [HTTPS连接的前几毫秒发生了什么](http://blog.jobbole.com/48369/)\n    - [Yslow](http://uicss.cn/yslow/#more-12319)\n    - [Essential Web Performance Metrics — A Primer, Part 1](http://blog.smartbear.com/web-performance/essential-web-performance-metrics-a-primer-part-1/)\n    - [Essential Web Performance Metrics — Part 2](http://blog.smartbear.com/performance/essential-web-performance-metrics-part-2/)\n    - [YUISlide,针对移动设备的动画性能优化](http://jayli.github.io/blog/data/2011/12/23/yuislide.html)\n    - [Improving Site Performance](http://joelglovier.com/improving-site-performance/)\n    - [让网站提速的最佳前端实践](http://segmentfault.com/a/1190000000367899)\n    - [Why Website Speed is Important](http://sixrevisions.com/web-development/why-website-speed-is-important/)\n    - [Need for Speed – How to Improve your Website Performance](https://www.devbridge.com/articles/need-for-speed-how-to-improve-your-website-performance/)\n    - [阿里无线前端性能优化指南 (Pt.1 加载期优化) ](https://github.com/amfe/article/issues/1)\n    - []()\n\n2. 优化工具\n\n    - [JavaScript 性能分析新工具 OneProfile](http://www.html-js.com/article/3083)\n    - [JavaScript 堆内存分析新工具 OneHeap](http://www.html-js.com/article/3091)\n\n3. 在线工具\n\n    - [google在线工具](https://developers.google.com/speed/pagespeed/insights/)\n    - [阿里测](http://www.alibench.com/)\n    - [阿里-免费测试服务](http://itest.aliyun.com/)\n    - [阿里-F2etest多浏览器兼容性测试解决方案](https://github.com/alibaba/f2etest)\n    - [js性能测试](http://jsperf.com/)\n    - []()\n    \n###十一. 前端架构\n\n- [技术架构](http://www.zhihu.com/topic/19612641)\n- [前端架构](http://saito.im/note/The-Architecture-of-F2E/)\n- [如何成为前端架构师](http://www.zhihu.com/question/24092572)\n- [关于前端架构-张克军](http://hikejun.com/sharing/2010webrebuild/?file=fe-infrastructure.html)\n- [百度腾讯offer比较（腾讯游戏VS百度基础架构）](http://www.zhihu.com/question/25583350)\n- []()\n\n\n###十二. 个人作品\n\n####1. 推荐作品\n\n- [winter代码片段需要翻墙](https://gist.github.com/wintercn)\n- [fgm](http://www.fgm.cc/learn/)\n- [岑安作品集](https://github.com/hongru/hongru.github.com)\n- [当耐特demo集合](http://kmdjs.github.io/)\n- [米空格 js作品](http://www.laoshu133.com/Lab/)\n- [myFocus](http://koen301.github.io/)\n- [SeaJS组件库](http://panxuepeng.github.io/seajslib/)\n- [颜海镜作品](http://yanhaijing.com/myProject/)\n- [脚儿网作品](http://jo2.org/category/myworks/)\n- [javascript个人作品](http://www.cnitblog.com/yemoo/category/3107.html)\n- [妙味的雷东升游戏作品](http://bbs.miaov.com/forum.php?mod=viewthread&tid=7790)\n- [javascript作品集](http://bbs.csdn.net/topics/380227212)\n- [云五笔，灰度产生生成工具](https://github.com/TooBug/works)\n- [项目主页](http://koen301.github.io/)\n- [个性的作品主页](http://zaole.net/)\n- [播放器](http://static.tingall.com/v2/player/)\n- [ucren js demos 集](http://ucren.com/blog/demos)\n- [智能社](http://www.zhinengshe.com/works_list.html)\n- [实例陈列架](http://demos.shizuwu.cn/)\n- [zoye demo](http://zoye.sinaapp.com/demo)\n- [王员外](http://lab.yuanwai.wang/)\n- [平凡](http://pingfan1990.sinaapp.com)\n- [jyg 游戏案例](http://www.lovewebgames.com/)\n- [很多jquery插件](http://www.helloweba.com/list.html)\n- [不羁虫 - soJs 作品系列](http://www.bujichong.com/sojs/api/index.html)\n- [frozenui](http://frozenui.github.io/case.html)\n- [黑白棋](http://js-game.github.io/othello/)\n- [fromone](http://yansm.github.io/fromone/index.html)\n\n####2. 群员作品\n\n- [MDialog - [合肥-M.J]](http://demo.webjyh.com/)\n- [轮播图 - [上海－冷静]](http://sandbox.runjs.cn/show/do6zlrrk )\n- [[广州—坚壳]](http://www.replace5.com/)\n- [[成都 - 无痕]　感恩节专题](http://www.seejs.com/demos/)\n- [[球霸天]](http://hacke2.github.io/works)\n- [[北京-小数]](http://www.cnblogs.com/mcat/)\n- [[ptf] Magix 工具](http://thx.github.io/magix/)\n- [[杭州-Pft] Magix 基于 MVC 结构和 Hash 驱动的 OPOA（One Page One Application）应用](http://thx.github.io/magix/)\n- [[上海-剧中人]-实验室](http://bh-lay.com/labs/)\n- [[上海-豪情 ] 作品集合](http://jikeytang.github.io)\n- [[成都-feeling]](http://guoshan.sinaapp.com/)\n- [[上海-angela]](http://www.cnblogs.com/liyunhua/)\n- [[海南-hank]作品](http://hcjp.github.io/work/demo/)\n- [[上海-张力]博客](https://github.com/yibuyisheng/blogs/issues)\n- [[上海-zenki]作品](http://zkske121.github.io/)\n- [移动端图案解锁](http://01google.sinaapp.com/locker.html)\n- [[合肥-M.J] - MPreview 移动端图片预览组](https://github.com/webjyh/MPreview.mobile)\n- [[合肥-M.J] - Mexam 移动端在线做题组](https://github.com/webjyh/Mexam)\n- [[北京-苏瑞] - dancer小人](http://letyougo.github.io/dancer/)\n- [[上海-玄沐]- 个人网站](http://k.swao.cn/js/)\n- [[厦门-二哲]- 个人博客](http://www.meckodo.com/)\n\n####3. 国外大牛精品\n\n- [pazguille](http://pazguille.me/)\n\n###十三. 简历模板\n\n- [不错的个人简历](http://learnshare.github.io/about/index.html)\n- [简历](http://hcy2367.github.io/resume/)\n- [张伦](http://ncuey.sinaapp.com/CrispElite/ )\n- [简历](https://github.com/hacke2/ResumeSample)\n- [翁天信](http://blog.dandyweng.com/2013/07/how-my-website-was-created/)\n- [动画方式的简历](http://www.webhek.com/misc/interactive-resume/)\n- [组件丰富简历](http://www.linqing07.com/resume.html)\n- [简历池](http://www.mojianli.com/resume/view)\n- [haorooms博客](http://www.haorooms.com/about)\n- [Justin Young](http://cv.youngdze.com/)\n- []()\n\n###十四. 面试题\n\n- [那几个月在找工作（百度，网易游戏）](http://www.nowcoder.com/discuss/3196)\n- [2014最新面试题](http://www.html-js.com/article/1743)\n- [阿里前端面试题](http://www.w3cfuns.com/thread-5598563-2-1.html)\n- [2016校招内推 -- 阿里巴巴前端 -- 三面面试经历 ](http://www.cnblogs.com/imwtr/p/4685546.html)\n- [腾讯面试题](http://www.w3cfuns.com/article-5599657-1-1.html)\n- [年后跳槽那点事：乐视+金山+360面试之行](http://www.cnblogs.com/lvdabao/p/3660707.html)\n- [阿里前端面试题上线](http://fatesinger.com/2722.html)\n- [拉勾网js面试题](http://www.cnblogs.com/52cik/p/js-question-lg.html)\n- [前端面试](http://www.cnblogs.com/allenxing/p/3724382.html)\n- [Web开发笔试面试题 大全](http://mianshiti.diandian.com/)\n- [前端开发面试题](http://segmentfault.com/a/1190000000465431)\n- [2014最新前端面试题](https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions)\n- [百度面试](https://github.com/fex-team/interview-questions)\n- [面试题](http://www.w3cfuns.com/forum.php?mod=forumdisplay&fid=51&filter=typeid&typeid=177)\n- [前端工作面试问题](https://github.com/darcyclarke/Front-end-Developer-Interview-Questions/tree/master/Chinese)\n- [前端开发面试题](http://segmentfault.com/a/1190000000465431)\n- [5个经典的前端面试问题](http://ourjs.com/detail/5%E4%B8%AA%E7%BB%8F%E5%85%B8%E7%9A%84%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98)\n- [最全前端面试问题及答案总结 ](http://segmentfault.com/a/1190000002562454)\n- [如何面试一名前端开发工程师？](http://www.html-js.com/article/Large-search-front-team-column%202961)\n- [史上最全 前端开发面试问题及答案整理](https://github.com/hawx1993/Front-end-Interview-questions)\n- [前端实习生面试总结 ](http://www.cnblogs.com/xiaoruo/p/4665163.html)\n- [史上最全 前端开发面试问题及答案整理](https://github.com/hawx1993/Front-end-Interview-questions)\n- [BAT及各大互联网公司2014前端笔试面试题：JavaScript篇](http://blog.jobbole.com/78738/)\n- [前端开发面试题大收集](https://github.com/paddingme/Front-end-Web-Development-Interview-Question)\n- [收集的前端面试题和答案](https://github.com/qiu-deqing/FE-interview)\n- [如何面试前端工程师](http://www.zhihu.com/question/19568008)\n- [前端开发面试题](https://github.com/markyun/My-blog/blob/master/Front-end-Developer-Questions/Questions-and-Answers/README.md)\n- [牛客网-笔试面经](http://www.nowcoder.com/discuss?type=2)\n\n###十五. iconfont\n\n- [中文字体](http://www.zhihu.com/question/21253343)\n- [淘宝字库](http://iconfont.cn)\n- [字体](http://mux.alimama.com/fonts)\n- [制作教程](http://iconfont.cn/help/platform.html)\n- [zhangxinxu-icommon](http://www.zhangxinxu.com/wordpress/?s=icomoon)\n- [icommon](https://icomoon.io/app/)\n- [用字体在网页中画ICON图标(推荐教程)](http://imooc.com/learn/243)\n- [字体压缩工具](http://font-spider.org/) 感谢初级群　[深圳-小鱼] 的推荐\n\n###十六. 开发工具类\n\n1. 前端开发工具\n\n    - [IntelliJ IDEA 简体中文专题教程](https://github.com/judasn/IntelliJ-IDEA-Tutorial)\n    - [Webstorm,InterllIdea,Phpstorm](http://t.cn/8kZZ1Uy)\n    - [SublimeText](https://github.com/jikeytang/sublime-text)\n    - [Atom](https://atom.io/)\n    - [visual studio code](https://code.visualstudio.com/)\n\n2. Chrome, Firebug, Filddle 调试\n\n    1. Fiddler\n        - [Fiddler调式使用知多少(一)深入研究](http://www.cnblogs.com/tugenhua0707/p/4623317.html)\n        - [微信fiddle](http://www.cnblogs.com/strick/p/4570006.html)\n        - [微信fiddle](http://gaoboy.com/article/26.html)\n        - []()\n    \n    2. Chrome\n        - [Google Chrome 官方](https://developer.chrome.com/devtools)\n        - [Chrome - 基础](http://www.cnblogs.com/constantince/p/4565261.html)\n        - [Chrome - 进阶](http://www.cnblogs.com/constantince/p/4579121.html)\n        - [Chrome - 性能](http://www.cnblogs.com/constantince/p/4585983.html)\n        - [Chrome - 性能进阶](http://www.cnblogs.com/constantince/p/4607497.html)\n        - [Chrome - 移动](http://www.cnblogs.com/constantince/p/4624241.html)\n        - [Chrome - 使用技巧](http://www.cnblogs.com/liyunhua/p/4544738.html)\n        - [Chrome - Console控制台不完全指南](http://www.cnblogs.com/Wayou/p/chrome-console-tips-and-tricks.html)\n        - [Chrome - Workspace使浏览器变成IDE](http://c7sky.com/chrome-devtools-workspace.html)\n        - [network面板](http://www.html-js.com/article/Nothing-blind%202975)\n        - [chrome开发工具快捷键](http://anti-code.com/devtools-cheatsheet/)\n        - [chrome调试工具常用功能整理](http://www.html-js.com/article/2327)\n        - [Chrome 开发工具 Workspace 使用](http://www.iinterest.net/2014/05/09/chrome-dev-tool-workspace/)\n        - [Chrome神器Vimium快捷键学习记录 ](http://www.cppblog.com/deercoder/archive/2011/10/22/158886.html)\n        - [sass调试-w3cplus](http://www.w3cplus.com/sassguide/debug.html)\n        - [如何更专业的使用Chrome开发者工具-w3cplus](http://www.w3cplus.com/tools/how-to-use-chrome-devtools-like-a-pro.html)\n        - [chrome调试canvas](http://sentsin.com/web/253.html)\n        - [chrome profiles1](https://developer.chrome.com/devtools/index)\n        - [chrome profiles2](http://h5dev.uc.cn/article-25-1.html)\n        - [chrome profiles3](http://www.oschina.net/translate/performance-optimisation-with-timeline-profiles)\n        - [chrome移动版调试](https://developer.chrome.com/devtools/docs/mobile-emulation)\n        - [chrome调试](http://ued.taobao.org/blog/2012/06/debug-with-chrome-dev-tool/)\n        - [chrome的调试](http://www.cnblogs.com/QLeelulu/archive/2011/08/28/2156402.html)\n        - [chrome console 命令详解](https://developer.chrome.com/devtools/docs/commandline-api)\n        - [查看事件绑定1](http://www.cnblogs.com/leonkao/p/3809655.html)\n        - [查看事件绑定2](http://www.cnblogs.com/xiaoyao2011/p/3447421.html)\n        - [神器——Chrome开发者工具(一)](http://segmentfault.com/a/1190000000683599)\n        - [奇趣百科性能优化(Chrome DevTools 中的 Timeline Profils 等工具使用介绍)](https://xinranliu.me/2015-05-22-qiqu-performance/)\n        - [chrome 开发者工具的 15 个小技巧](http://frontenddev.org/link/15-tips-of-chrome-developer-tools.html)\n        - [Chrome开发者工具不完全指南](http://1ke.co/course/361)\n        - [Chrome 开发者工具使用技巧](http://segmentfault.com/a/1190000003882567)\n\n    3. Firebug\n        - [firebug视频教程](http://www.imooc.com/learn/137)\n        - [firefox 模拟器](https://developer.mozilla.org/zh-CN/docs/Tools/WebIDE)\n        - [console.log 命令详解](http://www.cnblogs.com/ctriphire/p/4116207.html)\n        - [Firebug入门指南](http://www.ruanyifeng.com/blog/2008/06/firebug_tutorial.html)\n        - [Firebug控制台详解](http://www.ruanyifeng.com/blog/2011/03/firebug_console_tutorial.html)\n        - []()\n    \n    4. 移动,微信调试\n        - [浏览器端调试安卓](https://openstf.github.io/)\n        - [移动端前端开发调试](http://yujiangshui.com/multidevice-frontend-debug/)\n        - [使用 Chrome 远程调试 Android 设备](https://github.com/yujiangshui/CN-Chrome-DevTools/blob/remote-debugging/md/Use-Tools/remote-debugging.md)\n        - [mac移动端调试](http://plus.uc.cn/document/webapp/doc5.html)\n        - [mac移动端调试](http://www.mihtool.com/)\n        - [无线调试攻略](http://thx.github.io/mobile/debugging-in-mobile/)\n        - [无线调试攻略](http://yanhaijing.com/mobile/2014/12/17/web-debug-for-mobile/)\n        - [屌爆了,完美调试 微信webview(x5)](http://www.jianshu.com/p/ccf124f1f74b)\n        - [微信调试的那些事](http://liyaodong.com/2015/07/06/%E5%BE%AE%E4%BF%A1%E8%B0%83%E8%AF%95%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B/)\n        - [远程console](http://jsconsole.com/)\n        - [微信调试工具](http://blog.qqbrowser.cc/)\n        - [各种真机远程调试方法汇总](https://github.com/jieyou/remote_inspect_web_on_real_device)\n    \n    5. iOS Simulator\n        - [Simulator](https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html)\n        - [Xcode中的iOS模拟器(iOS Simulator)的介绍和使用心得](http://www.crifan.com/intro_ios_simulator_in_xcode_and_usage_summary/)\n\n3. img\n\n    - [loading img](http://preloaders.net/en/circular)\n    - [智图-图片优化平台](http://zhitu.isux.us/)\n    - [在线png优化](https://tinypng.com/)\n\n4. 生成二维码\n\n    - [生成二维码](http://cli.im/)\n    \n5. 浏览器同步\n    - [puer](https://github.com/leeluolee/puer)\n    - [liveReload](http://livereload.com/)\n    - [f5](http://getf5.com/)\n    - [File Watchers](http://geek100.com/2608/)\n\n6. 在线PPT制作\n    - [nodePPT](http://js8.in/2013/11/16/%E6%8E%A8%E8%8D%90nodeppt%EF%BC%9A%E4%BD%BF%E7%94%A8markdown%E8%AF%AD%E6%B3%95%E6%9D%A5%E5%86%99%E7%BD%91%E9%A1%B5ppt/)\n    - [PPT](https://github.com/ksky521/nodePPT)\n    - [reveal](https://github.com/hakimel/reveal.js/)\n    - [slippy](https://github.com/Seldaek/slippy)\n\n###十七. 前端导航网站\n\n- [界面清爽的前端导航](http://uxbees.com/index.html)\n- [前端导航](http://whycss.com/)\n- [前端网址导航](http://www.daqianduan.com/nav)\n- [前端名录](http://sentsin.com/daohang/)\n- [前端导航](http://123.jser.us/)\n- [前端开发资源](http://www.css88.com/nav/)\n- [网址导航](http://www.haourl.cn/)\n- [前端开发仓库 - 众多效果的收集地](http://code.ciaoca.com/) \n- [前端资源导航](https://github.com/jnoodle/f2e-collect)\n- [F2E 前端导航](http://f2e.im/static/pages/nav/index.html)\n\n###十八. 常用CDN\n\n- [新浪CDN](http://lib.sinaapp.com/)\n- [百度静态资源公共库](http://cdn.code.baidu.com/)\n- [360网站卫士常用前端公共库CDN服务](http://libs.useso.com/)\n- [Bootstrap中文网开源项目免费 CDN 服务](http://www.bootcdn.cn/)\n- [开放静态文件 CDN - 七牛](http://staticfile.org/)\n- [CDN加速 - jq22](http://www.jq22.com/cdn/)\n- [jQuery CDN](http://code.jquery.com/)\n- [Google jQuery CDN](http://www.google-jquery-cdn.com/)\n- [微软CDN](http://www.asp.net/ajax/cdn)\n\n###十九. Git,SVN,Github\n\n1. Git\n\n    - [git-scm](http://git-scm.com/)\n    - [廖雪峰-Git教程](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)\n    - [git-for-windows](https://git-for-windows.github.io/)\n    - [GitHub 添加 SSH keys](http://daemon369.github.io/git/2015/03/10/add-ssh-keys-for-github/)\n    - [gogithub](http://www.worldhello.net/gotgithub/index.html)\n    - [git常规命令练习](http://pcottle.github.io/learnGitBranching/)\n    - [git的资料整理](https://github.com/xirong/my-git)\n    - [我所记录的git命令（非常实用）](http://www.cnblogs.com/fanfan259/p/4810517.html)\n    - [企业开发git工作流模式探索部分休整](https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md)\n    - [GitHub 漫游指南](https://github.com/phodal/github-roam)\n    - [GitHub秘籍](https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md)\n    - [使用git和github进行协同开发流程](http://livoras.com/post/28)\n    - [动画方式练习git](http://onlywei.github.io/explain-git-with-d3/)\n\n新增：https://github.com/AutumnsWind/Front-end-tutorial/blob/master/project.md\n\n内容是出自：\nhttps://github.com/jsfront/src/blob/master/qq.md\n\nhttps://github.com/jsfront/src/blob/master/qq.md\n\nhttps://github.com/jsfront/src/blob/master/qq.md\n\n综合类 | 地址\n--- | --- \n前端知识体系|http://www.cnblogs.com/sb19871023/p/3894452.html\n前端知识结构|https://github.com/JacksonTian/fks\nWeb前端开发大系概览|https://github.com/unruledboy/WebFrontEndStack\nWeb前端开发大系概览-中文版|http://www.cnblogs.com/unruledboy/p/WebFrontEndStack.html\nWeb Front-end Stack v2.2|https://raw.githubusercontent.com/unruledboy/WebFrontEndStack/master/Web%20Front%20End%20Stack.png\n免费的编程中文书籍索引|https://github.com/justjavac/free-programming-books-zh_CN\n前端书籍|https://github.com/dypsilon/frontend-dev-bookmarks\n前端免费书籍大全|https://github.com/vhf/free-programming-books\n前端知识体系|http://www.cnblogs.com/sb19871023/p/3894452.html\n免费的编程中文书籍索引|https://github.com/justjavac/free-programming-books-zh_CN\n智能社 - 精通JavaScript开发|http://study.163.com/course/introduction/224014.htm\n重新介绍 JavaScript（JS 教程）|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript\n麻省理工学院公开课：计算机科学及编程导论|http://v.163.com/special/opencourse/bianchengdaolun.html\nJavaScript中的this陷阱的最全收集--没有之一|http://segmentfault.com/a/1190000002640298\nJS函数式编程指南|https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch1.html\nJavaScript Promise迷你书（中文版）|http://liubin.github.io/promises-book\n腾讯移动Web前端知识库|https://github.com/AlloyTeam/Mars\nFront-End-Develop-Guide 前端开发指南|https://github.com/Front-End-Developers-Hunan/Front-End-Develop-Guide\n前端开发笔记本|https://li-xinyang.gitbooks.io/frontend-notebook/content\n大前端工具集 - 聂微东|https://github.com/nieweidong/fetool\n前端开发者手册|https://dwqs.gitbooks.io/frontenddevhandbook/content\n\n\n入门类 | 地址\n--- | --- \n前端入门教程|http://www.cnblogs.com/jikey/p/3613082.html\n瘳雪峰的Javascript教程|http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000\njQuery基础教程|http://www.imooc.com/view/11\n前端工程师必备的PS技能——切图篇|http://www.imooc.com/view/506\n结合个人经历总结的前端入门方法|https://github.com/qiu-deqing/FE-learning\n\n\n效果类 | 地址\n--- | --- \n弹出层|http://www.imooc.com/learn/58\n焦点图轮播特效|http://www.imooc.com/learn/18\n    \n\n工具类| 地址\n--- | --- \ncss sprite 雪碧图制作|http://www.imooc.com/learn/93\n版本控制入门 – 搬进 Github|http://www.imooc.com/learn/390\nGrunt-beginner前端自动化工具|http://www.imooc.com/learn/30\n\n\n慕课专题| 地址\n--- | --- \n张鑫旭 - 慕课系列|http://www.imooc.com/space/teacher/id/197450\nlyn - 慕课系列|http://www.imooc.com/space/teacher/id/104593\n艾伦 - 慕课系列|http://www.imooc.com/space/teacher/id/290139\n碧仔 - Hello，移动WEB|http://www.imooc.com/view/494\n\n\n周报类| 地址\n--- | --- \n平安科技移动开发二队技术周报|https://github.com/PaicHyperionDev/MobileDevWeekly\n\n###API:\n开发中心| 地址\n--- | --- \nmozilla js参考|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript\nchrome开发中心（chrome的内核已转向blink）|https://developer.chrome.com/extensions/api_index.html\nsafari开发中心|https://developer.apple.com/library/safari/navigation\nmicrosoft js参考|https://msdn.microsoft.com/zh-cn/library/d1et7k7c(v=vs.94.aspx\njs秘密花园|http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html\njs秘密花园|http://bonsaiden.github.io/JavaScript-Garden/zh\nw3help|http://www.w3help.org 综合Bug集合网站\n\n\n综合搜索| 地址\n--- | --- \njavascripting|http://www.javascripting.com\n各种流行库搜索|http://microjs.com\n\n\n综合API| 地址\n--- | ---    \nrunoob.com-包含各种API集合|http://www.runoob.com\n开源中国在线API文档合集|http://tool.oschina.net/apidocs\ndevdocs|http://devdocs.io 英文综合API网站\n\n\njQuery| 地址\n--- | ---    \njQuery API 中文文档|http://www.jquery123.com\nhemin 在线版|http://hemin.cn/jq\ncss88 jq api|http://www.css88.com/jqapi-1.9/on\ncss88 jqui api|http://www.css88.com/jquery-ui-api\n学习jquery|http://learn.jquery.com\njquery 源码查找|http://james.padolsey.com/jquery\n\n\nEcmascript| 地址\n--- | ---    \nUnderstanding ECMAScript 6 - Nicholas C. Zakas|https://leanpub.com/understandinges6/read\nexploring-es6|https://leanpub.com/exploring-es6/read\nexploring-es6翻译|https://github.com/es6-org/exploring-es6\nexploring-es6翻译后预览|http://es6-org.github.io/exploring-es6\n阮一峰 es6|http://es6.ruanyifeng.com\n阮一峰 Javascript|http://javascript.ruanyifeng.com\nECMA-262，第 5 版|http://yanhaijing.com/es5\nes5|http://es5.github.io\n\n\nJs template| 地址\n--- | ---    \ntemplate-chooser|http://garann.github.io/template-chooser\nartTemplate|https://github.com/aui/artTemplate\ntomdjs|https://github.com/aui/tmodjs/blob/master/README.md\n淘宝模板juicer模板|http://juicer.name/docs/docs_zh_cn.html\nFxtpl v1.0 繁星前端模板引擎|http://koen301.github.io/fxtpl\nlaytpl|http://laytpl.layui.com\nmozilla - nunjucks|https://github.com/mozilla/nunjucks\nJuicer|https://github.com/PaulGuo/Juicer\ndustjs|http://akdubya.github.io/dustjs\netpl|http://ecomfe.github.io/etpl\n\n\n弹出层| 地址\n--- | ---    \nartDialog 最新版|https://github.com/aui/artDialog\nartDialog 文档|http://aui.github.io/artDialog/doc/index.html\ngoogle code 下载地址|https://code.google.com/p/artdialog/downloads/list\n贤心弹出层|http://layer.layui.com\n响应式用户交互组件库|https://github.com/bh-lay/UI\nsweetalert-有css3动画弹出层|http://t4t5.github.io/sweetalert\n\n\nCSS| 地址\n--- | ---    \nCSS 语法参考|http://tympanus.net/codrops/css_reference\nCSS3动画手册|http://isux.tencent.com/css3/index.html\n腾讯css3动画制作工具|http://isux.tencent.com/css3/tools.html\n志爷css小工具集合|http://linxz.github.io/tianyizone\ncss3 js 移动大杂烩|http://www.note12.com/category/blog/2014-6-5/538fe0a9f786f1b7019a4dfb\nbouncejs 触摸库|http://bouncejs.com\ncss3 按钮动画|http://fian.my.id/Waves\nanimate.css|http://daneden.github.io/animate.css\n全局CSS的终结(狗带 [译]|http://www.alloyteam.com/2015/10/8536\n\n\nAngularjs| 地址\n--- | ---    \nAngular.js 的一些学习资源|https://github.com/dolymood/AngularLearning\nangularjs中文社区|http://angularjs.cn\nAngularjs源码学习|http://www.cnblogs.com/xuwenmin888/p/3739096.html\nAngularjs源码学习|http://www.ifeenan.com/?c=AngularJS\nangular对bootstrap的封装|http://angular-ui.github.io/bootstrap\nangularjs + nodejs|https://cnodejs.org/topic/51404e0f069911196d2e3923\n吕大豹 Angularjs|http://www.cnblogs.com/lvdabao/tag/AngularJs\nAngularJS 最佳实践|http://www.infoq.com/cn/news/2013/02/angular-web-app\nAngular的一些扩展指令|http://www.lovelucy.info/angularjs-best-practices.html\nAngular数据绑定原理|https://github.com/Pasvaz/bindonce\n一些扩展Angular UI组件|https://github.com/angular-ui\nEmber和AngularJS的性能测试|http://voidcanvas.com/emberjs-vs-angularjs-performance-testing\n带你走近AngularJS - 基本功能介绍|http://www.cnblogs.com/powertoolsteam/p/angularjs-introdection.html\nAngularjs开发指南|http://angular.duapp.com/docs/guide\nAngularjs学习|http://www.cnblogs.com/amosli/p/3710648.html\n不要带着jQuery的思维去学习AngularJS|http://www.rainweb.cn/article/angularjs-jquery.html\nangularjs 学习笔记|http://wangjiatao.diandian.com/?tag=angularjs\nangularjs 开发指南|http://www.angularjs.cn/T008\nangularjs 英文资料|https://github.com/jmcunningham/AngularJS-Learning\nangular bootstrap|http://angular-ui.github.io/bootstrap\nangular jq mobile|https://github.com/opitzconsulting/jquery-mobile-angular-adapter\nangular ui|http://mgcrea.github.io/angular-strap\n整合jQuery Mobile+AngularJS经验谈|http://www.tuicool.com/articles/7ZZVr2\n有jQuery背景，该如何用AngularJS编程思想|http://blog.jobbole.com/46589/ \nAngularJS在线教程|http://each.sinaapp.com/angular\nangular学习笔记|http://www.zouyesheng.com/angular.html\n\n\nReact| 地址\n--- | ---    \nreact.js 中文论坛|http://www.react-china.org\nreact.js 官方网址|https://facebook.github.io/react/index.html\nreact.js 官方文档|https://facebook.github.io/react/docs/getting-started.html\nreact.js material UI|http://material-ui.com/#\nreact.js TouchstoneJS UI|http://touchstonejs.io\nreact.js amazeui UI|http://amazeui.org/react\nReact 入门实例教程 - 阮一峰|http://www.ruanyifeng.com/blog/2015/03/react.html\nReact Native 中文版|http://wiki.jikexueyuan.com/project/react-native\nWebpack 和 React 小书 - 前端乱炖|http://www.html-js.com/article/Fakefish%203053\nWebpack 和 React 小书 - gitbook|https://fakefish.github.io/react-webpack-cookbook\nwebpack|https://github.com/webpack/webpack\nWebpack，101入门体验|http://html-js.com/article/3009\nwebpack入门教程|http://html-js.com/article/3113\n基于webpack搭建前端工程解决方案探索|http://segmentfault.com/a/1190000003499526\nReact原创实战视频教程|http://www.piliyu.com\n\n####移动端API\nAPI| 地址\n--- | --- \n99移动端知识集合|https://github.com/jtyjty99999/mobileTech\n移动端前端开发知识库|https://github.com/AlloyTeam/Mars\n移动前端的一些坑和解决方法（外观表现）|http://caibaojian.com/mobile-web-bug.html\n【原】移动web资源整理|http://www.cnblogs.com/PeunZhang/p/3407453.html\nzepto 1.0 中文手册|http://mweb.baidu.com/zeptoapi\nzepto 1.0 中文手册|http://www.html-5.cn/Manual/Zepto\nzepto 1.1.2|http://www.css88.com/doc/zeptojs_api\nzepto 中文注释|http://www.cnblogs.com/sky000/archive/2013/03/29/2988952.html\njqmobile 手册|http://app-framework-software.intel.com/api.php\n移动浏览器开发集合|https://github.com/maxzhang/maxzhang.github.com/issues\n移动开发大杂烩|https://github.com/hoosin/mobile-web-favorites\n微信webview中的一些问题|http://lin-chao.github.io/2014/11/14/%E5%BE%AE%E4%BF%A1webview%E4%B8%AD%E7%9A%84%E4%B8%80%E4%BA%9B%E9%97%AE%E9%A2%98\n2. 框架\n框架| 地址\n--- | --- \n特色的HTML框架可以创建精美的iOS应用|http://framework7.taobao.org\n淘宝SUI|http://m.sui.taobao.org\n\n####10. avalon\navalon| 地址\n--- | --- \navalonjs|http://avalonjs.github.io\nAvalon新一代UI库： OniUI|http://ued.qunar.com/oniui/index.html\navalon.oniui-基于avalon的组件库|https://github.com/RubyLouvre/avalon.oniui\n|\n\n####11. Requriejs\nRequriejs| 地址\n--- | --- \nJavascript模块化编程（一）：模块的写法 |http://www.ruanyifeng.com/blog/2012/10/javascript_module.html\nJavascript模块化编程（二）：AMD规范|http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html\nJavascript模块化编程（三）：require.js的用法|http://www.ruanyifeng.com/blog/2012/11/require_js.html\nRequireJS入门（一）|http://www.cnblogs.com/snandy/archive/2012/05/22/2513652.html\nRequireJS入门（二）|http://www.cnblogs.com/snandy/archive/2012/05/23/2513712.html\nRequireJS进阶（三）|http://www.cnblogs.com/snandy/archive/2012/06/08/2538001.html\nrequrie源码学习|http://www.cnblogs.com/yexiaochai/p/3632580.html \nrequrie 入门指南|http://www.oschina.net/translate/getting-started-with-the-requirejs-library \nrequrieJS 学习笔记|http://www.cnblogs.com/yexiaochai/p/3214926.html \nrequriejs 其一 |http://cyj.me/why-seajs/requirejs/ \nrequire backbone结合|http://www.cnblogs.com/yexiaochai/p/3221081.html \n\n####12. Seajs\nSeajs| 地址\n--- | --- \nseajs|http://seajs.org\nseajs 中文手册|http://cyj.me/why-seajs/zh\n\n####13. Less,sass\nLess,sass| 地址\n--- | --- \nsass|http://www.w3cplus.com/sassguide\nsass教程-sass中国|http://www.sass.hk\nSass 中文文档|http://sass.bootcss.com\nless|http://less.bootcss.com\n\n####14. Markdown\nMarkdown| 地址\n--- | --- \nMarkdown 语法说明 (简体中文版|http://wowubuntu.com/markdown\nmarkdown入门参考|https://github.com/LearnShare/Learning-Markdown/blob/master/README.md\ngitbook|https://www.gitbook.com 国外的在线markdown可编辑成书\nmdeditor|https://www.zybuluo.com/mdeditor  一款国内的在线markdown编辑器\nstackedit|https://stackedit.io 国外的在线markdown编辑器，功能强大，同步云盘\nmditor|http://bh-lay.github.io/mditor 一款轻量级的markdown编辑器\nlepture-editor|https://github.com/lepture/editor\nmarkdown-editor|https://github.com/jbt/markdown-editor\n\n####15. D3\nD3| 地址\n--- | --- \nd3 Tutorials|https://github.com/mbostock/d3/wiki/Tutorials\nGallery|https://github.com/mbostock/d3/wiki/Gallery\nlofter|http://datavisual.lofter.com/post/40cf3a_188e535\niteye|http://alanland.iteye.com/blog/1878595\nruanyifeng|http://javascript.ruanyifeng.com/library/d3.html\n\n####16. 兼容性\n兼容性| 地址\n--- | --- \nesma 兼容列表|http://kangax.github.io/compat-table/es6\nW3C CSS验证服务|http://jigsaw.w3.org/css-validator/validator.html.zh-cn\ncaniuse|http://caniuse.com/#index \ncsscreator|http://csscreator.com/properties\nmicrosoft|https://msdn.microsoft.com/zh-cn/library/cc351024(v=vs.85.aspx\n在线测兼容-移动端|http://www.responsinator.com\nemulators|https://www.manymo.com/emulators\n\n####17. UI相关\nUI相关| 地址\n--- | --- \nbootcss|http://v3.bootcss.com\nMetroUICSS|http://www.w3cplus.com/MetroUICSS\nsemantic|http://semantic-ui.com\nButtons|http://alexwolfe.github.io/Buttons\nkitecss|http://hiloki.github.io/kitecss\npintuer|http://www.pintuer.com\namazeui|http://amazeui.org\nworldhello|http://www.worldhello.net/gotgithub/index.html\nlinuxtoy|http://igit.linuxtoy.org/contents.html\ngitmagic|http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn\nrogerdudler|http://rogerdudler.github.io/git-guide/index.zh.html\ngitref|http://gitref.justjavac.com\nbook|http://git-scm.com/book/zh\ngogojimmy|http://gogojimmy.net/2012/01/17/how-to-use-git-1-git-basic\n\n####18. HTTP\nHTTP| 地址\n--- | --- \nHTTP API 设计指南|http://segmentfault.com/bookmark/1230000002521721\n\n####19. 其它API\n其它API| 地址\n--- | --- \njavascript流行库汇总|javascriptoo\n验证api|http://niceue.com/validator/demo/index.php\nunderscore 中文手册|http://www.css88.com/doc/underscore\nunderscore源码分析|http://www.html-js.com/article/Underscorejs-source-code-analysis-of-underscorejs-source-code-analysis%203031\nunderscore源码分析-亚里士朱德的博客|http://yalishizhude.github.io/tags/underscore\nunderscrejs en api|http://underscorejs.org\nlodash - underscore的代替品|https://lodash.com\next4api|http://extjs-doc-cn.github.io/ext4api\nbackbone 中文手册|http://www.csser.com/tools/backbone/backbone.js.html\nqwrap手册|http://dev.qwrap.com/resource/js/_docs/_youa/#/qw/base/loadJs_.htm\n缓动函数|http://easings.net/zh-cn\nsvg 中文参考|http://www.w3school.com.cn/svg/svg_reference.asp\nsvg mdn参考|https://developer.mozilla.org/en-US/docs/Web/SVG\nsvg 导出 canvas|https://github.com/gabelerner/canvg\nsvg 导出 png|https://github.com/exupero/saveSvgAsPng\nai-to-svg|http://www.zamzar.com/convert/ai-to-svg\nlocalStorage 库|https://github.com/machao/localStorage\n\n####20. 图表类\n图表类| 地址\n--- | --- \nHighcharts 中文API|http://www.hcharts.cn/api/index.php\nHighcharts 英文API|http://api.highcharts.com/highcharts\nECharts 百度的图表软件|http://echarts.baidu.com/ \n高德地图|http://lbs.amap.com/api\n开源的矢量图脚本框架|http://paperjs.org\nsvg 地图|http://jvectormap.com\n\n####21. vue\nvue| 地址\n--- | --- \nVue|http://cn.vuejs.org\nVue 论坛|http://forum.vuejs.org\nVue 入门指南|http://www.cnblogs.com/aaronjs/p/3660102.html\nVue 的一些资源索引|http://segmentfault.com/a/1190000000411057\nawesome-vue|https://github.com/vuejs/awesome-vue\n\n####21. 正则\n正则| 地址\n--- | --- \nJS正则表达式元字符|http://segmentfault.com/a/1190000002471140\n正则表达式30分钟入门教程|http://deerchao.net/tutorials/regex/regex.htm\nMDN-正则表达式|https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions\nruanyifeng - RegExp对象|http://javascript.ruanyifeng.com/stdlib/regexp.html\n小胡子哥 - 进阶正则表达式|http://div.io/topic/764?page=1\nis.js|https://github.com/Cedriking/is.js/blob/master/is.js\n正则在线测试|http://regexper.com\n|\n\n####22. ionic\nionic| 地址\n--- | --- \nionic|https://github.com/ychow/ionic-guide\n\n####23. 其它\n其它| 地址\n--- | --- \nMock.js 是一款模拟数据生成器|http://mockjs.com\n\n###开发规范\n1. 前端\n\n前端| 地址\n--- | --- \n通过分析github代码库总结出来的工程师代码书写习惯|http://alloyteam.github.io/CodeGuide\nHTML&CSS编码规范 by @mdo|http://codeguide.bootcss.com\n团队合作的css命名规范-腾讯AlloyTeam前端团队|http://www.alloyteam.com/2011/10/107\n前端编码规范之js - by yuwenhui|http://yuwenhui.github.io\n前端编码规范之js - by 李靖|http://www.cnblogs.com/hustskyking/p/javascript-spec.html\n前端开发规范手册|http://zhibimo.com/read/Ashu/front-end-style-guide\nAirbnb JavaScript 编码规范（简体中文版）|https://github.com/yuche/javascript#table-of-contents\nAMD与CMD规范的区别|http://www.zhihu.com/question/20351507\nAMD与CMD规范的区别|http://www.cnblogs.com/tugenhua0707/p/3507957.html\nKISSY 源码规范|http://docs.kissyui.com/1.4/docs/html/tutorials/style-guide/kissy-source-style.html\nbt编码规范|http://codeguide.bootcss.com\n规范加强版|https://github.com/Suxiaogang/Code_Guide\n前端代码规范 及 最佳实践|http://blog.jobbole.com/79075\n百度前端规范|http://coderlmn.github.io/code-standards\n百度前端规范|http://isobar-idev.github.io/code-standards\n百度前端规范|http://zhuanlan.zhihu.com/fuyun/19884834\nECMAScript6 编码规范--广发证券前端团队|https://github.com/gf-rd/es6-coding-style\nJavaScript 风格指南/编码规范（Airbnb公司版）|http://blog.jobbole.com/79484\n网易前端开发规范|http://nec.netease.com/standard\ncss模块|http://www.75team.com/archives/1049\n前端规范资源列表|https://github.com/ecomfe/spec\n\n2. PHP\n\nPHP| 地址\n--- | --- \n最流行的PHP 代码规范|http://segmentfault.com/a/1190000000443795\n最流行的PHP 代码规范|https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-2-coding-style-guide.md\n        \n3. Android\n\nAndroid| 地址\n--- | --- \n【敏捷开发】Android团队开发规范|http://www.cnblogs.com/lcw/p/3619181.html\nAndroid 开发规范与应用|http://www.jianshu.com/p/4390f4fe19b3\n\n###其它收集\n\n####1. 各大公司开源项目\n各大公司开源项目| 地址\n--- | --- \nFacebook Projects|https://code.facebook.com/projects/web\n百度web前端研发部|http://fex.baidu.com\n百度EFE|http://efe.baidu.com\n百度github|https://github.com/fex-team\nalloyteam|http://www.alloyteam.com\nalloyteam-github|http://alloyteam.github.io\nalloyteam-AlloyGameEngine|https://github.com/AlloyTeam/AlloyGameEngine\nAlloyDesigner|http://alloyteam.github.io/AlloyDesigner 即时修改，即时保存，设计稿较正，其它开发辅助工具\nH5交互页编辑器AEditor介绍|http://www.alloyteam.com/2015/06/h5-jiao-hu-ye-bian-ji-qi-aeditor-jie-shao H5动画交互页开发的工具介绍\nAEditor|http://aeditor.alloyteam.com H5动画交互页开发的工具\nmaka|http://forum.maka.im/wordpress\n值得订阅的weekly|https://github.com/fenbility/weekly-feed\n腾讯html5|http://cube.qq.com\n奇舞团开源项目|http://75team.github.io\nQunar UED|http://ued.qunar.com\nScrat|http://scrat.io\n\n####2. Javascript\n\n1. 常用\n\n常用 |地址\n--- | --- \nieBetter.js-让IE6-IE8拥有IE9+,Chrome等浏览器特性|http://www.zhangxinxu.com/wordpress/2013/12/iebetter-js-make-ie6-ie8-like-modern-browser-ie9-chrome\n模拟键盘|http://mottie.github.io/Keyboard\n拼音|https://github.com/hotoo/pinyin\n中国个人身份证号验证|https://github.com/mc-zone/IDValidator\n\n2. 算法\n\n算法 | 地址\n--- | --- \n数据结构与算法 JavaScript 描述. 章节练习|https://github.com/Ralph-Wang/algorithm.in.js\n常见排序算法（JS版）|https://github.com/twobin/twobinSort\n经典排序|https://github.com/luofei2011/jsAgm/blob/master/js/sort.js\n常见排序算法-js版本|https://github.com/hechangmin/jssort\nJavaScript 算法与数据结构 精华集|https://github.com/lightningtgc/JavaScript-Algorithms\n面试常考算法题精讲|http://www.nowcoder.com/live/courses\n\n3. 移动端\n\n移动端 | 地址\n--- | --- \nfastclick|https://github.com/ftlabs/fastclick\nno-click-delay|https://github.com/mmastrac/jquery-noclickdelay\n\n4. JSON\n\nJSON | 地址\n--- | --- \n模拟生成JSON数据|http://beta.json-generator.com\n返回跨域JSONAPI|http://jsonp.afeld.me\n\n####3. Html5\nHtml5 | 地址\n--- | --- \nHTML5 有哪些让你惊艳的 demo？|http://www.zhihu.com/question/24398907\n\n####4. CSS\nCSS | 地址\n--- | --- \nbrowserhacks|http://browserhacks.com\n\n####5. jQuery\n\n1. 焦点图\n\n焦点图 | 地址\n--- | --- \nmyfocus|https://github.com/koen301/myfocus\nmyfocus-官方演示站|http://www.chhua.com/myfocus\nSuperSlidev2.1 -- 大话主席|http://www.superslide2.com\nsoChange|http://www.bujichong.com/sojs/soChange/index.html\n\n####6. Ext, EasyUI, J-UI 及其它各种UI方案\n1. Ext\n\nExt, EasyUI, J-UI 及其它各种UI方案 | 地址\n--- | ---\nextjs|https://www.sencha.com/products/extjs\next4英文api|http://docs.sencha.com/extjs/4.0.7\next4中文api|http://extjs-doc-cn.github.io/ext4api\n\n2. EasyUI\n\nEasyUI | 地址\n--- | --- \njquery easyui 未压缩源代码|http://jquery-easyui.googlecode.com/svn/trunk/src\n\n3. J-UI\n\nJ-UI | 地址\n--- | --- \nJ-UI|http://jui.org\n   \n4. Other\n\nOther | 地址\n--- | --- \nMUI-最接近原生APP体验的高性能前端框架|http://dcloudio.github.io/mui\nAmaze UI | 中国首个开源 HTML5 跨屏前端框架|http://amazeui.org\n淘宝 HTML5 前端框架|http://m.sui.taobao.org\nKISSY - 阿里前端JavaScript库|http://docs.kissyui.com\n网易Nej - Nice Easy Javascript|http://nej.netease.com\nKendo UI MVVM Demo|http://demos.telerik.com/kendo-ui/mvvm/index\nBootstrap|http://www.bootcss.com\nSmart UI|http://smartui.chinamzz.com\n雅虎UI - CSS UI|http://developer.yahoo.com/yui/grids\n\n####7. 页面 社会化 分享功能\n页面 社会化 分享功能 | 地址\n--- | --- \n百度分享|http://share.baidu.com pc端\nJiaThis|http://jiathis.com pc端\n社会化分享组件|http://developer.baidu.com/soc/share 移动端\nShareSDK 轻松实现社会化功能|http://www.mob.com/#/index 移动端\n友盟分享|http://dev.umeng.com/social/android/quick-integration 移动端\n\n####8. 富文本编辑器\n富文本编辑器 | 地址\n--- | --- \n功能齐全 tinymce|https://www.tinymce.com\n百度 ueditor|http://ueditor.baidu.com/website\n经典的ckeditor|http://ckeditor.com\n经典的kindeditor|http://kindeditor.net\nwysiwyg|http://www.bootcss.com/p/bootstrap-wysiwyg\n一个有情怀的编辑器。Bach's Editor|http://integ.github.io/BachEditor\ntower用的编辑器|https://github.com/mycolorway/simditor\nsummernote 编辑器|https://github.com/summernote/summernote\nhtml5编辑器|http://neilj.github.io/Squire\nXEditor|http://lab.hustlzp.com/XEditor\nwangEditor|https://github.com/wangfupeng1988/wangEditor \n\n####9. 日历\n\n1. PC\n\nPC | 地址\n--- | --- \n经典my97|http://www.my97.net/dp/demo/index.htm\n强大的独立日期选择器|http://www.cnblogs.com/gbin1/archive/2012/04/16/2452105.html\nfullcalendar|http://fullcalendar.io\nfullcalendar日历控件知识点集合 |http://blog.csdn.net/francislaw/article/details/7740630\n中文api|http://blog.sina.com.cn/s/blog_9475b1c101012c5f.html\n农历日历|https://github.com/zzyss86/LunarCalendar\n超酷的仿百度带节日日历老黄历控件|http://www.sucaisj.com/jiaoben/date/201509/16856.html\n日期格式化|http://momentjs.com\n大牛日历控件|https://github.com/Johnqing/QPAYCalendar\n我群某管理作品|https://github.com/Iamlars/dateMarker\ninput按位替换-官网|http://digitalbush.com/projects/masked-input-plugin\ninput按位替换-github|https://github.com/digitalBush/jquery.maskedinput/tree/1.2.2\nbootstrap-daterangepicker|https://github.com/dangrossman/bootstrap-daterangepicker\n国外30个插件集合|http://www.vandelaydesign.com/30-best-free-jquery-plugins\nJavaScript datepicker|http://dbushell.com/2012/10/09/pikaday-javascript-datepicker\nDatepair.js|http://jonthornton.github.io/Datepair.js\n一个风格多样的日历|https://github.com/glad/glDatePicker\n弹出层式的全日历|http://amsul.ca/pickadate.js/date\njquery双日历|http://www.daterangepicker.com\n\n2. 移动\n\n移动 | 地址\n--- | --- \n大气实用jQuery手机移动端日历日期选择插件|http://www.frankdemo.cn/index.php?c=content&a=show&id=115\njQuery Mobile 移动开发中的日期插件Mobiscroll |https://mobiscroll.com\n\n\n3. Date library\n\nDate library | 地址\n--- | --- \nDatejs|https://github.com/datejs/Datejs\nsugarjs|http://sugarjs.com/api/Date\n\n####10. 综合效果搜索平台\n\n综合效果搜索平台 | 地址\n--- | --- \n效果网|http://www.jq22.com\n17素材|http://www.17sucai.com\n常用的JavaScript代码片段|http://microjs.com\n\n####11. 前端工程化\n\n1. 概述\n\n概述 | 地址\n--- | --- \n前端工具大全|http://www.awesomes.cn\n什么是前端工程化|https://github.com/fouber/blog/issues/10?from=timeline&isappinstalled=0#\n\n2. Gulp \n\nGulp  | 地址\n--- | ---  \nGulp官网|http://gulpjs.com\nGulp中文网|http://www.gulpjs.com.cn\ngulp资料收集|https://github.com/Platform-CUF/use-gulp\nGulp：任务自动管理工具 - ruanyifeng|http://javascript.ruanyifeng.com/tool/gulp.html\nGulp插件|http://gulpjs.com/plugins\nGulp不完全入门教程|http://www.ido321.com/1622.html\n为什么使用gulp?|https://github.com/hjzheng/CUF_meeting_knowledge_share/issues/33\nGulp安装及配合组件构建前端开发一体化|http://www.dbpoo.com/getting-started-with-gulp\nGulp 入门指南|https://github.com/nimojs/gulp-book\nGulp 入门指南 - nimojs|https://github.com/nimojs/blog/issues/19\nGulp入门教程|http://markpop.github.io/2014/09/17/Gulp%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B\nGulp in Action|http://www.imooc.com/video/5692\nGulp开发教程（翻译）|http://www.w3ctech.com/topic/134\n前端构建工具gulpjs的使用介绍及技巧|http://www.cnblogs.com/2050/p/4198792.html\n\n3. Grunt\n\nGrunt  | 地址\n--- | ---  \ngruntjs|http://gruntjs.com\nGrunt中文网|http://www.gruntjs.net\n\n4. Fis\n\nFis  | 地址\n--- | ---  \nfis 官网|http://fex-team.github.io/fis-site/index.html\nfis|http://fis.baidu.com\n\n####12. 轮播图\n\n1. pc图轮\n\npc图轮  | 地址\n--- | ---  \n单屏轮播sochange|http://www.jsfoot.com/jquery/demo/2011-09-20/192.html\n左右按钮多图切换|http://bxslider.com/examples/carousel-demystified\nfullpage全屏轮播|https://github.com/alvarotrigo/fullPage.js\n\n2. 移动端\n\n移动端  | 地址\n--- | ---  \n无缝切换|http://www.swipejs.com\n滑屏效果|http://www.idangero.us/swiper\n全屏fullpage|https://github.com/peunzhang/fullpage\n单个图片切换|https://github.com/qiqiboy/touchslider\n单个全屏切换|https://github.com/peunzhang/slip.js\n百度的切换库|http://touch.code.baidu.com/examples.html?qq-pf-to=pcqq.group\n单个全屏切换|https://github.com/peunzhang/iSlider\n滑屏效果|https://github.com/saw/touch-interfaces\n旋转拖动设置|http://baijs.com/tinycircleslider\n类似于swipe切换|http://touchslider.com\n支持多种形式的触摸滑动|http://www.swiper.com.cn/demo/index.html\n滑屏效果|https://github.com/joker-ye/main/blob/master/wap/index.html\n大话主席pc移动图片轮换|http://www.superslide2.com\n滑屏效果|https://github.com/hahnzhu/parallax.js\n基于zepto的fullpage|https://github.com/yanhaijing/zepto.fullpage\n[WebApp]定宽网页设计下，固定宽度布局开发WebApp并实现多终端下WebApp布局自适应|http://www.cnblogs.com/plums/archive/2013/01/10/WebApp-fixed-width-layout-of-multi-terminal-adapter-since.html\n判断微信客户端的那些坑|http://loo2k.com/blog/detecting-wechat-client\n可以通过javascript直接调用原生分享的工具|https://github.com/JefferyWang/nativeShare.js\nJiaThis 分享到微信代码|http://www.jiathis.com/help/html/weixin-share-code\n聊聊移动端跨平台开发的各种技术|http://fex.baidu.com/blog/2015/05/cross-mobile\n前端自动化测试|http://www.zhihu.com/question/29922082\n多种轮换图片|http://ajccom.github.io/niceslider\n滑动侧边栏|https://mango.github.io/slideout\n\n####13. 文件上传\n\n文件上传  | 地址\n--- | ---  \n百度上传组件|http://fex.baidu.com/webuploader\n上传|https://blueimp.github.io/jQuery-File-Upload\nflash 头像上传|http://www.hdfu.net\n图片上传预览|http://www.dropzonejs.com\n图片裁剪|http://elemefe.github.io/image-cropper\n图片裁剪-shearphoto|http://www.shearphoto.com\njQuery图片处理|http://www.oschina.net/project/tag/284/jquery-image-tools?lang=0&os=0&sort=view&p=2\n|\n\n####14. 模拟select\n\n模拟select  | 地址\n--- | ---  \n糖饼 select|http://aui.github.io/popupjs/doc/selectbox.html\nflexselect|https://github.com/rmm5t/jquery-flexselect\n双select|http://loudev.com\nselect2|http://select2.github.io\n|\n\n####15. 取色插件\n\n取色插件  | 地址\n--- | ---  \n类似 Photoshop 的界面取色插件|http://www.jq22.com/plugin/367\njquery color|https://github.com/jquery/jquery-color\n取色插件集合|http://www.oschina.net/project/tag/287/color-picker\nfarbtastic 圆环＋正方形|https://github.com/mattfarina/farbtastic\n|\n\n####16. 城市联动\n\n城市联动  | 地址\n--- | ---  \njquery.cityselect.js基于jQuery+JSON的省市或自定义联动效果|http://www.ijquery.cn/?p=360\n|\n\n####17. 剪贴板\n\n剪贴板  | 地址\n--- | ---  \n剪贴板|https://github.com/zeroclipboard/zeroclipboard\nclipboard 最新的剪切方案|http://zenorocha.github.io/clipboard.js\n不是Flash的剪贴板|https://github.com/zenorocha/clipboard.js\n\n####18. 简繁转换\n\n简繁转换  | 地址\n--- | ---  \n简繁转换|https://github.com/BYVoid/OpenCC\n\n####19. 表格 Grid\n\n表格 Grid  | 地址\n--- | ---  \nfacebook表格|http://facebook.github.io/fixed-data-table\n类似于Excel编辑表格-handsontable|http://handsontable.com\nbootstrap-table插件|http://bootstrap-table.wenzhixin.net.cn\ndatatables|https://www.datatables.net\n\n####20. 在线演示\n\n在线演示  | 地址\n--- | ---  \njs 在线编辑 - runjs|http://runjs.cn\njs 在线编辑 - jsbin|http://jsbin.com\njs 在线编辑 - codepen|http://codepen.io\njs 在线编辑 - jsfiddle|http://jsfiddle.net\njava 在线编辑 - runjs|http://ideone.com\njs 在线编辑 - hcharts|http://code.hcharts.cn\njs 在线编辑 - jsdm|http://jsdm.com\nsql 在线编辑 - sqlfiddle|http://sqlfiddle.com\nmozilla 在线编辑器|https://thimble.mozilla.org\n\n####21. 播放器\n\n播放器  | 地址\n--- | ---  \nHtml5 VideoPlayer|https://github.com/zmmbreeze/DeadSimpleVideoPlayer\n\n####22. 粒子动画\n\n粒子动画  | 地址\n--- | ---  \nProton 烟花|http://a-jie.github.io/Proton/#example\n\n###九. Nodejs\n\nNodejs  | 地址\n--- | ---  \nnodejs 篇幅比较巨大|http://liuqing.pw\nNode.js 包教不包会|https://github.com/alsotang/node-lessons\n篇幅比较少|http://www.rainweb.cn/article/category/Nodejs\nnode express 入门教程|http://www.w3cfuns.com/article-5598538-1-1.html\nnodejs定时任务|http://my.oschina.net/u/568264/blog/193773\n一个nodejs博客|http://60sky.com\n【NodeJS 学习笔记04】新闻发布系统|http://www.cnblogs.com/yexiaochai/p/3536547.html\n过年7天乐，学nodejs 也快乐|http://www.cnblogs.com/qqloving/p/3541099.html\n七天学会NodeJS|https://github.com/nqdeng/7-days-nodejs\nNodejs学习笔记（二）--- 事件模块|http://www.cnblogs.com/zhongweiv/p/nodejs_events.html\nnodejs入门|http://www.cnblogs.com/liusuqi/p/3735491.html\nangularjs nodejs|https://github.com/zensh/jsgen\n从零开始nodejs系列文章|http://blog.fens.me/series-nodejs\n理解nodejs|http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb\nnodejs事件轮询|http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop\nnode入门|http://www.nodebeginner.org/index-zh-cn.html\nnodejs cms|http://ourjs.com/detail/53e1f281c5910a9806000001\nNode初学者入门，一本全面的NodeJS教程|http://ourjs.com/detail/529ca5950cb6498814000005\nNodeJS的代码调试和性能调优|http://www.barretlee.com/blog/2015/10/07/debug-nodejs-in-command-line\n\n###十. 性能优化\n\n1. 常规优化\n\n常规优化|地址\n--- | ---\nJavascript高性能动画与页面渲染|http://www.infoq.com/cn/articles/javascript-high-performance-animation-and-page-rendering\n移动H5前端性能优化指南|http://isux.tencent.com/h5-performance.html\n5173首页前端性能优化实践|http://ued.5173.com/?p=1731\n给网页设计师和前端开发者看的前端性能优化|http://www.uisdc.com/front-end-performance-for-web-designers-and-front-end-developers\n复杂应用的 CSS 性能分析和优化建议|http://www.orzpoint.com/profiling-css-and-optimization-notes\n张鑫旭——前端性能|http://www.zhangxinxu.com/wordpress/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD\n前端性能监控总结|http://www.xiaoqiang.org/javascript/font-end-performance-monitor.html\n网站性能优化之CSS无图片技术|http://udc.weibo.com/2013/05/%E7%BD%91%E7%AB%99%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8Bcss%E6%97%A0%E5%9B%BE%E7%89%87%E6%8A%80%E6%9C%AF\nweb前端性能优化进阶路|http://www.aliued.cn/2013/01/20/web%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E8%BF%9B%E9%98%B6%E8%B7%AF.html\n前端技术：网站性能优化之CSS无图片技术|http://my.eoe.cn/tuwandou/archive/4544.html\n浏览器的加载与页面性能优化|http://www.baiduux.com/blog/2011/02/15/browser-loading\n页面加载中的图片性能优化|http://www.w3ctech.com/p/1503\nHey——前端性能|http://www.feelcss.com/tag/%E5%89%8D%E7%AB%AF%E6%80%A7%E8%83%BD\nhtml优化|http://www.baiduux.com/blog/2010/03/15/html%E4%BC%98%E5%8C%96-2\n99css——性能|http://www.99css.com/tag/%e6%80%a7%e8%83%bd\nYslow——性能优化|http://www.yslow.net/category.php?cid=20\nYSLOW中文介绍|http://www.cnblogs.com/yslow\n转一篇Yahoo关于网站性能优化的文章，兼谈本站要做的优化|http://www.360ito.com/article/40.html\nYahoo!团队实践分享：网站性能|http://www.360doc.com/content/10/0928/09/2588264_56971287.shtml\n网站性能优化指南：什么使我们的网站变慢？|http://blog.jiasule.com/i/153\n网站性能优化实践，减少加载时间，提高用户体验|http://www.powereasy.net/helpyou/knowledge/ecommerce/9593.html\n浅谈网站性能优化 前端篇|http://www.umtry.com/archives/747.html\n前端重构实践之如何对网站性能优化？|http://www.adinnet.cn/blog/designview/2012-7-12/678.html\n前端性能优化：使用媒体查询加载指定大小的背景图片|http://www.gbin1.com/technology/javascript/20130708-front-end-performance-optimization-9\n网站性能系列博文|http://www.mykuer.com/post/factors-that-affect-the-speed-of-web-site-open.html\n加载，不只是少一点点|http://tgideas.qq.com/webplat/info/news_version3/804/808/811/m579/201109/41355.shtml\n前端性能的测试与优化|http://mzhou.me/article/95310\n分享网页加载速度优化的一些技巧？|http://www.gbin1.com/technology/html/20130217-tips-for-speed-up-page-loading\n页面加载中的图片性能优化|http://www.f2es.com/images-bytes-opt\nweb前端优化(基于Yslow|http://www.tcreator.info/webSchool/website/Front-end-Opt-Yslow.html\n网站性能优化工具大全|https://www.qianduan.net/website-performance-optimization-tool.html\n【高性能前端1】高性能HTML|http://www.alloyteam.com/2012/10/high-performance-html\n【高性能前端2】高性能CSS|http://www.alloyteam.com/2012/10/high-performance-css\n由12306谈谈网站前端性能和后端性能优化|http://coolshell.cn/articles/6470.html\nAlloyTeam——前端优化|http://www.alloyteam.com/webfrontend/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96\n毫秒必争，前端网页性能最佳实践|http://www.cnblogs.com/developersupport/p/3248695.html\n网站性能工具Yslow的使用方法|http://blog.sina.com.cn/s/blog_6e9d2e0701017kvu.html\n前端工程与性能优化（上）：静态资源版本更新与缓存|http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part1\n前端工程与性能优化（下）：静态资源管理与模板框架|http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part2\nHTTPS连接的前几毫秒发生了什么|http://blog.jobbole.com/48369\nYslow|http://uicss.cn/yslow/#more-12319\nEssential Web Performance Metrics — A Primer, Part 1|http://blog.smartbear.com/web-performance/essential-web-performance-metrics-a-primer-part-1\nEssential Web Performance Metrics — Part 2|http://blog.smartbear.com/performance/essential-web-performance-metrics-part-2\nYUISlide,针对移动设备的动画性能优化|http://jayli.github.io/blog/data/2011/12/23/yuislide.html\nImproving Site Performance|http://joelglovier.com/improving-site-performance\n让网站提速的最佳前端实践|http://segmentfault.com/a/1190000000367899\nWhy Website Speed is Important|http://sixrevisions.com/web-development/why-website-speed-is-important\nNeed for Speed – How to Improve your Website Performance|https://www.devbridge.com/articles/need-for-speed-how-to-improve-your-website-performance\n阿里无线前端性能优化指南 (Pt.1 加载期优化 |https://github.com/amfe/article/issues/1\n|\n\n2. 优化工具\n\n优化工具|地址\n--- | ---\nJavaScript 性能分析新工具 OneProfile|http://www.html-js.com/article/3083\nJavaScript 堆内存分析新工具 OneHeap|http://www.html-js.com/article/3091\n\n3. 在线工具\n\n在线工具|地址\n--- | ---\ngoogle在线工具|https://developers.google.com/speed/pagespeed/insights\n阿里测|http://www.alibench.com\n阿里-免费测试服务|http://itest.aliyun.com\n阿里-F2etest多浏览器兼容性测试解决方案|https://github.com/alibaba/f2etest\njs性能测试|http://jsperf.com\n|\n    \n###十一. 前端架构\n\n前端架构|地址\n--- | ---\n技术架构|http://www.zhihu.com/topic/19612641\n前端架构|http://saito.im/note/The-Architecture-of-F2E\n如何成为前端架构师|http://www.zhihu.com/question/24092572\n关于前端架构-张克军|http://hikejun.com/sharing/2010webrebuild/?file=fe-infrastructure.html\n百度腾讯offer比较（腾讯游戏VS百度基础架构）|http://www.zhihu.com/question/25583350\n|\n\n\n###十二. 个人作品\n\n####1. 推荐作品\n\n推荐作品|地址\n--- | ---\nwinter代码片段需要翻墙|https://gist.github.com/wintercn\nfgm|http://www.fgm.cc/learn\n岑安作品集|https://github.com/hongru/hongru.github.com\n当耐特demo集合|http://kmdjs.github.io\n米空格 js作品|http://www.laoshu133.com/Lab\nmyFocus|http://koen301.github.io\nSeaJS组件库|http://panxuepeng.github.io/seajslib\n颜海镜作品|http://yanhaijing.com/myProject\n脚儿网作品|http://jo2.org/category/myworks\njavascript个人作品|http://www.cnitblog.com/yemoo/category/3107.html\n妙味的雷东升游戏作品|http://bbs.miaov.com/forum.php?mod=viewthread&tid=7790\njavascript作品集|http://bbs.csdn.net/topics/380227212\n云五笔，灰度产生生成工具|https://github.com/TooBug/works\n项目主页|http://koen301.github.io\n个性的作品主页|http://zaole.net\n播放器|http://static.tingall.com/v2/player\nucren js demos 集|http://ucren.com/blog/demos\n智能社|http://www.zhinengshe.com/works_list.html\n实例陈列架|http://demos.shizuwu.cn\nzoye demo|http://zoye.sinaapp.com/demo\n王员外|http://lab.yuanwai.wang\n平凡|http://pingfan1990.sinaapp.com\njyg 游戏案例|http://www.lovewebgames.com\n很多jquery插件|http://www.helloweba.com/list.html\n不羁虫 - soJs 作品系列|http://www.bujichong.com/sojs/api/index.html\nfrozenui|http://frozenui.github.io/case.html\n黑白棋|http://js-game.github.io/othello\nfromone|http://yansm.github.io/fromone/index.html\n\n####2. 群员作品\n\n群员作品|地址\n--- | ---\nMDialog 合肥-M.J]|http://demo.webjyh.com\n轮播图 上海－冷静]|http://sandbox.runjs.cn/show/do6zlrrk \n[广州—坚壳]|http://www.replace5.com\n[成都 - 无痕]　感恩节专题|http://www.seejs.com/demos\n[球霸天]|http://hacke2.github.io/works\n[北京-小数]|http://www.cnblogs.com/mcat\n[ptf] Magix 工具|http://thx.github.io/magix\n[杭州-Pft] Magix 基于 MVC 结构和 Hash 驱动的 OPOA（One Page One Application）应用|http://thx.github.io/magix\n[上海-剧中人]-实验室|http://bh-lay.com/labs\n[上海-豪情 ] 作品集合|http://jikeytang.github.io\n[成都-feeling]|http://guoshan.sinaapp.com\n[上海-angela]|http://www.cnblogs.com/liyunhua\n[海南-hank]作品|http://hcjp.github.io/work/demo\n[上海-张力]博客|https://github.com/yibuyisheng/blogs/issues\n[上海-zenki]作品|http://zkske121.github.io\n移动端图案解锁|http://01google.sinaapp.com/locker.html\n[合肥-M.J] - MPreview 移动端图片预览组|https://github.com/webjyh/MPreview.mobile\n[合肥-M.J] - Mexam 移动端在线做题组|https://github.com/webjyh/Mexam\n[北京-苏瑞] - dancer小人|http://letyougo.github.io/dancer\n[上海-玄沐]- 个人网站|http://k.swao.cn/js\n[厦门-二哲]- 个人博客|http://www.meckodo.com\n\n####3. 国外大牛精品\n\n国外大牛精品|地址\n--- | ---\npazguille|http://pazguille.me\n\n###十三. 简历模板\n\n简历模板|地址\n--- | ---\n不错的个人简历|http://learnshare.github.io/about/index.html\n简历|http://hcy2367.github.io/resume\n张伦|http://ncuey.sinaapp.com/CrispElite/ \n简历|https://github.com/hacke2/ResumeSample\n翁天信|http://blog.dandyweng.com/2013/07/how-my-website-was-created\n动画方式的简历|http://www.webhek.com/misc/interactive-resume\n组件丰富简历|http://www.linqing07.com/resume.html\n简历池|http://www.mojianli.com/resume/view\nhaorooms博客|http://www.haorooms.com/about\nJustin Young|http://cv.youngdze.com\n|\n\n###十四. 面试题\n\n面试题|地址\n--- | ---\n那几个月在找工作（百度，网易游戏）|http://www.nowcoder.com/discuss/3196\n2014最新面试题|http://www.html-js.com/article/1743\n阿里前端面试题|http://www.w3cfuns.com/thread-5598563-2-1.html\n2016校招内推 -- 阿里巴巴前端 -- 三面面试经历 |http://www.cnblogs.com/imwtr/p/4685546.html\n腾讯面试题|http://www.w3cfuns.com/article-5599657-1-1.html\n年后跳槽那点事：乐视+金山+360面试之行|http://www.cnblogs.com/lvdabao/p/3660707.html\n阿里前端面试题上线|http://fatesinger.com/2722.html\n拉勾网js面试题|http://www.cnblogs.com/52cik/p/js-question-lg.html\n前端面试|http://www.cnblogs.com/allenxing/p/3724382.html\nWeb开发笔试面试题 大全|http://mianshiti.diandian.com\n前端开发面试题|http://segmentfault.com/a/1190000000465431\n2014最新前端面试题|https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions\n百度面试|https://github.com/fex-team/interview-questions\n面试题|http://www.w3cfuns.com/forum.php?mod=forumdisplay&fid=51&filter=typeid&typeid=177\n前端工作面试问题|https://github.com/darcyclarke/Front-end-Developer-Interview-Questions/tree/master/Chinese\n前端开发面试题|http://segmentfault.com/a/1190000000465431\n5个经典的前端面试问题|http://ourjs.com/detail/5%E4%B8%AA%E7%BB%8F%E5%85%B8%E7%9A%84%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%97%AE%E9%A2%98\n最全前端面试问题及答案总结 |http://segmentfault.com/a/1190000002562454\n如何面试一名前端开发工程师？|http://www.html-js.com/article/Large-search-front-team-column%202961\n史上最全 前端开发面试问题及答案整理|https://github.com/hawx1993/Front-end-Interview-questions\n前端实习生面试总结 |http://www.cnblogs.com/xiaoruo/p/4665163.html\n史上最全 前端开发面试问题及答案整理|https://github.com/hawx1993/Front-end-Interview-questions\nBAT及各大互联网公司2014前端笔试面试题：JavaScript篇|http://blog.jobbole.com/78738\n前端开发面试题大收集|https://github.com/paddingme/Front-end-Web-Development-Interview-Question\n收集的前端面试题和答案|https://github.com/qiu-deqing/FE-interview\n如何面试前端工程师|http://www.zhihu.com/question/19568008\n前端开发面试题|https://github.com/markyun/My-blog/blob/master/Front-end-Developer-Questions/Questions-and-Answers/README.md\n牛客网-笔试面经|http://www.nowcoder.com/discuss?type=2\n\n###十五. iconfont\n\niconfont|地址\n--- | ---\n中文字体|http://www.zhihu.com/question/21253343\n淘宝字库|http://iconfont.cn\n字体|http://mux.alimama.com/fonts\n制作教程|http://iconfont.cn/help/platform.html\nzhangxinxu-icommon|http://www.zhangxinxu.com/wordpress/?s=icomoon\nicommon|https://icomoon.io/app\n用字体在网页中画ICON图标(推荐教程|http://imooc.com/learn/243\n字体压缩工具|http://font-spider.org 感谢初级群　[深圳-小鱼] 的推荐\n\n###十六. 开发工具类\n\n1. 前端开发工具\n\n前端开发工具|地址\n--- | ---\nIntelliJ IDEA 简体中文专题教程|https://github.com/judasn/IntelliJ-IDEA-Tutorial\nWebstorm,InterllIdea,Phpstorm|http://t.cn/8kZZ1Uy\nSublimeText|https://github.com/jikeytang/sublime-text\nAtom|https://atom.io\nvisual studio code|https://code.visualstudio.com\n\n2. Chrome, Firebug, Filddle 调试\n\n\n1. Fiddler\n\nFiddler|地址\n--- | ---\nFiddler调式使用知多少(一深入研究|http://www.cnblogs.com/tugenhua0707/p/4623317.html\n微信fiddle|http://www.cnblogs.com/strick/p/4570006.html\n微信fiddle|http://gaoboy.com/article/26.html\n\n    \n2. Chrome\n\nChrome|地址\n--- | ---\nGoogle Chrome 官方|https://developer.chrome.com/devtools\nChrome - 基础|http://www.cnblogs.com/constantince/p/4565261.html\nChrome - 进阶|http://www.cnblogs.com/constantince/p/4579121.html\nChrome - 性能|http://www.cnblogs.com/constantince/p/4585983.html\nChrome - 性能进阶|http://www.cnblogs.com/constantince/p/4607497.html\nChrome - 移动|http://www.cnblogs.com/constantince/p/4624241.html\nChrome - 使用技巧|http://www.cnblogs.com/liyunhua/p/4544738.html\nChrome - Console控制台不完全指南|http://www.cnblogs.com/Wayou/p/chrome-console-tips-and-tricks.html\nChrome - Workspace使浏览器变成IDE|http://c7sky.com/chrome-devtools-workspace.html\nnetwork面板|http://www.html-js.com/article/Nothing-blind%202975\nchrome开发工具快捷键|http://anti-code.com/devtools-cheatsheet\nchrome调试工具常用功能整理|http://www.html-js.com/article/2327\nChrome 开发工具 Workspace 使用|http://www.iinterest.net/2014/05/09/chrome-dev-tool-workspace\nChrome神器Vimium快捷键学习记录 |http://www.cppblog.com/deercoder/archive/2011/10/22/158886.html\nsass调试-w3cplus|http://www.w3cplus.com/sassguide/debug.html\n如何更专业的使用Chrome开发者工具-w3cplus|http://www.w3cplus.com/tools/how-to-use-chrome-devtools-like-a-pro.html\nchrome调试canvas|http://sentsin.com/web/253.html\nchrome profiles1|https://developer.chrome.com/devtools/index\nchrome profiles2|http://h5dev.uc.cn/article-25-1.html\nchrome profiles3|http://www.oschina.net/translate/performance-optimisation-with-timeline-profiles\nchrome移动版调试|https://developer.chrome.com/devtools/docs/mobile-emulation\nchrome调试|http://ued.taobao.org/blog/2012/06/debug-with-chrome-dev-tool\nchrome的调试|http://www.cnblogs.com/QLeelulu/archive/2011/08/28/2156402.html\nchrome console 命令详解|https://developer.chrome.com/devtools/docs/commandline-api\n查看事件绑定1|http://www.cnblogs.com/leonkao/p/3809655.html\n查看事件绑定2|http://www.cnblogs.com/xiaoyao2011/p/3447421.html\n神器——Chrome开发者工具(一|http://segmentfault.com/a/1190000000683599\n奇趣百科性能优化(Chrome DevTools 中的 Timeline Profils 等工具使用介绍|https://xinranliu.me/2015-05-22-qiqu-performance\nchrome 开发者工具的 15 个小技巧|http://frontenddev.org/link/15-tips-of-chrome-developer-tools.html\nChrome开发者工具不完全指南|http://1ke.co/course/361\nChrome 开发者工具使用技巧|http://segmentfault.com/a/1190000003882567\n\n3. Firebug\n\nFirebug|地址\n--- | ---\nfirebug视频教程|http://www.imooc.com/learn/137\nfirefox 模拟器|https://developer.mozilla.org/zh-CN/docs/Tools/WebIDE\nconsole.log 命令详解|http://www.cnblogs.com/ctriphire/p/4116207.html\nFirebug入门指南|http://www.ruanyifeng.com/blog/2008/06/firebug_tutorial.html\nFirebug控制台详解|http://www.ruanyifeng.com/blog/2011/03/firebug_console_tutorial.html\n\n    \n4. 移动,微信调试\n\n移动,微信调试|地址\n--- | ---\n浏览器端调试安卓|https://openstf.github.io\n移动端前端开发调试|http://yujiangshui.com/multidevice-frontend-debug\n使用 Chrome 远程调试 Android 设备|https://github.com/yujiangshui/CN-Chrome-DevTools/blob/remote-debugging/md/Use-Tools/remote-debugging.md\nmac移动端调试|http://plus.uc.cn/document/webapp/doc5.html\nmac移动端调试|http://www.mihtool.com\n无线调试攻略|http://thx.github.io/mobile/debugging-in-mobile\n无线调试攻略|http://yanhaijing.com/mobile/2014/12/17/web-debug-for-mobile\n屌爆了,完美调试 微信webview(x5|http://www.jianshu.com/p/ccf124f1f74b\n微信调试的那些事|http://liyaodong.com/2015/07/06/%E5%BE%AE%E4%BF%A1%E8%B0%83%E8%AF%95%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B\n远程console|http://jsconsole.com\n微信调试工具|http://blog.qqbrowser.cc\n各种真机远程调试方法汇总|https://github.com/jieyou/remote_inspect_web_on_real_device\n    \n5. iOS Simulator\n\niOS Simulator|地址\n--- | ---\nSimulator|https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/iOS_Simulator_Guide/Introduction/Introduction.html\nXcode中的iOS模拟器(iOS Simulator的介绍和使用心得|http://www.crifan.com/intro_ios_simulator_in_xcode_and_usage_summary\n\n3. img\n\nimg|地址\n--- | ---\nloading img|http://preloaders.net/en/circular\n智图-图片优化平台|http://zhitu.isux.us\n在线png优化|https://tinypng.com\n\n4. 生成二维码\n\n生成二维码|地址\n--- | ---\n生成二维码|http://cli.im\n    \n5. 浏览器同步\n\n浏览器同步|地址\n--- | ---\npuer|https://github.com/leeluolee/puer\nliveReload|http://livereload.com\nf5|http://getf5.com\nFile Watchers|http://geek100.com/2608\n\n6. 在线PPT制作\n\n在线PPT制作|地址\n--- | ---\nnodePPT|http://js8.in/2013/11/16/%E6%8E%A8%E8%8D%90nodeppt%EF%BC%9A%E4%BD%BF%E7%94%A8markdown%E8%AF%AD%E6%B3%95%E6%9D%A5%E5%86%99%E7%BD%91%E9%A1%B5ppt\nPPT|https://github.com/ksky521/nodePPT\nreveal|https://github.com/hakimel/reveal.js\nslippy|https://github.com/Seldaek/slippy\n\n###十七. 前端导航网站\n\n前端导航网站|地址\n--- | ---\n界面清爽的前端导航|http://uxbees.com/index.html\n前端导航|http://whycss.com\n前端网址导航|http://www.daqianduan.com/nav\n前端名录|http://sentsin.com/daohang\n前端导航|http://123.jser.us\n前端开发资源|http://www.css88.com/nav\n网址导航|http://www.haourl.cn\n前端开发仓库 - 众多效果的收集地|http://code.ciaoca.com \n前端资源导航|https://github.com/jnoodle/f2e-collect\nF2E 前端导航|http://f2e.im/static/pages/nav/index.html\n\n###十八. 常用CDN\n\n常用CDN|地址\n--- | ---\n新浪CDN|http://lib.sinaapp.com\n百度静态资源公共库|http://cdn.code.baidu.com\n360网站卫士常用前端公共库CDN服务|http://libs.useso.com\nBootstrap中文网开源项目免费 CDN 服务|http://www.bootcdn.cn\n开放静态文件 CDN - 七牛|http://staticfile.org\nCDN加速 - jq22|http://www.jq22.com/cdn\njQuery CDN|http://code.jquery.com\nGoogle jQuery CDN|http://www.google-jquery-cdn.com\n微软CDN|http://www.asp.net/ajax/cdn\n\n###十九. Git,SVN,Github\n\n1. Git\n\nGit|地址\n--- | ---\ngit-scm|http://git-scm.com\n廖雪峰-Git教程|http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000\ngit-for-windows|https://git-for-windows.github.io\nGitHub 添加 SSH keys|http://daemon369.github.io/git/2015/03/10/add-ssh-keys-for-github\ngogithub|http://www.worldhello.net/gotgithub/index.html\ngit常规命令练习|http://pcottle.github.io/learnGitBranching\ngit的资料整理|https://github.com/xirong/my-git\n我所记录的git命令（非常实用）|http://www.cnblogs.com/fanfan259/p/4810517.html\n企业开发git工作流模式探索部分休整|https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md\nGitHub 漫游指南|https://github.com/phodal/github-roam\nGitHub秘籍|https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md\n使用git和github进行协同开发流程|http://livoras.com/post/28\n动画方式练习git|http://onlywei.github.io/explain-git-with-d3\n\n"
  },
  {
    "path": "04-Front-end-tutorial-master/project.md",
    "content": "Github个人收集的优秀JavaScript项目\n- [Angular和Webpack种子文件](https://github.com/AngularClass/angular2-webpack-starter)\n- [Fis3面向前端的工程构建系统](https://github.com/fex-team/fis3)\n- [Fis3 DEMO](https://github.com/fex-team/fis3-demo)\n- [前端JQuery系列：入门教程 | 源码剖析 | 框架设计 | 慕课网教程](https://github.com/JsAaron/jQuery)\n- [avalon框架](https://github.com/RubyLouvre/avalon)\n- [Microsoft ChakraCore 微软的Chakra引擎](https://github.com/Microsoft/ChakraCore)\n- [Quintus HTML游戏引擎](https://github.com/cykod/Quintus)\n- [一个用node.js搭建的有趣博客](https://github.com/STRML/strml.net)\n- [Web前端助手--FeHelper（Chrome扩展）](https://github.com/zxlie/FeHelper)\n- [百度前端技术学院](https://github.com/baidu-ife/ife)\n- [Cheerio（node.js中的jQuery）](https://github.com/cheeriojs/cheerio)\n- [nodejs的一个聊天软件 类似微信](https://github.com/BryanYang/freechat)\n- [使用html5和node.js构建的网易云音乐](https://github.com/stkevintan/Cube)\n- [babel ES6转换为ES5](https://github.com/babel/babel)\n- [一个JS富文本编辑器](https://github.com/fex-team/ueditor)\n- [一个JS脑图可视化工具](https://github.com/fex-team/kityminder-core)\n- [一个JS写的Flappy Bird Game](https://github.com/ellisonleao/clumsy-bird)\n- [一个JS写的GBA模拟器](https://github.com/taisel/IodineGBA)\n- [SegmentFault写的Markdown解析器](https://github.com/SegmentFault/HyperDown.js)\n- [基于node.js的Ghost博客](https://github.com/TryGhost/Ghost)\n- [学习react的demos](https://github.com/ruanyf/react-demos)\n"
  },
  {
    "path": "05-fks-master/.gitignore",
    "content": "parallel.html\n*~\n"
  },
  {
    "path": "05-fks-master/Makefile",
    "content": "all:\n\tnode ./bin/generate.js\n"
  },
  {
    "path": "05-fks-master/README.en.md",
    "content": "Frontend Knowledge Structure\n========\n## Original purpose\nOnce upon a time, there's a graph of Frontend Knowledge Structure original posted by @jayli ...\n\n![Frontend Knowledge](https://raw.github.com/JacksonTian/fks/master/figures/fks.jpg)\n\nA shortcoming of releasing the graph in form of picture is, as the technology develops, we can't make any contribution to the graph without its source file -- That is why this GitHub repository comes. In this repository, every one could contribute to the project. The development of frontend profession will also be written to the history by Git.\n\nAlthough the project would be maintained in plain text instead, I promise a small tool based on project DataV would be developed for us to generate more funny graphs.\n\n## Knowledge Structure of Frontend Development\n- Frontend Engineer\n    - Web browsers\n        - IE6/[7](http://www.microsoft.com/en-us/download/internet-explorer-7-details.aspx)/[8](http://windows.microsoft.com/en-US/internet-explorer/downloads/ie-8)/[9](http://windows.microsoft.com/en-US/internet-explorer/downloads/ie-9/worldwide-languages)/[10](http://windows.microsoft.com/en-US/internet-explorer/ie-10-worldwide-languages)/[11](http://windows.microsoft.com/en-US/internet-explorer/ie-11-worldwide-languages) (Trident)\n        - [Firefox](http://www.mozilla.org/en-US/) (Gecko)\n        - [Chrome](http://www.google.com/chrome)/[Chromium](http://www.chromium.org/) (Blink)\n        - [Safari](http://www.apple.com/safari/) (WebKit)\n        - [Opera](http://www.opera.com/) (Blink)\n    - Programming Languages\n        - [JavaScript](https://developer.mozilla.org/en-US/docs/JavaScript)/[Node.js](http://nodejs.org/)\n        - [CoffeeScript](http://coffeescript.org/)\n        - [TypeScript](http://www.typescriptlang.org/)\n    - Slicing\n        - [HTML](http://www.w3.org/html/)/[HTML5](http://www.w3.org/TR/html5/)\n        - [CSS](http://www.w3.org/Style/CSS/)/CSS3\n        - [Sass](http://sass-lang.com/)/[LESS](http://lesscss.org/)/[Stylus](http://learnboost.github.io/stylus/)/[PostCSS](http://postcss.org/)\n        - [PhotoShop](http://www.photoshop.com/products/photoshop)/[Paint.net](http://www.getpaint.net/)/[Fireworks](http://www.adobe.com/cn/products/fireworks.html)/[GIMP](http://www.gimp.org/)/[Sketch](http://bohemiancoding.com/sketch/)\n    - Development tools\n        - Editors and IDEs\n            - [VIM](http://www.vim.org/)/[Sublime Text2](http://www.sublimetext.com/)\n            - [Notepad++](http://notepad-plus-plus.org/)/[EditPlus](http://www.editplus.com/)\n            - [WebStorm](http://www.jetbrains.com/webstorm/)\n            - [Emacs](http://www.gnu.org/software/emacs/)  [EmacsWiki](http://emacswiki.org)\n            - [Brackets](http://brackets.io)\n            - [Atom](https://atom.io/)\n            - [Lime Text](http://limetext.org/)\n            - [Light Table](http://lighttable.com/)\n            - [Codebox](https://www.codebox.io/)\n            - [TextMate](http://macromates.com/)\n            - [Neovim](http://neovim.org/)\n            - [Komodo IDE / Edit](http://www.activestate.com/komodo-edit)\n            - [Eclipse](http://www.eclipse.org/)\n            - [Visual Studio](http://www.visualstudio.com/)/[Visual Studio Code](https://code.visualstudio.com/)\n            - [NetBeans](https://netbeans.org/)\n            - [Cloud9 IDE](http://c9.io/)\n            - [HBuilder](http://www.dcloud.io/)\n            - [Nuclide](http://nuclide.io/)\n        - Debugging\n            - [Firebug](http://getfirebug.com/)/[Firecookie](https://addons.mozilla.org/en-US/firefox/addon/firecookie/)\n            - [YSlow](http://developer.yahoo.com/yslow/)\n            - [IEDeveloperToolbar](http://www.microsoft.com/en-us/download/details.aspx?id=18359)/[IETester](http://www.my-debugbar.com/wiki/IETester/HomePage)\n            - [Fiddler](http://www.telerik.com/fiddler)\n            - [Chrome Dev Tools](https://developer.chrome.com/devtools)\n            - [Dragonfly](http://www.opera.com/dragonfly/)\n            - [DebugBar](http://www.debugbar.com/)\n            - [Venkman](https://developer.mozilla.org/en-US/docs/Venkman)\n            - [Charles](https://www.charlesproxy.com/)\n        - Revision Control\n            - [Git](http://git-scm.com/)/[SVN](http://subversion.apache.org/)/[Mercurial](http://mercurial.selenic.com/)\n            - [Github](https://github.com/)/[GitLab](https://about.gitlab.com/)/[Bitbucket](https://bitbucket.org/)/[Google Code](http://code.google.com/hosting/)/[Gitorious](https://gitorious.org/)/[GNU Savannah](http://savannah.gnu.org/)/[Launchpad](https://launchpad.net/)/[SourceForge](http://sourceforge.net/)/[TeamForge](http://www.collab.net/products/teamforge)\n    - Code quality\n        - Coding style\n            - [JSLint](http://www.jslint.com/)/[JSHint](http://www.jshint.com/)/[jscs](https://github.com/mdevils/node-jscs)\n            - [CSSLint](http://csslint.net/)\n            - [Markup Validation Service](http://validator.w3.org/)\n            - [HTML Validators](https://validator.whatwg.org/)\n        - Unit testing\n            - [QUnit](http://qunitjs.com/)/[Jasmine](http://jasmine.github.io/)\n            - [Mocha](http://mochajs.org/)/[Should](https://github.com/visionmedia/should.js/)/[Chai](http://chaijs.com/)/[Expect](https://github.com/LearnBoost/expect.js/)\n            - [Unit JS](http://unitjs.com/)\n        - Auto-testing\n            - [WebDriver](http://docs.seleniumhq.org/docs/03_webdriver.jsp)/[Protractor](https://github.com/angular/protractor)/[Karma Runner](https://github.com/karma-runner/karma)/[Sahi](http://sahi.co.in/)\n            - [phantomjs](http://phantomjs.org/)\n            - [SourceLabs](https://saucelabs.com/)/[BrowserStack](http://www.browserstack.com/)\n    - Frontend libraries / frameworks\n        - [jQuery](http://jquery.com/)/[Underscore](http://underscorejs.org/)/[Mootools](http://mootools.net/)/[Prototype.js](http://www.prototypejs.org/)\n        - [YUI3](http://yuilibrary.com/projects/yui3/)/[Dojo](http://dojotoolkit.org/)/[ExtJS](http://www.sencha.com/products/extjs)/[KISSY](http://docs.kissyui.com/)\n        - [Backbone](http://backbonejs.org/)/[KnockoutJS](http://knockoutjs.com/)/[Emberjs](http://emberjs.com/)\n        - [AngularJS](http://angularjs.org/)\n            - [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk)\n        - [Bootstrap](http://getbootstrap.com/)\n        - [Semantic UI](http://www.semantic-ui.com/)\n        - [Juice UI](http://juiceui.com/)\n        - [Web Atoms](http://webatomsjs.neurospeech.com/)\n        - [Polymer](https://www.polymer-project.org/)\n        - [Dhtmlx](http://dhtmlx.com/)\n        - [qooxdoo](http://qooxdoo.org/)\n        - [React](http://facebook.github.io/react/)\n        - [Brick](http://mozbrick.github.io/)\n    - Frontend standards / specifications\n        - HTTP/1.1: RFCs 7230-7235\n        - [HTTP/2](https://http2.github.io/)\n        - [ECMAScript3/5](http://www.ecma-international.org/publications/standards/Ecma-262.htm)\n        - [W3C: DOM/BOM/XHTML/XML/JSON/JSONP/...](http://www.w3.org/TR/)\n        - [CommonJS Modules](http://wiki.commonjs.org/wiki/Modules/1.0)/[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)\n        - [HTML5](http://www.w3.org/html/wg/drafts/html/master/)/[CSS3](http://www.w3.org/Style/CSS/specs.en.html)\n        - [Semantic Web](http://semanticweb.org/)\n            - [MicroData](http://schema.org)\n            - [RDFa](http://www.w3.org/TR/rdfa-core/)\n        - [Web Accessibility](http://www.w3.org/WAI/)\n            - [WCAG](http://www.w3.org/TR/WAI-WEBCONTENT/)\n            - [Role Attribute](http://www.w3.org/TR/role-attribute/)\n            - [WAI-ARIA](http://www.w3.org/TR/wai-aria/)\n    - Performance\n        - [JSPerf](http://jsperf.com/)\n        - [YSlow 35 rules](http://developer.yahoo.com/performance/rules.html)\n        - [PageSpeed](https://developers.google.com/speed/pagespeed/)\n        - [HTTPWatch](http://www.httpwatch.com/)\n        - [DynaTrace's Ajax](http://www.compuware.com/application-performance-management/dynatrace-ajax-download.html)\n        - [High-performance JavaScript](http://book.douban.com/subject/5362856/)\n    - SEO\n    - General programming knowledge\n        - [Data structure](http://en.wikipedia.org/wiki/Data_structure)\n        - OOP/AOP\n        - [Prototype chain](http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/)/Scope chain\n        - [Closure](http://www.jibbering.com/faq/notes/closures/)\n        - [Programming paradigms](http://en.wikipedia.org/wiki/Programming_paradigm)\n        - [Design Patterns](http://addyosmani.com/resources/essentialjsdesignpatterns/book/)\n        - [Javascript Tips](http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html)\n    - Deployment flow\n        - Compressing and merging\n            - [YUI Compressor](http://developer.yahoo.com/yui/compressor/)\n            - [Google Clousure Complier](https://developers.google.com/closure/compiler/)\n            - [UglifyJS](https://github.com/mishoo/UglifyJS)\n            - [CleanCSS](https://github.com/GoalSmashers/clean-css)\n        - Documentation generating\n            - [JSDoc](http://code.google.com/p/jsdoc-toolkit/)\n            - [Dox](https://github.com/visionmedia/dox)/[Doxmate](https://github.com/JacksonTian/doxmate)/[Grunt-Doxmate](https://github.com/luozhihua/grunt-doxmate)\n        - Building\n            - [make](http://www.gnu.org/software/make/)/[Ant](http://ant.apache.org/)\n            - [GYP](http://code.google.com/p/gyp/)\n            - [Grunt](http://gruntjs.com/)\n            - [Gulp](http://gulpjs.com/)\n            - [Yeoman](http://yeoman.io/)\n            - [FIS](http://fis.baidu.com/)\n            - [Mod](https://github.com/modulejs/modjs)\n        - ES6+ transpiler\n            - [Traceur](https://github.com/google/traceur-compiler)\n            - [Babel](https://babeljs.io/)\n    - Code organizing\n        - Modularizing libraries\n            - [CommonJS](http://www.commonjs.org/)/AMD\n            - YUI3 Modules\n        - Modularizing business logic\n            - [bower](https://github.com/twitter/bower)/[component](https://github.com/component/component)\n        - File loaders\n            - [LABjs](http://labjs.com/)\n            - [SeaJS](http://seajs.org/)/[Require.js](http://requirejs.org/)\n        - Modular preprocessor\n            - [Browserify](https://github.com/substack/node-browserify)\n    - Security\n        - [CSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)/[XSS](http://en.wikipedia.org/wiki/Cross-site_scripting)\n        - [CSP](http://www.w3.org/TR/CSP/)\n        - [Same-origin policy](https://developer.mozilla.org/docs/Web/Security/Same-origin_policy)\n        - ADsafe/Caja/Sandbox\n    - Mobile Web\n        - HTML5/CSS3\n        - [Responsive web design](http://en.wikipedia.org/wiki/Responsive_web_design)\n        - [Zeptojs](http://zeptojs.com/)/[iScroll](http://cubiq.org/iscroll)\n        - V5/[Sencha Touch](http://www.sencha.com/products/touch)\n        - [PhoneGap](http://phonegap.com/)\n        - [jQuery Mobile](http://jquerymobile.com/)\n        - [W3C Mobile Web Initiative](http://www.w3.org/Mobile/)\n        - [W3C mobileOK Checker](http://validator.w3.org/mobile/)\n        - [Open Mobile Alliance](http://openmobilealliance.org/)\n        - [React Native](https://facebook.github.io/react-native/)\n    - Advanced technology communities/conferences\n        - [D2](http://d2forum.org)/[WebRebuild](http://www.webrebuild.org/)\n        - NodeParty/[W3CTech](http://w3ctech.com)/[HTML5梦工厂(HTML5 Dreamworks)](http://www.html5dw.com)\n        - [JSConf](http://jsconf.com/)/[沪JS(JSConf.cn)](http://jsconf.cn)\n        - QCon/Velocity/SDCC\n        - [JSConf](http://jsconf.com/)/[NodeConf](http://www.nodeconf.com/)\n        - [CSSConf](http://cssconf.com/)\n        - YDN/YUIConf\n        - HybridApp\n        - [WHATWG](http://whatwg.org/)\n        - [MDN](https://developer.mozilla.org/en-US/)\n        - [codepen](http://codepen.io/)\n        - [w3cplus](http://www.w3cplus.com/)\n        - [CNode](https://cnodejs.org/)\n    - Computer science\n        - Compilation principle\n        - [Computer network](http://en.wikipedia.org/wiki/Computer_network)\n        - [OS](http://en.wikipedia.org/wiki/Operating_system)\n        - Algorithm principle\n        - Software Engineering/Software testing principle\n        - [Unicode](http://www.unicode.org/)\n    - Soft skills\n        - Knowledge Management/Sharing\n        - Communication/Teamwork\n        - Requirements Management/PM\n        - Interaction Design/Availability/Accessibility\n    - Visualization\n        - SVG/Canvas/VML\n        - SVG: [D3](http://d3js.org/)/[Raphaël](http://raphaeljs.com/)/[Snap.svg](http://snapsvg.io/)/[DataV](http://datavlab.org/datavjs/)\n        - Canvas: [CreateJS](http://www.createjs.com/)/[KineticJS](http://kineticjs.com/)\n        - [WebGL](http://zh.wikipedia.org/wiki/WebGL)/[Three.JS](http://threejs.org/)\n- Backend Engineer\n    - Programming languages\n        - C/C++/Java/PHP/Ruby/Python/...\n    - Web server\n        - [Nginx](http://nginx.org/en/)\n        - [Apache](http://httpd.apache.org/)\n        - [Lighttpd](http://www.lighttpd.net/)\n    - Databases\n        - SQL\n        - [MySQL](http://www.mysql.com/)/[PostgreSQL](http://www.postgresql.org/)/[Oracle](http://www.oracle.com/us/products/database/overview/index.html)/[DB2](http://www-01.ibm.com/software/data/db2)\n        - [MongoDB](http://www.mongodb.org/)/[CouchDB](http://couchdb.apache.org/)\n    - Data Caching\n        - [Redis](http://redis.io/)\n        - [Memcached](http://memcached.org/)\n    - File Cashing/Proxying\n        - [Varnish](https://www.varnish-cache.org/)\n        - [Squid](http://www.squid-cache.org/)\n    - OS\n        - Unix/Linux/OS X/Windows\n    - Data structure\n\n## Book Recommendations for Frontend-ers\nThe ★ less and easier, the more suitable for starters\n\n### CSS\n- [More Eric Meyer on CSS](http://www.amazon.com/More-Eric-Meyer-Voices-Matter/dp/0735714258/)★★★\n- [CSS: The Definitive Guide (3rd Edition)](http://www.amazon.com/CSS-Definitive-Eric-A-Meyer/dp/0596527330/)★★\n- [CSS Mastery: Advanced Web Standards Solutions](http://www.amazon.com/CSS-Mastery-Advanced-Standards-Solutions/dp/1430223979/)★★★\n\n### JavaScript\n- [DOM Scripting: Web Design with JavaScript and the Document Object Model](http://www.amazon.com/DOM-Scripting-Design-JavaScript-Document/dp/1430233893/)★\n- [Professional JavaScript for Web Developsers (Third Edition)](http://www.amazon.com/Professional-JavaScript-Developers-Nicholas-Zakas/dp/1118026691/)★★\n- [锋利的jQuery](http://book.douban.com/subject/10792216/)★★\n- [High Performance JavaScript](ihttp://www.amazon.com/Performance-JavaScript-Faster-Application-Interfaces/dp/059680279X/)★★★\n- [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/)★★★\n- [JavaScript: The Definitive Guide (Sixth Edition)](http://www.amazon.com/JavaScript-Definitive-Guide-Activate-Guides/dp/0596805527/)★★★\n- [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680/)★★★\n- [JAVASCRIPT语言精髓与编程实践](http://book.douban.com/subject/3012828/)★★★\n- [Effective Javascript](http://www.amazon.com/Effective-JavaScript-Specific-Software-Development/dp/0321812182)★★★\n- [Secrets of the JavaScript Ninja](http://book.douban.com/subject/3176860/)★★★\n- [JavaScript Patterns](http://www.amazon.cn/JavaScript-Patterns-Stefanov-Stoyan/dp/0596806752)★★★\n- [JavaScript设计模式](http://book.douban.com/subject/3329540/)★★★★\n- [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X)★★★★\n\n### Performance && Practice\n- [Web性能实践日志](http://book.douban.com/subject/25891125/)★★★\n- [Web性能权威指南](http://book.douban.com/subject/25856314/)★★★\n\n### CVS\n- [Pragmatic Version Control Using Git](http://book.douban.com/subject/3105192/)★★\n- [Pro Git](http://git-scm.com/book)★★★\n- [Git权威指南](http://book.douban.com/subject/6526452/)★★★★\n\n## Book Recommendations for Backend-ers\n### Linux administration\n- [Linux 系统管理技术手册](http://book.douban.com/subject/3042029/)\n- [鸟哥的 Linux 私房菜](http://book.douban.com/subject/4889838/)\n- [Linux 101 Hacks](http://www.thegeekstuff.com/linux-101-hacks-free-ebook-non-english/)\n- [UNIX Shell Scripting](http://book.douban.com/subject/3519360/)\n- [The Linux Command Line](http://linuxcommand.org/tlcl.php)\n- [Linux Network Administrator's Guide](http://oreilly.com/openbook/linag2/book/index.html)\n\n### Linux programming\n- [Linux程序设计](http://book.douban.com/subject/4831448/)\n- [Linux系统编程](http://book.douban.com/subject/3907181/)\n- [Unix环境高级编程](http://book.douban.com/subject/1788421/)\n- [The Art of UNIX Programming](http://www.catb.org/esr/writings/taoup/)\n- [The Linux Programming Interface](http://book.douban.com/subject/4292217/)\n- [程序员的自我修养](http://book.douban.com/subject/3652388/)\n- [深入理解Linux内核](http://book.douban.com/subject/2287506/)\n- [Unix网络编程](http://book.douban.com/subject/1500149/)\n- [TCP/IP高级编程](http://book.douban.com/subject/1088054/)\n- [Linux Kernel in a Nutshell](http://www.kroah.com/lkn/)\n- [Linux Device Drivers](http://lwn.net/Kernel/LDD3/)\n- [Advanced Linux Programming](http://www.advancedlinuxprogramming.com/)\n\n### C/C++\n- [Linux C编程一站式学习](http://book.douban.com/subject/4141733/)\n- [C和指针](http://book.douban.com/subject/3012360/)\n- [C陷阱与缺陷](http://book.douban.com/subject/2778632/)\n- [C专家编程](http://book.douban.com/subject/2377310/)\n- [C语言核心技术](http://book.douban.com/subject/2226913/)\n- [彻底搞定C指针](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDEQFjAA&url=http%3A%2F%2Fblogimg.chinaunix.net%2Fblog%2Fupfile2%2F110210170023.pdf&ei=P95mUfrmNKKriALS04HAAw&usg=AFQjCNEzB88PnpfL0fRgJDkP3O9TlBPswA&sig2=isyd4ktsByNBMa5M9EPhRQ&bvm=bv.45107431,d.cGE&cad=rjt)\n- [征服C指针](http://book.douban.com/subject/21317828/)\n- [C++编程思想](http://book.douban.com/subject/1094797/)\n- [高质量程序设计指南---C/C++语言](http://book.douban.com/subject/2116929/)\n- [Inside the C++ Object Model](http://book.douban.com/subject/1484262/)\n- [A Tour of C++](http://www.stroustrup.com/Tour.html)\n- [The C++ Programming Language](http://en.wikipedia.org/wiki/The_C%2B%2B_Programming_Language)\n- [The C++ Standard Library - A Tutorial and Reference](http://www.cppstdlib.com/)\n- [The C++ Standard (INCITS/ISO/IEC 14882-2011)](http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+14882-2012)\n- [Overview of the New C++](http://www.artima.com/shop/overview_of_the_new_cpp)\n\n## Front-end Developer Interview\n- [Front-end Developer Interview Questions](https://github.com/darcyclarke/Front-end-Developer-Interview-Questions)\n- [Front end Developer Questions( Chinese (Simple) Language)](https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Question)\n\n## Contributors\nThanks to Jayli who provided the original graph and contributors below. Generated by `git-summary` at 2014/01/03.\n\n```\n\n project  : fks\n repo age : 1 year, 3 months\n active   : 53 days\n commits  : 108\n files    : 4\n authors  :\n    56  Jackson Tian            51.9%\n     9  吴晓兰               8.3%\n     5  liyinkan                4.6%\n     3  chriscai                2.8%\n     3  fengxiaolong            2.8%\n     3  XiNGRZ                  2.8%\n     2  monkadd                 1.9%\n     2  Johnny                  1.9%\n     2  weiwenqing              1.9%\n     2  Yinkan Li               1.9%\n     2  Copypeng                1.9%\n     2  左岸                  1.9%\n     2  Jakukyo Friel           1.9%\n     2  Glowin                  1.9%\n     1  李亚川               0.9%\n     1  Evan You                0.9%\n     1  Mickey                  0.9%\n     1  Mickey-                 0.9%\n     1  Qi Junyuan              0.9%\n     1  browsnet                0.9%\n     1  doabit                  0.9%\n     1  guoxiangyang            0.9%\n     1  linkgod                 0.9%\n     1  popomore                0.9%\n     1  vipzhicheng             0.9%\n     1  zhaqiang                0.9%\n     1  Colin Luo               0.9%\n\n```\n"
  },
  {
    "path": "05-fks-master/README.md",
    "content": "Frontend Knowledge Structure\n========\n## 项目起源\n还记得@jayli 的这幅前端知识结构图么。\n\n![前端知识结构](https://raw.github.com/JacksonTian/fks/master/figures/fks.jpg)\n\n图片的形式具有诸多的不便。缺失源图的我们，无法为此图贡献些什么，随着时间的迁移，或许有些技术点会发生改变，所以有了这个GitHub项目。我们可以通过协作的方式来共同维护这个项目。Git的历史记录也可以见证前端行业的一些变迁。\n\n[可视化效果](http://html5ify.com/fks/fks_chart/)\n\n## 前端开发知识结构\n- 前端工程师\n    - 浏览器\n        - IE6/[7](http://www.microsoft.com/en-us/download/internet-explorer-7-details.aspx)/[8](http://windows.microsoft.com/en-US/internet-explorer/downloads/ie-8)/[9](http://windows.microsoft.com/en-US/internet-explorer/downloads/ie-9/worldwide-languages)/[10](http://windows.microsoft.com/en-US/internet-explorer/ie-10-worldwide-languages)/[11](http://windows.microsoft.com/en-US/internet-explorer/ie-11-worldwide-languages) (Trident)\n        - [Firefox](http://www.mozilla.org/en-US/) (Gecko)\n        - [Chrome](http://www.google.com/chrome)/[Chromium](http://www.chromium.org/) (Blink)\n        - [Safari](http://www.apple.com/safari/) (WebKit)\n        - [Opera](http://www.opera.com/) (Blink)\n    - 编程语言\n        - [JavaScript](https://developer.mozilla.org/en-US/docs/JavaScript)/[Node.js](http://nodejs.org/)\n        - [CoffeeScript](http://coffeescript.org/)\n        - [TypeScript](http://www.typescriptlang.org/)\n    - 切页面\n        - [HTML](http://www.w3.org/html/)/[HTML5](http://www.w3.org/TR/html5/)\n        - [CSS/CSS3](http://www.w3.org/Style/CSS/)\n        - [Sass](http://sass-lang.com/)/[LESS](http://lesscss.org/)/[Stylus](http://learnboost.github.io/stylus/)/[postCSS](https://github.com/postcss/postcss)\n        - [PhotoShop](http://www.photoshop.com/products/photoshop)/[Paint.net](http://www.getpaint.net/)/[Fireworks](http://www.adobe.com/cn/products/fireworks.html)/[GIMP](http://www.gimp.org/)/[Sketch](http://bohemiancoding.com/sketch/)\n    - 开发工具\n        - 编辑器和IDE\n            - [VIM](http://www.vim.org/)/[Sublime Text2](http://www.sublimetext.com/)\n            - [Notepad++](http://notepad-plus-plus.org/)/[EditPlus](http://www.editplus.com/)\n            - [WebStorm](http://www.jetbrains.com/webstorm/)\n            - [Emacs](http://www.gnu.org/software/emacs/)  [EmacsWiki](http://emacswiki.org)\n            - [Brackets](http://brackets.io)\n            - [Atom](https://atom.io/)\n            - [Lime Text](http://limetext.org/)\n            - [Light Table](http://lighttable.com/)\n            - [Codebox](https://www.codebox.io/)\n            - [TextMate](http://macromates.com/)\n            - [Neovim](http://neovim.org/)\n            - [Komodo IDE / Edit](http://www.activestate.com/komodo-edit)\n            - [Eclipse](http://www.eclipse.org/)\n            - [Visual Studio](http://www.visualstudio.com/)/[Visual Studio Code](https://code.visualstudio.com/)\n            - [NetBeans](https://netbeans.org/)\n            - [Cloud9 IDE](http://c9.io/)\n            - [HBuilder](http://www.dcloud.io/)\n            - [Nuclide](http://nuclide.io/)\n            - [VS code](https://code.visualstudio.com/)\n        - 调试工具\n            - [Firebug](http://getfirebug.com/)/[Firecookie](https://addons.mozilla.org/en-US/firefox/addon/firecookie/)\n            - [YSlow](http://developer.yahoo.com/yslow/)\n            - [IEDeveloperToolbar](http://www.microsoft.com/en-us/download/details.aspx?id=18359)/[IETester](http://www.my-debugbar.com/wiki/IETester/HomePage)\n            - [Fiddler](http://www.telerik.com/fiddler)\n            - [Chrome Dev Tools](https://developer.chrome.com/devtools)\n            - [Dragonfly](http://www.opera.com/dragonfly/)\n            - [DebugBar](http://www.debugbar.com/)\n            - [Venkman](https://developer.mozilla.org/en-US/docs/Venkman)\n            - [Charles](https://www.charlesproxy.com/)\n        - 版本管理\n            - [Git](http://git-scm.com/)/[SVN](http://subversion.apache.org/)/[Mercurial](http://mercurial.selenic.com/)\n            - [Github](https://github.com/)/[GitLab](https://about.gitlab.com/)/[Bitbucket](https://bitbucket.org/)/[Gitorious](https://gitorious.org/)/[GNU Savannah](http://savannah.gnu.org/)/[Launchpad](https://launchpad.net/)/[SourceForge](http://sourceforge.net/)/[TeamForge](http://www.collab.net/products/teamforge)\n    - 代码质量\n        - Coding style\n            - [JSLint](http://www.jslint.com/)/[JSHint](http://www.jshint.com/)/[jscs](https://github.com/mdevils/node-jscs)/[ESLint](https://github.com/eslint/eslint)\n            - [CSSLint](http://csslint.net/)\n            - [Markup Validation Service](http://validator.w3.org/)\n            - [HTML Validators](https://validator.whatwg.org/)\n        - 单元测试\n            - [QUnit](http://qunitjs.com/)/[Jasmine](http://jasmine.github.io/)\n            - [Mocha](http://mochajs.org/)/[Should](https://github.com/visionmedia/should.js/)/[Chai](http://chaijs.com/)/[Expect](https://github.com/LearnBoost/expect.js/)\n            - [Unit JS](http://unitjs.com/)\n        - 自动化测试\n            - [WebDriver](http://docs.seleniumhq.org/docs/03_webdriver.jsp)/[Protractor](https://github.com/angular/protractor)/[Karma Runner](https://github.com/karma-runner/karma)/[Sahi](http://sahi.co.in/)\n            - [phantomjs](http://phantomjs.org/)\n            - [SourceLabs](https://saucelabs.com/)/[BrowserStack](http://www.browserstack.com/)\n    - 前端库/框架\n        - [jQuery](http://jquery.com/)/[Underscore](http://underscorejs.org/)/[Mootools](http://mootools.net/)/[Prototype.js](http://www.prototypejs.org/)\n        - [YUI3](http://yuilibrary.com/projects/yui3/)/[Dojo](http://dojotoolkit.org/)/[ExtJS](http://www.sencha.com/products/extjs)/[KISSY](http://docs.kissyui.com/)\n        - [Backbone](http://backbonejs.org/)/[KnockoutJS](http://knockoutjs.com/)/[Emberjs](http://emberjs.com/)\n        - [AngularJS](http://angularjs.org/)\n            - [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk)\n        - [Bootstrap](http://getbootstrap.com/)\n        - [Semantic UI](http://www.semantic-ui.com/)\n        - [Juice UI](http://juiceui.com/)\n        - [Web Atoms](http://webatomsjs.neurospeech.com/)\n        - [Polymer](http://docs.polymerchina.org/)\n        - [Dhtmlx](http://dhtmlx.com/)\n        - [qooxdoo](http://qooxdoo.org/)\n        - [React](http://facebook.github.io/react/)\n        - [Brick](http://mozbrick.github.io/)\n        - [vue.js](http://cn.vuejs.org/)\n    - 前端标准/规范\n        - HTTP/1.1: RFCs 7230-7235\n        - [HTTP/2](https://http2.github.io/)\n        - [ECMAScript3/5](http://www.ecma-international.org/publications/standards/Ecma-262.htm)\n        - [ECMAScript6](http://www.ecma-international.org/ecma-262/6.0/index.html)\n        - [W3C: DOM/BOM/XHTML/XML/JSON/JSONP/...](http://www.w3.org/TR/)\n        - [CommonJS Modules](http://wiki.commonjs.org/wiki/Modules/1.0)/[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)\n        - [HTML5](http://www.w3.org/html/wg/drafts/html/master/)/[CSS3](http://www.w3.org/Style/CSS/specs.en.html)\n        - [Semantic Web](http://semanticweb.org/)\n            - [MicroData](http://schema.org)\n            - [RDFa](http://www.w3.org/TR/rdfa-core/)\n        - [Web Accessibility](http://www.w3.org/WAI/)\n            - [WCAG](http://www.w3.org/TR/WAI-WEBCONTENT/)\n            - [Role Attribute](http://www.w3.org/TR/role-attribute/)\n            - [WAI-ARIA](http://www.w3.org/TR/wai-aria/)\n    - 性能\n        - [JSPerf](http://jsperf.com/)\n        - [YSlow 35 rules](http://developer.yahoo.com/performance/rules.html)\n        - [PageSpeed](https://developers.google.com/speed/pagespeed/)\n        - [HTTPWatch](http://www.httpwatch.com/)\n        - [DynaTrace's Ajax](http://www.compuware.com/application-performance-management/dynatrace-ajax-download.html)\n        - [高性能JavaScript](http://book.douban.com/subject/5362856/)\n    - SEO\n    - 编程知识储备\n        - [数据结构](http://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84)\n        - OOP/AOP\n        - [原型链](http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/)/作用域链\n        - [闭包](http://www.jibbering.com/faq/notes/closures/)\n        - [编程范型](http://zh.wikipedia.org/wiki/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%9E%8B)\n        - [设计模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/)\n        - [Javascript Tips](http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html)\n    - 部署流程\n        - 压缩合并\n            - [YUI Compressor](http://developer.yahoo.com/yui/compressor/)\n            - [Google Clousure Complier](https://developers.google.com/closure/compiler/)\n            - [UglifyJS](https://github.com/mishoo/UglifyJS)\n            - [CleanCSS](https://github.com/GoalSmashers/clean-css)\n        - 文档输出\n            - [JSDoc](https://github.com/jsdoc3/jsdoc)\n            - [Dox](https://github.com/visionmedia/dox)/[Doxmate](https://github.com/JacksonTian/doxmate)/[Grunt-Doxmate](https://github.com/luozhihua/grunt-doxmate)\n        - 项目构建工具\n            - [make](http://www.gnu.org/software/make/)/[Ant](http://ant.apache.org/)\n            - [GYP](http://code.google.com/p/gyp/)\n            - [Grunt](http://gruntjs.com/)\n            - [Gulp](http://gulpjs.com/)\n            - [Yeoman](http://yeoman.io/)\n            - [FIS](http://fis.baidu.com/)\n            - [Mod](https://github.com/modulejs/modjs)\n        - ES6＋ 转换器\n            - [Traceur](https://github.com/google/traceur-compiler)\n            - [Babel](https://babeljs.io/)\n    - 代码组织\n        - 类库模块化\n            - [CommonJS](http://www.commonjs.org/)/AMD\n            - [YUI3模块](http://yuilibrary.com/projects/yui3/)\n            - [webpack](http://webpack.github.io/)\n        - 业务逻辑模块化\n            - [bower](https://github.com/twitter/bower)/[component](https://github.com/component/component)\n        - 文件加载\n            - [LABjs](http://labjs.com/)\n            - [SeaJS](http://seajs.org/)/[Require.js](http://requirejs.org/)\n        - 模块化预处理器\n            - [Browserify](https://github.com/substack/node-browserify)\n    - 安全\n        - [CSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)/[XSS](http://en.wikipedia.org/wiki/Cross-site_scripting)\n        - [CSP](http://www.w3.org/TR/CSP/)\n        - [Same-origin policy](https://developer.mozilla.org/docs/Web/Security/Same-origin_policy)\n        - ADsafe/Caja/Sandbox\n    - 移动Web\n        - HTML5/CSS3\n        - [响应式网页设计](http://zh.wikipedia.org/wiki/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1)\n        - [Zeptojs](http://zeptojs.com/)/[iScroll](http://cubiq.org/iscroll)\n        - V5/[Sencha Touch](http://www.sencha.com/products/touch)\n        - [PhoneGap](http://phonegap.com/)\n        - [jQuery Mobile](http://jquerymobile.com/)\n        - [W3C Mobile Web Initiative](http://www.w3.org/Mobile/)\n        - [W3C mobileOK Checker](http://validator.w3.org/mobile/)\n        - [Open Mobile Alliance](http://openmobilealliance.org/)\n        - [React Native](https://facebook.github.io/react-native/)\n    - 前沿技术社区/会议\n        - [D2](http://d2forum.org)/[WebRebuild](http://www.webrebuild.org/)\n        - NodeParty/[W3CTech](http://w3ctech.com)/[HTML5梦工厂](http://www.html5dw.com)\n        - [JSConf](http://jsconf.com/)/[沪JS(JSConf.cn)](http://jsconf.cn)\n        - QCon/Velocity/SDCC\n        - [JSConf](http://jsconf.com/)/[NodeConf](http://www.nodeconf.com/)\n        - [CSSConf](http://cssconf.com/)\n        - YDN/YUIConf\n        - HybridApp\n        - [WHATWG](http://whatwg.org/)\n        - [MDN](https://developer.mozilla.org/zh-CN/)\n        - [codepen](http://codepen.io/)\n        - [w3cplus](http://www.w3cplus.com/)\n        - [CNode](https://cnodejs.org/)\n    - 计算机知识储备\n        - 编译原理\n        - [计算机网络](http://zh.wikipedia.org/wiki/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C)\n        - [操作系统](http://zh.wikipedia.org/wiki/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F)\n        - 算法原理\n        - 软件工程/软件测试原理\n        - [Unicode](http://www.unicode.org/)\n    - 软技能\n        - 知识管理/总结分享\n        - 沟通技巧/团队协作\n        - 需求管理/PM\n        - 交互设计/可用性/可访问性知识\n    - 可视化\n        - SVG/Canvas/VML\n        - SVG: [D3](http://d3js.org/)/[Raphaël](http://raphaeljs.com/)/[Snap.svg](http://snapsvg.io/)/[DataV](http://datavlab.org/datavjs/)\n        - Canvas: [CreateJS](http://www.createjs.com/)/[KineticJS](http://kineticjs.com/)\n        - [WebGL](http://en.wikipedia.org/wiki/WebGL)/[Three.JS](http://threejs.org/)\n\n- 后端工程师\n    - 编程语言\n        - C/C++/Java/PHP/Ruby/Python/...\n    - 网页服务器\n        - [Nginx](http://nginx.org/en/)\n        - [Apache](http://httpd.apache.org/)\n        - [Lighttpd](http://www.lighttpd.net/)\n    - 数据库\n        - SQL\n        - [MySQL](http://www.mysql.com/)/[PostgreSQL](http://www.postgresql.org/)/[Oracle](http://www.oracle.com/us/products/database/overview/index.html)/[DB2](http://www-01.ibm.com/software/data/db2)\n        - [MongoDB](http://www.mongodb.org/)/[CouchDB](http://couchdb.apache.org/)\n    - 数据缓存\n        - [Redis](http://redis.io/)\n        - [Memcached](http://memcached.org/)\n    - 文件缓存/代理\n        - [Varnish](https://www.varnish-cache.org/)\n        - [Squid](http://www.squid-cache.org/)\n    - 操作系统\n        - Unix/Linux/OS X/Windows\n    - 数据结构\n\n## 前端书籍推荐\n★越少越简单,越适合入门,★多的要么是难度比较高,要么是比较适合在后面看,比如讲性能之类的书.\n\n### CSS\n- [Eric Meyer 谈 CSS（卷二）](http://www.amazon.cn/Eric-Meyer-谈-CSS-迈耶/dp/B00170M84I/)★★★\n- [CSS权威指南 （第3版）](http://book.douban.com/subject/2308234/)★★\n- [精通CSS](http://book.douban.com/subject/4736167/)★★★\n- [HTML & CSS设计与构建网站](http://book.douban.com/subject/21338365/)★\n\n### JavaScript\n- [JavaScript & jQuery交互式Web前端开发](http://book.douban.com/subject/26433805/)★\n- [JavaScript DOM编程艺术 （第2版）](http://book.douban.com/subject/6038371/)★\n- [JavaScript高级程序设计（第3版）](http://book.douban.com/subject/10546125/)★★\n- [锋利的jQuery](http://book.douban.com/subject/10792216/)★★\n- [高性能JavaScript](http://book.douban.com/subject/5362856/)★★★\n- [JavaScript语言精粹](http://book.douban.com/subject/3590768/)★★★\n- [JavaScript权威指南](http://book.douban.com/subject/10549733/)★★★\n- [编写可维护的JavaScript](http://book.douban.com/subject/21792530/)★★★\n- [JAVASCRIPT语言精髓与编程实践](http://book.douban.com/subject/3012828/)★★★\n- [Effective Javascript](http://www.amazon.com/Effective-JavaScript-Specific-Software-Development/dp/0321812182)★★★\n- [Secrets of the JavaScript Ninja](http://book.douban.com/subject/3176860/)★★★\n- [JavaScript模式](http://book.douban.com/subject/11506062/)★★★\n- [JavaScript设计模式](http://book.douban.com/subject/3329540/)★★★★\n- [基于MVC的JavaScript Web富应用开发](http://book.douban.com/subject/10733304/)★★★\n\n### 性能实践\n- [高性能网站建设指南](https://book.douban.com/subject/3132277/)★\n- [高性能网站建设进阶指南](https://book.douban.com/subject/4719162/)★★\n- [Web性能实践日志](http://book.douban.com/subject/25891125/)★★★\n- [Web性能权威指南](http://book.douban.com/subject/25856314/)★★★\n\n### 版本控制工具\n- [版本控制之道 (git)](http://book.douban.com/subject/4813786/)★★\n- [Pro Git](http://iissnan.com/progit/)★★★\n- [Git权威指南](http://book.douban.com/subject/6526452/)★★★★\n\n## 后端书籍推荐\n### Linux管理\n- [Linux 系统管理技术手册](http://book.douban.com/subject/3042029/)\n- [鸟哥的 Linux 私房菜](http://book.douban.com/subject/4889838/)\n- [Linux 101 Hacks](http://www.thegeekstuff.com/linux-101-hacks-free-ebook-non-english/)\n- [UNIX Shell Scripting](http://book.douban.com/subject/3519360/)\n- [The Linux Command Line](http://book.douban.com/subject/6806862/)\n- [Linux Network Administrator's Guide](http://oreilly.com/openbook/linag2/book/index.html)\n\n### Linux编程\n- [Linux程序设计](http://book.douban.com/subject/4831448/)\n- [Linux系统编程](http://book.douban.com/subject/3907181/)\n- [Unix环境高级编程](http://book.douban.com/subject/1788421/)\n- [Unix编程艺术](http://book.douban.com/subject/1467587/)\n- [The Linux Programming Interface](http://book.douban.com/subject/4292217/)\n- [程序员的自我修养](http://book.douban.com/subject/3652388/)\n- [深入理解Linux内核](http://book.douban.com/subject/2287506/)\n- [Unix网络编程](http://book.douban.com/subject/1500149/)\n- [TCP/IP高级编程](http://book.douban.com/subject/1088054/)\n\n### C/C++\n- [Linux C编程一站式学习](http://book.douban.com/subject/4141733/)\n- [C和指针](http://book.douban.com/subject/3012360/)\n- [C陷阱与缺陷](http://book.douban.com/subject/2778632/)\n- [C专家编程](http://book.douban.com/subject/2377310/)\n- [C语言核心技术](http://book.douban.com/subject/2226913/)\n- [彻底搞定C指针](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDEQFjAA&url=http%3A%2F%2Fblogimg.chinaunix.net%2Fblog%2Fupfile2%2F110210170023.pdf&ei=P95mUfrmNKKriALS04HAAw&usg=AFQjCNEzB88PnpfL0fRgJDkP3O9TlBPswA&sig2=isyd4ktsByNBMa5M9EPhRQ&bvm=bv.45107431,d.cGE&cad=rjt)\n- [征服C指针](http://book.douban.com/subject/21317828/)\n- [C++编程思想](http://book.douban.com/subject/1094797/)\n- [高质量程序设计指南---C/C++语言](http://book.douban.com/subject/2116929/)\n- [Inside the C++ Object Model](http://book.douban.com/subject/1484262/)\n- [A Tour of C++](http://www.stroustrup.com/Tour.html)\n- [The C++ Programming Language](http://en.wikipedia.org/wiki/The_C%2B%2B_Programming_Language)\n- [The C++ Standard Library - A Tutorial and Reference](http://www.cppstdlib.com/)\n- [The C++ Standard (INCITS/ISO/IEC 14882-2011)](http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+14882-2012)\n- [Overview of the New C++](http://www.artima.com/shop/overview_of_the_new_cpp)\n\n## 前端工作面试\n- [前端工作面试问题](https://github.com/darcyclarke/Front-end-Developer-Interview-Questions)\n- [前端开发面试题（中文）](https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Question)\n\n## 内容贡献者\n除了感谢Jayli提供了知识结构图的原本来，还感谢以下的内容贡献者们，结果由`git-summary`生成于2014-01-03：\n\n```\n\n project  : fks\n repo age : 1 year, 3 months\n active   : 53 days\n commits  : 108\n files    : 4\n authors  :\n    56  Jackson Tian            51.9%\n     9  吴晓兰               8.3%\n     5  liyinkan                4.6%\n     3  chriscai                2.8%\n     3  fengxiaolong            2.8%\n     3  XiNGRZ                  2.8%\n     2  monkadd                 1.9%\n     2  Johnny                  1.9%\n     2  weiwenqing              1.9%\n     2  Yinkan Li               1.9%\n     2  Copypeng                1.9%\n     2  左岸                  1.9%\n     2  Jakukyo Friel           1.9%\n     2  Glowin                  1.9%\n     1  李亚川               0.9%\n     1  Evan You                0.9%\n     1  Mickey                  0.9%\n     1  Mickey-                 0.9%\n     1  Qi Junyuan              0.9%\n     1  browsnet                0.9%\n     1  doabit                  0.9%\n     1  guoxiangyang            0.9%\n     1  linkgod                 0.9%\n     1  popomore                0.9%\n     1  vipzhicheng             0.9%\n     1  zhaqiang                0.9%\n     1  Colin Luo               0.9%\n\n```\n"
  },
  {
    "path": "05-fks-master/bin/generate.js",
    "content": "var fs = require('fs');\nvar path = require('path');\n\nvar readme = fs.readFileSync(path.join(__dirname, '../README.md'), 'utf8');\n\nvar getItems = function (str) {\n  var patt = /([ ]*)-(.*)/g;\n  var result;\n\n  var list = [];\n  while ((result = patt.exec(str)) != null)  {\n    list.push({level: result[1].length / 4, content: result[2].trim()});\n  }\n  return list;\n};\n\nvar filter = function (list) {\n  var j = 0;\n  var f2e = [];\n  for (var i = 0; i < list.length; i++) {\n    var item = list[i];\n    if (item.level === 0) {\n      j = j + 1;\n      if (j === 2) {\n        break;\n      }\n    }\n\n    f2e.push(item);\n  }\n  return f2e;\n};\n\nvar format = function (list) {\n  var result = [];\n  for (var i = 0; i < list.length; i++) {\n    var item = list[i];\n    var data = {\n      id: '' + i,\n      name: item.content,\n      level: item.level\n    };\n    result.push(data);\n  }\n  return result;\n};\n\nvar items = getItems(readme);\nvar f2e = filter(items);\nvar formated = format(f2e);\n\nvar buildTree = function (list) {\n  var root = null;\n  for (var i = 0; i < list.length; i++) {\n    var item = list[i];\n    if (root === null) {\n      root = item;\n      root.children = [];\n    }\n\n    var lastLevel0 = root.children;\n    if (item.level === 1) {\n      delete item.level;\n      lastLevel0.push(item);\n    }\n\n    if (item.level === 2) {\n      var lastLevel1 = lastLevel0[lastLevel0.length - 1];\n      lastLevel1.children = lastLevel1.children || [];\n      lastLevel1.children.push(item);\n    }\n\n    if (item.level === 3) {\n      var lastLevel1Child = lastLevel0[lastLevel0.length - 1].children;\n      var lastLevel2 = lastLevel1Child[lastLevel1Child.length - 1];\n      lastLevel2.children = lastLevel2.children || [];\n      lastLevel2.children.push(item);\n    }\n    delete item.level;\n  }\n  return root;\n};\n\nvar tree = buildTree(formated);\nfs.writeFileSync(path.join(__dirname, '../fks_chart/data/front-end.json'), JSON.stringify(tree, null, '  '));\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower.json",
    "content": "{\n  \"name\": \"front-end-collect-\",\n  \"version\": \"0.0.0\",\n  \"authors\": [\n    \"hjzheng <zhenghaoju700@163.com>\"\n  ],\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"node_modules\",\n    \"bower_components\",\n    \"test\",\n    \"tests\"\n  ],\n  \"dependencies\": {\n    \"angular\": \"~1.2.19\",\n    \"d3\": \"~3.4.9\",\n    \"angular-marked\": \"~0.0.12\",\n    \"jquery\": \"~2.1.3\"\n  }\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular/.bower.json",
    "content": "{\n  \"name\": \"angular\",\n  \"version\": \"1.2.28\",\n  \"main\": \"./angular.js\",\n  \"ignore\": [],\n  \"dependencies\": {},\n  \"homepage\": \"https://github.com/angular/bower-angular\",\n  \"_release\": \"1.2.28\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v1.2.28\",\n    \"commit\": \"d1369fe05d3a7d85961a2223292b67ee82b9f80a\"\n  },\n  \"_source\": \"git://github.com/angular/bower-angular.git\",\n  \"_target\": \"~1.2.19\",\n  \"_originalSource\": \"angular\"\n}"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular/README.md",
    "content": "# packaged angular\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main AngularJS repo](https://github.com/angular/angular.js).\nPlease file issues and pull requests against that repo.\n\n## Install\n\nYou can install this package either with `npm` or with `bower`.\n\n### npm\n\n```shell\nnpm install angular\n```\n\nThen add a `<script>` to your `index.html`:\n\n```html\n<script src=\"/node_modules/angular/angular.js\"></script>\n```\n\nNote that this package is not in CommonJS format, so doing `require('angular')` will return `undefined`.\nIf you're using [Browserify](https://github.com/substack/node-browserify), you can use\n[exposify](https://github.com/thlorenz/exposify) to have `require('angular')` return the `angular`\nglobal.\n\n### bower\n\n```shell\nbower install angular\n```\n\nThen add a `<script>` to your `index.html`:\n\n```html\n<script src=\"/bower_components/angular/angular.js\"></script>\n```\n\n## Documentation\n\nDocumentation is available on the\n[AngularJS docs site](http://docs.angularjs.org/).\n\n## License\n\nThe MIT License\n\nCopyright (c) 2010-2012 Google, Inc. http://angularjs.org\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular/angular-csp.css",
    "content": "/* Include this file in your html if you are using the CSP mode. */\n\n@charset \"UTF-8\";\n\n[ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],\n.ng-cloak, .x-ng-cloak,\n.ng-hide {\n  display: none !important;\n}\n\nng\\:form {\n  display: block;\n}\n\n.ng-animate-block-transitions {\n  transition:0s all!important;\n  -webkit-transition:0s all!important;\n}\n\n/* show the element during a show/hide animation when the\n * animation is ongoing, but the .ng-hide class is active */\n.ng-hide-add-active, .ng-hide-remove {\n  display: block!important;\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular/angular.js",
    "content": "/**\n * @license AngularJS v1.2.28\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, document, undefined) {'use strict';\n\n/**\n * @description\n *\n * This object provides a utility for producing rich Error messages within\n * Angular. It can be called as follows:\n *\n * var exampleMinErr = minErr('example');\n * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);\n *\n * The above creates an instance of minErr in the example namespace. The\n * resulting error will have a namespaced error code of example.one.  The\n * resulting error will replace {0} with the value of foo, and {1} with the\n * value of bar. The object is not restricted in the number of arguments it can\n * take.\n *\n * If fewer arguments are specified than necessary for interpolation, the extra\n * interpolation markers will be preserved in the final string.\n *\n * Since data will be parsed statically during a build step, some restrictions\n * are applied with respect to how minErr instances are created and called.\n * Instances should have names of the form namespaceMinErr for a minErr created\n * using minErr('namespace') . Error codes, namespaces and template strings\n * should all be static strings, not variables or general expressions.\n *\n * @param {string} module The namespace to use for the new minErr instance.\n * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance\n */\n\nfunction minErr(module) {\n  return function () {\n    var code = arguments[0],\n      prefix = '[' + (module ? module + ':' : '') + code + '] ',\n      template = arguments[1],\n      templateArgs = arguments,\n      stringify = function (obj) {\n        if (typeof obj === 'function') {\n          return obj.toString().replace(/ \\{[\\s\\S]*$/, '');\n        } else if (typeof obj === 'undefined') {\n          return 'undefined';\n        } else if (typeof obj !== 'string') {\n          return JSON.stringify(obj);\n        }\n        return obj;\n      },\n      message, i;\n\n    message = prefix + template.replace(/\\{\\d+\\}/g, function (match) {\n      var index = +match.slice(1, -1), arg;\n\n      if (index + 2 < templateArgs.length) {\n        arg = templateArgs[index + 2];\n        if (typeof arg === 'function') {\n          return arg.toString().replace(/ ?\\{[\\s\\S]*$/, '');\n        } else if (typeof arg === 'undefined') {\n          return 'undefined';\n        } else if (typeof arg !== 'string') {\n          return toJson(arg);\n        }\n        return arg;\n      }\n      return match;\n    });\n\n    message = message + '\\nhttp://errors.angularjs.org/1.2.28/' +\n      (module ? module + '/' : '') + code;\n    for (i = 2; i < arguments.length; i++) {\n      message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +\n        encodeURIComponent(stringify(arguments[i]));\n    }\n\n    return new Error(message);\n  };\n}\n\n/* We need to tell jshint what variables are being exported */\n/* global angular: true,\n    msie: true,\n    jqLite: true,\n    jQuery: true,\n    slice: true,\n    push: true,\n    toString: true,\n    ngMinErr: true,\n    angularModule: true,\n    nodeName_: true,\n    uid: true,\n    VALIDITY_STATE_PROPERTY: true,\n\n    lowercase: true,\n    uppercase: true,\n    manualLowercase: true,\n    manualUppercase: true,\n    nodeName_: true,\n    isArrayLike: true,\n    forEach: true,\n    sortedKeys: true,\n    forEachSorted: true,\n    reverseParams: true,\n    nextUid: true,\n    setHashKey: true,\n    extend: true,\n    int: true,\n    inherit: true,\n    noop: true,\n    identity: true,\n    valueFn: true,\n    isUndefined: true,\n    isDefined: true,\n    isObject: true,\n    isString: true,\n    isNumber: true,\n    isDate: true,\n    isArray: true,\n    isFunction: true,\n    isRegExp: true,\n    isWindow: true,\n    isScope: true,\n    isFile: true,\n    isBlob: true,\n    isBoolean: true,\n    isPromiseLike: true,\n    trim: true,\n    isElement: true,\n    makeMap: true,\n    map: true,\n    size: true,\n    includes: true,\n    indexOf: true,\n    arrayRemove: true,\n    isLeafNode: true,\n    copy: true,\n    shallowCopy: true,\n    equals: true,\n    csp: true,\n    concat: true,\n    sliceArgs: true,\n    bind: true,\n    toJsonReplacer: true,\n    toJson: true,\n    fromJson: true,\n    toBoolean: true,\n    startingTag: true,\n    tryDecodeURIComponent: true,\n    parseKeyValue: true,\n    toKeyValue: true,\n    encodeUriSegment: true,\n    encodeUriQuery: true,\n    angularInit: true,\n    bootstrap: true,\n    snake_case: true,\n    bindJQuery: true,\n    assertArg: true,\n    assertArgFn: true,\n    assertNotHasOwnProperty: true,\n    getter: true,\n    getBlockElements: true,\n    hasOwnProperty: true,\n*/\n\n////////////////////////////////////\n\n/**\n * @ngdoc module\n * @name ng\n * @module ng\n * @description\n *\n * # ng (core module)\n * The ng module is loaded by default when an AngularJS application is started. The module itself\n * contains the essential components for an AngularJS application to function. The table below\n * lists a high level breakdown of each of the services/factories, filters, directives and testing\n * components available within this core module.\n *\n * <div doc-module-components=\"ng\"></div>\n */\n\n// The name of a form control's ValidityState property.\n// This is used so that it's possible for internal tests to create mock ValidityStates.\nvar VALIDITY_STATE_PROPERTY = 'validity';\n\n/**\n * @ngdoc function\n * @name angular.lowercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to lowercase.\n * @param {string} string String to be converted to lowercase.\n * @returns {string} Lowercased string.\n */\nvar lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * @ngdoc function\n * @name angular.uppercase\n * @module ng\n * @kind function\n *\n * @description Converts the specified string to uppercase.\n * @param {string} string String to be converted to uppercase.\n * @returns {string} Uppercased string.\n */\nvar uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};\n\n\nvar manualLowercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})\n      : s;\n};\nvar manualUppercase = function(s) {\n  /* jshint bitwise: false */\n  return isString(s)\n      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})\n      : s;\n};\n\n\n// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish\n// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods\n// with correct but slower alternatives.\nif ('i' !== 'I'.toLowerCase()) {\n  lowercase = manualLowercase;\n  uppercase = manualUppercase;\n}\n\n\nvar\n    msie,             // holds major version number for IE, or NaN if UA is not IE.\n    jqLite,           // delay binding since jQuery could be loaded after us.\n    jQuery,           // delay binding\n    slice             = [].slice,\n    push              = [].push,\n    toString          = Object.prototype.toString,\n    ngMinErr          = minErr('ng'),\n\n    /** @name angular */\n    angular           = window.angular || (window.angular = {}),\n    angularModule,\n    nodeName_,\n    uid               = ['0', '0', '0'];\n\n/**\n * IE 11 changed the format of the UserAgent string.\n * See http://msdn.microsoft.com/en-us/library/ms537503.aspx\n */\nmsie = int((/msie (\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);\nif (isNaN(msie)) {\n  msie = int((/trident\\/.*; rv:(\\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);\n}\n\n\n/**\n * @private\n * @param {*} obj\n * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,\n *                   String ...)\n */\nfunction isArrayLike(obj) {\n  if (obj == null || isWindow(obj)) {\n    return false;\n  }\n\n  var length = obj.length;\n\n  if (obj.nodeType === 1 && length) {\n    return true;\n  }\n\n  return isString(obj) || isArray(obj) || length === 0 ||\n         typeof length === 'number' && length > 0 && (length - 1) in obj;\n}\n\n/**\n * @ngdoc function\n * @name angular.forEach\n * @module ng\n * @kind function\n *\n * @description\n * Invokes the `iterator` function once for each item in `obj` collection, which can be either an\n * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`\n * is the value of an object property or an array element and `key` is the object property key or\n * array element index. Specifying a `context` for the function is optional.\n *\n * It is worth noting that `.forEach` does not iterate over inherited properties because it filters\n * using the `hasOwnProperty` method.\n *\n   ```js\n     var values = {name: 'misko', gender: 'male'};\n     var log = [];\n     angular.forEach(values, function(value, key) {\n       this.push(key + ': ' + value);\n     }, log);\n     expect(log).toEqual(['name: misko', 'gender: male']);\n   ```\n *\n * @param {Object|Array} obj Object to iterate over.\n * @param {Function} iterator Iterator function.\n * @param {Object=} context Object to become context (`this`) for the iterator function.\n * @returns {Object|Array} Reference to `obj`.\n */\nfunction forEach(obj, iterator, context) {\n  var key;\n  if (obj) {\n    if (isFunction(obj)) {\n      for (key in obj) {\n        // Need to check if hasOwnProperty exists,\n        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function\n        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    } else if (isArray(obj) || isArrayLike(obj)) {\n      for (key = 0; key < obj.length; key++) {\n        iterator.call(context, obj[key], key);\n      }\n    } else if (obj.forEach && obj.forEach !== forEach) {\n        obj.forEach(iterator, context);\n    } else {\n      for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n          iterator.call(context, obj[key], key);\n        }\n      }\n    }\n  }\n  return obj;\n}\n\nfunction sortedKeys(obj) {\n  var keys = [];\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      keys.push(key);\n    }\n  }\n  return keys.sort();\n}\n\nfunction forEachSorted(obj, iterator, context) {\n  var keys = sortedKeys(obj);\n  for ( var i = 0; i < keys.length; i++) {\n    iterator.call(context, obj[keys[i]], keys[i]);\n  }\n  return keys;\n}\n\n\n/**\n * when using forEach the params are value, key, but it is often useful to have key, value.\n * @param {function(string, *)} iteratorFn\n * @returns {function(*, string)}\n */\nfunction reverseParams(iteratorFn) {\n  return function(value, key) { iteratorFn(key, value); };\n}\n\n/**\n * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric\n * characters such as '012ABC'. The reason why we are not using simply a number counter is that\n * the number string gets longer over time, and it can also overflow, where as the nextId\n * will grow much slower, it is a string, and it will never overflow.\n *\n * @returns {string} an unique alpha-numeric string\n */\nfunction nextUid() {\n  var index = uid.length;\n  var digit;\n\n  while(index) {\n    index--;\n    digit = uid[index].charCodeAt(0);\n    if (digit == 57 /*'9'*/) {\n      uid[index] = 'A';\n      return uid.join('');\n    }\n    if (digit == 90  /*'Z'*/) {\n      uid[index] = '0';\n    } else {\n      uid[index] = String.fromCharCode(digit + 1);\n      return uid.join('');\n    }\n  }\n  uid.unshift('0');\n  return uid.join('');\n}\n\n\n/**\n * Set or clear the hashkey for an object.\n * @param obj object\n * @param h the hashkey (!truthy to delete the hashkey)\n */\nfunction setHashKey(obj, h) {\n  if (h) {\n    obj.$$hashKey = h;\n  }\n  else {\n    delete obj.$$hashKey;\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.extend\n * @module ng\n * @kind function\n *\n * @description\n * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)\n * to `dst`. You can specify multiple `src` objects.\n *\n * @param {Object} dst Destination object.\n * @param {...Object} src Source object(s).\n * @returns {Object} Reference to `dst`.\n */\nfunction extend(dst) {\n  var h = dst.$$hashKey;\n  forEach(arguments, function(obj) {\n    if (obj !== dst) {\n      forEach(obj, function(value, key) {\n        dst[key] = value;\n      });\n    }\n  });\n\n  setHashKey(dst,h);\n  return dst;\n}\n\nfunction int(str) {\n  return parseInt(str, 10);\n}\n\n\nfunction inherit(parent, extra) {\n  return extend(new (extend(function() {}, {prototype:parent}))(), extra);\n}\n\n/**\n * @ngdoc function\n * @name angular.noop\n * @module ng\n * @kind function\n *\n * @description\n * A function that performs no operations. This function can be useful when writing code in the\n * functional style.\n   ```js\n     function foo(callback) {\n       var result = calculateResult();\n       (callback || angular.noop)(result);\n     }\n   ```\n */\nfunction noop() {}\nnoop.$inject = [];\n\n\n/**\n * @ngdoc function\n * @name angular.identity\n * @module ng\n * @kind function\n *\n * @description\n * A function that returns its first argument. This function is useful when writing code in the\n * functional style.\n *\n   ```js\n     function transformer(transformationFn, value) {\n       return (transformationFn || angular.identity)(value);\n     };\n   ```\n */\nfunction identity($) {return $;}\nidentity.$inject = [];\n\n\nfunction valueFn(value) {return function() {return value;};}\n\n/**\n * @ngdoc function\n * @name angular.isUndefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is undefined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is undefined.\n */\nfunction isUndefined(value){return typeof value === 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDefined\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is defined.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is defined.\n */\nfunction isDefined(value){return typeof value !== 'undefined';}\n\n\n/**\n * @ngdoc function\n * @name angular.isObject\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not\n * considered to be objects. Note that JavaScript arrays are objects.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Object` but not `null`.\n */\nfunction isObject(value){return value != null && typeof value === 'object';}\n\n\n/**\n * @ngdoc function\n * @name angular.isString\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `String`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `String`.\n */\nfunction isString(value){return typeof value === 'string';}\n\n\n/**\n * @ngdoc function\n * @name angular.isNumber\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Number`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Number`.\n */\nfunction isNumber(value){return typeof value === 'number';}\n\n\n/**\n * @ngdoc function\n * @name angular.isDate\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a value is a date.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Date`.\n */\nfunction isDate(value) {\n  return toString.call(value) === '[object Date]';\n}\n\n\n/**\n * @ngdoc function\n * @name angular.isArray\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is an `Array`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is an `Array`.\n */\nvar isArray = (function() {\n  if (!isFunction(Array.isArray)) {\n    return function(value) {\n      return toString.call(value) === '[object Array]';\n    };\n  }\n  return Array.isArray;\n})();\n\n/**\n * @ngdoc function\n * @name angular.isFunction\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a `Function`.\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `Function`.\n */\nfunction isFunction(value){return typeof value === 'function';}\n\n\n/**\n * Determines if a value is a regular expression object.\n *\n * @private\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a `RegExp`.\n */\nfunction isRegExp(value) {\n  return toString.call(value) === '[object RegExp]';\n}\n\n\n/**\n * Checks if `obj` is a window object.\n *\n * @private\n * @param {*} obj Object to check\n * @returns {boolean} True if `obj` is a window obj.\n */\nfunction isWindow(obj) {\n  return obj && obj.document && obj.location && obj.alert && obj.setInterval;\n}\n\n\nfunction isScope(obj) {\n  return obj && obj.$evalAsync && obj.$watch;\n}\n\n\nfunction isFile(obj) {\n  return toString.call(obj) === '[object File]';\n}\n\n\nfunction isBlob(obj) {\n  return toString.call(obj) === '[object Blob]';\n}\n\n\nfunction isBoolean(value) {\n  return typeof value === 'boolean';\n}\n\n\nfunction isPromiseLike(obj) {\n  return obj && isFunction(obj.then);\n}\n\n\nvar trim = (function() {\n  // native trim is way faster: http://jsperf.com/angular-trim-test\n  // but IE doesn't have it... :-(\n  // TODO: we should move this into IE/ES5 polyfill\n  if (!String.prototype.trim) {\n    return function(value) {\n      return isString(value) ? value.replace(/^\\s\\s*/, '').replace(/\\s\\s*$/, '') : value;\n    };\n  }\n  return function(value) {\n    return isString(value) ? value.trim() : value;\n  };\n})();\n\n\n/**\n * @ngdoc function\n * @name angular.isElement\n * @module ng\n * @kind function\n *\n * @description\n * Determines if a reference is a DOM element (or wrapped jQuery element).\n *\n * @param {*} value Reference to check.\n * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).\n */\nfunction isElement(node) {\n  return !!(node &&\n    (node.nodeName  // we are a direct element\n    || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API\n}\n\n/**\n * @param str 'key1,key2,...'\n * @returns {object} in the form of {key1:true, key2:true, ...}\n */\nfunction makeMap(str) {\n  var obj = {}, items = str.split(\",\"), i;\n  for ( i = 0; i < items.length; i++ )\n    obj[ items[i] ] = true;\n  return obj;\n}\n\n\nif (msie < 9) {\n  nodeName_ = function(element) {\n    element = element.nodeName ? element : element[0];\n    return (element.scopeName && element.scopeName != 'HTML')\n      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;\n  };\n} else {\n  nodeName_ = function(element) {\n    return element.nodeName ? element.nodeName : element[0].nodeName;\n  };\n}\n\n\nfunction map(obj, iterator, context) {\n  var results = [];\n  forEach(obj, function(value, index, list) {\n    results.push(iterator.call(context, value, index, list));\n  });\n  return results;\n}\n\n\n/**\n * @description\n * Determines the number of elements in an array, the number of properties an object has, or\n * the length of a string.\n *\n * Note: This function is used to augment the Object type in Angular expressions. See\n * {@link angular.Object} for more information about Angular arrays.\n *\n * @param {Object|Array|string} obj Object, array, or string to inspect.\n * @param {boolean} [ownPropsOnly=false] Count only \"own\" properties in an object\n * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.\n */\nfunction size(obj, ownPropsOnly) {\n  var count = 0, key;\n\n  if (isArray(obj) || isString(obj)) {\n    return obj.length;\n  } else if (isObject(obj)) {\n    for (key in obj)\n      if (!ownPropsOnly || obj.hasOwnProperty(key))\n        count++;\n  }\n\n  return count;\n}\n\n\nfunction includes(array, obj) {\n  return indexOf(array, obj) != -1;\n}\n\nfunction indexOf(array, obj) {\n  if (array.indexOf) return array.indexOf(obj);\n\n  for (var i = 0; i < array.length; i++) {\n    if (obj === array[i]) return i;\n  }\n  return -1;\n}\n\nfunction arrayRemove(array, value) {\n  var index = indexOf(array, value);\n  if (index >=0)\n    array.splice(index, 1);\n  return value;\n}\n\nfunction isLeafNode (node) {\n  if (node) {\n    switch (node.nodeName) {\n    case \"OPTION\":\n    case \"PRE\":\n    case \"TITLE\":\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * @ngdoc function\n * @name angular.copy\n * @module ng\n * @kind function\n *\n * @description\n * Creates a deep copy of `source`, which should be an object or an array.\n *\n * * If no destination is supplied, a copy of the object or array is created.\n * * If a destination is provided, all of its elements (for array) or properties (for objects)\n *   are deleted and then all elements/properties from the source are copied to it.\n * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.\n * * If `source` is identical to 'destination' an exception will be thrown.\n *\n * @param {*} source The source that will be used to make a copy.\n *                   Can be any type, including primitives, `null`, and `undefined`.\n * @param {(Object|Array)=} destination Destination into which the source is copied. If\n *     provided, must be of the same type as `source`.\n * @returns {*} The copy or updated `destination`, if `destination` was specified.\n *\n * @example\n <example module=\"copyExample\">\n <file name=\"index.html\">\n <div ng-controller=\"ExampleController\">\n <form novalidate class=\"simple-form\">\n Name: <input type=\"text\" ng-model=\"user.name\" /><br />\n E-mail: <input type=\"email\" ng-model=\"user.email\" /><br />\n Gender: <input type=\"radio\" ng-model=\"user.gender\" value=\"male\" />male\n <input type=\"radio\" ng-model=\"user.gender\" value=\"female\" />female<br />\n <button ng-click=\"reset()\">RESET</button>\n <button ng-click=\"update(user)\">SAVE</button>\n </form>\n <pre>form = {{user | json}}</pre>\n <pre>master = {{master | json}}</pre>\n </div>\n\n <script>\n  angular.module('copyExample', [])\n    .controller('ExampleController', ['$scope', function($scope) {\n      $scope.master= {};\n\n      $scope.update = function(user) {\n        // Example with 1 argument\n        $scope.master= angular.copy(user);\n      };\n\n      $scope.reset = function() {\n        // Example with 2 arguments\n        angular.copy($scope.master, $scope.user);\n      };\n\n      $scope.reset();\n    }]);\n </script>\n </file>\n </example>\n */\nfunction copy(source, destination, stackSource, stackDest) {\n  if (isWindow(source) || isScope(source)) {\n    throw ngMinErr('cpws',\n      \"Can't copy! Making copies of Window or Scope instances is not supported.\");\n  }\n\n  if (!destination) {\n    destination = source;\n    if (source) {\n      if (isArray(source)) {\n        destination = copy(source, [], stackSource, stackDest);\n      } else if (isDate(source)) {\n        destination = new Date(source.getTime());\n      } else if (isRegExp(source)) {\n        destination = new RegExp(source.source, source.toString().match(/[^\\/]*$/)[0]);\n        destination.lastIndex = source.lastIndex;\n      } else if (isObject(source)) {\n        destination = copy(source, {}, stackSource, stackDest);\n      }\n    }\n  } else {\n    if (source === destination) throw ngMinErr('cpi',\n      \"Can't copy! Source and destination are identical.\");\n\n    stackSource = stackSource || [];\n    stackDest = stackDest || [];\n\n    if (isObject(source)) {\n      var index = indexOf(stackSource, source);\n      if (index !== -1) return stackDest[index];\n\n      stackSource.push(source);\n      stackDest.push(destination);\n    }\n\n    var result;\n    if (isArray(source)) {\n      destination.length = 0;\n      for ( var i = 0; i < source.length; i++) {\n        result = copy(source[i], null, stackSource, stackDest);\n        if (isObject(source[i])) {\n          stackSource.push(source[i]);\n          stackDest.push(result);\n        }\n        destination.push(result);\n      }\n    } else {\n      var h = destination.$$hashKey;\n      if (isArray(destination)) {\n        destination.length = 0;\n      } else {\n        forEach(destination, function(value, key) {\n          delete destination[key];\n        });\n      }\n      for ( var key in source) {\n        result = copy(source[key], null, stackSource, stackDest);\n        if (isObject(source[key])) {\n          stackSource.push(source[key]);\n          stackDest.push(result);\n        }\n        destination[key] = result;\n      }\n      setHashKey(destination,h);\n    }\n\n  }\n  return destination;\n}\n\n/**\n * Creates a shallow copy of an object, an array or a primitive\n */\nfunction shallowCopy(src, dst) {\n  if (isArray(src)) {\n    dst = dst || [];\n\n    for ( var i = 0; i < src.length; i++) {\n      dst[i] = src[i];\n    }\n  } else if (isObject(src)) {\n    dst = dst || {};\n\n    for (var key in src) {\n      if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {\n        dst[key] = src[key];\n      }\n    }\n  }\n\n  return dst || src;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.equals\n * @module ng\n * @kind function\n *\n * @description\n * Determines if two objects or two values are equivalent. Supports value types, regular\n * expressions, arrays and objects.\n *\n * Two objects or values are considered equivalent if at least one of the following is true:\n *\n * * Both objects or values pass `===` comparison.\n * * Both objects or values are of the same type and all of their properties are equal by\n *   comparing them with `angular.equals`.\n * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)\n * * Both values represent the same regular expression (In JavaScript,\n *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual\n *   representation matches).\n *\n * During a property comparison, properties of `function` type and properties with names\n * that begin with `$` are ignored.\n *\n * Scope and DOMWindow objects are being compared only by identify (`===`).\n *\n * @param {*} o1 Object or value to compare.\n * @param {*} o2 Object or value to compare.\n * @returns {boolean} True if arguments are equal.\n */\nfunction equals(o1, o2) {\n  if (o1 === o2) return true;\n  if (o1 === null || o2 === null) return false;\n  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN\n  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;\n  if (t1 == t2) {\n    if (t1 == 'object') {\n      if (isArray(o1)) {\n        if (!isArray(o2)) return false;\n        if ((length = o1.length) == o2.length) {\n          for(key=0; key<length; key++) {\n            if (!equals(o1[key], o2[key])) return false;\n          }\n          return true;\n        }\n      } else if (isDate(o1)) {\n        if (!isDate(o2)) return false;\n        return (isNaN(o1.getTime()) && isNaN(o2.getTime())) || (o1.getTime() === o2.getTime());\n      } else if (isRegExp(o1) && isRegExp(o2)) {\n        return o1.toString() == o2.toString();\n      } else {\n        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;\n        keySet = {};\n        for(key in o1) {\n          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;\n          if (!equals(o1[key], o2[key])) return false;\n          keySet[key] = true;\n        }\n        for(key in o2) {\n          if (!keySet.hasOwnProperty(key) &&\n              key.charAt(0) !== '$' &&\n              o2[key] !== undefined &&\n              !isFunction(o2[key])) return false;\n        }\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nvar csp = function() {\n  if (isDefined(csp.isActive_)) return csp.isActive_;\n\n  var active = !!(document.querySelector('[ng-csp]') ||\n                  document.querySelector('[data-ng-csp]'));\n\n  if (!active) {\n    try {\n      /* jshint -W031, -W054 */\n      new Function('');\n      /* jshint +W031, +W054 */\n    } catch (e) {\n      active = true;\n    }\n  }\n\n  return (csp.isActive_ = active);\n};\n\n\n\nfunction concat(array1, array2, index) {\n  return array1.concat(slice.call(array2, index));\n}\n\nfunction sliceArgs(args, startIndex) {\n  return slice.call(args, startIndex || 0);\n}\n\n\n/* jshint -W101 */\n/**\n * @ngdoc function\n * @name angular.bind\n * @module ng\n * @kind function\n *\n * @description\n * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for\n * `fn`). You can supply optional `args` that are prebound to the function. This feature is also\n * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as\n * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).\n *\n * @param {Object} self Context which `fn` should be evaluated in.\n * @param {function()} fn Function to be bound.\n * @param {...*} args Optional arguments to be prebound to the `fn` function call.\n * @returns {function()} Function that wraps the `fn` with all the specified bindings.\n */\n/* jshint +W101 */\nfunction bind(self, fn) {\n  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];\n  if (isFunction(fn) && !(fn instanceof RegExp)) {\n    return curryArgs.length\n      ? function() {\n          return arguments.length\n            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))\n            : fn.apply(self, curryArgs);\n        }\n      : function() {\n          return arguments.length\n            ? fn.apply(self, arguments)\n            : fn.call(self);\n        };\n  } else {\n    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)\n    return fn;\n  }\n}\n\n\nfunction toJsonReplacer(key, value) {\n  var val = value;\n\n  if (typeof key === 'string' && key.charAt(0) === '$') {\n    val = undefined;\n  } else if (isWindow(value)) {\n    val = '$WINDOW';\n  } else if (value &&  document === value) {\n    val = '$DOCUMENT';\n  } else if (isScope(value)) {\n    val = '$SCOPE';\n  }\n\n  return val;\n}\n\n\n/**\n * @ngdoc function\n * @name angular.toJson\n * @module ng\n * @kind function\n *\n * @description\n * Serializes input into a JSON-formatted string. Properties with leading $ characters will be\n * stripped since angular uses this notation internally.\n *\n * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.\n * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.\n * @returns {string|undefined} JSON-ified string representing `obj`.\n */\nfunction toJson(obj, pretty) {\n  if (typeof obj === 'undefined') return undefined;\n  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);\n}\n\n\n/**\n * @ngdoc function\n * @name angular.fromJson\n * @module ng\n * @kind function\n *\n * @description\n * Deserializes a JSON string.\n *\n * @param {string} json JSON string to deserialize.\n * @returns {Object|Array|string|number} Deserialized thingy.\n */\nfunction fromJson(json) {\n  return isString(json)\n      ? JSON.parse(json)\n      : json;\n}\n\n\nfunction toBoolean(value) {\n  if (typeof value === 'function') {\n    value = true;\n  } else if (value && value.length !== 0) {\n    var v = lowercase(\"\" + value);\n    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');\n  } else {\n    value = false;\n  }\n  return value;\n}\n\n/**\n * @returns {string} Returns the string representation of the element.\n */\nfunction startingTag(element) {\n  element = jqLite(element).clone();\n  try {\n    // turns out IE does not let you set .html() on elements which\n    // are not allowed to have children. So we just ignore it.\n    element.empty();\n  } catch(e) {}\n  // As Per DOM Standards\n  var TEXT_NODE = 3;\n  var elemHtml = jqLite('<div>').append(element).html();\n  try {\n    return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :\n        elemHtml.\n          match(/^(<[^>]+>)/)[1].\n          replace(/^<([\\w\\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });\n  } catch(e) {\n    return lowercase(elemHtml);\n  }\n\n}\n\n\n/////////////////////////////////////////////////\n\n/**\n * Tries to decode the URI component without throwing an exception.\n *\n * @private\n * @param str value potential URI component to check.\n * @returns {boolean} True if `value` can be decoded\n * with the decodeURIComponent function.\n */\nfunction tryDecodeURIComponent(value) {\n  try {\n    return decodeURIComponent(value);\n  } catch(e) {\n    // Ignore any invalid uri component\n  }\n}\n\n\n/**\n * Parses an escaped url query string into key-value pairs.\n * @returns {Object.<string,boolean|Array>}\n */\nfunction parseKeyValue(/**string*/keyValue) {\n  var obj = {}, key_value, key;\n  forEach((keyValue || \"\").split('&'), function(keyValue) {\n    if ( keyValue ) {\n      key_value = keyValue.replace(/\\+/g,'%20').split('=');\n      key = tryDecodeURIComponent(key_value[0]);\n      if ( isDefined(key) ) {\n        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;\n        if (!hasOwnProperty.call(obj, key)) {\n          obj[key] = val;\n        } else if(isArray(obj[key])) {\n          obj[key].push(val);\n        } else {\n          obj[key] = [obj[key],val];\n        }\n      }\n    }\n  });\n  return obj;\n}\n\nfunction toKeyValue(obj) {\n  var parts = [];\n  forEach(obj, function(value, key) {\n    if (isArray(value)) {\n      forEach(value, function(arrayValue) {\n        parts.push(encodeUriQuery(key, true) +\n                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));\n      });\n    } else {\n    parts.push(encodeUriQuery(key, true) +\n               (value === true ? '' : '=' + encodeUriQuery(value, true)));\n    }\n  });\n  return parts.length ? parts.join('&') : '';\n}\n\n\n/**\n * We need our custom method because encodeURIComponent is too aggressive and doesn't follow\n * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path\n * segments:\n *    segment       = *pchar\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriSegment(val) {\n  return encodeUriQuery(val, true).\n             replace(/%26/gi, '&').\n             replace(/%3D/gi, '=').\n             replace(/%2B/gi, '+');\n}\n\n\n/**\n * This method is intended for encoding *key* or *value* parts of query component. We need a custom\n * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be\n * encoded per http://tools.ietf.org/html/rfc3986:\n *    query       = *( pchar / \"/\" / \"?\" )\n *    pchar         = unreserved / pct-encoded / sub-delims / \":\" / \"@\"\n *    unreserved    = ALPHA / DIGIT / \"-\" / \".\" / \"_\" / \"~\"\n *    pct-encoded   = \"%\" HEXDIG HEXDIG\n *    sub-delims    = \"!\" / \"$\" / \"&\" / \"'\" / \"(\" / \")\"\n *                     / \"*\" / \"+\" / \",\" / \";\" / \"=\"\n */\nfunction encodeUriQuery(val, pctEncodeSpaces) {\n  return encodeURIComponent(val).\n             replace(/%40/gi, '@').\n             replace(/%3A/gi, ':').\n             replace(/%24/g, '$').\n             replace(/%2C/gi, ',').\n             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));\n}\n\n\n/**\n * @ngdoc directive\n * @name ngApp\n * @module ng\n *\n * @element ANY\n * @param {angular.Module} ngApp an optional application\n *   {@link angular.module module} name to load.\n *\n * @description\n *\n * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive\n * designates the **root element** of the application and is typically placed near the root element\n * of the page - e.g. on the `<body>` or `<html>` tags.\n *\n * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`\n * found in the document will be used to define the root element to auto-bootstrap as an\n * application. To run multiple applications in an HTML document you must manually bootstrap them using\n * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.\n *\n * You can specify an **AngularJS module** to be used as the root module for the application.  This\n * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and\n * should contain the application code needed or have dependencies on other modules that will\n * contain the code. See {@link angular.module} for more information.\n *\n * In the example below if the `ngApp` directive were not placed on the `html` element then the\n * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`\n * would not be resolved to `3`.\n *\n * `ngApp` is the easiest, and most common, way to bootstrap an application.\n *\n <example module=\"ngAppDemo\">\n   <file name=\"index.html\">\n   <div ng-controller=\"ngAppDemoController\">\n     I can add: {{a}} + {{b}} =  {{ a+b }}\n   </div>\n   </file>\n   <file name=\"script.js\">\n   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {\n     $scope.a = 1;\n     $scope.b = 2;\n   });\n   </file>\n </example>\n *\n */\nfunction angularInit(element, bootstrap) {\n  var elements = [element],\n      appElement,\n      module,\n      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],\n      NG_APP_CLASS_REGEXP = /\\sng[:\\-]app(:\\s*([\\w\\d_]+);?)?\\s/;\n\n  function append(element) {\n    element && elements.push(element);\n  }\n\n  forEach(names, function(name) {\n    names[name] = true;\n    append(document.getElementById(name));\n    name = name.replace(':', '\\\\:');\n    if (element.querySelectorAll) {\n      forEach(element.querySelectorAll('.' + name), append);\n      forEach(element.querySelectorAll('.' + name + '\\\\:'), append);\n      forEach(element.querySelectorAll('[' + name + ']'), append);\n    }\n  });\n\n  forEach(elements, function(element) {\n    if (!appElement) {\n      var className = ' ' + element.className + ' ';\n      var match = NG_APP_CLASS_REGEXP.exec(className);\n      if (match) {\n        appElement = element;\n        module = (match[2] || '').replace(/\\s+/g, ',');\n      } else {\n        forEach(element.attributes, function(attr) {\n          if (!appElement && names[attr.name]) {\n            appElement = element;\n            module = attr.value;\n          }\n        });\n      }\n    }\n  });\n  if (appElement) {\n    bootstrap(appElement, module ? [module] : []);\n  }\n}\n\n/**\n * @ngdoc function\n * @name angular.bootstrap\n * @module ng\n * @description\n * Use this function to manually start up angular application.\n *\n * See: {@link guide/bootstrap Bootstrap}\n *\n * Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.\n * They must use {@link ng.directive:ngApp ngApp}.\n *\n * Angular will detect if it has been loaded into the browser more than once and only allow the\n * first loaded script to be bootstrapped and will report a warning to the browser console for\n * each of the subsequent scripts. This prevents strange results in applications, where otherwise\n * multiple instances of Angular try to work on the DOM.\n *\n * <example name=\"multi-bootstrap\" module=\"multi-bootstrap\">\n * <file name=\"index.html\">\n * <script src=\"../../../angular.js\"></script>\n * <div ng-controller=\"BrokenTable\">\n *   <table>\n *   <tr>\n *     <th ng-repeat=\"heading in headings\">{{heading}}</th>\n *   </tr>\n *   <tr ng-repeat=\"filling in fillings\">\n *     <td ng-repeat=\"fill in filling\">{{fill}}</td>\n *   </tr>\n * </table>\n * </div>\n * </file>\n * <file name=\"controller.js\">\n * var app = angular.module('multi-bootstrap', [])\n *\n * .controller('BrokenTable', function($scope) {\n *     $scope.headings = ['One', 'Two', 'Three'];\n *     $scope.fillings = [[1, 2, 3], ['A', 'B', 'C'], [7, 8, 9]];\n * });\n * </file>\n * <file name=\"protractor.js\" type=\"protractor\">\n * it('should only insert one table cell for each item in $scope.fillings', function() {\n *  expect(element.all(by.css('td')).count())\n *      .toBe(9);\n * });\n * </file>\n * </example>\n *\n * @param {DOMElement} element DOM element which is the root of angular application.\n * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.\n *     Each item in the array should be the name of a predefined module or a (DI annotated)\n *     function that will be invoked by the injector as a run block.\n *     See: {@link angular.module modules}\n * @returns {auto.$injector} Returns the newly created injector for this app.\n */\nfunction bootstrap(element, modules) {\n  var doBootstrap = function() {\n    element = jqLite(element);\n\n    if (element.injector()) {\n      var tag = (element[0] === document) ? 'document' : startingTag(element);\n      //Encode angle brackets to prevent input from being sanitized to empty string #8683\n      throw ngMinErr(\n          'btstrpd',\n          \"App Already Bootstrapped with this Element '{0}'\",\n          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));\n    }\n\n    modules = modules || [];\n    modules.unshift(['$provide', function($provide) {\n      $provide.value('$rootElement', element);\n    }]);\n    modules.unshift('ng');\n    var injector = createInjector(modules);\n    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',\n       function(scope, element, compile, injector, animate) {\n        scope.$apply(function() {\n          element.data('$injector', injector);\n          compile(element)(scope);\n        });\n      }]\n    );\n    return injector;\n  };\n\n  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;\n\n  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {\n    return doBootstrap();\n  }\n\n  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');\n  angular.resumeBootstrap = function(extraModules) {\n    forEach(extraModules, function(module) {\n      modules.push(module);\n    });\n    doBootstrap();\n  };\n}\n\nvar SNAKE_CASE_REGEXP = /[A-Z]/g;\nfunction snake_case(name, separator) {\n  separator = separator || '_';\n  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {\n    return (pos ? separator : '') + letter.toLowerCase();\n  });\n}\n\nfunction bindJQuery() {\n  // bind to jQuery if present;\n  jQuery = window.jQuery;\n  // Use jQuery if it exists with proper functionality, otherwise default to us.\n  // Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.\n  if (jQuery && jQuery.fn.on) {\n    jqLite = jQuery;\n    extend(jQuery.fn, {\n      scope: JQLitePrototype.scope,\n      isolateScope: JQLitePrototype.isolateScope,\n      controller: JQLitePrototype.controller,\n      injector: JQLitePrototype.injector,\n      inheritedData: JQLitePrototype.inheritedData\n    });\n    // Method signature:\n    //     jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)\n    jqLitePatchJQueryRemove('remove', true, true, false);\n    jqLitePatchJQueryRemove('empty', false, false, false);\n    jqLitePatchJQueryRemove('html', false, false, true);\n  } else {\n    jqLite = JQLite;\n  }\n  angular.element = jqLite;\n}\n\n/**\n * throw error if the argument is falsy.\n */\nfunction assertArg(arg, name, reason) {\n  if (!arg) {\n    throw ngMinErr('areq', \"Argument '{0}' is {1}\", (name || '?'), (reason || \"required\"));\n  }\n  return arg;\n}\n\nfunction assertArgFn(arg, name, acceptArrayAnnotation) {\n  if (acceptArrayAnnotation && isArray(arg)) {\n      arg = arg[arg.length - 1];\n  }\n\n  assertArg(isFunction(arg), name, 'not a function, got ' +\n      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));\n  return arg;\n}\n\n/**\n * throw error if the name given is hasOwnProperty\n * @param  {String} name    the name to test\n * @param  {String} context the context in which the name is used, such as module or directive\n */\nfunction assertNotHasOwnProperty(name, context) {\n  if (name === 'hasOwnProperty') {\n    throw ngMinErr('badname', \"hasOwnProperty is not a valid {0} name\", context);\n  }\n}\n\n/**\n * Return the value accessible from the object by path. Any undefined traversals are ignored\n * @param {Object} obj starting object\n * @param {String} path path to traverse\n * @param {boolean} [bindFnToScope=true]\n * @returns {Object} value as accessible by path\n */\n//TODO(misko): this function needs to be removed\nfunction getter(obj, path, bindFnToScope) {\n  if (!path) return obj;\n  var keys = path.split('.');\n  var key;\n  var lastInstance = obj;\n  var len = keys.length;\n\n  for (var i = 0; i < len; i++) {\n    key = keys[i];\n    if (obj) {\n      obj = (lastInstance = obj)[key];\n    }\n  }\n  if (!bindFnToScope && isFunction(obj)) {\n    return bind(lastInstance, obj);\n  }\n  return obj;\n}\n\n/**\n * Return the DOM siblings between the first and last node in the given array.\n * @param {Array} array like object\n * @returns {DOMElement} object containing the elements\n */\nfunction getBlockElements(nodes) {\n  var startNode = nodes[0],\n      endNode = nodes[nodes.length - 1];\n  if (startNode === endNode) {\n    return jqLite(startNode);\n  }\n\n  var element = startNode;\n  var elements = [element];\n\n  do {\n    element = element.nextSibling;\n    if (!element) break;\n    elements.push(element);\n  } while (element !== endNode);\n\n  return jqLite(elements);\n}\n\n/**\n * @ngdoc type\n * @name angular.Module\n * @module ng\n * @description\n *\n * Interface for configuring angular {@link angular.module modules}.\n */\n\nfunction setupModuleLoader(window) {\n\n  var $injectorMinErr = minErr('$injector');\n  var ngMinErr = minErr('ng');\n\n  function ensure(obj, name, factory) {\n    return obj[name] || (obj[name] = factory());\n  }\n\n  var angular = ensure(window, 'angular', Object);\n\n  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap\n  angular.$$minErr = angular.$$minErr || minErr;\n\n  return ensure(angular, 'module', function() {\n    /** @type {Object.<string, angular.Module>} */\n    var modules = {};\n\n    /**\n     * @ngdoc function\n     * @name angular.module\n     * @module ng\n     * @description\n     *\n     * The `angular.module` is a global place for creating, registering and retrieving Angular\n     * modules.\n     * All modules (angular core or 3rd party) that should be available to an application must be\n     * registered using this mechanism.\n     *\n     * When passed two or more arguments, a new module is created.  If passed only one argument, an\n     * existing module (the name passed as the first argument to `module`) is retrieved.\n     *\n     *\n     * # Module\n     *\n     * A module is a collection of services, directives, controllers, filters, and configuration information.\n     * `angular.module` is used to configure the {@link auto.$injector $injector}.\n     *\n     * ```js\n     * // Create a new module\n     * var myModule = angular.module('myModule', []);\n     *\n     * // register a new service\n     * myModule.value('appName', 'MyCoolApp');\n     *\n     * // configure existing services inside initialization blocks.\n     * myModule.config(['$locationProvider', function($locationProvider) {\n     *   // Configure existing providers\n     *   $locationProvider.hashPrefix('!');\n     * }]);\n     * ```\n     *\n     * Then you can create an injector and load your modules like this:\n     *\n     * ```js\n     * var injector = angular.injector(['ng', 'myModule'])\n     * ```\n     *\n     * However it's more likely that you'll just use\n     * {@link ng.directive:ngApp ngApp} or\n     * {@link angular.bootstrap} to simplify this process for you.\n     *\n     * @param {!string} name The name of the module to create or retrieve.\n     * @param {!Array.<string>=} requires If specified then new module is being created. If\n     *        unspecified then the module is being retrieved for further configuration.\n     * @param {Function=} configFn Optional configuration function for the module. Same as\n     *        {@link angular.Module#config Module#config()}.\n     * @returns {module} new module with the {@link angular.Module} api.\n     */\n    return function module(name, requires, configFn) {\n      var assertNotHasOwnProperty = function(name, context) {\n        if (name === 'hasOwnProperty') {\n          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);\n        }\n      };\n\n      assertNotHasOwnProperty(name, 'module');\n      if (requires && modules.hasOwnProperty(name)) {\n        modules[name] = null;\n      }\n      return ensure(modules, name, function() {\n        if (!requires) {\n          throw $injectorMinErr('nomod', \"Module '{0}' is not available! You either misspelled \" +\n             \"the module name or forgot to load it. If registering a module ensure that you \" +\n             \"specify the dependencies as the second argument.\", name);\n        }\n\n        /** @type {!Array.<Array.<*>>} */\n        var invokeQueue = [];\n\n        /** @type {!Array.<Function>} */\n        var runBlocks = [];\n\n        var config = invokeLater('$injector', 'invoke');\n\n        /** @type {angular.Module} */\n        var moduleInstance = {\n          // Private state\n          _invokeQueue: invokeQueue,\n          _runBlocks: runBlocks,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#requires\n           * @module ng\n           *\n           * @description\n           * Holds the list of modules which the injector will load before the current module is\n           * loaded.\n           */\n          requires: requires,\n\n          /**\n           * @ngdoc property\n           * @name angular.Module#name\n           * @module ng\n           *\n           * @description\n           * Name of the module.\n           */\n          name: name,\n\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#provider\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerType Construction function for creating new instance of the\n           *                                service.\n           * @description\n           * See {@link auto.$provide#provider $provide.provider()}.\n           */\n          provider: invokeLater('$provide', 'provider'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#factory\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} providerFunction Function for creating new instance of the service.\n           * @description\n           * See {@link auto.$provide#factory $provide.factory()}.\n           */\n          factory: invokeLater('$provide', 'factory'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#service\n           * @module ng\n           * @param {string} name service name\n           * @param {Function} constructor A constructor function that will be instantiated.\n           * @description\n           * See {@link auto.$provide#service $provide.service()}.\n           */\n          service: invokeLater('$provide', 'service'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#value\n           * @module ng\n           * @param {string} name service name\n           * @param {*} object Service instance object.\n           * @description\n           * See {@link auto.$provide#value $provide.value()}.\n           */\n          value: invokeLater('$provide', 'value'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#constant\n           * @module ng\n           * @param {string} name constant name\n           * @param {*} object Constant value.\n           * @description\n           * Because the constant are fixed, they get applied before other provide methods.\n           * See {@link auto.$provide#constant $provide.constant()}.\n           */\n          constant: invokeLater('$provide', 'constant', 'unshift'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#animation\n           * @module ng\n           * @param {string} name animation name\n           * @param {Function} animationFactory Factory function for creating new instance of an\n           *                                    animation.\n           * @description\n           *\n           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.\n           *\n           *\n           * Defines an animation hook that can be later used with\n           * {@link ngAnimate.$animate $animate} service and directives that use this service.\n           *\n           * ```js\n           * module.animation('.animation-name', function($inject1, $inject2) {\n           *   return {\n           *     eventName : function(element, done) {\n           *       //code to run the animation\n           *       //once complete, then run done()\n           *       return function cancellationFunction(element) {\n           *         //code to cancel the animation\n           *       }\n           *     }\n           *   }\n           * })\n           * ```\n           *\n           * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and\n           * {@link ngAnimate ngAnimate module} for more information.\n           */\n          animation: invokeLater('$animateProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#filter\n           * @module ng\n           * @param {string} name Filter name.\n           * @param {Function} filterFactory Factory function for creating new instance of filter.\n           * @description\n           * See {@link ng.$filterProvider#register $filterProvider.register()}.\n           */\n          filter: invokeLater('$filterProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#controller\n           * @module ng\n           * @param {string|Object} name Controller name, or an object map of controllers where the\n           *    keys are the names and the values are the constructors.\n           * @param {Function} constructor Controller constructor function.\n           * @description\n           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.\n           */\n          controller: invokeLater('$controllerProvider', 'register'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#directive\n           * @module ng\n           * @param {string|Object} name Directive name, or an object map of directives where the\n           *    keys are the names and the values are the factories.\n           * @param {Function} directiveFactory Factory function for creating new instance of\n           * directives.\n           * @description\n           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.\n           */\n          directive: invokeLater('$compileProvider', 'directive'),\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#config\n           * @module ng\n           * @param {Function} configFn Execute this function on module load. Useful for service\n           *    configuration.\n           * @description\n           * Use this method to register work which needs to be performed on module loading.\n           * For more about how to configure services, see\n           * {@link providers#providers_provider-recipe Provider Recipe}.\n           */\n          config: config,\n\n          /**\n           * @ngdoc method\n           * @name angular.Module#run\n           * @module ng\n           * @param {Function} initializationFn Execute this function after injector creation.\n           *    Useful for application initialization.\n           * @description\n           * Use this method to register work which should be performed when the injector is done\n           * loading all modules.\n           */\n          run: function(block) {\n            runBlocks.push(block);\n            return this;\n          }\n        };\n\n        if (configFn) {\n          config(configFn);\n        }\n\n        return  moduleInstance;\n\n        /**\n         * @param {string} provider\n         * @param {string} method\n         * @param {String=} insertMethod\n         * @returns {angular.Module}\n         */\n        function invokeLater(provider, method, insertMethod) {\n          return function() {\n            invokeQueue[insertMethod || 'push']([provider, method, arguments]);\n            return moduleInstance;\n          };\n        }\n      });\n    };\n  });\n\n}\n\n/* global angularModule: true,\n  version: true,\n\n  $LocaleProvider,\n  $CompileProvider,\n\n    htmlAnchorDirective,\n    inputDirective,\n    inputDirective,\n    formDirective,\n    scriptDirective,\n    selectDirective,\n    styleDirective,\n    optionDirective,\n    ngBindDirective,\n    ngBindHtmlDirective,\n    ngBindTemplateDirective,\n    ngClassDirective,\n    ngClassEvenDirective,\n    ngClassOddDirective,\n    ngCspDirective,\n    ngCloakDirective,\n    ngControllerDirective,\n    ngFormDirective,\n    ngHideDirective,\n    ngIfDirective,\n    ngIncludeDirective,\n    ngIncludeFillContentDirective,\n    ngInitDirective,\n    ngNonBindableDirective,\n    ngPluralizeDirective,\n    ngRepeatDirective,\n    ngShowDirective,\n    ngStyleDirective,\n    ngSwitchDirective,\n    ngSwitchWhenDirective,\n    ngSwitchDefaultDirective,\n    ngOptionsDirective,\n    ngTranscludeDirective,\n    ngModelDirective,\n    ngListDirective,\n    ngChangeDirective,\n    requiredDirective,\n    requiredDirective,\n    ngValueDirective,\n    ngAttributeAliasDirectives,\n    ngEventDirectives,\n\n    $AnchorScrollProvider,\n    $AnimateProvider,\n    $BrowserProvider,\n    $CacheFactoryProvider,\n    $ControllerProvider,\n    $DocumentProvider,\n    $ExceptionHandlerProvider,\n    $FilterProvider,\n    $InterpolateProvider,\n    $IntervalProvider,\n    $HttpProvider,\n    $HttpBackendProvider,\n    $LocationProvider,\n    $LogProvider,\n    $ParseProvider,\n    $RootScopeProvider,\n    $QProvider,\n    $$SanitizeUriProvider,\n    $SceProvider,\n    $SceDelegateProvider,\n    $SnifferProvider,\n    $TemplateCacheProvider,\n    $TimeoutProvider,\n    $$RAFProvider,\n    $$AsyncCallbackProvider,\n    $WindowProvider\n*/\n\n\n/**\n * @ngdoc object\n * @name angular.version\n * @module ng\n * @description\n * An object that contains information about the current AngularJS version. This object has the\n * following properties:\n *\n * - `full` – `{string}` – Full version string, such as \"0.9.18\".\n * - `major` – `{number}` – Major version number, such as \"0\".\n * - `minor` – `{number}` – Minor version number, such as \"9\".\n * - `dot` – `{number}` – Dot version number, such as \"18\".\n * - `codeName` – `{string}` – Code name of the release, such as \"jiggling-armfat\".\n */\nvar version = {\n  full: '1.2.28',    // all of these placeholder strings will be replaced by grunt's\n  major: 1,    // package task\n  minor: 2,\n  dot: 28,\n  codeName: 'finnish-disembarkation'\n};\n\n\nfunction publishExternalAPI(angular){\n  extend(angular, {\n    'bootstrap': bootstrap,\n    'copy': copy,\n    'extend': extend,\n    'equals': equals,\n    'element': jqLite,\n    'forEach': forEach,\n    'injector': createInjector,\n    'noop': noop,\n    'bind': bind,\n    'toJson': toJson,\n    'fromJson': fromJson,\n    'identity': identity,\n    'isUndefined': isUndefined,\n    'isDefined': isDefined,\n    'isString': isString,\n    'isFunction': isFunction,\n    'isObject': isObject,\n    'isNumber': isNumber,\n    'isElement': isElement,\n    'isArray': isArray,\n    'version': version,\n    'isDate': isDate,\n    'lowercase': lowercase,\n    'uppercase': uppercase,\n    'callbacks': {counter: 0},\n    '$$minErr': minErr,\n    '$$csp': csp\n  });\n\n  angularModule = setupModuleLoader(window);\n  try {\n    angularModule('ngLocale');\n  } catch (e) {\n    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);\n  }\n\n  angularModule('ng', ['ngLocale'], ['$provide',\n    function ngModule($provide) {\n      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.\n      $provide.provider({\n        $$sanitizeUri: $$SanitizeUriProvider\n      });\n      $provide.provider('$compile', $CompileProvider).\n        directive({\n            a: htmlAnchorDirective,\n            input: inputDirective,\n            textarea: inputDirective,\n            form: formDirective,\n            script: scriptDirective,\n            select: selectDirective,\n            style: styleDirective,\n            option: optionDirective,\n            ngBind: ngBindDirective,\n            ngBindHtml: ngBindHtmlDirective,\n            ngBindTemplate: ngBindTemplateDirective,\n            ngClass: ngClassDirective,\n            ngClassEven: ngClassEvenDirective,\n            ngClassOdd: ngClassOddDirective,\n            ngCloak: ngCloakDirective,\n            ngController: ngControllerDirective,\n            ngForm: ngFormDirective,\n            ngHide: ngHideDirective,\n            ngIf: ngIfDirective,\n            ngInclude: ngIncludeDirective,\n            ngInit: ngInitDirective,\n            ngNonBindable: ngNonBindableDirective,\n            ngPluralize: ngPluralizeDirective,\n            ngRepeat: ngRepeatDirective,\n            ngShow: ngShowDirective,\n            ngStyle: ngStyleDirective,\n            ngSwitch: ngSwitchDirective,\n            ngSwitchWhen: ngSwitchWhenDirective,\n            ngSwitchDefault: ngSwitchDefaultDirective,\n            ngOptions: ngOptionsDirective,\n            ngTransclude: ngTranscludeDirective,\n            ngModel: ngModelDirective,\n            ngList: ngListDirective,\n            ngChange: ngChangeDirective,\n            required: requiredDirective,\n            ngRequired: requiredDirective,\n            ngValue: ngValueDirective\n        }).\n        directive({\n          ngInclude: ngIncludeFillContentDirective\n        }).\n        directive(ngAttributeAliasDirectives).\n        directive(ngEventDirectives);\n      $provide.provider({\n        $anchorScroll: $AnchorScrollProvider,\n        $animate: $AnimateProvider,\n        $browser: $BrowserProvider,\n        $cacheFactory: $CacheFactoryProvider,\n        $controller: $ControllerProvider,\n        $document: $DocumentProvider,\n        $exceptionHandler: $ExceptionHandlerProvider,\n        $filter: $FilterProvider,\n        $interpolate: $InterpolateProvider,\n        $interval: $IntervalProvider,\n        $http: $HttpProvider,\n        $httpBackend: $HttpBackendProvider,\n        $location: $LocationProvider,\n        $log: $LogProvider,\n        $parse: $ParseProvider,\n        $rootScope: $RootScopeProvider,\n        $q: $QProvider,\n        $sce: $SceProvider,\n        $sceDelegate: $SceDelegateProvider,\n        $sniffer: $SnifferProvider,\n        $templateCache: $TemplateCacheProvider,\n        $timeout: $TimeoutProvider,\n        $window: $WindowProvider,\n        $$rAF: $$RAFProvider,\n        $$asyncCallback : $$AsyncCallbackProvider\n      });\n    }\n  ]);\n}\n\n/* global JQLitePrototype: true,\n  addEventListenerFn: true,\n  removeEventListenerFn: true,\n  BOOLEAN_ATTR: true\n*/\n\n//////////////////////////////////\n//JQLite\n//////////////////////////////////\n\n/**\n * @ngdoc function\n * @name angular.element\n * @module ng\n * @kind function\n *\n * @description\n * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.\n *\n * If jQuery is available, `angular.element` is an alias for the\n * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`\n * delegates to Angular's built-in subset of jQuery, called \"jQuery lite\" or \"jqLite.\"\n *\n * <div class=\"alert alert-success\">jqLite is a tiny, API-compatible subset of jQuery that allows\n * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most\n * commonly needed functionality with the goal of having a very small footprint.</div>\n *\n * To use jQuery, simply load it before `DOMContentLoaded` event fired.\n *\n * <div class=\"alert\">**Note:** all element references in Angular are always wrapped with jQuery or\n * jqLite; they are never raw DOM references.</div>\n *\n * ## Angular's jqLite\n * jqLite provides only the following jQuery methods:\n *\n * - [`addClass()`](http://api.jquery.com/addClass/)\n * - [`after()`](http://api.jquery.com/after/)\n * - [`append()`](http://api.jquery.com/append/)\n * - [`attr()`](http://api.jquery.com/attr/)\n * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData\n * - [`children()`](http://api.jquery.com/children/) - Does not support selectors\n * - [`clone()`](http://api.jquery.com/clone/)\n * - [`contents()`](http://api.jquery.com/contents/)\n * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyles()`\n * - [`data()`](http://api.jquery.com/data/)\n * - [`empty()`](http://api.jquery.com/empty/)\n * - [`eq()`](http://api.jquery.com/eq/)\n * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name\n * - [`hasClass()`](http://api.jquery.com/hasClass/)\n * - [`html()`](http://api.jquery.com/html/)\n * - [`next()`](http://api.jquery.com/next/) - Does not support selectors\n * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData\n * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors\n * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors\n * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors\n * - [`prepend()`](http://api.jquery.com/prepend/)\n * - [`prop()`](http://api.jquery.com/prop/)\n * - [`ready()`](http://api.jquery.com/ready/)\n * - [`remove()`](http://api.jquery.com/remove/)\n * - [`removeAttr()`](http://api.jquery.com/removeAttr/)\n * - [`removeClass()`](http://api.jquery.com/removeClass/)\n * - [`removeData()`](http://api.jquery.com/removeData/)\n * - [`replaceWith()`](http://api.jquery.com/replaceWith/)\n * - [`text()`](http://api.jquery.com/text/)\n * - [`toggleClass()`](http://api.jquery.com/toggleClass/)\n * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.\n * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces\n * - [`val()`](http://api.jquery.com/val/)\n * - [`wrap()`](http://api.jquery.com/wrap/)\n *\n * ## jQuery/jqLite Extras\n * Angular also provides the following additional methods and events to both jQuery and jqLite:\n *\n * ### Events\n * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event\n *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM\n *    element before it is removed.\n *\n * ### Methods\n * - `controller(name)` - retrieves the controller of the current element or its parent. By default\n *   retrieves controller associated with the `ngController` directive. If `name` is provided as\n *   camelCase directive name, then the controller for this directive will be retrieved (e.g.\n *   `'ngModel'`).\n * - `injector()` - retrieves the injector of the current element or its parent.\n * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current\n *   element or its parent.\n * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the\n *   current element. This getter should be used only on elements that contain a directive which starts a new isolate\n *   scope. Calling `scope()` on this element always returns the original non-isolate scope.\n * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top\n *   parent element is reached.\n *\n * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.\n * @returns {Object} jQuery object.\n */\n\nJQLite.expando = 'ng339';\n\nvar jqCache = JQLite.cache = {},\n    jqId = 1,\n    addEventListenerFn = (window.document.addEventListener\n      ? function(element, type, fn) {element.addEventListener(type, fn, false);}\n      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),\n    removeEventListenerFn = (window.document.removeEventListener\n      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }\n      : function(element, type, fn) {element.detachEvent('on' + type, fn); });\n\n/*\n * !!! This is an undocumented \"private\" function !!!\n */\nvar jqData = JQLite._data = function(node) {\n  //jQuery always returns an object on cache miss\n  return this.cache[node[this.expando]] || {};\n};\n\nfunction jqNextId() { return ++jqId; }\n\n\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\nvar jqLiteMinErr = minErr('jqLite');\n\n/**\n * Converts snake_case to camelCase.\n * Also there is special case for Moz prefix starting with upper case letter.\n * @param name Name to normalize\n */\nfunction camelCase(name) {\n  return name.\n    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {\n      return offset ? letter.toUpperCase() : letter;\n    }).\n    replace(MOZ_HACK_REGEXP, 'Moz$1');\n}\n\n/////////////////////////////////////////////\n// jQuery mutation patch\n//\n// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a\n// $destroy event on all DOM nodes being removed.\n//\n/////////////////////////////////////////////\n\nfunction jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {\n  var originalJqFn = jQuery.fn[name];\n  originalJqFn = originalJqFn.$original || originalJqFn;\n  removePatch.$original = originalJqFn;\n  jQuery.fn[name] = removePatch;\n\n  function removePatch(param) {\n    // jshint -W040\n    var list = filterElems && param ? [this.filter(param)] : [this],\n        fireEvent = dispatchThis,\n        set, setIndex, setLength,\n        element, childIndex, childLength, children;\n\n    if (!getterIfNoArguments || param != null) {\n      while(list.length) {\n        set = list.shift();\n        for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {\n          element = jqLite(set[setIndex]);\n          if (fireEvent) {\n            element.triggerHandler('$destroy');\n          } else {\n            fireEvent = !fireEvent;\n          }\n          for(childIndex = 0, childLength = (children = element.children()).length;\n              childIndex < childLength;\n              childIndex++) {\n            list.push(jQuery(children[childIndex]));\n          }\n        }\n      }\n    }\n    return originalJqFn.apply(this, arguments);\n  }\n}\n\nvar SINGLE_TAG_REGEXP = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/;\nvar HTML_REGEXP = /<|&#?\\w+;/;\nvar TAG_NAME_REGEXP = /<([\\w:]+)/;\nvar XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi;\n\nvar wrapMap = {\n  'option': [1, '<select multiple=\"multiple\">', '</select>'],\n\n  'thead': [1, '<table>', '</table>'],\n  'col': [2, '<table><colgroup>', '</colgroup></table>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n  'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],\n  '_default': [0, \"\", \"\"]\n};\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\nfunction jqLiteIsTextNode(html) {\n  return !HTML_REGEXP.test(html);\n}\n\nfunction jqLiteBuildFragment(html, context) {\n  var elem, tmp, tag, wrap,\n      fragment = context.createDocumentFragment(),\n      nodes = [], i, j, jj;\n\n  if (jqLiteIsTextNode(html)) {\n    // Convert non-html into a text node\n    nodes.push(context.createTextNode(html));\n  } else {\n    tmp = fragment.appendChild(context.createElement('div'));\n    // Convert html into DOM nodes\n    tag = (TAG_NAME_REGEXP.exec(html) || [\"\", \"\"])[1].toLowerCase();\n    wrap = wrapMap[tag] || wrapMap._default;\n    tmp.innerHTML = '<div>&#160;</div>' +\n      wrap[1] + html.replace(XHTML_TAG_REGEXP, \"<$1></$2>\") + wrap[2];\n    tmp.removeChild(tmp.firstChild);\n\n    // Descend through wrappers to the right content\n    i = wrap[0];\n    while (i--) {\n      tmp = tmp.lastChild;\n    }\n\n    for (j=0, jj=tmp.childNodes.length; j<jj; ++j) nodes.push(tmp.childNodes[j]);\n\n    tmp = fragment.firstChild;\n    tmp.textContent = \"\";\n  }\n\n  // Remove wrapper from fragment\n  fragment.textContent = \"\";\n  fragment.innerHTML = \"\"; // Clear inner HTML\n  return nodes;\n}\n\nfunction jqLiteParseHTML(html, context) {\n  context = context || document;\n  var parsed;\n\n  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {\n    return [context.createElement(parsed[1])];\n  }\n\n  return jqLiteBuildFragment(html, context);\n}\n\n/////////////////////////////////////////////\nfunction JQLite(element) {\n  if (element instanceof JQLite) {\n    return element;\n  }\n  if (isString(element)) {\n    element = trim(element);\n  }\n  if (!(this instanceof JQLite)) {\n    if (isString(element) && element.charAt(0) != '<') {\n      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');\n    }\n    return new JQLite(element);\n  }\n\n  if (isString(element)) {\n    jqLiteAddNodes(this, jqLiteParseHTML(element));\n    var fragment = jqLite(document.createDocumentFragment());\n    fragment.append(this);\n  } else {\n    jqLiteAddNodes(this, element);\n  }\n}\n\nfunction jqLiteClone(element) {\n  return element.cloneNode(true);\n}\n\nfunction jqLiteDealoc(element){\n  jqLiteRemoveData(element);\n  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {\n    jqLiteDealoc(children[i]);\n  }\n}\n\nfunction jqLiteOff(element, type, fn, unsupported) {\n  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');\n\n  var events = jqLiteExpandoStore(element, 'events'),\n      handle = jqLiteExpandoStore(element, 'handle');\n\n  if (!handle) return; //no listeners registered\n\n  if (isUndefined(type)) {\n    forEach(events, function(eventHandler, type) {\n      removeEventListenerFn(element, type, eventHandler);\n      delete events[type];\n    });\n  } else {\n    forEach(type.split(' '), function(type) {\n      if (isUndefined(fn)) {\n        removeEventListenerFn(element, type, events[type]);\n        delete events[type];\n      } else {\n        arrayRemove(events[type] || [], fn);\n      }\n    });\n  }\n}\n\nfunction jqLiteRemoveData(element, name) {\n  var expandoId = element.ng339,\n      expandoStore = jqCache[expandoId];\n\n  if (expandoStore) {\n    if (name) {\n      delete jqCache[expandoId].data[name];\n      return;\n    }\n\n    if (expandoStore.handle) {\n      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');\n      jqLiteOff(element);\n    }\n    delete jqCache[expandoId];\n    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it\n  }\n}\n\nfunction jqLiteExpandoStore(element, key, value) {\n  var expandoId = element.ng339,\n      expandoStore = jqCache[expandoId || -1];\n\n  if (isDefined(value)) {\n    if (!expandoStore) {\n      element.ng339 = expandoId = jqNextId();\n      expandoStore = jqCache[expandoId] = {};\n    }\n    expandoStore[key] = value;\n  } else {\n    return expandoStore && expandoStore[key];\n  }\n}\n\nfunction jqLiteData(element, key, value) {\n  var data = jqLiteExpandoStore(element, 'data'),\n      isSetter = isDefined(value),\n      keyDefined = !isSetter && isDefined(key),\n      isSimpleGetter = keyDefined && !isObject(key);\n\n  if (!data && !isSimpleGetter) {\n    jqLiteExpandoStore(element, 'data', data = {});\n  }\n\n  if (isSetter) {\n    data[key] = value;\n  } else {\n    if (keyDefined) {\n      if (isSimpleGetter) {\n        // don't create data in this case.\n        return data && data[key];\n      } else {\n        extend(data, key);\n      }\n    } else {\n      return data;\n    }\n  }\n}\n\nfunction jqLiteHasClass(element, selector) {\n  if (!element.getAttribute) return false;\n  return ((\" \" + (element.getAttribute('class') || '') + \" \").replace(/[\\n\\t]/g, \" \").\n      indexOf( \" \" + selector + \" \" ) > -1);\n}\n\nfunction jqLiteRemoveClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    forEach(cssClasses.split(' '), function(cssClass) {\n      element.setAttribute('class', trim(\n          (\" \" + (element.getAttribute('class') || '') + \" \")\n          .replace(/[\\n\\t]/g, \" \")\n          .replace(\" \" + trim(cssClass) + \" \", \" \"))\n      );\n    });\n  }\n}\n\nfunction jqLiteAddClass(element, cssClasses) {\n  if (cssClasses && element.setAttribute) {\n    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')\n                            .replace(/[\\n\\t]/g, \" \");\n\n    forEach(cssClasses.split(' '), function(cssClass) {\n      cssClass = trim(cssClass);\n      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {\n        existingClasses += cssClass + ' ';\n      }\n    });\n\n    element.setAttribute('class', trim(existingClasses));\n  }\n}\n\nfunction jqLiteAddNodes(root, elements) {\n  if (elements) {\n    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))\n      ? elements\n      : [ elements ];\n    for(var i=0; i < elements.length; i++) {\n      root.push(elements[i]);\n    }\n  }\n}\n\nfunction jqLiteController(element, name) {\n  return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');\n}\n\nfunction jqLiteInheritedData(element, name, value) {\n  // if element is the document object work with the html element instead\n  // this makes $(document).scope() possible\n  if(element.nodeType == 9) {\n    element = element.documentElement;\n  }\n  var names = isArray(name) ? name : [name];\n\n  while (element) {\n    for (var i = 0, ii = names.length; i < ii; i++) {\n      if ((value = jqLite.data(element, names[i])) !== undefined) return value;\n    }\n\n    // If dealing with a document fragment node with a host element, and no parent, use the host\n    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM\n    // to lookup parent controllers.\n    element = element.parentNode || (element.nodeType === 11 && element.host);\n  }\n}\n\nfunction jqLiteEmpty(element) {\n  for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n    jqLiteDealoc(childNodes[i]);\n  }\n  while (element.firstChild) {\n    element.removeChild(element.firstChild);\n  }\n}\n\n//////////////////////////////////////////\n// Functions which are declared directly.\n//////////////////////////////////////////\nvar JQLitePrototype = JQLite.prototype = {\n  ready: function(fn) {\n    var fired = false;\n\n    function trigger() {\n      if (fired) return;\n      fired = true;\n      fn();\n    }\n\n    // check if document already is loaded\n    if (document.readyState === 'complete'){\n      setTimeout(trigger);\n    } else {\n      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9\n      // we can not use jqLite since we are not done loading and jQuery could be loaded later.\n      // jshint -W064\n      JQLite(window).on('load', trigger); // fallback to window.onload for others\n      // jshint +W064\n    }\n  },\n  toString: function() {\n    var value = [];\n    forEach(this, function(e){ value.push('' + e);});\n    return '[' + value.join(', ') + ']';\n  },\n\n  eq: function(index) {\n      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);\n  },\n\n  length: 0,\n  push: push,\n  sort: [].sort,\n  splice: [].splice\n};\n\n//////////////////////////////////////////\n// Functions iterating getter/setters.\n// these functions return self on setter and\n// value on get.\n//////////////////////////////////////////\nvar BOOLEAN_ATTR = {};\nforEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {\n  BOOLEAN_ATTR[lowercase(value)] = value;\n});\nvar BOOLEAN_ELEMENTS = {};\nforEach('input,select,option,textarea,button,form,details'.split(','), function(value) {\n  BOOLEAN_ELEMENTS[uppercase(value)] = true;\n});\n\nfunction getBooleanAttrName(element, name) {\n  // check dom last since we will most likely fail on name\n  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];\n\n  // booleanAttr is here twice to minimize DOM access\n  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;\n}\n\nforEach({\n  data: jqLiteData,\n  removeData: jqLiteRemoveData\n}, function(fn, name) {\n  JQLite[name] = fn;\n});\n\nforEach({\n  data: jqLiteData,\n  inheritedData: jqLiteInheritedData,\n\n  scope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);\n  },\n\n  isolateScope: function(element) {\n    // Can't use jqLiteData here directly so we stay compatible with jQuery!\n    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');\n  },\n\n  controller: jqLiteController,\n\n  injector: function(element) {\n    return jqLiteInheritedData(element, '$injector');\n  },\n\n  removeAttr: function(element,name) {\n    element.removeAttribute(name);\n  },\n\n  hasClass: jqLiteHasClass,\n\n  css: function(element, name, value) {\n    name = camelCase(name);\n\n    if (isDefined(value)) {\n      element.style[name] = value;\n    } else {\n      var val;\n\n      if (msie <= 8) {\n        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why\n        val = element.currentStyle && element.currentStyle[name];\n        if (val === '') val = 'auto';\n      }\n\n      val = val || element.style[name];\n\n      if (msie <= 8) {\n        // jquery weirdness :-/\n        val = (val === '') ? undefined : val;\n      }\n\n      return  val;\n    }\n  },\n\n  attr: function(element, name, value){\n    var lowercasedName = lowercase(name);\n    if (BOOLEAN_ATTR[lowercasedName]) {\n      if (isDefined(value)) {\n        if (!!value) {\n          element[name] = true;\n          element.setAttribute(name, lowercasedName);\n        } else {\n          element[name] = false;\n          element.removeAttribute(lowercasedName);\n        }\n      } else {\n        return (element[name] ||\n                 (element.attributes.getNamedItem(name)|| noop).specified)\n               ? lowercasedName\n               : undefined;\n      }\n    } else if (isDefined(value)) {\n      element.setAttribute(name, value);\n    } else if (element.getAttribute) {\n      // the extra argument \"2\" is to get the right thing for a.href in IE, see jQuery code\n      // some elements (e.g. Document) don't have get attribute, so return undefined\n      var ret = element.getAttribute(name, 2);\n      // normalize non-existing attributes to undefined (as jQuery)\n      return ret === null ? undefined : ret;\n    }\n  },\n\n  prop: function(element, name, value) {\n    if (isDefined(value)) {\n      element[name] = value;\n    } else {\n      return element[name];\n    }\n  },\n\n  text: (function() {\n    var NODE_TYPE_TEXT_PROPERTY = [];\n    if (msie < 9) {\n      NODE_TYPE_TEXT_PROPERTY[1] = 'innerText';    /** Element **/\n      NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue';    /** Text **/\n    } else {\n      NODE_TYPE_TEXT_PROPERTY[1] =                 /** Element **/\n      NODE_TYPE_TEXT_PROPERTY[3] = 'textContent';  /** Text **/\n    }\n    getText.$dv = '';\n    return getText;\n\n    function getText(element, value) {\n      var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];\n      if (isUndefined(value)) {\n        return textProp ? element[textProp] : '';\n      }\n      element[textProp] = value;\n    }\n  })(),\n\n  val: function(element, value) {\n    if (isUndefined(value)) {\n      if (nodeName_(element) === 'SELECT' && element.multiple) {\n        var result = [];\n        forEach(element.options, function (option) {\n          if (option.selected) {\n            result.push(option.value || option.text);\n          }\n        });\n        return result.length === 0 ? null : result;\n      }\n      return element.value;\n    }\n    element.value = value;\n  },\n\n  html: function(element, value) {\n    if (isUndefined(value)) {\n      return element.innerHTML;\n    }\n    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {\n      jqLiteDealoc(childNodes[i]);\n    }\n    element.innerHTML = value;\n  },\n\n  empty: jqLiteEmpty\n}, function(fn, name){\n  /**\n   * Properties: writes return selection, reads return first value\n   */\n  JQLite.prototype[name] = function(arg1, arg2) {\n    var i, key;\n    var nodeCount = this.length;\n\n    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it\n    // in a way that survives minification.\n    // jqLiteEmpty takes no arguments but is a setter.\n    if (fn !== jqLiteEmpty &&\n        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {\n      if (isObject(arg1)) {\n\n        // we are a write, but the object properties are the key/values\n        for (i = 0; i < nodeCount; i++) {\n          if (fn === jqLiteData) {\n            // data() takes the whole object in jQuery\n            fn(this[i], arg1);\n          } else {\n            for (key in arg1) {\n              fn(this[i], key, arg1[key]);\n            }\n          }\n        }\n        // return self for chaining\n        return this;\n      } else {\n        // we are a read, so read the first child.\n        // TODO: do we still need this?\n        var value = fn.$dv;\n        // Only if we have $dv do we iterate over all, otherwise it is just the first element.\n        var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;\n        for (var j = 0; j < jj; j++) {\n          var nodeValue = fn(this[j], arg1, arg2);\n          value = value ? value + nodeValue : nodeValue;\n        }\n        return value;\n      }\n    } else {\n      // we are a write, so apply to all children\n      for (i = 0; i < nodeCount; i++) {\n        fn(this[i], arg1, arg2);\n      }\n      // return self for chaining\n      return this;\n    }\n  };\n});\n\nfunction createEventHandler(element, events) {\n  var eventHandler = function (event, type) {\n    if (!event.preventDefault) {\n      event.preventDefault = function() {\n        event.returnValue = false; //ie\n      };\n    }\n\n    if (!event.stopPropagation) {\n      event.stopPropagation = function() {\n        event.cancelBubble = true; //ie\n      };\n    }\n\n    if (!event.target) {\n      event.target = event.srcElement || document;\n    }\n\n    if (isUndefined(event.defaultPrevented)) {\n      var prevent = event.preventDefault;\n      event.preventDefault = function() {\n        event.defaultPrevented = true;\n        prevent.call(event);\n      };\n      event.defaultPrevented = false;\n    }\n\n    event.isDefaultPrevented = function() {\n      return event.defaultPrevented || event.returnValue === false;\n    };\n\n    // Copy event handlers in case event handlers array is modified during execution.\n    var eventHandlersCopy = shallowCopy(events[type || event.type] || []);\n\n    forEach(eventHandlersCopy, function(fn) {\n      fn.call(element, event);\n    });\n\n    // Remove monkey-patched methods (IE),\n    // as they would cause memory leaks in IE8.\n    if (msie <= 8) {\n      // IE7/8 does not allow to delete property on native object\n      event.preventDefault = null;\n      event.stopPropagation = null;\n      event.isDefaultPrevented = null;\n    } else {\n      // It shouldn't affect normal browsers (native methods are defined on prototype).\n      delete event.preventDefault;\n      delete event.stopPropagation;\n      delete event.isDefaultPrevented;\n    }\n  };\n  eventHandler.elem = element;\n  return eventHandler;\n}\n\n//////////////////////////////////////////\n// Functions iterating traversal.\n// These functions chain results into a single\n// selector.\n//////////////////////////////////////////\nforEach({\n  removeData: jqLiteRemoveData,\n\n  dealoc: jqLiteDealoc,\n\n  on: function onFn(element, type, fn, unsupported){\n    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');\n\n    var events = jqLiteExpandoStore(element, 'events'),\n        handle = jqLiteExpandoStore(element, 'handle');\n\n    if (!events) jqLiteExpandoStore(element, 'events', events = {});\n    if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));\n\n    forEach(type.split(' '), function(type){\n      var eventFns = events[type];\n\n      if (!eventFns) {\n        if (type == 'mouseenter' || type == 'mouseleave') {\n          var contains = document.body.contains || document.body.compareDocumentPosition ?\n          function( a, b ) {\n            // jshint bitwise: false\n            var adown = a.nodeType === 9 ? a.documentElement : a,\n            bup = b && b.parentNode;\n            return a === bup || !!( bup && bup.nodeType === 1 && (\n              adown.contains ?\n              adown.contains( bup ) :\n              a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n              ));\n            } :\n            function( a, b ) {\n              if ( b ) {\n                while ( (b = b.parentNode) ) {\n                  if ( b === a ) {\n                    return true;\n                  }\n                }\n              }\n              return false;\n            };\n\n          events[type] = [];\n\n          // Refer to jQuery's implementation of mouseenter & mouseleave\n          // Read about mouseenter and mouseleave:\n          // http://www.quirksmode.org/js/events_mouse.html#link8\n          var eventmap = { mouseleave : \"mouseout\", mouseenter : \"mouseover\"};\n\n          onFn(element, eventmap[type], function(event) {\n            var target = this, related = event.relatedTarget;\n            // For mousenter/leave call the handler if related is outside the target.\n            // NB: No relatedTarget if the mouse left/entered the browser window\n            if ( !related || (related !== target && !contains(target, related)) ){\n              handle(event, type);\n            }\n          });\n\n        } else {\n          addEventListenerFn(element, type, handle);\n          events[type] = [];\n        }\n        eventFns = events[type];\n      }\n      eventFns.push(fn);\n    });\n  },\n\n  off: jqLiteOff,\n\n  one: function(element, type, fn) {\n    element = jqLite(element);\n\n    //add the listener twice so that when it is called\n    //you can remove the original function and still be\n    //able to call element.off(ev, fn) normally\n    element.on(type, function onFn() {\n      element.off(type, fn);\n      element.off(type, onFn);\n    });\n    element.on(type, fn);\n  },\n\n  replaceWith: function(element, replaceNode) {\n    var index, parent = element.parentNode;\n    jqLiteDealoc(element);\n    forEach(new JQLite(replaceNode), function(node){\n      if (index) {\n        parent.insertBefore(node, index.nextSibling);\n      } else {\n        parent.replaceChild(node, element);\n      }\n      index = node;\n    });\n  },\n\n  children: function(element) {\n    var children = [];\n    forEach(element.childNodes, function(element){\n      if (element.nodeType === 1)\n        children.push(element);\n    });\n    return children;\n  },\n\n  contents: function(element) {\n    return element.contentDocument || element.childNodes || [];\n  },\n\n  append: function(element, node) {\n    forEach(new JQLite(node), function(child){\n      if (element.nodeType === 1 || element.nodeType === 11) {\n        element.appendChild(child);\n      }\n    });\n  },\n\n  prepend: function(element, node) {\n    if (element.nodeType === 1) {\n      var index = element.firstChild;\n      forEach(new JQLite(node), function(child){\n        element.insertBefore(child, index);\n      });\n    }\n  },\n\n  wrap: function(element, wrapNode) {\n    wrapNode = jqLite(wrapNode)[0];\n    var parent = element.parentNode;\n    if (parent) {\n      parent.replaceChild(wrapNode, element);\n    }\n    wrapNode.appendChild(element);\n  },\n\n  remove: function(element) {\n    jqLiteDealoc(element);\n    var parent = element.parentNode;\n    if (parent) parent.removeChild(element);\n  },\n\n  after: function(element, newElement) {\n    var index = element, parent = element.parentNode;\n    forEach(new JQLite(newElement), function(node){\n      parent.insertBefore(node, index.nextSibling);\n      index = node;\n    });\n  },\n\n  addClass: jqLiteAddClass,\n  removeClass: jqLiteRemoveClass,\n\n  toggleClass: function(element, selector, condition) {\n    if (selector) {\n      forEach(selector.split(' '), function(className){\n        var classCondition = condition;\n        if (isUndefined(classCondition)) {\n          classCondition = !jqLiteHasClass(element, className);\n        }\n        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);\n      });\n    }\n  },\n\n  parent: function(element) {\n    var parent = element.parentNode;\n    return parent && parent.nodeType !== 11 ? parent : null;\n  },\n\n  next: function(element) {\n    if (element.nextElementSibling) {\n      return element.nextElementSibling;\n    }\n\n    // IE8 doesn't have nextElementSibling\n    var elm = element.nextSibling;\n    while (elm != null && elm.nodeType !== 1) {\n      elm = elm.nextSibling;\n    }\n    return elm;\n  },\n\n  find: function(element, selector) {\n    if (element.getElementsByTagName) {\n      return element.getElementsByTagName(selector);\n    } else {\n      return [];\n    }\n  },\n\n  clone: jqLiteClone,\n\n  triggerHandler: function(element, event, extraParameters) {\n\n    var dummyEvent, eventFnsCopy, handlerArgs;\n    var eventName = event.type || event;\n    var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName];\n\n    if (eventFns) {\n\n      // Create a dummy event to pass to the handlers\n      dummyEvent = {\n        preventDefault: function() { this.defaultPrevented = true; },\n        isDefaultPrevented: function() { return this.defaultPrevented === true; },\n        stopPropagation: noop,\n        type: eventName,\n        target: element\n      };\n\n      // If a custom event was provided then extend our dummy event with it\n      if (event.type) {\n        dummyEvent = extend(dummyEvent, event);\n      }\n\n      // Copy event handlers in case event handlers array is modified during execution.\n      eventFnsCopy = shallowCopy(eventFns);\n      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];\n\n      forEach(eventFnsCopy, function(fn) {\n        fn.apply(element, handlerArgs);\n      });\n\n    }\n  }\n}, function(fn, name){\n  /**\n   * chaining functions\n   */\n  JQLite.prototype[name] = function(arg1, arg2, arg3) {\n    var value;\n    for(var i=0; i < this.length; i++) {\n      if (isUndefined(value)) {\n        value = fn(this[i], arg1, arg2, arg3);\n        if (isDefined(value)) {\n          // any function which returns a value needs to be wrapped\n          value = jqLite(value);\n        }\n      } else {\n        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));\n      }\n    }\n    return isDefined(value) ? value : this;\n  };\n\n  // bind legacy bind/unbind to on/off\n  JQLite.prototype.bind = JQLite.prototype.on;\n  JQLite.prototype.unbind = JQLite.prototype.off;\n});\n\n/**\n * Computes a hash of an 'obj'.\n * Hash of a:\n *  string is string\n *  number is number as string\n *  object is either result of calling $$hashKey function on the object or uniquely generated id,\n *         that is also assigned to the $$hashKey property of the object.\n *\n * @param obj\n * @returns {string} hash string such that the same input will have the same hash string.\n *         The resulting string key is in 'type:hashKey' format.\n */\nfunction hashKey(obj, nextUidFn) {\n  var objType = typeof obj,\n      key;\n\n  if (objType == 'function' || (objType == 'object' && obj !== null)) {\n    if (typeof (key = obj.$$hashKey) == 'function') {\n      // must invoke on object to keep the right this\n      key = obj.$$hashKey();\n    } else if (key === undefined) {\n      key = obj.$$hashKey = (nextUidFn || nextUid)();\n    }\n  } else {\n    key = obj;\n  }\n\n  return objType + ':' + key;\n}\n\n/**\n * HashMap which can use objects as keys\n */\nfunction HashMap(array, isolatedUid) {\n  if (isolatedUid) {\n    var uid = 0;\n    this.nextUid = function() {\n      return ++uid;\n    };\n  }\n  forEach(array, this.put, this);\n}\nHashMap.prototype = {\n  /**\n   * Store key value pair\n   * @param key key to store can be any type\n   * @param value value to store can be any type\n   */\n  put: function(key, value) {\n    this[hashKey(key, this.nextUid)] = value;\n  },\n\n  /**\n   * @param key\n   * @returns {Object} the value for the key\n   */\n  get: function(key) {\n    return this[hashKey(key, this.nextUid)];\n  },\n\n  /**\n   * Remove the key/value pair\n   * @param key\n   */\n  remove: function(key) {\n    var value = this[key = hashKey(key, this.nextUid)];\n    delete this[key];\n    return value;\n  }\n};\n\n/**\n * @ngdoc function\n * @module ng\n * @name angular.injector\n * @kind function\n *\n * @description\n * Creates an injector object that can be used for retrieving services as well as for\n * dependency injection (see {@link guide/di dependency injection}).\n *\n\n * @param {Array.<string|Function>} modules A list of module functions or their aliases. See\n *        {@link angular.module}. The `ng` module must be explicitly added.\n * @returns {injector} Injector object. See {@link auto.$injector $injector}.\n *\n * @example\n * Typical usage\n * ```js\n *   // create an injector\n *   var $injector = angular.injector(['ng']);\n *\n *   // use the injector to kick off your application\n *   // use the type inference to auto inject arguments, or use implicit injection\n *   $injector.invoke(function($rootScope, $compile, $document){\n *     $compile($document)($rootScope);\n *     $rootScope.$digest();\n *   });\n * ```\n *\n * Sometimes you want to get access to the injector of a currently running Angular app\n * from outside Angular. Perhaps, you want to inject and compile some markup after the\n * application has been bootstrapped. You can do this using the extra `injector()` added\n * to JQuery/jqLite elements. See {@link angular.element}.\n *\n * *This is fairly rare but could be the case if a third party library is injecting the\n * markup.*\n *\n * In the following example a new block of HTML containing a `ng-controller`\n * directive is added to the end of the document body by JQuery. We then compile and link\n * it into the current AngularJS scope.\n *\n * ```js\n * var $div = $('<div ng-controller=\"MyCtrl\">{{content.label}}</div>');\n * $(document.body).append($div);\n *\n * angular.element(document).injector().invoke(function($compile) {\n *   var scope = angular.element($div).scope();\n *   $compile($div)(scope);\n * });\n * ```\n */\n\n\n/**\n * @ngdoc module\n * @name auto\n * @description\n *\n * Implicit module which gets automatically added to each {@link auto.$injector $injector}.\n */\n\nvar FN_ARGS = /^function\\s*[^\\(]*\\(\\s*([^\\)]*)\\)/m;\nvar FN_ARG_SPLIT = /,/;\nvar FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/;\nvar STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/mg;\nvar $injectorMinErr = minErr('$injector');\nfunction annotate(fn) {\n  var $inject,\n      fnText,\n      argDecl,\n      last;\n\n  if (typeof fn === 'function') {\n    if (!($inject = fn.$inject)) {\n      $inject = [];\n      if (fn.length) {\n        fnText = fn.toString().replace(STRIP_COMMENTS, '');\n        argDecl = fnText.match(FN_ARGS);\n        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){\n          arg.replace(FN_ARG, function(all, underscore, name){\n            $inject.push(name);\n          });\n        });\n      }\n      fn.$inject = $inject;\n    }\n  } else if (isArray(fn)) {\n    last = fn.length - 1;\n    assertArgFn(fn[last], 'fn');\n    $inject = fn.slice(0, last);\n  } else {\n    assertArgFn(fn, 'fn', true);\n  }\n  return $inject;\n}\n\n///////////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $injector\n *\n * @description\n *\n * `$injector` is used to retrieve object instances as defined by\n * {@link auto.$provide provider}, instantiate types, invoke methods,\n * and load modules.\n *\n * The following always holds true:\n *\n * ```js\n *   var $injector = angular.injector();\n *   expect($injector.get('$injector')).toBe($injector);\n *   expect($injector.invoke(function($injector){\n *     return $injector;\n *   })).toBe($injector);\n * ```\n *\n * # Injection Function Annotation\n *\n * JavaScript does not have annotations, and annotations are needed for dependency injection. The\n * following are all valid ways of annotating function with injection arguments and are equivalent.\n *\n * ```js\n *   // inferred (only works if code not minified/obfuscated)\n *   $injector.invoke(function(serviceA){});\n *\n *   // annotated\n *   function explicit(serviceA) {};\n *   explicit.$inject = ['serviceA'];\n *   $injector.invoke(explicit);\n *\n *   // inline\n *   $injector.invoke(['serviceA', function(serviceA){}]);\n * ```\n *\n * ## Inference\n *\n * In JavaScript calling `toString()` on a function returns the function definition. The definition\n * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with\n * minification, and obfuscation tools since these tools change the argument names.\n *\n * ## `$inject` Annotation\n * By adding an `$inject` property onto a function the injection parameters can be specified.\n *\n * ## Inline\n * As an array of injection names, where the last item in the array is the function to call.\n */\n\n/**\n * @ngdoc method\n * @name $injector#get\n *\n * @description\n * Return an instance of the service.\n *\n * @param {string} name The name of the instance to retrieve.\n * @return {*} The instance.\n */\n\n/**\n * @ngdoc method\n * @name $injector#invoke\n *\n * @description\n * Invoke the method and supply the method arguments from the `$injector`.\n *\n * @param {!Function} fn The function to invoke. Function parameters are injected according to the\n *   {@link guide/di $inject Annotation} rules.\n * @param {Object=} self The `this` for the invoked method.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n *                         object first, before the `$injector` is consulted.\n * @returns {*} the value returned by the invoked `fn` function.\n */\n\n/**\n * @ngdoc method\n * @name $injector#has\n *\n * @description\n * Allows the user to query if the particular service exists.\n *\n * @param {string} name Name of the service to query.\n * @returns {boolean} `true` if injector has given service.\n */\n\n/**\n * @ngdoc method\n * @name $injector#instantiate\n * @description\n * Create a new instance of JS type. The method takes a constructor function, invokes the new\n * operator, and supplies all of the arguments to the constructor function as specified by the\n * constructor annotation.\n *\n * @param {Function} Type Annotated constructor function.\n * @param {Object=} locals Optional object. If preset then any argument names are read from this\n * object first, before the `$injector` is consulted.\n * @returns {Object} new instance of `Type`.\n */\n\n/**\n * @ngdoc method\n * @name $injector#annotate\n *\n * @description\n * Returns an array of service names which the function is requesting for injection. This API is\n * used by the injector to determine which services need to be injected into the function when the\n * function is invoked. There are three ways in which the function can be annotated with the needed\n * dependencies.\n *\n * # Argument names\n *\n * The simplest form is to extract the dependencies from the arguments of the function. This is done\n * by converting the function into a string using `toString()` method and extracting the argument\n * names.\n * ```js\n *   // Given\n *   function MyController($scope, $route) {\n *     // ...\n *   }\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * This method does not work with code minification / obfuscation. For this reason the following\n * annotation strategies are supported.\n *\n * # The `$inject` property\n *\n * If a function has an `$inject` property and its value is an array of strings, then the strings\n * represent names of services to be injected into the function.\n * ```js\n *   // Given\n *   var MyController = function(obfuscatedScope, obfuscatedRoute) {\n *     // ...\n *   }\n *   // Define function dependencies\n *   MyController['$inject'] = ['$scope', '$route'];\n *\n *   // Then\n *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);\n * ```\n *\n * # The array notation\n *\n * It is often desirable to inline Injected functions and that's when setting the `$inject` property\n * is very inconvenient. In these situations using the array notation to specify the dependencies in\n * a way that survives minification is a better choice:\n *\n * ```js\n *   // We wish to write this (not minification / obfuscation safe)\n *   injector.invoke(function($compile, $rootScope) {\n *     // ...\n *   });\n *\n *   // We are forced to write break inlining\n *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {\n *     // ...\n *   };\n *   tmpFn.$inject = ['$compile', '$rootScope'];\n *   injector.invoke(tmpFn);\n *\n *   // To better support inline function the inline annotation is supported\n *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {\n *     // ...\n *   }]);\n *\n *   // Therefore\n *   expect(injector.annotate(\n *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])\n *    ).toEqual(['$compile', '$rootScope']);\n * ```\n *\n * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to\n * be retrieved as described above.\n *\n * @returns {Array.<string>} The names of the services which the function requires.\n */\n\n\n\n\n/**\n * @ngdoc service\n * @name $provide\n *\n * @description\n *\n * The {@link auto.$provide $provide} service has a number of methods for registering components\n * with the {@link auto.$injector $injector}. Many of these functions are also exposed on\n * {@link angular.Module}.\n *\n * An Angular **service** is a singleton object created by a **service factory**.  These **service\n * factories** are functions which, in turn, are created by a **service provider**.\n * The **service providers** are constructor functions. When instantiated they must contain a\n * property called `$get`, which holds the **service factory** function.\n *\n * When you request a service, the {@link auto.$injector $injector} is responsible for finding the\n * correct **service provider**, instantiating it and then calling its `$get` **service factory**\n * function to get the instance of the **service**.\n *\n * Often services have no configuration options and there is no need to add methods to the service\n * provider.  The provider will be no more than a constructor function with a `$get` property. For\n * these cases the {@link auto.$provide $provide} service has additional helper methods to register\n * services without specifying a provider.\n *\n * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the\n *     {@link auto.$injector $injector}\n * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by\n *     providers and services.\n * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by\n *     services, not providers.\n * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,\n *     that will be wrapped in a **service provider** object, whose `$get` property will contain the\n *     given factory function.\n * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`\n *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate\n *      a new object using the given constructor function.\n *\n * See the individual methods for more information and examples.\n */\n\n/**\n * @ngdoc method\n * @name $provide#provider\n * @description\n *\n * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions\n * are constructor functions, whose instances are responsible for \"providing\" a factory for a\n * service.\n *\n * Service provider names start with the name of the service they provide followed by `Provider`.\n * For example, the {@link ng.$log $log} service has a provider called\n * {@link ng.$logProvider $logProvider}.\n *\n * Service provider objects can have additional methods which allow configuration of the provider\n * and its service. Importantly, you can configure what kind of service is created by the `$get`\n * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a\n * method {@link ng.$logProvider#debugEnabled debugEnabled}\n * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the\n * console or not.\n *\n * @param {string} name The name of the instance. NOTE: the provider will be available under `name +\n                        'Provider'` key.\n * @param {(Object|function())} provider If the provider is:\n *\n *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using\n *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.\n *   - `Constructor`: a new instance of the provider will be created using\n *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.\n *\n * @returns {Object} registered provider instance\n\n * @example\n *\n * The following example shows how to create a simple event tracking service and register it using\n * {@link auto.$provide#provider $provide.provider()}.\n *\n * ```js\n *  // Define the eventTracker provider\n *  function EventTrackerProvider() {\n *    var trackingUrl = '/track';\n *\n *    // A provider method for configuring where the tracked events should been saved\n *    this.setTrackingUrl = function(url) {\n *      trackingUrl = url;\n *    };\n *\n *    // The service factory function\n *    this.$get = ['$http', function($http) {\n *      var trackedEvents = {};\n *      return {\n *        // Call this to track an event\n *        event: function(event) {\n *          var count = trackedEvents[event] || 0;\n *          count += 1;\n *          trackedEvents[event] = count;\n *          return count;\n *        },\n *        // Call this to save the tracked events to the trackingUrl\n *        save: function() {\n *          $http.post(trackingUrl, trackedEvents);\n *        }\n *      };\n *    }];\n *  }\n *\n *  describe('eventTracker', function() {\n *    var postSpy;\n *\n *    beforeEach(module(function($provide) {\n *      // Register the eventTracker provider\n *      $provide.provider('eventTracker', EventTrackerProvider);\n *    }));\n *\n *    beforeEach(module(function(eventTrackerProvider) {\n *      // Configure eventTracker provider\n *      eventTrackerProvider.setTrackingUrl('/custom-track');\n *    }));\n *\n *    it('tracks events', inject(function(eventTracker) {\n *      expect(eventTracker.event('login')).toEqual(1);\n *      expect(eventTracker.event('login')).toEqual(2);\n *    }));\n *\n *    it('saves to the tracking url', inject(function(eventTracker, $http) {\n *      postSpy = spyOn($http, 'post');\n *      eventTracker.event('login');\n *      eventTracker.save();\n *      expect(postSpy).toHaveBeenCalled();\n *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');\n *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');\n *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });\n *    }));\n *  });\n * ```\n */\n\n/**\n * @ngdoc method\n * @name $provide#factory\n * @description\n *\n * Register a **service factory**, which will be called to return the service instance.\n * This is short for registering a service where its provider consists of only a `$get` property,\n * which is the given service factory function.\n * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to\n * configure your service in a provider.\n *\n * @param {string} name The name of the instance.\n * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand\n *                            for `$provide.provider(name, {$get: $getFn})`.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service\n * ```js\n *   $provide.factory('ping', ['$http', function($http) {\n *     return function ping() {\n *       return $http.send('/ping');\n *     };\n *   }]);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#service\n * @description\n *\n * Register a **service constructor**, which will be invoked with `new` to create the service\n * instance.\n * This is short for registering a service where its provider's `$get` property is the service\n * constructor function that will be used to instantiate the service instance.\n *\n * You should use {@link auto.$provide#service $provide.service(class)} if you define your service\n * as a type/class.\n *\n * @param {string} name The name of the instance.\n * @param {Function} constructor A class (constructor function) that will be instantiated.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here is an example of registering a service using\n * {@link auto.$provide#service $provide.service(class)}.\n * ```js\n *   var Ping = function($http) {\n *     this.$http = $http;\n *   };\n *\n *   Ping.$inject = ['$http'];\n *\n *   Ping.prototype.send = function() {\n *     return this.$http.get('/ping');\n *   };\n *   $provide.service('ping', Ping);\n * ```\n * You would then inject and use this service like this:\n * ```js\n *   someModule.controller('Ctrl', ['ping', function(ping) {\n *     ping.send();\n *   }]);\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#value\n * @description\n *\n * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a\n * number, an array, an object or a function.  This is short for registering a service where its\n * provider's `$get` property is a factory function that takes no arguments and returns the **value\n * service**.\n *\n * Value services are similar to constant services, except that they cannot be injected into a\n * module configuration function (see {@link angular.Module#config}) but they can be overridden by\n * an Angular\n * {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the instance.\n * @param {*} value The value.\n * @returns {Object} registered provider instance\n *\n * @example\n * Here are some examples of creating value services.\n * ```js\n *   $provide.value('ADMIN_USER', 'admin');\n *\n *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });\n *\n *   $provide.value('halfOf', function(value) {\n *     return value / 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#constant\n * @description\n *\n * Register a **constant service**, such as a string, a number, an array, an object or a function,\n * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be\n * injected into a module configuration function (see {@link angular.Module#config}) and it cannot\n * be overridden by an Angular {@link auto.$provide#decorator decorator}.\n *\n * @param {string} name The name of the constant.\n * @param {*} value The constant value.\n * @returns {Object} registered instance\n *\n * @example\n * Here a some examples of creating constants:\n * ```js\n *   $provide.constant('SHARD_HEIGHT', 306);\n *\n *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);\n *\n *   $provide.constant('double', function(value) {\n *     return value * 2;\n *   });\n * ```\n */\n\n\n/**\n * @ngdoc method\n * @name $provide#decorator\n * @description\n *\n * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator\n * intercepts the creation of a service, allowing it to override or modify the behaviour of the\n * service. The object returned by the decorator may be the original service, or a new service\n * object which replaces or wraps and delegates to the original service.\n *\n * @param {string} name The name of the service to decorate.\n * @param {function()} decorator This function will be invoked when the service needs to be\n *    instantiated and should return the decorated service instance. The function is called using\n *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.\n *    Local injection arguments:\n *\n *    * `$delegate` - The original service instance, which can be monkey patched, configured,\n *      decorated or delegated to.\n *\n * @example\n * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting\n * calls to {@link ng.$log#error $log.warn()}.\n * ```js\n *   $provide.decorator('$log', ['$delegate', function($delegate) {\n *     $delegate.warn = $delegate.error;\n *     return $delegate;\n *   }]);\n * ```\n */\n\n\nfunction createInjector(modulesToLoad) {\n  var INSTANTIATING = {},\n      providerSuffix = 'Provider',\n      path = [],\n      loadedModules = new HashMap([], true),\n      providerCache = {\n        $provide: {\n            provider: supportObject(provider),\n            factory: supportObject(factory),\n            service: supportObject(service),\n            value: supportObject(value),\n            constant: supportObject(constant),\n            decorator: decorator\n          }\n      },\n      providerInjector = (providerCache.$injector =\n          createInternalInjector(providerCache, function() {\n            throw $injectorMinErr('unpr', \"Unknown provider: {0}\", path.join(' <- '));\n          })),\n      instanceCache = {},\n      instanceInjector = (instanceCache.$injector =\n          createInternalInjector(instanceCache, function(servicename) {\n            var provider = providerInjector.get(servicename + providerSuffix);\n            return instanceInjector.invoke(provider.$get, provider);\n          }));\n\n\n  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });\n\n  return instanceInjector;\n\n  ////////////////////////////////////\n  // $provider\n  ////////////////////////////////////\n\n  function supportObject(delegate) {\n    return function(key, value) {\n      if (isObject(key)) {\n        forEach(key, reverseParams(delegate));\n      } else {\n        return delegate(key, value);\n      }\n    };\n  }\n\n  function provider(name, provider_) {\n    assertNotHasOwnProperty(name, 'service');\n    if (isFunction(provider_) || isArray(provider_)) {\n      provider_ = providerInjector.instantiate(provider_);\n    }\n    if (!provider_.$get) {\n      throw $injectorMinErr('pget', \"Provider '{0}' must define $get factory method.\", name);\n    }\n    return providerCache[name + providerSuffix] = provider_;\n  }\n\n  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }\n\n  function service(name, constructor) {\n    return factory(name, ['$injector', function($injector) {\n      return $injector.instantiate(constructor);\n    }]);\n  }\n\n  function value(name, val) { return factory(name, valueFn(val)); }\n\n  function constant(name, value) {\n    assertNotHasOwnProperty(name, 'constant');\n    providerCache[name] = value;\n    instanceCache[name] = value;\n  }\n\n  function decorator(serviceName, decorFn) {\n    var origProvider = providerInjector.get(serviceName + providerSuffix),\n        orig$get = origProvider.$get;\n\n    origProvider.$get = function() {\n      var origInstance = instanceInjector.invoke(orig$get, origProvider);\n      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});\n    };\n  }\n\n  ////////////////////////////////////\n  // Module Loading\n  ////////////////////////////////////\n  function loadModules(modulesToLoad){\n    var runBlocks = [], moduleFn, invokeQueue, i, ii;\n    forEach(modulesToLoad, function(module) {\n      if (loadedModules.get(module)) return;\n      loadedModules.put(module, true);\n\n      try {\n        if (isString(module)) {\n          moduleFn = angularModule(module);\n          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);\n\n          for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {\n            var invokeArgs = invokeQueue[i],\n                provider = providerInjector.get(invokeArgs[0]);\n\n            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);\n          }\n        } else if (isFunction(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else if (isArray(module)) {\n            runBlocks.push(providerInjector.invoke(module));\n        } else {\n          assertArgFn(module, 'module');\n        }\n      } catch (e) {\n        if (isArray(module)) {\n          module = module[module.length - 1];\n        }\n        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {\n          // Safari & FF's stack traces don't contain error.message content\n          // unlike those of Chrome and IE\n          // So if stack doesn't contain message, we create a new string that contains both.\n          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.\n          /* jshint -W022 */\n          e = e.message + '\\n' + e.stack;\n        }\n        throw $injectorMinErr('modulerr', \"Failed to instantiate module {0} due to:\\n{1}\",\n                  module, e.stack || e.message || e);\n      }\n    });\n    return runBlocks;\n  }\n\n  ////////////////////////////////////\n  // internal Injector\n  ////////////////////////////////////\n\n  function createInternalInjector(cache, factory) {\n\n    function getService(serviceName) {\n      if (cache.hasOwnProperty(serviceName)) {\n        if (cache[serviceName] === INSTANTIATING) {\n          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',\n                    serviceName + ' <- ' + path.join(' <- '));\n        }\n        return cache[serviceName];\n      } else {\n        try {\n          path.unshift(serviceName);\n          cache[serviceName] = INSTANTIATING;\n          return cache[serviceName] = factory(serviceName);\n        } catch (err) {\n          if (cache[serviceName] === INSTANTIATING) {\n            delete cache[serviceName];\n          }\n          throw err;\n        } finally {\n          path.shift();\n        }\n      }\n    }\n\n    function invoke(fn, self, locals){\n      var args = [],\n          $inject = annotate(fn),\n          length, i,\n          key;\n\n      for(i = 0, length = $inject.length; i < length; i++) {\n        key = $inject[i];\n        if (typeof key !== 'string') {\n          throw $injectorMinErr('itkn',\n                  'Incorrect injection token! Expected service name as string, got {0}', key);\n        }\n        args.push(\n          locals && locals.hasOwnProperty(key)\n          ? locals[key]\n          : getService(key)\n        );\n      }\n      if (isArray(fn)) {\n        fn = fn[length];\n      }\n\n      // http://jsperf.com/angularjs-invoke-apply-vs-switch\n      // #5388\n      return fn.apply(self, args);\n    }\n\n    function instantiate(Type, locals) {\n      var Constructor = function() {},\n          instance, returnedValue;\n\n      // Check if Type is annotated and use just the given function at n-1 as parameter\n      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);\n      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;\n      instance = new Constructor();\n      returnedValue = invoke(Type, instance, locals);\n\n      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;\n    }\n\n    return {\n      invoke: invoke,\n      instantiate: instantiate,\n      get: getService,\n      annotate: annotate,\n      has: function(name) {\n        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);\n      }\n    };\n  }\n}\n\n/**\n * @ngdoc service\n * @name $anchorScroll\n * @kind function\n * @requires $window\n * @requires $location\n * @requires $rootScope\n *\n * @description\n * When called, it checks current value of `$location.hash()` and scrolls to the related element,\n * according to rules specified in\n * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).\n *\n * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.\n * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <div id=\"scrollArea\" ng-controller=\"ScrollCtrl\">\n         <a ng-click=\"gotoBottom()\">Go to bottom</a>\n         <a id=\"bottom\"></a> You're at the bottom!\n       </div>\n     </file>\n     <file name=\"script.js\">\n       function ScrollCtrl($scope, $location, $anchorScroll) {\n         $scope.gotoBottom = function (){\n           // set the location.hash to the id of\n           // the element you wish to scroll to.\n           $location.hash('bottom');\n\n           // call $anchorScroll()\n           $anchorScroll();\n         };\n       }\n     </file>\n     <file name=\"style.css\">\n       #scrollArea {\n         height: 350px;\n         overflow: auto;\n       }\n\n       #bottom {\n         display: block;\n         margin-top: 2000px;\n       }\n     </file>\n   </example>\n */\nfunction $AnchorScrollProvider() {\n\n  var autoScrollingEnabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $anchorScrollProvider#disableAutoScrolling\n   *\n   * @description\n   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to\n   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />\n   * Use this method to disable automatic scrolling.\n   *\n   * If automatic scrolling is disabled, one must explicitly call\n   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the\n   * current hash.\n   */\n  this.disableAutoScrolling = function() {\n    autoScrollingEnabled = false;\n  };\n\n  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {\n    var document = $window.document;\n\n    // helper function to get first anchor from a NodeList\n    // can't use filter.filter, as it accepts only instances of Array\n    // and IE can't convert NodeList to an array using [].slice\n    // TODO(vojta): use filter if we change it to accept lists as well\n    function getFirstAnchor(list) {\n      var result = null;\n      forEach(list, function(element) {\n        if (!result && lowercase(element.nodeName) === 'a') result = element;\n      });\n      return result;\n    }\n\n    function scroll() {\n      var hash = $location.hash(), elm;\n\n      // empty hash, scroll to the top of the page\n      if (!hash) $window.scrollTo(0, 0);\n\n      // element with given id\n      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();\n\n      // first anchor with given name :-D\n      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();\n\n      // no element and hash == 'top', scroll to the top of the page\n      else if (hash === 'top') $window.scrollTo(0, 0);\n    }\n\n    // does not scroll when user clicks on anchor link that is currently on\n    // (no url change, no $location.hash() change), browser native does scroll\n    if (autoScrollingEnabled) {\n      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},\n        function autoScrollWatchAction() {\n          $rootScope.$evalAsync(scroll);\n        });\n    }\n\n    return scroll;\n  }];\n}\n\nvar $animateMinErr = minErr('$animate');\n\n/**\n * @ngdoc provider\n * @name $animateProvider\n *\n * @description\n * Default implementation of $animate that doesn't perform any animations, instead just\n * synchronously performs DOM\n * updates and calls done() callbacks.\n *\n * In order to enable animations the ngAnimate module has to be loaded.\n *\n * To see the functional implementation check out src/ngAnimate/animate.js\n */\nvar $AnimateProvider = ['$provide', function($provide) {\n\n\n  this.$$selectors = {};\n\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#register\n   *\n   * @description\n   * Registers a new injectable animation factory function. The factory function produces the\n   * animation object which contains callback functions for each event that is expected to be\n   * animated.\n   *\n   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`\n   *   must be called once the element animation is complete. If a function is returned then the\n   *   animation service will use this function to cancel the animation whenever a cancel event is\n   *   triggered.\n   *\n   *\n   * ```js\n   *   return {\n     *     eventFn : function(element, done) {\n     *       //code to run the animation\n     *       //once complete, then run done()\n     *       return function cancellationFunction() {\n     *         //code to cancel the animation\n     *       }\n     *     }\n     *   }\n   * ```\n   *\n   * @param {string} name The name of the animation.\n   * @param {Function} factory The factory function that will be executed to return the animation\n   *                           object.\n   */\n  this.register = function(name, factory) {\n    var key = name + '-animation';\n    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',\n        \"Expecting class selector starting with '.' got '{0}'.\", name);\n    this.$$selectors[name.substr(1)] = key;\n    $provide.factory(key, factory);\n  };\n\n  /**\n   * @ngdoc method\n   * @name $animateProvider#classNameFilter\n   *\n   * @description\n   * Sets and/or returns the CSS class regular expression that is checked when performing\n   * an animation. Upon bootstrap the classNameFilter value is not set at all and will\n   * therefore enable $animate to attempt to perform an animation on any element.\n   * When setting the classNameFilter value, animations will only be performed on elements\n   * that successfully match the filter expression. This in turn can boost performance\n   * for low-powered devices as well as applications containing a lot of structural operations.\n   * @param {RegExp=} expression The className expression which will be checked against all animations\n   * @return {RegExp} The current CSS className expression value. If null then there is no expression value\n   */\n  this.classNameFilter = function(expression) {\n    if(arguments.length === 1) {\n      this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;\n    }\n    return this.$$classNameFilter;\n  };\n\n  this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {\n\n    function async(fn) {\n      fn && $$asyncCallback(fn);\n    }\n\n    /**\n     *\n     * @ngdoc service\n     * @name $animate\n     * @description The $animate service provides rudimentary DOM manipulation functions to\n     * insert, remove and move elements within the DOM, as well as adding and removing classes.\n     * This service is the core service used by the ngAnimate $animator service which provides\n     * high-level animation hooks for CSS and JavaScript.\n     *\n     * $animate is available in the AngularJS core, however, the ngAnimate module must be included\n     * to enable full out animation support. Otherwise, $animate will only perform simple DOM\n     * manipulation operations.\n     *\n     * To learn more about enabling animation support, click here to visit the {@link ngAnimate\n     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service\n     * page}.\n     */\n    return {\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#enter\n       * @kind function\n       * @description Inserts the element into the DOM either after the `after` element or within\n       *   the `parent` element. Once complete, the done() callback will be fired (if provided).\n       * @param {DOMElement} element the element which will be inserted into the DOM\n       * @param {DOMElement} parent the parent element which will append the element as\n       *   a child (if the after element is not present)\n       * @param {DOMElement} after the sibling element which will append the element\n       *   after itself\n       * @param {Function=} done callback function that will be called after the element has been\n       *   inserted into the DOM\n       */\n      enter : function(element, parent, after, done) {\n        if (after) {\n          after.after(element);\n        } else {\n          if (!parent || !parent[0]) {\n            parent = after.parent();\n          }\n          parent.append(element);\n        }\n        async(done);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#leave\n       * @kind function\n       * @description Removes the element from the DOM. Once complete, the done() callback will be\n       *   fired (if provided).\n       * @param {DOMElement} element the element which will be removed from the DOM\n       * @param {Function=} done callback function that will be called after the element has been\n       *   removed from the DOM\n       */\n      leave : function(element, done) {\n        element.remove();\n        async(done);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#move\n       * @kind function\n       * @description Moves the position of the provided element within the DOM to be placed\n       * either after the `after` element or inside of the `parent` element. Once complete, the\n       * done() callback will be fired (if provided).\n       *\n       * @param {DOMElement} element the element which will be moved around within the\n       *   DOM\n       * @param {DOMElement} parent the parent element where the element will be\n       *   inserted into (if the after element is not present)\n       * @param {DOMElement} after the sibling element where the element will be\n       *   positioned next to\n       * @param {Function=} done the callback function (if provided) that will be fired after the\n       *   element has been moved to its new position\n       */\n      move : function(element, parent, after, done) {\n        // Do not remove element before insert. Removing will cause data associated with the\n        // element to be dropped. Insert will implicitly do the remove.\n        this.enter(element, parent, after, done);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#addClass\n       * @kind function\n       * @description Adds the provided className CSS class value to the provided element. Once\n       * complete, the done() callback will be fired (if provided).\n       * @param {DOMElement} element the element which will have the className value\n       *   added to it\n       * @param {string} className the CSS class which will be added to the element\n       * @param {Function=} done the callback function (if provided) that will be fired after the\n       *   className value has been added to the element\n       */\n      addClass : function(element, className, done) {\n        className = isString(className) ?\n                      className :\n                      isArray(className) ? className.join(' ') : '';\n        forEach(element, function (element) {\n          jqLiteAddClass(element, className);\n        });\n        async(done);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#removeClass\n       * @kind function\n       * @description Removes the provided className CSS class value from the provided element.\n       * Once complete, the done() callback will be fired (if provided).\n       * @param {DOMElement} element the element which will have the className value\n       *   removed from it\n       * @param {string} className the CSS class which will be removed from the element\n       * @param {Function=} done the callback function (if provided) that will be fired after the\n       *   className value has been removed from the element\n       */\n      removeClass : function(element, className, done) {\n        className = isString(className) ?\n                      className :\n                      isArray(className) ? className.join(' ') : '';\n        forEach(element, function (element) {\n          jqLiteRemoveClass(element, className);\n        });\n        async(done);\n      },\n\n      /**\n       *\n       * @ngdoc method\n       * @name $animate#setClass\n       * @kind function\n       * @description Adds and/or removes the given CSS classes to and from the element.\n       * Once complete, the done() callback will be fired (if provided).\n       * @param {DOMElement} element the element which will have its CSS classes changed\n       *   removed from it\n       * @param {string} add the CSS classes which will be added to the element\n       * @param {string} remove the CSS class which will be removed from the element\n       * @param {Function=} done the callback function (if provided) that will be fired after the\n       *   CSS classes have been set on the element\n       */\n      setClass : function(element, add, remove, done) {\n        forEach(element, function (element) {\n          jqLiteAddClass(element, add);\n          jqLiteRemoveClass(element, remove);\n        });\n        async(done);\n      },\n\n      enabled : noop\n    };\n  }];\n}];\n\nfunction $$AsyncCallbackProvider(){\n  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {\n    return $$rAF.supported\n      ? function(fn) { return $$rAF(fn); }\n      : function(fn) {\n        return $timeout(fn, 0, false);\n      };\n  }];\n}\n\n/* global stripHash: true */\n\n/**\n * ! This is a private undocumented service !\n *\n * @name $browser\n * @requires $log\n * @description\n * This object has two goals:\n *\n * - hide all the global state in the browser caused by the window object\n * - abstract away all the browser specific features and inconsistencies\n *\n * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`\n * service, which can be used for convenient testing of the application without the interaction with\n * the real browser apis.\n */\n/**\n * @param {object} window The global window object.\n * @param {object} document jQuery wrapped document.\n * @param {function()} XHR XMLHttpRequest constructor.\n * @param {object} $log console.log or an object with the same interface.\n * @param {object} $sniffer $sniffer service\n */\nfunction Browser(window, document, $log, $sniffer) {\n  var self = this,\n      rawDocument = document[0],\n      location = window.location,\n      history = window.history,\n      setTimeout = window.setTimeout,\n      clearTimeout = window.clearTimeout,\n      pendingDeferIds = {};\n\n  self.isMock = false;\n\n  var outstandingRequestCount = 0;\n  var outstandingRequestCallbacks = [];\n\n  // TODO(vojta): remove this temporary api\n  self.$$completeOutstandingRequest = completeOutstandingRequest;\n  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };\n\n  /**\n   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`\n   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.\n   */\n  function completeOutstandingRequest(fn) {\n    try {\n      fn.apply(null, sliceArgs(arguments, 1));\n    } finally {\n      outstandingRequestCount--;\n      if (outstandingRequestCount === 0) {\n        while(outstandingRequestCallbacks.length) {\n          try {\n            outstandingRequestCallbacks.pop()();\n          } catch (e) {\n            $log.error(e);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * @private\n   * Note: this method is used only by scenario runner\n   * TODO(vojta): prefix this method with $$ ?\n   * @param {function()} callback Function that will be called when no outstanding request\n   */\n  self.notifyWhenNoOutstandingRequests = function(callback) {\n    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire\n    // at some deterministic time in respect to the test runner's actions. Leaving things up to the\n    // regular poller would result in flaky tests.\n    forEach(pollFns, function(pollFn){ pollFn(); });\n\n    if (outstandingRequestCount === 0) {\n      callback();\n    } else {\n      outstandingRequestCallbacks.push(callback);\n    }\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Poll Watcher API\n  //////////////////////////////////////////////////////////////\n  var pollFns = [],\n      pollTimeout;\n\n  /**\n   * @name $browser#addPollFn\n   *\n   * @param {function()} fn Poll function to add\n   *\n   * @description\n   * Adds a function to the list of functions that poller periodically executes,\n   * and starts polling if not started yet.\n   *\n   * @returns {function()} the added function\n   */\n  self.addPollFn = function(fn) {\n    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);\n    pollFns.push(fn);\n    return fn;\n  };\n\n  /**\n   * @param {number} interval How often should browser call poll functions (ms)\n   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.\n   *\n   * @description\n   * Configures the poller to run in the specified intervals, using the specified\n   * setTimeout fn and kicks it off.\n   */\n  function startPoller(interval, setTimeout) {\n    (function check() {\n      forEach(pollFns, function(pollFn){ pollFn(); });\n      pollTimeout = setTimeout(check, interval);\n    })();\n  }\n\n  //////////////////////////////////////////////////////////////\n  // URL API\n  //////////////////////////////////////////////////////////////\n\n  var lastBrowserUrl = location.href,\n      baseElement = document.find('base'),\n      reloadLocation = null;\n\n  /**\n   * @name $browser#url\n   *\n   * @description\n   * GETTER:\n   * Without any argument, this method just returns current value of location.href.\n   *\n   * SETTER:\n   * With at least one argument, this method sets url to new value.\n   * If html5 history api supported, pushState/replaceState is used, otherwise\n   * location.href/location.replace is used.\n   * Returns its own instance to allow chaining\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to change url.\n   *\n   * @param {string} url New url (when used as setter)\n   * @param {boolean=} replace Should new url replace current history record ?\n   */\n  self.url = function(url, replace) {\n    // Android Browser BFCache causes location, history reference to become stale.\n    if (location !== window.location) location = window.location;\n    if (history !== window.history) history = window.history;\n\n    // setter\n    if (url) {\n      if (lastBrowserUrl == url) return;\n      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);\n      lastBrowserUrl = url;\n      // Don't use history API if only the hash changed\n      // due to a bug in IE10/IE11 which leads\n      // to not firing a `hashchange` nor `popstate` event\n      // in some cases (see #9143).\n      if (!sameBase && $sniffer.history) {\n        if (replace) history.replaceState(null, '', url);\n        else {\n          history.pushState(null, '', url);\n          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462\n          baseElement.attr('href', baseElement.attr('href'));\n        }\n      } else {\n        if (!sameBase) {\n          reloadLocation = url;\n        }\n        if (replace) {\n          location.replace(url);\n        } else {\n          location.href = url;\n        }\n      }\n      return self;\n    // getter\n    } else {\n      // - reloadLocation is needed as browsers don't allow to read out\n      //   the new location.href if a reload happened.\n      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172\n      return reloadLocation || location.href.replace(/%27/g,\"'\");\n    }\n  };\n\n  var urlChangeListeners = [],\n      urlChangeInit = false;\n\n  function fireUrlChange() {\n    if (lastBrowserUrl == self.url()) return;\n\n    lastBrowserUrl = self.url();\n    forEach(urlChangeListeners, function(listener) {\n      listener(self.url());\n    });\n  }\n\n  /**\n   * @name $browser#onUrlChange\n   *\n   * @description\n   * Register callback function that will be called, when url changes.\n   *\n   * It's only called when the url is changed from outside of angular:\n   * - user types different url into address bar\n   * - user clicks on history (forward/back) button\n   * - user clicks on a link\n   *\n   * It's not called when url is changed by $browser.url() method\n   *\n   * The listener gets called with new url as parameter.\n   *\n   * NOTE: this api is intended for use only by the $location service. Please use the\n   * {@link ng.$location $location service} to monitor url changes in angular apps.\n   *\n   * @param {function(string)} listener Listener function to be called when url changes.\n   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.\n   */\n  self.onUrlChange = function(callback) {\n    // TODO(vojta): refactor to use node's syntax for events\n    if (!urlChangeInit) {\n      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)\n      // don't fire popstate when user change the address bar and don't fire hashchange when url\n      // changed by push/replaceState\n\n      // html5 history api - popstate event\n      if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);\n      // hashchange event\n      if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);\n      // polling\n      else self.addPollFn(fireUrlChange);\n\n      urlChangeInit = true;\n    }\n\n    urlChangeListeners.push(callback);\n    return callback;\n  };\n\n  /**\n   * Checks whether the url has changed outside of Angular.\n   * Needs to be exported to be able to check for changes that have been done in sync,\n   * as hashchange/popstate events fire in async.\n   */\n  self.$$checkUrlChange = fireUrlChange;\n\n  //////////////////////////////////////////////////////////////\n  // Misc API\n  //////////////////////////////////////////////////////////////\n\n  /**\n   * @name $browser#baseHref\n   *\n   * @description\n   * Returns current <base href>\n   * (always relative - without domain)\n   *\n   * @returns {string} The current base href\n   */\n  self.baseHref = function() {\n    var href = baseElement.attr('href');\n    return href ? href.replace(/^(https?\\:)?\\/\\/[^\\/]*/, '') : '';\n  };\n\n  //////////////////////////////////////////////////////////////\n  // Cookies API\n  //////////////////////////////////////////////////////////////\n  var lastCookies = {};\n  var lastCookieString = '';\n  var cookiePath = self.baseHref();\n\n  /**\n   * @name $browser#cookies\n   *\n   * @param {string=} name Cookie name\n   * @param {string=} value Cookie value\n   *\n   * @description\n   * The cookies method provides a 'private' low level access to browser cookies.\n   * It is not meant to be used directly, use the $cookie service instead.\n   *\n   * The return values vary depending on the arguments that the method was called with as follows:\n   *\n   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify\n   *   it\n   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie\n   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that\n   *   way)\n   *\n   * @returns {Object} Hash of all cookies (if called without any parameter)\n   */\n  self.cookies = function(name, value) {\n    /* global escape: false, unescape: false */\n    var cookieLength, cookieArray, cookie, i, index;\n\n    if (name) {\n      if (value === undefined) {\n        rawDocument.cookie = escape(name) + \"=;path=\" + cookiePath +\n                                \";expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n      } else {\n        if (isString(value)) {\n          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) +\n                                ';path=' + cookiePath).length + 1;\n\n          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:\n          // - 300 cookies\n          // - 20 cookies per unique domain\n          // - 4096 bytes per cookie\n          if (cookieLength > 4096) {\n            $log.warn(\"Cookie '\"+ name +\n              \"' possibly not set or overflowed because it was too large (\"+\n              cookieLength + \" > 4096 bytes)!\");\n          }\n        }\n      }\n    } else {\n      if (rawDocument.cookie !== lastCookieString) {\n        lastCookieString = rawDocument.cookie;\n        cookieArray = lastCookieString.split(\"; \");\n        lastCookies = {};\n\n        for (i = 0; i < cookieArray.length; i++) {\n          cookie = cookieArray[i];\n          index = cookie.indexOf('=');\n          if (index > 0) { //ignore nameless cookies\n            name = unescape(cookie.substring(0, index));\n            // the first value that is seen for a cookie is the most\n            // specific one.  values for the same cookie name that\n            // follow are for less specific paths.\n            if (lastCookies[name] === undefined) {\n              lastCookies[name] = unescape(cookie.substring(index + 1));\n            }\n          }\n        }\n      }\n      return lastCookies;\n    }\n  };\n\n\n  /**\n   * @name $browser#defer\n   * @param {function()} fn A function, who's execution should be deferred.\n   * @param {number=} [delay=0] of milliseconds to defer the function execution.\n   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.\n   *\n   * @description\n   * Executes a fn asynchronously via `setTimeout(fn, delay)`.\n   *\n   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using\n   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed\n   * via `$browser.defer.flush()`.\n   *\n   */\n  self.defer = function(fn, delay) {\n    var timeoutId;\n    outstandingRequestCount++;\n    timeoutId = setTimeout(function() {\n      delete pendingDeferIds[timeoutId];\n      completeOutstandingRequest(fn);\n    }, delay || 0);\n    pendingDeferIds[timeoutId] = true;\n    return timeoutId;\n  };\n\n\n  /**\n   * @name $browser#defer.cancel\n   *\n   * @description\n   * Cancels a deferred task identified with `deferId`.\n   *\n   * @param {*} deferId Token returned by the `$browser.defer` function.\n   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n   *                    canceled.\n   */\n  self.defer.cancel = function(deferId) {\n    if (pendingDeferIds[deferId]) {\n      delete pendingDeferIds[deferId];\n      clearTimeout(deferId);\n      completeOutstandingRequest(noop);\n      return true;\n    }\n    return false;\n  };\n\n}\n\nfunction $BrowserProvider(){\n  this.$get = ['$window', '$log', '$sniffer', '$document',\n      function( $window,   $log,   $sniffer,   $document){\n        return new Browser($window, $document, $log, $sniffer);\n      }];\n}\n\n/**\n * @ngdoc service\n * @name $cacheFactory\n *\n * @description\n * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to\n * them.\n *\n * ```js\n *\n *  var cache = $cacheFactory('cacheId');\n *  expect($cacheFactory.get('cacheId')).toBe(cache);\n *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();\n *\n *  cache.put(\"key\", \"value\");\n *  cache.put(\"another key\", \"another value\");\n *\n *  // We've specified no options on creation\n *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});\n *\n * ```\n *\n *\n * @param {string} cacheId Name or id of the newly created cache.\n * @param {object=} options Options object that specifies the cache behavior. Properties:\n *\n *   - `{number=}` `capacity` — turns the cache into LRU cache.\n *\n * @returns {object} Newly created cache object with the following set of methods:\n *\n * - `{object}` `info()` — Returns id, size, and options of cache.\n * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns\n *   it.\n * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.\n * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.\n * - `{void}` `removeAll()` — Removes all cached values.\n * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.\n *\n * @example\n   <example module=\"cacheExampleApp\">\n     <file name=\"index.html\">\n       <div ng-controller=\"CacheController\">\n         <input ng-model=\"newCacheKey\" placeholder=\"Key\">\n         <input ng-model=\"newCacheValue\" placeholder=\"Value\">\n         <button ng-click=\"put(newCacheKey, newCacheValue)\">Cache</button>\n\n         <p ng-if=\"keys.length\">Cached Values</p>\n         <div ng-repeat=\"key in keys\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"cache.get(key)\"></b>\n         </div>\n\n         <p>Cache Info</p>\n         <div ng-repeat=\"(key, value) in cache.info()\">\n           <span ng-bind=\"key\"></span>\n           <span>: </span>\n           <b ng-bind=\"value\"></b>\n         </div>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('cacheExampleApp', []).\n         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {\n           $scope.keys = [];\n           $scope.cache = $cacheFactory('cacheId');\n           $scope.put = function(key, value) {\n             if ($scope.cache.get(key) === undefined) {\n               $scope.keys.push(key);\n             }\n             $scope.cache.put(key, value === undefined ? null : value);\n           };\n         }]);\n     </file>\n     <file name=\"style.css\">\n       p {\n         margin: 10px 0 3px;\n       }\n     </file>\n   </example>\n */\nfunction $CacheFactoryProvider() {\n\n  this.$get = function() {\n    var caches = {};\n\n    function cacheFactory(cacheId, options) {\n      if (cacheId in caches) {\n        throw minErr('$cacheFactory')('iid', \"CacheId '{0}' is already taken!\", cacheId);\n      }\n\n      var size = 0,\n          stats = extend({}, options, {id: cacheId}),\n          data = {},\n          capacity = (options && options.capacity) || Number.MAX_VALUE,\n          lruHash = {},\n          freshEnd = null,\n          staleEnd = null;\n\n      /**\n       * @ngdoc type\n       * @name $cacheFactory.Cache\n       *\n       * @description\n       * A cache object used to store and retrieve data, primarily used by\n       * {@link $http $http} and the {@link ng.directive:script script} directive to cache\n       * templates and other data.\n       *\n       * ```js\n       *  angular.module('superCache')\n       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {\n       *      return $cacheFactory('super-cache');\n       *    }]);\n       * ```\n       *\n       * Example test:\n       *\n       * ```js\n       *  it('should behave like a cache', inject(function(superCache) {\n       *    superCache.put('key', 'value');\n       *    superCache.put('another key', 'another value');\n       *\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 2\n       *    });\n       *\n       *    superCache.remove('another key');\n       *    expect(superCache.get('another key')).toBeUndefined();\n       *\n       *    superCache.removeAll();\n       *    expect(superCache.info()).toEqual({\n       *      id: 'super-cache',\n       *      size: 0\n       *    });\n       *  }));\n       * ```\n       */\n      return caches[cacheId] = {\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#put\n         * @kind function\n         *\n         * @description\n         * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be\n         * retrieved later, and incrementing the size of the cache if the key was not already\n         * present in the cache. If behaving like an LRU cache, it will also remove stale\n         * entries from the set.\n         *\n         * It will not insert undefined values into the cache.\n         *\n         * @param {string} key the key under which the cached data is stored.\n         * @param {*} value the value to store alongside the key. If it is undefined, the key\n         *    will not be stored.\n         * @returns {*} the value stored.\n         */\n        put: function(key, value) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key] || (lruHash[key] = {key: key});\n\n            refresh(lruEntry);\n          }\n\n          if (isUndefined(value)) return;\n          if (!(key in data)) size++;\n          data[key] = value;\n\n          if (size > capacity) {\n            this.remove(staleEnd.key);\n          }\n\n          return value;\n        },\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#get\n         * @kind function\n         *\n         * @description\n         * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the data to be retrieved\n         * @returns {*} the value stored.\n         */\n        get: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            refresh(lruEntry);\n          }\n\n          return data[key];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#remove\n         * @kind function\n         *\n         * @description\n         * Removes an entry from the {@link $cacheFactory.Cache Cache} object.\n         *\n         * @param {string} key the key of the entry to be removed\n         */\n        remove: function(key) {\n          if (capacity < Number.MAX_VALUE) {\n            var lruEntry = lruHash[key];\n\n            if (!lruEntry) return;\n\n            if (lruEntry == freshEnd) freshEnd = lruEntry.p;\n            if (lruEntry == staleEnd) staleEnd = lruEntry.n;\n            link(lruEntry.n,lruEntry.p);\n\n            delete lruHash[key];\n          }\n\n          delete data[key];\n          size--;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#removeAll\n         * @kind function\n         *\n         * @description\n         * Clears the cache object of any entries.\n         */\n        removeAll: function() {\n          data = {};\n          size = 0;\n          lruHash = {};\n          freshEnd = staleEnd = null;\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#destroy\n         * @kind function\n         *\n         * @description\n         * Destroys the {@link $cacheFactory.Cache Cache} object entirely,\n         * removing it from the {@link $cacheFactory $cacheFactory} set.\n         */\n        destroy: function() {\n          data = null;\n          stats = null;\n          lruHash = null;\n          delete caches[cacheId];\n        },\n\n\n        /**\n         * @ngdoc method\n         * @name $cacheFactory.Cache#info\n         * @kind function\n         *\n         * @description\n         * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.\n         *\n         * @returns {object} an object with the following properties:\n         *   <ul>\n         *     <li>**id**: the id of the cache instance</li>\n         *     <li>**size**: the number of entries kept in the cache instance</li>\n         *     <li>**...**: any additional properties from the options object when creating the\n         *       cache.</li>\n         *   </ul>\n         */\n        info: function() {\n          return extend({}, stats, {size: size});\n        }\n      };\n\n\n      /**\n       * makes the `entry` the freshEnd of the LRU linked list\n       */\n      function refresh(entry) {\n        if (entry != freshEnd) {\n          if (!staleEnd) {\n            staleEnd = entry;\n          } else if (staleEnd == entry) {\n            staleEnd = entry.n;\n          }\n\n          link(entry.n, entry.p);\n          link(entry, freshEnd);\n          freshEnd = entry;\n          freshEnd.n = null;\n        }\n      }\n\n\n      /**\n       * bidirectionally links two entries of the LRU linked list\n       */\n      function link(nextEntry, prevEntry) {\n        if (nextEntry != prevEntry) {\n          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify\n          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify\n        }\n      }\n    }\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#info\n   *\n   * @description\n   * Get information about all the caches that have been created\n   *\n   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`\n   */\n    cacheFactory.info = function() {\n      var info = {};\n      forEach(caches, function(cache, cacheId) {\n        info[cacheId] = cache.info();\n      });\n      return info;\n    };\n\n\n  /**\n   * @ngdoc method\n   * @name $cacheFactory#get\n   *\n   * @description\n   * Get access to a cache object by the `cacheId` used when it was created.\n   *\n   * @param {string} cacheId Name or id of a cache to access.\n   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.\n   */\n    cacheFactory.get = function(cacheId) {\n      return caches[cacheId];\n    };\n\n\n    return cacheFactory;\n  };\n}\n\n/**\n * @ngdoc service\n * @name $templateCache\n *\n * @description\n * The first time a template is used, it is loaded in the template cache for quick retrieval. You\n * can load templates directly into the cache in a `script` tag, or by consuming the\n * `$templateCache` service directly.\n *\n * Adding via the `script` tag:\n *\n * ```html\n *   <script type=\"text/ng-template\" id=\"templateId.html\">\n *     <p>This is the content of the template</p>\n *   </script>\n * ```\n *\n * **Note:** the `script` tag containing the template does not need to be included in the `head` of\n * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,\n * element with ng-app attribute), otherwise the template will be ignored.\n *\n * Adding via the $templateCache service:\n *\n * ```js\n * var myApp = angular.module('myApp', []);\n * myApp.run(function($templateCache) {\n *   $templateCache.put('templateId.html', 'This is the content of the template');\n * });\n * ```\n *\n * To retrieve the template later, simply use it in your HTML:\n * ```html\n * <div ng-include=\" 'templateId.html' \"></div>\n * ```\n *\n * or get it via Javascript:\n * ```js\n * $templateCache.get('templateId.html')\n * ```\n *\n * See {@link ng.$cacheFactory $cacheFactory}.\n *\n */\nfunction $TemplateCacheProvider() {\n  this.$get = ['$cacheFactory', function($cacheFactory) {\n    return $cacheFactory('templates');\n  }];\n}\n\n/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!\n *\n * DOM-related variables:\n *\n * - \"node\" - DOM Node\n * - \"element\" - DOM Element or Node\n * - \"$node\" or \"$element\" - jqLite-wrapped node or element\n *\n *\n * Compiler related stuff:\n *\n * - \"linkFn\" - linking fn of a single directive\n * - \"nodeLinkFn\" - function that aggregates all linking fns for a particular node\n * - \"childLinkFn\" -  function that aggregates all linking fns for child nodes of a particular node\n * - \"compositeLinkFn\" - function that aggregates all linking fns for a compilation root (nodeList)\n */\n\n\n/**\n * @ngdoc service\n * @name $compile\n * @kind function\n *\n * @description\n * Compiles an HTML string or DOM into a template and produces a template function, which\n * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.\n *\n * The compilation is a process of walking the DOM tree and matching DOM elements to\n * {@link ng.$compileProvider#directive directives}.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** This document is an in-depth reference of all directive options.\n * For a gentle introduction to directives with examples of common use cases,\n * see the {@link guide/directive directive guide}.\n * </div>\n *\n * ## Comprehensive Directive API\n *\n * There are many different options for a directive.\n *\n * The difference resides in the return value of the factory function.\n * You can either return a \"Directive Definition Object\" (see below) that defines the directive properties,\n * or just the `postLink` function (all other properties will have the default values).\n *\n * <div class=\"alert alert-success\">\n * **Best Practice:** It's recommended to use the \"directive definition object\" form.\n * </div>\n *\n * Here's an example directive declared with a Directive Definition Object:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       priority: 0,\n *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },\n *       // or\n *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },\n *       transclude: false,\n *       restrict: 'A',\n *       scope: false,\n *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },\n *       controllerAs: 'stringAlias',\n *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],\n *       compile: function compile(tElement, tAttrs, transclude) {\n *         return {\n *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *           post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *         }\n *         // or\n *         // return function postLink( ... ) { ... }\n *       },\n *       // or\n *       // link: {\n *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },\n *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }\n *       // }\n *       // or\n *       // link: function postLink( ... ) { ... }\n *     };\n *     return directiveDefinitionObject;\n *   });\n * ```\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Any unspecified options will use the default value. You can see the default values below.\n * </div>\n *\n * Therefore the above can be simplified as:\n *\n * ```js\n *   var myModule = angular.module(...);\n *\n *   myModule.directive('directiveName', function factory(injectables) {\n *     var directiveDefinitionObject = {\n *       link: function postLink(scope, iElement, iAttrs) { ... }\n *     };\n *     return directiveDefinitionObject;\n *     // or\n *     // return function postLink(scope, iElement, iAttrs) { ... }\n *   });\n * ```\n *\n *\n *\n * ### Directive Definition Object\n *\n * The directive definition object provides instructions to the {@link ng.$compile\n * compiler}. The attributes are:\n *\n * #### `priority`\n * When there are multiple directives defined on a single DOM element, sometimes it\n * is necessary to specify the order in which the directives are applied. The `priority` is used\n * to sort the directives before their `compile` functions get called. Priority is defined as a\n * number. Directives with greater numerical `priority` are compiled first. Pre-link functions\n * are also run in priority order, but post-link functions are run in reverse order. The order\n * of directives with the same priority is undefined. The default priority is `0`.\n *\n * #### `terminal`\n * If set to true then the current `priority` will be the last set of directives\n * which will execute (any directives at the current priority will still execute\n * as the order of execution on same `priority` is undefined).\n *\n * #### `scope`\n * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the\n * same element request a new scope, only one new scope is created. The new scope rule does not\n * apply for the root of the template since the root of the template always gets a new scope.\n *\n * **If set to `{}` (object hash),** then a new \"isolate\" scope is created. The 'isolate' scope differs from\n * normal scope in that it does not prototypically inherit from the parent scope. This is useful\n * when creating reusable components, which should not accidentally read or modify data in the\n * parent scope.\n *\n * The 'isolate' scope takes an object hash which defines a set of local scope properties\n * derived from the parent scope. These local properties are useful for aliasing values for\n * templates. Locals definition is a hash of local scope property to its source:\n *\n * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is\n *   always a string since DOM attributes are strings. If no `attr` name is specified  then the\n *   attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"hello {{name}}\">` and widget definition\n *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect\n *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the\n *   `localName` property on the widget scope. The `name` is read from the parent scope (not\n *   component scope).\n *\n * * `=` or `=attr` - set up bi-directional binding between a local scope property and the\n *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`\n *   name is specified then the attribute name is assumed to be the same as the local name.\n *   Given `<widget my-attr=\"parentModel\">` and widget definition of\n *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the\n *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected\n *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent\n *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You\n *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.\n *\n * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.\n *   If no `attr` name is specified then the attribute name is assumed to be the same as the\n *   local name. Given `<widget my-attr=\"count = count + value\">` and widget definition of\n *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to\n *   a function wrapper for the `count = count + value` expression. Often it's desirable to\n *   pass data from the isolated scope via an expression to the parent scope, this can be\n *   done by passing a map of local variable names and values into the expression wrapper fn.\n *   For example, if the expression is `increment(amount)` then we can specify the amount value\n *   by calling the `localFn` as `localFn({amount: 22})`.\n *\n *\n *\n * #### `controller`\n * Controller constructor function. The controller is instantiated before the\n * pre-linking phase and it is shared with other directives (see\n * `require` attribute). This allows the directives to communicate with each other and augment\n * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:\n *\n * * `$scope` - Current scope associated with the element\n * * `$element` - Current element\n * * `$attrs` - Current attributes object for the element\n * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope.\n *    The scope can be overridden by an optional first argument.\n *   `function([scope], cloneLinkingFn)`.\n *\n *\n * #### `require`\n * Require another directive and inject its controller as the fourth argument to the linking function. The\n * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the\n * injected argument will be an array in corresponding order. If no such directive can be\n * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:\n *\n * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.\n * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.\n * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.\n * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass\n *   `null` to the `link` fn if not found.\n *\n *\n * #### `controllerAs`\n * Controller alias at the directive scope. An alias for the controller so it\n * can be referenced at the directive template. The directive needs to define a scope for this\n * configuration to be used. Useful in the case when directive is used as component.\n *\n *\n * #### `restrict`\n * String of subset of `EACM` which restricts the directive to a specific directive\n * declaration style. If omitted, the default (attributes only) is used.\n *\n * * `E` - Element name: `<my-directive></my-directive>`\n * * `A` - Attribute (default): `<div my-directive=\"exp\"></div>`\n * * `C` - Class: `<div class=\"my-directive: exp;\"></div>`\n * * `M` - Comment: `<!-- directive: my-directive exp -->`\n *\n *\n * #### `template`\n * HTML markup that may:\n * * Replace the contents of the directive's element (default).\n * * Replace the directive's element itself (if `replace` is true - DEPRECATED).\n * * Wrap the contents of the directive's element (if `transclude` is true).\n *\n * Value may be:\n *\n * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.\n * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`\n *   function api below) and returns a string value.\n *\n *\n * #### `templateUrl`\n * Same as `template` but the template is loaded from the specified URL. Because\n * the template loading is asynchronous the compilation/linking is suspended until the template\n * is loaded.\n *\n * You can specify `templateUrl` as a string representing the URL or as a function which takes two\n * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns\n * a string value representing the url.  In either case, the template URL is passed through {@link\n * api/ng.$sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.\n *\n *\n * #### `replace` ([*DEPRECATED*!], will be removed in next major release)\n * specify what the template should replace. Defaults to `false`.\n *\n * * `true` - the template will replace the directive's element.\n * * `false` - the template will replace the contents of the directive's element.\n *\n * The replacement process migrates all of the attributes / classes from the old element to the new\n * one. See the {@link guide/directive#creating-custom-directives_creating-directives_template-expanding-directive\n * Directives Guide} for an example.\n *\n * #### `transclude`\n * compile the content of the element and make it available to the directive.\n * Typically used with {@link ng.directive:ngTransclude\n * ngTransclude}. The advantage of transclusion is that the linking function receives a\n * transclusion function which is pre-bound to the correct scope. In a typical setup the widget\n * creates an `isolate` scope, but the transclusion is not a child, but a sibling of the `isolate`\n * scope. This makes it possible for the widget to have private state, and the transclusion to\n * be bound to the parent (pre-`isolate`) scope.\n *\n * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the\n * directive's element or the entire element:\n *\n * * `true` - transclude the content (i.e. the child nodes) of the directive's element.\n * * `'element'` - transclude the whole of the directive's element including any directives on this\n *   element that defined at a lower priority than this directive. When used, the `template`\n *   property is ignored.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** When testing an element transclude directive you must not place the directive at the root of the\n * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives\n * Testing Transclusion Directives}.\n * </div>\n *\n * #### `compile`\n *\n * ```js\n *   function compile(tElement, tAttrs, transclude) { ... }\n * ```\n *\n * The compile function deals with transforming the template DOM. Since most directives do not do\n * template transformation, it is not used often. The compile function takes the following arguments:\n *\n *   * `tElement` - template element - The element where the directive has been declared. It is\n *     safe to do template transformation on the element and child elements only.\n *\n *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared\n *     between all directive compile functions.\n *\n *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`\n *\n * <div class=\"alert alert-warning\">\n * **Note:** The template instance and the link instance may be different objects if the template has\n * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that\n * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration\n * should be done in a linking function rather than in a compile function.\n * </div>\n\n * <div class=\"alert alert-warning\">\n * **Note:** The compile function cannot handle directives that recursively use themselves in their\n * own templates or compile functions. Compiling these directives results in an infinite loop and a\n * stack overflow errors.\n *\n * This can be avoided by manually using $compile in the postLink function to imperatively compile\n * a directive's template instead of relying on automatic template compilation via `template` or\n * `templateUrl` declaration or manual compilation inside the compile function.\n * </div>\n *\n * <div class=\"alert alert-error\">\n * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it\n *   e.g. does not know about the right outer scope. Please use the transclude function that is passed\n *   to the link function instead.\n * </div>\n\n * A compile function can have a return value which can be either a function or an object.\n *\n * * returning a (post-link) function - is equivalent to registering the linking function via the\n *   `link` property of the config object when the compile function is empty.\n *\n * * returning an object with function(s) registered via `pre` and `post` properties - allows you to\n *   control when a linking function should be called during the linking phase. See info about\n *   pre-linking and post-linking functions below.\n *\n *\n * #### `link`\n * This property is used only if the `compile` property is not defined.\n *\n * ```js\n *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }\n * ```\n *\n * The link function is responsible for registering DOM listeners as well as updating the DOM. It is\n * executed after the template has been cloned. This is where most of the directive logic will be\n * put.\n *\n *   * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the\n *     directive for registering {@link ng.$rootScope.Scope#$watch watches}.\n *\n *   * `iElement` - instance element - The element where the directive is to be used. It is safe to\n *     manipulate the children of the element only in `postLink` function since the children have\n *     already been linked.\n *\n *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared\n *     between all directive linking functions.\n *\n *   * `controller` - a controller instance - A controller instance if at least one directive on the\n *     element defines a controller. The controller is shared among all the directives, which allows\n *     the directives to use the controllers as a communication channel.\n *\n *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.\n *     The scope can be overridden by an optional first argument. This is the same as the `$transclude`\n *     parameter of directive controllers.\n *     `function([scope], cloneLinkingFn)`.\n *\n *\n * #### Pre-linking function\n *\n * Executed before the child elements are linked. Not safe to do DOM transformation since the\n * compiler linking function will fail to locate the correct elements for linking.\n *\n * #### Post-linking function\n *\n * Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.\n *\n * <a name=\"Attributes\"></a>\n * ### Attributes\n *\n * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the\n * `link()` or `compile()` functions. It has a variety of uses.\n *\n * accessing *Normalized attribute names:*\n * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.\n * the attributes object allows for normalized access to\n *   the attributes.\n *\n * * *Directive inter-communication:* All directives share the same instance of the attributes\n *   object which allows the directives to use the attributes object as inter directive\n *   communication.\n *\n * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object\n *   allowing other directives to read the interpolated value.\n *\n * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes\n *   that contain interpolation (e.g. `src=\"{{bar}}\"`). Not only is this very efficient but it's also\n *   the only way to easily get the actual value because during the linking phase the interpolation\n *   hasn't been evaluated yet and so the value is at this time set to `undefined`.\n *\n * ```js\n * function linkingFn(scope, elm, attrs, ctrl) {\n *   // get the attribute value\n *   console.log(attrs.ngModel);\n *\n *   // change the attribute\n *   attrs.$set('ngModel', 'new value');\n *\n *   // observe changes to interpolated attribute\n *   attrs.$observe('ngModel', function(value) {\n *     console.log('ngModel has changed value to ' + value);\n *   });\n * }\n * ```\n *\n * ## Example\n *\n * <div class=\"alert alert-warning\">\n * **Note**: Typically directives are registered with `module.directive`. The example below is\n * to illustrate how `$compile` works.\n * </div>\n *\n <example module=\"compileExample\">\n   <file name=\"index.html\">\n    <script>\n      angular.module('compileExample', [], function($compileProvider) {\n        // configure new 'compile' directive by passing a directive\n        // factory function. The factory function injects the '$compile'\n        $compileProvider.directive('compile', function($compile) {\n          // directive factory creates a link function\n          return function(scope, element, attrs) {\n            scope.$watch(\n              function(scope) {\n                 // watch the 'compile' expression for changes\n                return scope.$eval(attrs.compile);\n              },\n              function(value) {\n                // when the 'compile' expression changes\n                // assign it into the current DOM\n                element.html(value);\n\n                // compile the new DOM and link it to the current\n                // scope.\n                // NOTE: we only compile .childNodes so that\n                // we don't get into infinite loop compiling ourselves\n                $compile(element.contents())(scope);\n              }\n            );\n          };\n        });\n      })\n      .controller('GreeterController', ['$scope', function($scope) {\n        $scope.name = 'Angular';\n        $scope.html = 'Hello {{name}}';\n      }]);\n    </script>\n    <div ng-controller=\"GreeterController\">\n      <input ng-model=\"name\"> <br>\n      <textarea ng-model=\"html\"></textarea> <br>\n      <div compile=\"html\"></div>\n    </div>\n   </file>\n   <file name=\"protractor.js\" type=\"protractor\">\n     it('should auto compile', function() {\n       var textarea = $('textarea');\n       var output = $('div[compile]');\n       // The initial state reads 'Hello Angular'.\n       expect(output.getText()).toBe('Hello Angular');\n       textarea.clear();\n       textarea.sendKeys('{{name}}!');\n       expect(output.getText()).toBe('Angular!');\n     });\n   </file>\n </example>\n\n *\n *\n * @param {string|DOMElement} element Element or HTML string to compile into a template function.\n * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives.\n * @param {number} maxPriority only apply directives lower than given priority (Only effects the\n *                 root element(s), not their children)\n * @returns {function(scope, cloneAttachFn=)} a link function which is used to bind template\n * (a DOM element/tree) to a scope. Where:\n *\n *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.\n *  * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the\n *  `template` and call the `cloneAttachFn` function allowing the caller to attach the\n *  cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is\n *  called as: <br> `cloneAttachFn(clonedElement, scope)` where:\n *\n *      * `clonedElement` - is a clone of the original `element` passed into the compiler.\n *      * `scope` - is the current scope with which the linking function is working with.\n *\n * Calling the linking function returns the element of the template. It is either the original\n * element passed in, or the clone of the element if the `cloneAttachFn` is provided.\n *\n * After linking the view is not updated until after a call to $digest which typically is done by\n * Angular automatically.\n *\n * If you need access to the bound view, there are two ways to do it:\n *\n * - If you are not asking the linking function to clone the template, create the DOM element(s)\n *   before you send them to the compiler and keep this reference around.\n *   ```js\n *     var element = $compile('<p>{{total}}</p>')(scope);\n *   ```\n *\n * - if on the other hand, you need the element to be cloned, the view reference from the original\n *   example would not point to the clone, but rather to the original template that was cloned. In\n *   this case, you can access the clone via the cloneAttachFn:\n *   ```js\n *     var templateElement = angular.element('<p>{{total}}</p>'),\n *         scope = ....;\n *\n *     var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {\n *       //attach the clone to DOM document at the right place\n *     });\n *\n *     //now we have reference to the cloned DOM via `clonedElement`\n *   ```\n *\n *\n * For information on how the compiler works, see the\n * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.\n */\n\nvar $compileMinErr = minErr('$compile');\n\n/**\n * @ngdoc provider\n * @name $compileProvider\n * @kind function\n *\n * @description\n */\n$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];\nfunction $CompileProvider($provide, $$sanitizeUriProvider) {\n  var hasDirectives = {},\n      Suffix = 'Directive',\n      COMMENT_DIRECTIVE_REGEXP = /^\\s*directive\\:\\s*([\\d\\w_\\-]+)\\s+(.*)$/,\n      CLASS_DIRECTIVE_REGEXP = /(([\\d\\w_\\-]+)(?:\\:([^;]+))?;?)/;\n\n  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes\n  // The assumption is that future DOM event attribute names will begin with\n  // 'on' and be composed of only English letters.\n  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#directive\n   * @kind function\n   *\n   * @description\n   * Register a new directive with the compiler.\n   *\n   * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which\n   *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the\n   *    names and the values are the factories.\n   * @param {Function|Array} directiveFactory An injectable directive factory function. See\n   *    {@link guide/directive} for more info.\n   * @returns {ng.$compileProvider} Self for chaining.\n   */\n   this.directive = function registerDirective(name, directiveFactory) {\n    assertNotHasOwnProperty(name, 'directive');\n    if (isString(name)) {\n      assertArg(directiveFactory, 'directiveFactory');\n      if (!hasDirectives.hasOwnProperty(name)) {\n        hasDirectives[name] = [];\n        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',\n          function($injector, $exceptionHandler) {\n            var directives = [];\n            forEach(hasDirectives[name], function(directiveFactory, index) {\n              try {\n                var directive = $injector.invoke(directiveFactory);\n                if (isFunction(directive)) {\n                  directive = { compile: valueFn(directive) };\n                } else if (!directive.compile && directive.link) {\n                  directive.compile = valueFn(directive.link);\n                }\n                directive.priority = directive.priority || 0;\n                directive.index = index;\n                directive.name = directive.name || name;\n                directive.require = directive.require || (directive.controller && directive.name);\n                directive.restrict = directive.restrict || 'A';\n                directives.push(directive);\n              } catch (e) {\n                $exceptionHandler(e);\n              }\n            });\n            return directives;\n          }]);\n      }\n      hasDirectives[name].push(directiveFactory);\n    } else {\n      forEach(name, reverseParams(registerDirective));\n    }\n    return this;\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#aHrefSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.aHrefSanitizationWhitelist();\n    }\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $compileProvider#imgSrcSanitizationWhitelist\n   * @kind function\n   *\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);\n      return this;\n    } else {\n      return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();\n    }\n  };\n\n  this.$get = [\n            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',\n            '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',\n    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,\n             $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {\n\n    var Attributes = function(element, attr) {\n      this.$$element = element;\n      this.$attr = attr || {};\n    };\n\n    Attributes.prototype = {\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$normalize\n       * @kind function\n       *\n       * @description\n       * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or\n       * `data-`) to its normalized, camelCase form.\n       *\n       * Also there is special case for Moz prefix starting with upper case letter.\n       *\n       * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}\n       *\n       * @param {string} name Name to normalize\n       */\n      $normalize: directiveNormalize,\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$addClass\n       * @kind function\n       *\n       * @description\n       * Adds the CSS class value specified by the classVal parameter to the element. If animations\n       * are enabled then an animation will be triggered for the class addition.\n       *\n       * @param {string} classVal The className value that will be added to the element\n       */\n      $addClass : function(classVal) {\n        if(classVal && classVal.length > 0) {\n          $animate.addClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$removeClass\n       * @kind function\n       *\n       * @description\n       * Removes the CSS class value specified by the classVal parameter from the element. If\n       * animations are enabled then an animation will be triggered for the class removal.\n       *\n       * @param {string} classVal The className value that will be removed from the element\n       */\n      $removeClass : function(classVal) {\n        if(classVal && classVal.length > 0) {\n          $animate.removeClass(this.$$element, classVal);\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$updateClass\n       * @kind function\n       *\n       * @description\n       * Adds and removes the appropriate CSS class values to the element based on the difference\n       * between the new and old CSS class values (specified as newClasses and oldClasses).\n       *\n       * @param {string} newClasses The current CSS className value\n       * @param {string} oldClasses The former CSS className value\n       */\n      $updateClass : function(newClasses, oldClasses) {\n        var toAdd = tokenDifference(newClasses, oldClasses);\n        var toRemove = tokenDifference(oldClasses, newClasses);\n\n        if(toAdd.length === 0) {\n          $animate.removeClass(this.$$element, toRemove);\n        } else if(toRemove.length === 0) {\n          $animate.addClass(this.$$element, toAdd);\n        } else {\n          $animate.setClass(this.$$element, toAdd, toRemove);\n        }\n      },\n\n      /**\n       * Set a normalized attribute on the element in a way such that all directives\n       * can share the attribute. This function properly handles boolean attributes.\n       * @param {string} key Normalized key. (ie ngAttribute)\n       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.\n       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.\n       *     Defaults to true.\n       * @param {string=} attrName Optional none normalized name. Defaults to key.\n       */\n      $set: function(key, value, writeAttr, attrName) {\n        // TODO: decide whether or not to throw an error if \"class\"\n        //is set through this function since it may cause $updateClass to\n        //become unstable.\n\n        var booleanKey = getBooleanAttrName(this.$$element[0], key),\n            normalizedVal,\n            nodeName;\n\n        if (booleanKey) {\n          this.$$element.prop(key, value);\n          attrName = booleanKey;\n        }\n\n        this[key] = value;\n\n        // translate normalized key to actual key\n        if (attrName) {\n          this.$attr[key] = attrName;\n        } else {\n          attrName = this.$attr[key];\n          if (!attrName) {\n            this.$attr[key] = attrName = snake_case(key, '-');\n          }\n        }\n\n        nodeName = nodeName_(this.$$element);\n\n        // sanitize a[href] and img[src] values\n        if ((nodeName === 'A' && key === 'href') ||\n            (nodeName === 'IMG' && key === 'src')) {\n          this[key] = value = $$sanitizeUri(value, key === 'src');\n        }\n\n        if (writeAttr !== false) {\n          if (value === null || value === undefined) {\n            this.$$element.removeAttr(attrName);\n          } else {\n            this.$$element.attr(attrName, value);\n          }\n        }\n\n        // fire observers\n        var $$observers = this.$$observers;\n        $$observers && forEach($$observers[key], function(fn) {\n          try {\n            fn(value);\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        });\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $compile.directive.Attributes#$observe\n       * @kind function\n       *\n       * @description\n       * Observes an interpolated attribute.\n       *\n       * The observer function will be invoked once during the next `$digest` following\n       * compilation. The observer is then invoked whenever the interpolated value\n       * changes.\n       *\n       * @param {string} key Normalized key. (ie ngAttribute) .\n       * @param {function(interpolatedValue)} fn Function that will be called whenever\n                the interpolated value of the attribute changes.\n       *        See the {@link guide/directive#Attributes Directives} guide for more info.\n       * @returns {function()} the `fn` parameter.\n       */\n      $observe: function(key, fn) {\n        var attrs = this,\n            $$observers = (attrs.$$observers || (attrs.$$observers = {})),\n            listeners = ($$observers[key] || ($$observers[key] = []));\n\n        listeners.push(fn);\n        $rootScope.$evalAsync(function() {\n          if (!listeners.$$inter) {\n            // no one registered attribute interpolation function, so lets call it manually\n            fn(attrs[key]);\n          }\n        });\n        return fn;\n      }\n    };\n\n    var startSymbol = $interpolate.startSymbol(),\n        endSymbol = $interpolate.endSymbol(),\n        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')\n            ? identity\n            : function denormalizeTemplate(template) {\n              return template.replace(/\\{\\{/g, startSymbol).replace(/}}/g, endSymbol);\n        },\n        NG_ATTR_BINDING = /^ngAttr[A-Z]/;\n\n\n    return compile;\n\n    //================================\n\n    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,\n                        previousCompileContext) {\n      if (!($compileNodes instanceof jqLite)) {\n        // jquery always rewraps, whereas we need to preserve the original selector so that we can\n        // modify it.\n        $compileNodes = jqLite($compileNodes);\n      }\n      // We can not compile top level text elements since text nodes can be merged and we will\n      // not be able to attach scope data to them, so we will wrap them in <span>\n      forEach($compileNodes, function(node, index){\n        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\\S+/) /* non-empty */ ) {\n          $compileNodes[index] = node = jqLite(node).wrap('<span></span>').parent()[0];\n        }\n      });\n      var compositeLinkFn =\n              compileNodes($compileNodes, transcludeFn, $compileNodes,\n                           maxPriority, ignoreDirective, previousCompileContext);\n      safeAddClass($compileNodes, 'ng-scope');\n      return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn){\n        assertArg(scope, 'scope');\n        // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart\n        // and sometimes changes the structure of the DOM.\n        var $linkNode = cloneConnectFn\n          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!\n          : $compileNodes;\n\n        forEach(transcludeControllers, function(instance, name) {\n          $linkNode.data('$' + name + 'Controller', instance);\n        });\n\n        // Attach scope only to non-text nodes.\n        for(var i = 0, ii = $linkNode.length; i<ii; i++) {\n          var node = $linkNode[i],\n              nodeType = node.nodeType;\n          if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {\n            $linkNode.eq(i).data('$scope', scope);\n          }\n        }\n\n        if (cloneConnectFn) cloneConnectFn($linkNode, scope);\n        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);\n        return $linkNode;\n      };\n    }\n\n    function safeAddClass($element, className) {\n      try {\n        $element.addClass(className);\n      } catch(e) {\n        // ignore, since it means that we are trying to set class on\n        // SVG element, where class name is read-only.\n      }\n    }\n\n    /**\n     * Compile function matches each node in nodeList against the directives. Once all directives\n     * for a particular node are collected their compile functions are executed. The compile\n     * functions return values - the linking functions - are combined into a composite linking\n     * function, which is the a linking function for the node.\n     *\n     * @param {NodeList} nodeList an array of nodes or NodeList to compile\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *        scope argument is auto-generated to the new child of the transcluded parent scope.\n     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then\n     *        the rootElement must be set the jqLite collection of the compile root. This is\n     *        needed so that the jqLite collection items can be replaced with widgets.\n     * @param {number=} maxPriority Max directive priority.\n     * @returns {Function} A composite linking function of all of the matched directives or null.\n     */\n    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,\n                            previousCompileContext) {\n      var linkFns = [],\n          attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound;\n\n      for (var i = 0; i < nodeList.length; i++) {\n        attrs = new Attributes();\n\n        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.\n        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,\n                                        ignoreDirective);\n\n        nodeLinkFn = (directives.length)\n            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,\n                                      null, [], [], previousCompileContext)\n            : null;\n\n        if (nodeLinkFn && nodeLinkFn.scope) {\n          safeAddClass(attrs.$$element, 'ng-scope');\n        }\n\n        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||\n                      !(childNodes = nodeList[i].childNodes) ||\n                      !childNodes.length)\n            ? null\n            : compileNodes(childNodes,\n                 nodeLinkFn ? (\n                  (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)\n                     && nodeLinkFn.transclude) : transcludeFn);\n\n        linkFns.push(nodeLinkFn, childLinkFn);\n        linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;\n        //use the previous context only for the first element in the virtual group\n        previousCompileContext = null;\n      }\n\n      // return a linking function if we have found anything, null otherwise\n      return linkFnFound ? compositeLinkFn : null;\n\n      function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {\n        var nodeLinkFn, childLinkFn, node, childScope, i, ii, n, childBoundTranscludeFn;\n\n        // copy nodeList so that linking doesn't break due to live list updates.\n        var nodeListLength = nodeList.length,\n            stableNodeList = new Array(nodeListLength);\n        for (i = 0; i < nodeListLength; i++) {\n          stableNodeList[i] = nodeList[i];\n        }\n\n        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {\n          node = stableNodeList[n];\n          nodeLinkFn = linkFns[i++];\n          childLinkFn = linkFns[i++];\n\n          if (nodeLinkFn) {\n            if (nodeLinkFn.scope) {\n              childScope = scope.$new();\n              jqLite.data(node, '$scope', childScope);\n            } else {\n              childScope = scope;\n            }\n\n            if ( nodeLinkFn.transcludeOnThisElement ) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn);\n\n            } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {\n              childBoundTranscludeFn = parentBoundTranscludeFn;\n\n            } else if (!parentBoundTranscludeFn && transcludeFn) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);\n\n            } else {\n              childBoundTranscludeFn = null;\n            }\n\n            nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn);\n\n          } else if (childLinkFn) {\n            childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);\n          }\n        }\n      }\n    }\n\n    function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {\n\n      var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {\n        var scopeCreated = false;\n\n        if (!transcludedScope) {\n          transcludedScope = scope.$new();\n          transcludedScope.$$transcluded = true;\n          scopeCreated = true;\n        }\n\n        var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);\n        if (scopeCreated) {\n          clone.on('$destroy', function() { transcludedScope.$destroy(); });\n        }\n        return clone;\n      };\n\n      return boundTranscludeFn;\n    }\n\n    /**\n     * Looks for directives on the given node and adds them to the directive collection which is\n     * sorted.\n     *\n     * @param node Node to search.\n     * @param directives An array to which the directives are added to. This array is sorted before\n     *        the function returns.\n     * @param attrs The shared attrs object which is used to populate the normalized attributes.\n     * @param {number=} maxPriority Max directive priority.\n     */\n    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {\n      var nodeType = node.nodeType,\n          attrsMap = attrs.$attr,\n          match,\n          className;\n\n      switch(nodeType) {\n        case 1: /* Element */\n          // use the node name: <directive>\n          addDirective(directives,\n              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);\n\n          // iterate over the attributes\n          for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,\n                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {\n            var attrStartName = false;\n            var attrEndName = false;\n\n            attr = nAttrs[j];\n            if (!msie || msie >= 8 || attr.specified) {\n              name = attr.name;\n              value = trim(attr.value);\n\n              // support ngAttr attribute binding\n              ngAttrName = directiveNormalize(name);\n              if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {\n                name = snake_case(ngAttrName.substr(6), '-');\n              }\n\n              var directiveNName = ngAttrName.replace(/(Start|End)$/, '');\n              if (ngAttrName === directiveNName + 'Start') {\n                attrStartName = name;\n                attrEndName = name.substr(0, name.length - 5) + 'end';\n                name = name.substr(0, name.length - 6);\n              }\n\n              nName = directiveNormalize(name.toLowerCase());\n              attrsMap[nName] = name;\n              if (isNgAttr || !attrs.hasOwnProperty(nName)) {\n                  attrs[nName] = value;\n                  if (getBooleanAttrName(node, nName)) {\n                    attrs[nName] = true; // presence means true\n                  }\n              }\n              addAttrInterpolateDirective(node, directives, value, nName);\n              addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,\n                            attrEndName);\n            }\n          }\n\n          // use class as directive\n          className = node.className;\n          if (isString(className) && className !== '') {\n            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {\n              nName = directiveNormalize(match[2]);\n              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[3]);\n              }\n              className = className.substr(match.index + match[0].length);\n            }\n          }\n          break;\n        case 3: /* Text Node */\n          addTextInterpolateDirective(directives, node.nodeValue);\n          break;\n        case 8: /* Comment */\n          try {\n            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);\n            if (match) {\n              nName = directiveNormalize(match[1]);\n              if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {\n                attrs[nName] = trim(match[2]);\n              }\n            }\n          } catch (e) {\n            // turns out that under some circumstances IE9 throws errors when one attempts to read\n            // comment's node value.\n            // Just ignore it and continue. (Can't seem to reproduce in test case.)\n          }\n          break;\n      }\n\n      directives.sort(byPriority);\n      return directives;\n    }\n\n    /**\n     * Given a node with an directive-start it collects all of the siblings until it finds\n     * directive-end.\n     * @param node\n     * @param attrStart\n     * @param attrEnd\n     * @returns {*}\n     */\n    function groupScan(node, attrStart, attrEnd) {\n      var nodes = [];\n      var depth = 0;\n      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {\n        var startNode = node;\n        do {\n          if (!node) {\n            throw $compileMinErr('uterdir',\n                      \"Unterminated attribute, found '{0}' but no matching '{1}' found.\",\n                      attrStart, attrEnd);\n          }\n          if (node.nodeType == 1 /** Element **/) {\n            if (node.hasAttribute(attrStart)) depth++;\n            if (node.hasAttribute(attrEnd)) depth--;\n          }\n          nodes.push(node);\n          node = node.nextSibling;\n        } while (depth > 0);\n      } else {\n        nodes.push(node);\n      }\n\n      return jqLite(nodes);\n    }\n\n    /**\n     * Wrapper for linking function which converts normal linking function into a grouped\n     * linking function.\n     * @param linkFn\n     * @param attrStart\n     * @param attrEnd\n     * @returns {Function}\n     */\n    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {\n      return function(scope, element, attrs, controllers, transcludeFn) {\n        element = groupScan(element[0], attrStart, attrEnd);\n        return linkFn(scope, element, attrs, controllers, transcludeFn);\n      };\n    }\n\n    /**\n     * Once the directives have been collected, their compile functions are executed. This method\n     * is responsible for inlining directive templates as well as terminating the application\n     * of the directives if the terminal directive has been reached.\n     *\n     * @param {Array} directives Array of collected directives to execute their compile function.\n     *        this needs to be pre-sorted by priority order.\n     * @param {Node} compileNode The raw DOM node to apply the compile functions to\n     * @param {Object} templateAttrs The shared attribute function\n     * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the\n     *                                                  scope argument is auto-generated to the new\n     *                                                  child of the transcluded parent scope.\n     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this\n     *                              argument has the root jqLite array so that we can replace nodes\n     *                              on it.\n     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when\n     *                                           compiling the transclusion.\n     * @param {Array.<Function>} preLinkFns\n     * @param {Array.<Function>} postLinkFns\n     * @param {Object} previousCompileContext Context used for previous compilation of the current\n     *                                        node\n     * @returns {Function} linkFn\n     */\n    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,\n                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,\n                                   previousCompileContext) {\n      previousCompileContext = previousCompileContext || {};\n\n      var terminalPriority = -Number.MAX_VALUE,\n          newScopeDirective,\n          controllerDirectives = previousCompileContext.controllerDirectives,\n          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,\n          templateDirective = previousCompileContext.templateDirective,\n          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,\n          hasTranscludeDirective = false,\n          hasTemplate = false,\n          hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,\n          $compileNode = templateAttrs.$$element = jqLite(compileNode),\n          directive,\n          directiveName,\n          $template,\n          replaceDirective = originalReplaceDirective,\n          childTranscludeFn = transcludeFn,\n          linkFn,\n          directiveValue;\n\n      // executes all directives on the current element\n      for(var i = 0, ii = directives.length; i < ii; i++) {\n        directive = directives[i];\n        var attrStart = directive.$$start;\n        var attrEnd = directive.$$end;\n\n        // collect multiblock sections\n        if (attrStart) {\n          $compileNode = groupScan(compileNode, attrStart, attrEnd);\n        }\n        $template = undefined;\n\n        if (terminalPriority > directive.priority) {\n          break; // prevent further processing of directives\n        }\n\n        if (directiveValue = directive.scope) {\n          newScopeDirective = newScopeDirective || directive;\n\n          // skip the check for directives with async templates, we'll check the derived sync\n          // directive when the template arrives\n          if (!directive.templateUrl) {\n            assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,\n                              $compileNode);\n            if (isObject(directiveValue)) {\n              newIsolateScopeDirective = directive;\n            }\n          }\n        }\n\n        directiveName = directive.name;\n\n        if (!directive.templateUrl && directive.controller) {\n          directiveValue = directive.controller;\n          controllerDirectives = controllerDirectives || {};\n          assertNoDuplicate(\"'\" + directiveName + \"' controller\",\n              controllerDirectives[directiveName], directive, $compileNode);\n          controllerDirectives[directiveName] = directive;\n        }\n\n        if (directiveValue = directive.transclude) {\n          hasTranscludeDirective = true;\n\n          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.\n          // This option should only be used by directives that know how to safely handle element transclusion,\n          // where the transcluded nodes are added or replaced after linking.\n          if (!directive.$$tlb) {\n            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);\n            nonTlbTranscludeDirective = directive;\n          }\n\n          if (directiveValue == 'element') {\n            hasElementTranscludeDirective = true;\n            terminalPriority = directive.priority;\n            $template = $compileNode;\n            $compileNode = templateAttrs.$$element =\n                jqLite(document.createComment(' ' + directiveName + ': ' +\n                                              templateAttrs[directiveName] + ' '));\n            compileNode = $compileNode[0];\n            replaceWith(jqCollection, sliceArgs($template), compileNode);\n\n            childTranscludeFn = compile($template, transcludeFn, terminalPriority,\n                                        replaceDirective && replaceDirective.name, {\n                                          // Don't pass in:\n                                          // - controllerDirectives - otherwise we'll create duplicates controllers\n                                          // - newIsolateScopeDirective or templateDirective - combining templates with\n                                          //   element transclusion doesn't make sense.\n                                          //\n                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion\n                                          // on the same element more than once.\n                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective\n                                        });\n          } else {\n            $template = jqLite(jqLiteClone(compileNode)).contents();\n            $compileNode.empty(); // clear contents\n            childTranscludeFn = compile($template, transcludeFn);\n          }\n        }\n\n        if (directive.template) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          directiveValue = (isFunction(directive.template))\n              ? directive.template($compileNode, templateAttrs)\n              : directive.template;\n\n          directiveValue = denormalizeTemplate(directiveValue);\n\n          if (directive.replace) {\n            replaceDirective = directive;\n            if (jqLiteIsTextNode(directiveValue)) {\n              $template = [];\n            } else {\n              $template = jqLite(trim(directiveValue));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  directiveName, '');\n            }\n\n            replaceWith(jqCollection, $compileNode, compileNode);\n\n            var newTemplateAttrs = {$attr: {}};\n\n            // combine directives from the original node and from the template:\n            // - take the array of directives for this element\n            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)\n            // - collect directives from the template and sort them by priority\n            // - combine directives as: processed + template + unprocessed\n            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);\n            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));\n\n            if (newIsolateScopeDirective) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);\n            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);\n\n            ii = directives.length;\n          } else {\n            $compileNode.html(directiveValue);\n          }\n        }\n\n        if (directive.templateUrl) {\n          hasTemplate = true;\n          assertNoDuplicate('template', templateDirective, directive, $compileNode);\n          templateDirective = directive;\n\n          if (directive.replace) {\n            replaceDirective = directive;\n          }\n\n          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,\n              templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {\n                controllerDirectives: controllerDirectives,\n                newIsolateScopeDirective: newIsolateScopeDirective,\n                templateDirective: templateDirective,\n                nonTlbTranscludeDirective: nonTlbTranscludeDirective\n              });\n          ii = directives.length;\n        } else if (directive.compile) {\n          try {\n            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);\n            if (isFunction(linkFn)) {\n              addLinkFns(null, linkFn, attrStart, attrEnd);\n            } else if (linkFn) {\n              addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);\n            }\n          } catch (e) {\n            $exceptionHandler(e, startingTag($compileNode));\n          }\n        }\n\n        if (directive.terminal) {\n          nodeLinkFn.terminal = true;\n          terminalPriority = Math.max(terminalPriority, directive.priority);\n        }\n\n      }\n\n      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;\n      nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;\n      nodeLinkFn.templateOnThisElement = hasTemplate;\n      nodeLinkFn.transclude = childTranscludeFn;\n\n      previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;\n\n      // might be normal or delayed nodeLinkFn depending on if templateUrl is present\n      return nodeLinkFn;\n\n      ////////////////////\n\n      function addLinkFns(pre, post, attrStart, attrEnd) {\n        if (pre) {\n          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);\n          pre.require = directive.require;\n          pre.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            pre = cloneAndAnnotateFn(pre, {isolateScope: true});\n          }\n          preLinkFns.push(pre);\n        }\n        if (post) {\n          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);\n          post.require = directive.require;\n          post.directiveName = directiveName;\n          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {\n            post = cloneAndAnnotateFn(post, {isolateScope: true});\n          }\n          postLinkFns.push(post);\n        }\n      }\n\n\n      function getControllers(directiveName, require, $element, elementControllers) {\n        var value, retrievalMethod = 'data', optional = false;\n        if (isString(require)) {\n          while((value = require.charAt(0)) == '^' || value == '?') {\n            require = require.substr(1);\n            if (value == '^') {\n              retrievalMethod = 'inheritedData';\n            }\n            optional = optional || value == '?';\n          }\n          value = null;\n\n          if (elementControllers && retrievalMethod === 'data') {\n            value = elementControllers[require];\n          }\n          value = value || $element[retrievalMethod]('$' + require + 'Controller');\n\n          if (!value && !optional) {\n            throw $compileMinErr('ctreq',\n                \"Controller '{0}', required by directive '{1}', can't be found!\",\n                require, directiveName);\n          }\n          return value;\n        } else if (isArray(require)) {\n          value = [];\n          forEach(require, function(require) {\n            value.push(getControllers(directiveName, require, $element, elementControllers));\n          });\n        }\n        return value;\n      }\n\n\n      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {\n        var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;\n\n        attrs = (compileNode === linkNode)\n          ? templateAttrs\n          : shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));\n        $element = attrs.$$element;\n\n        if (newIsolateScopeDirective) {\n          var LOCAL_REGEXP = /^\\s*([@=&])(\\??)\\s*(\\w*)\\s*$/;\n\n          isolateScope = scope.$new(true);\n\n          if (templateDirective && (templateDirective === newIsolateScopeDirective ||\n              templateDirective === newIsolateScopeDirective.$$originalDirective)) {\n            $element.data('$isolateScope', isolateScope);\n          } else {\n            $element.data('$isolateScopeNoTemplate', isolateScope);\n          }\n\n\n\n          safeAddClass($element, 'ng-isolate-scope');\n\n          forEach(newIsolateScopeDirective.scope, function(definition, scopeName) {\n            var match = definition.match(LOCAL_REGEXP) || [],\n                attrName = match[3] || scopeName,\n                optional = (match[2] == '?'),\n                mode = match[1], // @, =, or &\n                lastValue,\n                parentGet, parentSet, compare;\n\n            isolateScope.$$isolateBindings[scopeName] = mode + attrName;\n\n            switch (mode) {\n\n              case '@':\n                attrs.$observe(attrName, function(value) {\n                  isolateScope[scopeName] = value;\n                });\n                attrs.$$observers[attrName].$$scope = scope;\n                if( attrs[attrName] ) {\n                  // If the attribute has been provided then we trigger an interpolation to ensure\n                  // the value is there for use in the link fn\n                  isolateScope[scopeName] = $interpolate(attrs[attrName])(scope);\n                }\n                break;\n\n              case '=':\n                if (optional && !attrs[attrName]) {\n                  return;\n                }\n                parentGet = $parse(attrs[attrName]);\n                if (parentGet.literal) {\n                  compare = equals;\n                } else {\n                  compare = function(a,b) { return a === b || (a !== a && b !== b); };\n                }\n                parentSet = parentGet.assign || function() {\n                  // reset the change, or we will throw this exception on every $digest\n                  lastValue = isolateScope[scopeName] = parentGet(scope);\n                  throw $compileMinErr('nonassign',\n                      \"Expression '{0}' used with directive '{1}' is non-assignable!\",\n                      attrs[attrName], newIsolateScopeDirective.name);\n                };\n                lastValue = isolateScope[scopeName] = parentGet(scope);\n                isolateScope.$watch(function parentValueWatch() {\n                  var parentValue = parentGet(scope);\n                  if (!compare(parentValue, isolateScope[scopeName])) {\n                    // we are out of sync and need to copy\n                    if (!compare(parentValue, lastValue)) {\n                      // parent changed and it has precedence\n                      isolateScope[scopeName] = parentValue;\n                    } else {\n                      // if the parent can be assigned then do so\n                      parentSet(scope, parentValue = isolateScope[scopeName]);\n                    }\n                  }\n                  return lastValue = parentValue;\n                }, null, parentGet.literal);\n                break;\n\n              case '&':\n                parentGet = $parse(attrs[attrName]);\n                isolateScope[scopeName] = function(locals) {\n                  return parentGet(scope, locals);\n                };\n                break;\n\n              default:\n                throw $compileMinErr('iscp',\n                    \"Invalid isolate scope definition for directive '{0}'.\" +\n                    \" Definition: {... {1}: '{2}' ...}\",\n                    newIsolateScopeDirective.name, scopeName, definition);\n            }\n          });\n        }\n        transcludeFn = boundTranscludeFn && controllersBoundTransclude;\n        if (controllerDirectives) {\n          forEach(controllerDirectives, function(directive) {\n            var locals = {\n              $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,\n              $element: $element,\n              $attrs: attrs,\n              $transclude: transcludeFn\n            }, controllerInstance;\n\n            controller = directive.controller;\n            if (controller == '@') {\n              controller = attrs[directive.name];\n            }\n\n            controllerInstance = $controller(controller, locals);\n            // For directives with element transclusion the element is a comment,\n            // but jQuery .data doesn't support attaching data to comment nodes as it's hard to\n            // clean up (http://bugs.jquery.com/ticket/8335).\n            // Instead, we save the controllers for the element in a local hash and attach to .data\n            // later, once we have the actual element.\n            elementControllers[directive.name] = controllerInstance;\n            if (!hasElementTranscludeDirective) {\n              $element.data('$' + directive.name + 'Controller', controllerInstance);\n            }\n\n            if (directive.controllerAs) {\n              locals.$scope[directive.controllerAs] = controllerInstance;\n            }\n          });\n        }\n\n        // PRELINKING\n        for(i = 0, ii = preLinkFns.length; i < ii; i++) {\n          try {\n            linkFn = preLinkFns[i];\n            linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // RECURSION\n        // We only pass the isolate scope, if the isolate directive has a template,\n        // otherwise the child elements do not belong to the isolate directive.\n        var scopeToChild = scope;\n        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {\n          scopeToChild = isolateScope;\n        }\n        childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);\n\n        // POSTLINKING\n        for(i = postLinkFns.length - 1; i >= 0; i--) {\n          try {\n            linkFn = postLinkFns[i];\n            linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,\n                linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn);\n          } catch (e) {\n            $exceptionHandler(e, startingTag($element));\n          }\n        }\n\n        // This is the function that is injected as `$transclude`.\n        function controllersBoundTransclude(scope, cloneAttachFn) {\n          var transcludeControllers;\n\n          // no scope passed\n          if (arguments.length < 2) {\n            cloneAttachFn = scope;\n            scope = undefined;\n          }\n\n          if (hasElementTranscludeDirective) {\n            transcludeControllers = elementControllers;\n          }\n\n          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);\n        }\n      }\n    }\n\n    function markDirectivesAsIsolate(directives) {\n      // mark all directives as needing isolate scope.\n      for (var j = 0, jj = directives.length; j < jj; j++) {\n        directives[j] = inherit(directives[j], {$$isolateScope: true});\n      }\n    }\n\n    /**\n     * looks up the directive and decorates it with exception handling and proper parameters. We\n     * call this the boundDirective.\n     *\n     * @param {string} name name of the directive to look up.\n     * @param {string} location The directive must be found in specific format.\n     *   String containing any of theses characters:\n     *\n     *   * `E`: element name\n     *   * `A': attribute\n     *   * `C`: class\n     *   * `M`: comment\n     * @returns {boolean} true if directive was added.\n     */\n    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,\n                          endAttrName) {\n      if (name === ignoreDirective) return null;\n      var match = null;\n      if (hasDirectives.hasOwnProperty(name)) {\n        for(var directive, directives = $injector.get(name + Suffix),\n            i = 0, ii = directives.length; i<ii; i++) {\n          try {\n            directive = directives[i];\n            if ( (maxPriority === undefined || maxPriority > directive.priority) &&\n                 directive.restrict.indexOf(location) != -1) {\n              if (startAttrName) {\n                directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});\n              }\n              tDirectives.push(directive);\n              match = directive;\n            }\n          } catch(e) { $exceptionHandler(e); }\n        }\n      }\n      return match;\n    }\n\n\n    /**\n     * When the element is replaced with HTML template then the new attributes\n     * on the template need to be merged with the existing attributes in the DOM.\n     * The desired effect is to have both of the attributes present.\n     *\n     * @param {object} dst destination attributes (original DOM)\n     * @param {object} src source attributes (from the directive template)\n     */\n    function mergeTemplateAttributes(dst, src) {\n      var srcAttr = src.$attr,\n          dstAttr = dst.$attr,\n          $element = dst.$$element;\n\n      // reapply the old attributes to the new element\n      forEach(dst, function(value, key) {\n        if (key.charAt(0) != '$') {\n          if (src[key] && src[key] !== value) {\n            value += (key === 'style' ? ';' : ' ') + src[key];\n          }\n          dst.$set(key, value, true, srcAttr[key]);\n        }\n      });\n\n      // copy the new attributes on the old attrs object\n      forEach(src, function(value, key) {\n        if (key == 'class') {\n          safeAddClass($element, value);\n          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;\n        } else if (key == 'style') {\n          $element.attr('style', $element.attr('style') + ';' + value);\n          dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;\n          // `dst` will never contain hasOwnProperty as DOM parser won't let it.\n          // You will get an \"InvalidCharacterError: DOM Exception 5\" error if you\n          // have an attribute like \"has-own-property\" or \"data-has-own-property\", etc.\n        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {\n          dst[key] = value;\n          dstAttr[key] = srcAttr[key];\n        }\n      });\n    }\n\n\n    function compileTemplateUrl(directives, $compileNode, tAttrs,\n        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {\n      var linkQueue = [],\n          afterTemplateNodeLinkFn,\n          afterTemplateChildLinkFn,\n          beforeTemplateCompileNode = $compileNode[0],\n          origAsyncDirective = directives.shift(),\n          // The fact that we have to copy and patch the directive seems wrong!\n          derivedSyncDirective = extend({}, origAsyncDirective, {\n            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective\n          }),\n          templateUrl = (isFunction(origAsyncDirective.templateUrl))\n              ? origAsyncDirective.templateUrl($compileNode, tAttrs)\n              : origAsyncDirective.templateUrl;\n\n      $compileNode.empty();\n\n      $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).\n        success(function(content) {\n          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;\n\n          content = denormalizeTemplate(content);\n\n          if (origAsyncDirective.replace) {\n            if (jqLiteIsTextNode(content)) {\n              $template = [];\n            } else {\n              $template = jqLite(trim(content));\n            }\n            compileNode = $template[0];\n\n            if ($template.length != 1 || compileNode.nodeType !== 1) {\n              throw $compileMinErr('tplrt',\n                  \"Template for directive '{0}' must have exactly one root element. {1}\",\n                  origAsyncDirective.name, templateUrl);\n            }\n\n            tempTemplateAttrs = {$attr: {}};\n            replaceWith($rootElement, $compileNode, compileNode);\n            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);\n\n            if (isObject(origAsyncDirective.scope)) {\n              markDirectivesAsIsolate(templateDirectives);\n            }\n            directives = templateDirectives.concat(directives);\n            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);\n          } else {\n            compileNode = beforeTemplateCompileNode;\n            $compileNode.html(content);\n          }\n\n          directives.unshift(derivedSyncDirective);\n\n          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,\n              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,\n              previousCompileContext);\n          forEach($rootElement, function(node, i) {\n            if (node == compileNode) {\n              $rootElement[i] = $compileNode[0];\n            }\n          });\n          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);\n\n          while(linkQueue.length) {\n            var scope = linkQueue.shift(),\n                beforeTemplateLinkNode = linkQueue.shift(),\n                linkRootElement = linkQueue.shift(),\n                boundTranscludeFn = linkQueue.shift(),\n                linkNode = $compileNode[0];\n\n            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {\n              var oldClasses = beforeTemplateLinkNode.className;\n\n              if (!(previousCompileContext.hasElementTranscludeDirective &&\n                  origAsyncDirective.replace)) {\n                // it was cloned therefore we have to clone as well.\n                linkNode = jqLiteClone(compileNode);\n              }\n\n              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);\n\n              // Copy in CSS classes from original node\n              safeAddClass(jqLite(linkNode), oldClasses);\n            }\n            if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n            } else {\n              childBoundTranscludeFn = boundTranscludeFn;\n            }\n            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,\n              childBoundTranscludeFn);\n          }\n          linkQueue = null;\n        }).\n        error(function(response, code, headers, config) {\n          throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);\n        });\n\n      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {\n        var childBoundTranscludeFn = boundTranscludeFn;\n        if (linkQueue) {\n          linkQueue.push(scope);\n          linkQueue.push(node);\n          linkQueue.push(rootElement);\n          linkQueue.push(childBoundTranscludeFn);\n        } else {\n          if (afterTemplateNodeLinkFn.transcludeOnThisElement) {\n            childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);\n          }\n          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn);\n        }\n      };\n    }\n\n\n    /**\n     * Sorting function for bound directives.\n     */\n    function byPriority(a, b) {\n      var diff = b.priority - a.priority;\n      if (diff !== 0) return diff;\n      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;\n      return a.index - b.index;\n    }\n\n\n    function assertNoDuplicate(what, previousDirective, directive, element) {\n      if (previousDirective) {\n        throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',\n            previousDirective.name, directive.name, what, startingTag(element));\n      }\n    }\n\n\n      function addTextInterpolateDirective(directives, text) {\n        var interpolateFn = $interpolate(text, true);\n        if (interpolateFn) {\n          directives.push({\n            priority: 0,\n            compile: function textInterpolateCompileFn(templateNode) {\n              // when transcluding a template that has bindings in the root\n              // then we don't have a parent and should do this in the linkFn\n              var parent = templateNode.parent(), hasCompileParent = parent.length;\n              if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');\n\n              return function textInterpolateLinkFn(scope, node) {\n                var parent = node.parent(),\n                  bindings = parent.data('$binding') || [];\n                bindings.push(interpolateFn);\n                parent.data('$binding', bindings);\n                if (!hasCompileParent) safeAddClass(parent, 'ng-binding');\n                scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {\n                  node[0].nodeValue = value;\n                });\n              };\n            }\n          });\n        }\n      }\n\n\n    function getTrustedContext(node, attrNormalizedName) {\n      if (attrNormalizedName == \"srcdoc\") {\n        return $sce.HTML;\n      }\n      var tag = nodeName_(node);\n      // maction[xlink:href] can source SVG.  It's not limited to <maction>.\n      if (attrNormalizedName == \"xlinkHref\" ||\n          (tag == \"FORM\" && attrNormalizedName == \"action\") ||\n          (tag != \"IMG\" && (attrNormalizedName == \"src\" ||\n                            attrNormalizedName == \"ngSrc\"))) {\n        return $sce.RESOURCE_URL;\n      }\n    }\n\n\n    function addAttrInterpolateDirective(node, directives, value, name) {\n      var interpolateFn = $interpolate(value, true);\n\n      // no interpolation found -> ignore\n      if (!interpolateFn) return;\n\n\n      if (name === \"multiple\" && nodeName_(node) === \"SELECT\") {\n        throw $compileMinErr(\"selmulti\",\n            \"Binding to the 'multiple' attribute is not supported. Element: {0}\",\n            startingTag(node));\n      }\n\n      directives.push({\n        priority: 100,\n        compile: function() {\n            return {\n              pre: function attrInterpolatePreLinkFn(scope, element, attr) {\n                var $$observers = (attr.$$observers || (attr.$$observers = {}));\n\n                if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {\n                  throw $compileMinErr('nodomevents',\n                      \"Interpolations for HTML DOM event attributes are disallowed.  Please use the \" +\n                          \"ng- versions (such as ng-click instead of onclick) instead.\");\n                }\n\n                // we need to interpolate again, in case the attribute value has been updated\n                // (e.g. by another directive's compile function)\n                interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name));\n\n                // if attribute was updated so that there is no interpolation going on we don't want to\n                // register any observers\n                if (!interpolateFn) return;\n\n                // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the\n                // actual attr value\n                attr[name] = interpolateFn(scope);\n                ($$observers[name] || ($$observers[name] = [])).$$inter = true;\n                (attr.$$observers && attr.$$observers[name].$$scope || scope).\n                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {\n                    //special case for class attribute addition + removal\n                    //so that class changes can tap into the animation\n                    //hooks provided by the $animate service. Be sure to\n                    //skip animations when the first digest occurs (when\n                    //both the new and the old values are the same) since\n                    //the CSS classes are the non-interpolated values\n                    if(name === 'class' && newValue != oldValue) {\n                      attr.$updateClass(newValue, oldValue);\n                    } else {\n                      attr.$set(name, newValue);\n                    }\n                  });\n              }\n            };\n          }\n      });\n    }\n\n\n    /**\n     * This is a special jqLite.replaceWith, which can replace items which\n     * have no parents, provided that the containing jqLite collection is provided.\n     *\n     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes\n     *                               in the root of the tree.\n     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep\n     *                                  the shell, but replace its DOM node reference.\n     * @param {Node} newNode The new DOM node.\n     */\n    function replaceWith($rootElement, elementsToRemove, newNode) {\n      var firstElementToRemove = elementsToRemove[0],\n          removeCount = elementsToRemove.length,\n          parent = firstElementToRemove.parentNode,\n          i, ii;\n\n      if ($rootElement) {\n        for(i = 0, ii = $rootElement.length; i < ii; i++) {\n          if ($rootElement[i] == firstElementToRemove) {\n            $rootElement[i++] = newNode;\n            for (var j = i, j2 = j + removeCount - 1,\n                     jj = $rootElement.length;\n                 j < jj; j++, j2++) {\n              if (j2 < jj) {\n                $rootElement[j] = $rootElement[j2];\n              } else {\n                delete $rootElement[j];\n              }\n            }\n            $rootElement.length -= removeCount - 1;\n            break;\n          }\n        }\n      }\n\n      if (parent) {\n        parent.replaceChild(newNode, firstElementToRemove);\n      }\n      var fragment = document.createDocumentFragment();\n      fragment.appendChild(firstElementToRemove);\n      newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];\n      for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {\n        var element = elementsToRemove[k];\n        jqLite(element).remove(); // must do this way to clean up expando\n        fragment.appendChild(element);\n        delete elementsToRemove[k];\n      }\n\n      elementsToRemove[0] = newNode;\n      elementsToRemove.length = 1;\n    }\n\n\n    function cloneAndAnnotateFn(fn, annotation) {\n      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);\n    }\n  }];\n}\n\nvar PREFIX_REGEXP = /^(x[\\:\\-_]|data[\\:\\-_])/i;\n/**\n * Converts all accepted directives format into proper directive name.\n * @param name Name to normalize\n */\nfunction directiveNormalize(name) {\n  return camelCase(name.replace(PREFIX_REGEXP, ''));\n}\n\n/**\n * @ngdoc type\n * @name $compile.directive.Attributes\n *\n * @description\n * A shared object between directive compile / linking functions which contains normalized DOM\n * element attributes. The values reflect current binding state `{{ }}`. The normalization is\n * needed since all of these are treated as equivalent in Angular:\n *\n * ```\n *    <span ng:bind=\"a\" ng-bind=\"a\" data-ng-bind=\"a\" x-ng-bind=\"a\">\n * ```\n */\n\n/**\n * @ngdoc property\n * @name $compile.directive.Attributes#$attr\n *\n * @description\n * A map of DOM element attribute names to the normalized name. This is\n * needed to do reverse lookup from normalized name back to actual name.\n */\n\n\n/**\n * @ngdoc method\n * @name $compile.directive.Attributes#$set\n * @kind function\n *\n * @description\n * Set DOM element attribute value.\n *\n *\n * @param {string} name Normalized element attribute name of the property to modify. The name is\n *          reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}\n *          property to the original name.\n * @param {string} value Value to set the attribute to. The value can be an interpolated string.\n */\n\n\n\n/**\n * Closure compiler type information\n */\n\nfunction nodesetLinkingFn(\n  /* angular.Scope */ scope,\n  /* NodeList */ nodeList,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction directiveLinkingFn(\n  /* nodesetLinkingFn */ nodesetLinkingFn,\n  /* angular.Scope */ scope,\n  /* Node */ node,\n  /* Element */ rootElement,\n  /* function(Function) */ boundTranscludeFn\n){}\n\nfunction tokenDifference(str1, str2) {\n  var values = '',\n      tokens1 = str1.split(/\\s+/),\n      tokens2 = str2.split(/\\s+/);\n\n  outer:\n  for(var i = 0; i < tokens1.length; i++) {\n    var token = tokens1[i];\n    for(var j = 0; j < tokens2.length; j++) {\n      if(token == tokens2[j]) continue outer;\n    }\n    values += (values.length > 0 ? ' ' : '') + token;\n  }\n  return values;\n}\n\n/**\n * @ngdoc provider\n * @name $controllerProvider\n * @description\n * The {@link ng.$controller $controller service} is used by Angular to create new\n * controllers.\n *\n * This provider allows controller registration via the\n * {@link ng.$controllerProvider#register register} method.\n */\nfunction $ControllerProvider() {\n  var controllers = {},\n      CNTRL_REG = /^(\\S+)(\\s+as\\s+(\\w+))?$/;\n\n\n  /**\n   * @ngdoc method\n   * @name $controllerProvider#register\n   * @param {string|Object} name Controller name, or an object map of controllers where the keys are\n   *    the names and the values are the constructors.\n   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI\n   *    annotations in the array notation).\n   */\n  this.register = function(name, constructor) {\n    assertNotHasOwnProperty(name, 'controller');\n    if (isObject(name)) {\n      extend(controllers, name);\n    } else {\n      controllers[name] = constructor;\n    }\n  };\n\n\n  this.$get = ['$injector', '$window', function($injector, $window) {\n\n    /**\n     * @ngdoc service\n     * @name $controller\n     * @requires $injector\n     *\n     * @param {Function|string} constructor If called with a function then it's considered to be the\n     *    controller constructor function. Otherwise it's considered to be a string which is used\n     *    to retrieve the controller constructor using the following steps:\n     *\n     *    * check if a controller with given name is registered via `$controllerProvider`\n     *    * check if evaluating the string on the current scope returns a constructor\n     *    * check `window[constructor]` on the global `window` object\n     *\n     * @param {Object} locals Injection locals for Controller.\n     * @return {Object} Instance of given controller.\n     *\n     * @description\n     * `$controller` service is responsible for instantiating controllers.\n     *\n     * It's just a simple call to {@link auto.$injector $injector}, but extracted into\n     * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).\n     */\n    return function(expression, locals) {\n      var instance, match, constructor, identifier;\n\n      if(isString(expression)) {\n        match = expression.match(CNTRL_REG),\n        constructor = match[1],\n        identifier = match[3];\n        expression = controllers.hasOwnProperty(constructor)\n            ? controllers[constructor]\n            : getter(locals.$scope, constructor, true) || getter($window, constructor, true);\n\n        assertArgFn(expression, constructor, true);\n      }\n\n      instance = $injector.instantiate(expression, locals);\n\n      if (identifier) {\n        if (!(locals && typeof locals.$scope === 'object')) {\n          throw minErr('$controller')('noscp',\n              \"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.\",\n              constructor || expression.name, identifier);\n        }\n\n        locals.$scope[identifier] = instance;\n      }\n\n      return instance;\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $document\n * @requires $window\n *\n * @description\n * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.\n *\n * @example\n   <example module=\"documentExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n         <p>$document title: <b ng-bind=\"title\"></b></p>\n         <p>window.document title: <b ng-bind=\"windowTitle\"></b></p>\n       </div>\n     </file>\n     <file name=\"script.js\">\n       angular.module('documentExample', [])\n         .controller('ExampleController', ['$scope', '$document', function($scope, $document) {\n           $scope.title = $document[0].title;\n           $scope.windowTitle = angular.element(window.document)[0].title;\n         }]);\n     </file>\n   </example>\n */\nfunction $DocumentProvider(){\n  this.$get = ['$window', function(window){\n    return jqLite(window.document);\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $exceptionHandler\n * @requires ng.$log\n *\n * @description\n * Any uncaught exception in angular expressions is delegated to this service.\n * The default implementation simply delegates to `$log.error` which logs it into\n * the browser console.\n *\n * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by\n * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.\n *\n * ## Example:\n *\n * ```js\n *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {\n *     return function (exception, cause) {\n *       exception.message += ' (caused by \"' + cause + '\")';\n *       throw exception;\n *     };\n *   });\n * ```\n *\n * This example will override the normal action of `$exceptionHandler`, to make angular\n * exceptions fail hard when they happen, instead of just logging to the console.\n *\n * @param {Error} exception Exception associated with the error.\n * @param {string=} cause optional information about the context in which\n *       the error was thrown.\n *\n */\nfunction $ExceptionHandlerProvider() {\n  this.$get = ['$log', function($log) {\n    return function(exception, cause) {\n      $log.error.apply($log, arguments);\n    };\n  }];\n}\n\n/**\n * Parse headers into key value object\n *\n * @param {string} headers Raw headers as a string\n * @returns {Object} Parsed headers as key value object\n */\nfunction parseHeaders(headers) {\n  var parsed = {}, key, val, i;\n\n  if (!headers) return parsed;\n\n  forEach(headers.split('\\n'), function(line) {\n    i = line.indexOf(':');\n    key = lowercase(trim(line.substr(0, i)));\n    val = trim(line.substr(i + 1));\n\n    if (key) {\n      parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n    }\n  });\n\n  return parsed;\n}\n\n\n/**\n * Returns a function that provides access to parsed headers.\n *\n * Headers are lazy parsed when first requested.\n * @see parseHeaders\n *\n * @param {(string|Object)} headers Headers to provide access to.\n * @returns {function(string=)} Returns a getter function which if called with:\n *\n *   - if called with single an argument returns a single header value or null\n *   - if called with no arguments returns an object containing all headers.\n */\nfunction headersGetter(headers) {\n  var headersObj = isObject(headers) ? headers : undefined;\n\n  return function(name) {\n    if (!headersObj) headersObj =  parseHeaders(headers);\n\n    if (name) {\n      return headersObj[lowercase(name)] || null;\n    }\n\n    return headersObj;\n  };\n}\n\n\n/**\n * Chain all given functions\n *\n * This function is used for both request and response transforming\n *\n * @param {*} data Data to transform.\n * @param {function(string=)} headers Http headers getter fn.\n * @param {(Function|Array.<Function>)} fns Function or an array of functions.\n * @returns {*} Transformed data.\n */\nfunction transformData(data, headers, fns) {\n  if (isFunction(fns))\n    return fns(data, headers);\n\n  forEach(fns, function(fn) {\n    data = fn(data, headers);\n  });\n\n  return data;\n}\n\n\nfunction isSuccess(status) {\n  return 200 <= status && status < 300;\n}\n\n\n/**\n * @ngdoc provider\n * @name $httpProvider\n * @description\n * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.\n * */\nfunction $HttpProvider() {\n  var JSON_START = /^\\s*(\\[|\\{[^\\{])/,\n      JSON_END = /[\\}\\]]\\s*$/,\n      PROTECTION_PREFIX = /^\\)\\]\\}',?\\n/,\n      CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#defaults\n   * @description\n   *\n   * Object containing default values for all {@link ng.$http $http} requests.\n   *\n   * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.\n   * Defaults value is `'XSRF-TOKEN'`.\n   *\n   * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the\n   * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.\n   *\n   * - **`defaults.headers`** - {Object} - Default headers for all $http requests.\n   * Refer to {@link ng.$http#setting-http-headers $http} for documentation on\n   * setting default headers.\n   *     - **`defaults.headers.common`**\n   *     - **`defaults.headers.post`**\n   *     - **`defaults.headers.put`**\n   *     - **`defaults.headers.patch`**\n   **/\n  var defaults = this.defaults = {\n    // transform incoming response data\n    transformResponse: [function(data) {\n      if (isString(data)) {\n        // strip json vulnerability protection prefix\n        data = data.replace(PROTECTION_PREFIX, '');\n        if (JSON_START.test(data) && JSON_END.test(data))\n          data = fromJson(data);\n      }\n      return data;\n    }],\n\n    // transform outgoing request data\n    transformRequest: [function(d) {\n      return isObject(d) && !isFile(d) && !isBlob(d) ? toJson(d) : d;\n    }],\n\n    // default headers\n    headers: {\n      common: {\n        'Accept': 'application/json, text/plain, */*'\n      },\n      post:   shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      put:    shallowCopy(CONTENT_TYPE_APPLICATION_JSON),\n      patch:  shallowCopy(CONTENT_TYPE_APPLICATION_JSON)\n    },\n\n    xsrfCookieName: 'XSRF-TOKEN',\n    xsrfHeaderName: 'X-XSRF-TOKEN'\n  };\n\n  /**\n   * @ngdoc property\n   * @name $httpProvider#interceptors\n   * @description\n   *\n   * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}\n   * pre-processing of request or postprocessing of responses.\n   *\n   * These service factories are ordered by request, i.e. they are applied in the same order as the\n   * array, on request, but reverse order, on response.\n   *\n   * {@link ng.$http#interceptors Interceptors detailed info}\n   **/\n  var interceptorFactories = this.interceptors = [];\n\n  /**\n   * For historical reasons, response interceptors are ordered by the order in which\n   * they are applied to the response. (This is the opposite of interceptorFactories)\n   */\n  var responseInterceptorFactories = this.responseInterceptors = [];\n\n  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',\n      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {\n\n    var defaultCache = $cacheFactory('$http');\n\n    /**\n     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.\n     * The reversal is needed so that we can build up the interception chain around the\n     * server request.\n     */\n    var reversedInterceptors = [];\n\n    forEach(interceptorFactories, function(interceptorFactory) {\n      reversedInterceptors.unshift(isString(interceptorFactory)\n          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));\n    });\n\n    forEach(responseInterceptorFactories, function(interceptorFactory, index) {\n      var responseFn = isString(interceptorFactory)\n          ? $injector.get(interceptorFactory)\n          : $injector.invoke(interceptorFactory);\n\n      /**\n       * Response interceptors go before \"around\" interceptors (no real reason, just\n       * had to pick one.) But they are already reversed, so we can't use unshift, hence\n       * the splice.\n       */\n      reversedInterceptors.splice(index, 0, {\n        response: function(response) {\n          return responseFn($q.when(response));\n        },\n        responseError: function(response) {\n          return responseFn($q.reject(response));\n        }\n      });\n    });\n\n\n    /**\n     * @ngdoc service\n     * @kind function\n     * @name $http\n     * @requires ng.$httpBackend\n     * @requires $cacheFactory\n     * @requires $rootScope\n     * @requires $q\n     * @requires $injector\n     *\n     * @description\n     * The `$http` service is a core Angular service that facilitates communication with the remote\n     * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)\n     * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).\n     *\n     * For unit testing applications that use `$http` service, see\n     * {@link ngMock.$httpBackend $httpBackend mock}.\n     *\n     * For a higher level of abstraction, please check out the {@link ngResource.$resource\n     * $resource} service.\n     *\n     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by\n     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage\n     * it is important to familiarize yourself with these APIs and the guarantees they provide.\n     *\n     *\n     * # General usage\n     * The `$http` service is a function which takes a single argument — a configuration object —\n     * that is used to generate an HTTP request and returns  a {@link ng.$q promise}\n     * with two $http specific methods: `success` and `error`.\n     *\n     * ```js\n     *   $http({method: 'GET', url: '/someUrl'}).\n     *     success(function(data, status, headers, config) {\n     *       // this callback will be called asynchronously\n     *       // when the response is available\n     *     }).\n     *     error(function(data, status, headers, config) {\n     *       // called asynchronously if an error occurs\n     *       // or server returns response with an error status.\n     *     });\n     * ```\n     *\n     * Since the returned value of calling the $http function is a `promise`, you can also use\n     * the `then` method to register callbacks, and these callbacks will receive a single argument –\n     * an object representing the response. See the API signature and type info below for more\n     * details.\n     *\n     * A response status code between 200 and 299 is considered a success status and\n     * will result in the success callback being called. Note that if the response is a redirect,\n     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be\n     * called for such responses.\n     *\n     * # Writing Unit Tests that use $http\n     * When unit testing (using {@link ngMock ngMock}), it is necessary to call\n     * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending\n     * request using trained responses.\n     *\n     * ```\n     * $httpBackend.expectGET(...);\n     * $http.get(...);\n     * $httpBackend.flush();\n     * ```\n     *\n     * # Shortcut methods\n     *\n     * Shortcut methods are also available. All shortcut methods require passing in the URL, and\n     * request data must be passed in for POST/PUT requests.\n     *\n     * ```js\n     *   $http.get('/someUrl').success(successCallback);\n     *   $http.post('/someUrl', data).success(successCallback);\n     * ```\n     *\n     * Complete list of shortcut methods:\n     *\n     * - {@link ng.$http#get $http.get}\n     * - {@link ng.$http#head $http.head}\n     * - {@link ng.$http#post $http.post}\n     * - {@link ng.$http#put $http.put}\n     * - {@link ng.$http#delete $http.delete}\n     * - {@link ng.$http#jsonp $http.jsonp}\n     * - {@link ng.$http#patch $http.patch}\n     *\n     *\n     * # Setting HTTP Headers\n     *\n     * The $http service will automatically add certain HTTP headers to all requests. These defaults\n     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration\n     * object, which currently contains this default configuration:\n     *\n     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):\n     *   - `Accept: application/json, text/plain, * / *`\n     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)\n     *   - `Content-Type: application/json`\n     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)\n     *   - `Content-Type: application/json`\n     *\n     * To add or overwrite these defaults, simply add or remove a property from these configuration\n     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object\n     * with the lowercased HTTP method name as the key, e.g.\n     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.\n     *\n     * The defaults can also be set at runtime via the `$http.defaults` object in the same\n     * fashion. For example:\n     *\n     * ```\n     * module.run(function($http) {\n     *   $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'\n     * });\n     * ```\n     *\n     * In addition, you can supply a `headers` property in the config object passed when\n     * calling `$http(config)`, which overrides the defaults without changing them globally.\n     *\n     * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,\n     * Use the `headers` property, setting the desired header to `undefined`. For example:\n     *\n     * ```js\n     * var req = {\n     *  method: 'POST',\n     *  url: 'http://example.com',\n     *  headers: {\n     *    'Content-Type': undefined\n     *  },\n     *  data: { test: 'test' },\n     * }\n     *\n     * $http(req).success(function(){...}).error(function(){...});\n     * ```\n     *\n     * # Transforming Requests and Responses\n     *\n     * Both requests and responses can be transformed using transform functions. By default, Angular\n     * applies these transformations:\n     *\n     * Request transformations:\n     *\n     * - If the `data` property of the request configuration object contains an object, serialize it\n     *   into JSON format.\n     *\n     * Response transformations:\n     *\n     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).\n     *  - If JSON response is detected, deserialize it using a JSON parser.\n     *\n     * To globally augment or override the default transforms, modify the\n     * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse`\n     * properties. These properties are by default an array of transform functions, which allows you\n     * to `push` or `unshift` a new transformation function into the transformation chain. You can\n     * also decide to completely override any default transformations by assigning your\n     * transformation functions to these properties directly without the array wrapper.  These defaults\n     * are again available on the $http factory at run-time, which may be useful if you have run-time\n     * services you wish to be involved in your transformations.\n     *\n     * Similarly, to locally override the request/response transforms, augment the\n     * `transformRequest` and/or `transformResponse` properties of the configuration object passed\n     * into `$http`.\n     *\n     *\n     * # Caching\n     *\n     * To enable caching, set the request configuration `cache` property to `true` (to use default\n     * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).\n     * When the cache is enabled, `$http` stores the response from the server in the specified\n     * cache. The next time the same request is made, the response is served from the cache without\n     * sending a request to the server.\n     *\n     * Note that even if the response is served from cache, delivery of the data is asynchronous in\n     * the same way that real requests are.\n     *\n     * If there are multiple GET requests for the same URL that should be cached using the same\n     * cache, but the cache is not populated yet, only one request to the server will be made and\n     * the remaining requests will be fulfilled using the response from the first request.\n     *\n     * You can change the default cache to a new object (built with\n     * {@link ng.$cacheFactory `$cacheFactory`}) by updating the\n     * {@link ng.$http#properties_defaults `$http.defaults.cache`} property. All requests who set\n     * their `cache` property to `true` will now use this cache object.\n     *\n     * If you set the default cache to `false` then only requests that specify their own custom\n     * cache object will be cached.\n     *\n     * # Interceptors\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication, or any kind of synchronous or\n     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be\n     * able to intercept requests before they are handed to the server and\n     * responses before they are handed over to the application code that\n     * initiated these requests. The interceptors leverage the {@link ng.$q\n     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.\n     *\n     * The interceptors are service factories that are registered with the `$httpProvider` by\n     * adding them to the `$httpProvider.interceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor.\n     *\n     * There are two kinds of interceptors (and two kinds of rejection interceptors):\n     *\n     *   * `request`: interceptors get called with a http `config` object. The function is free to\n     *     modify the `config` object or create a new one. The function needs to return the `config`\n     *     object directly, or a promise containing the `config` or a new `config` object.\n     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *   * `response`: interceptors get called with http `response` object. The function is free to\n     *     modify the `response` object or create a new one. The function needs to return the `response`\n     *     object directly, or as a promise containing the `response` or a new `response` object.\n     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or\n     *     resolved with a rejection.\n     *\n     *\n     * ```js\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return {\n     *       // optional method\n     *       'request': function(config) {\n     *         // do something on success\n     *         return config;\n     *       },\n     *\n     *       // optional method\n     *      'requestError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       },\n     *\n     *\n     *\n     *       // optional method\n     *       'response': function(response) {\n     *         // do something on success\n     *         return response;\n     *       },\n     *\n     *       // optional method\n     *      'responseError': function(rejection) {\n     *         // do something on error\n     *         if (canRecover(rejection)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(rejection);\n     *       }\n     *     };\n     *   });\n     *\n     *   $httpProvider.interceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // alternatively, register the interceptor via an anonymous factory\n     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {\n     *     return {\n     *      'request': function(config) {\n     *          // same as above\n     *       },\n     *\n     *       'response': function(response) {\n     *          // same as above\n     *       }\n     *     };\n     *   });\n     * ```\n     *\n     * # Response interceptors (DEPRECATED)\n     *\n     * Before you start creating interceptors, be sure to understand the\n     * {@link ng.$q $q and deferred/promise APIs}.\n     *\n     * For purposes of global error handling, authentication or any kind of synchronous or\n     * asynchronous preprocessing of received responses, it is desirable to be able to intercept\n     * responses for http requests before they are handed over to the application code that\n     * initiated these requests. The response interceptors leverage the {@link ng.$q\n     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.\n     *\n     * The interceptors are service factories that are registered with the $httpProvider by\n     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and\n     * injected with dependencies (if specified) and returns the interceptor  — a function that\n     * takes a {@link ng.$q promise} and returns the original or a new promise.\n     *\n     * ```js\n     *   // register the interceptor as a service\n     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       return promise.then(function(response) {\n     *         // do something on success\n     *         return response;\n     *       }, function(response) {\n     *         // do something on error\n     *         if (canRecover(response)) {\n     *           return responseOrNewPromise\n     *         }\n     *         return $q.reject(response);\n     *       });\n     *     }\n     *   });\n     *\n     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');\n     *\n     *\n     *   // register the interceptor via an anonymous factory\n     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {\n     *     return function(promise) {\n     *       // same as above\n     *     }\n     *   });\n     * ```\n     *\n     *\n     * # Security Considerations\n     *\n     * When designing web applications, consider security threats from:\n     *\n     * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)\n     *\n     * Both server and the client must cooperate in order to eliminate these threats. Angular comes\n     * pre-configured with strategies that address these issues, but for this to work backend server\n     * cooperation is required.\n     *\n     * ## JSON Vulnerability Protection\n     *\n     * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)\n     * allows third party website to turn your JSON resource URL into\n     * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To\n     * counter this your server can prefix all JSON requests with following string `\")]}',\\n\"`.\n     * Angular will automatically strip the prefix before processing it as JSON.\n     *\n     * For example if your server needs to return:\n     * ```js\n     * ['one','two']\n     * ```\n     *\n     * which is vulnerable to attack, your server can return:\n     * ```js\n     * )]}',\n     * ['one','two']\n     * ```\n     *\n     * Angular will strip the prefix, before processing the JSON.\n     *\n     *\n     * ## Cross Site Request Forgery (XSRF) Protection\n     *\n     * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which\n     * an unauthorized site can gain your user's private data. Angular provides a mechanism\n     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie\n     * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only\n     * JavaScript that runs on your domain could read the cookie, your server can be assured that\n     * the XHR came from JavaScript running on your domain. The header will not be set for\n     * cross-domain requests.\n     *\n     * To take advantage of this, your server needs to set a token in a JavaScript readable session\n     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the\n     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure\n     * that only JavaScript running on your domain could have sent the request. The token must be\n     * unique for each user and must be verifiable by the server (to prevent the JavaScript from\n     * making up its own tokens). We recommend that the token is a digest of your site's\n     * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)\n     * for added security.\n     *\n     * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName\n     * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,\n     * or the per-request config object.\n     *\n     *\n     * @param {object} config Object describing the request to be made and how it should be\n     *    processed. The object has following properties:\n     *\n     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)\n     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.\n     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned\n     *      to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be\n     *      JSONified.\n     *    - **data** – `{string|Object}` – Data to be sent as the request message data.\n     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing\n     *      HTTP headers to send to the server. If the return value of a function is null, the\n     *      header will not be sent.\n     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.\n     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.\n     *    - **transformRequest** –\n     *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      request body and headers and returns its transformed (typically serialized) version.\n     *    - **transformResponse** –\n     *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –\n     *      transform function or an array of such functions. The transform function takes the http\n     *      response body and headers and returns its transformed (typically deserialized) version.\n     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the\n     *      GET request, otherwise if a cache instance built with\n     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for\n     *      caching.\n     *    - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}\n     *      that should abort the request when resolved.\n     *    - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the\n     *      XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)\n     *      for more information.\n     *    - **responseType** - `{string}` - see\n     *      [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).\n     *\n     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the\n     *   standard `then` method and two http specific methods: `success` and `error`. The `then`\n     *   method takes two arguments a success and an error callback which will be called with a\n     *   response object. The `success` and `error` methods take a single argument - a function that\n     *   will be called when the request succeeds or fails respectively. The arguments passed into\n     *   these functions are destructured representation of the response object passed into the\n     *   `then` method. The response object has these properties:\n     *\n     *   - **data** – `{string|Object}` – The response body transformed with the transform\n     *     functions.\n     *   - **status** – `{number}` – HTTP status code of the response.\n     *   - **headers** – `{function([headerName])}` – Header getter function.\n     *   - **config** – `{Object}` – The configuration object that was used to generate the request.\n     *   - **statusText** – `{string}` – HTTP status text of the response.\n     *\n     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending\n     *   requests. This is primarily meant to be used for debugging purposes.\n     *\n     *\n     * @example\n<example module=\"httpExample\">\n<file name=\"index.html\">\n  <div ng-controller=\"FetchController\">\n    <select ng-model=\"method\">\n      <option>GET</option>\n      <option>JSONP</option>\n    </select>\n    <input type=\"text\" ng-model=\"url\" size=\"80\"/>\n    <button id=\"fetchbtn\" ng-click=\"fetch()\">fetch</button><br>\n    <button id=\"samplegetbtn\" ng-click=\"updateModel('GET', 'http-hello.html')\">Sample GET</button>\n    <button id=\"samplejsonpbtn\"\n      ng-click=\"updateModel('JSONP',\n                    'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')\">\n      Sample JSONP\n    </button>\n    <button id=\"invalidjsonpbtn\"\n      ng-click=\"updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')\">\n        Invalid JSONP\n      </button>\n    <pre>http status code: {{status}}</pre>\n    <pre>http response data: {{data}}</pre>\n  </div>\n</file>\n<file name=\"script.js\">\n  angular.module('httpExample', [])\n    .controller('FetchController', ['$scope', '$http', '$templateCache',\n      function($scope, $http, $templateCache) {\n        $scope.method = 'GET';\n        $scope.url = 'http-hello.html';\n\n        $scope.fetch = function() {\n          $scope.code = null;\n          $scope.response = null;\n\n          $http({method: $scope.method, url: $scope.url, cache: $templateCache}).\n            success(function(data, status) {\n              $scope.status = status;\n              $scope.data = data;\n            }).\n            error(function(data, status) {\n              $scope.data = data || \"Request failed\";\n              $scope.status = status;\n          });\n        };\n\n        $scope.updateModel = function(method, url) {\n          $scope.method = method;\n          $scope.url = url;\n        };\n      }]);\n</file>\n<file name=\"http-hello.html\">\n  Hello, $http!\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  var status = element(by.binding('status'));\n  var data = element(by.binding('data'));\n  var fetchBtn = element(by.id('fetchbtn'));\n  var sampleGetBtn = element(by.id('samplegetbtn'));\n  var sampleJsonpBtn = element(by.id('samplejsonpbtn'));\n  var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));\n\n  it('should make an xhr GET request', function() {\n    sampleGetBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('200');\n    expect(data.getText()).toMatch(/Hello, \\$http!/);\n  });\n\n// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185\n// it('should make a JSONP request to angularjs.org', function() {\n//   sampleJsonpBtn.click();\n//   fetchBtn.click();\n//   expect(status.getText()).toMatch('200');\n//   expect(data.getText()).toMatch(/Super Hero!/);\n// });\n\n  it('should make JSONP request to invalid URL and invoke the error handler',\n      function() {\n    invalidJsonpBtn.click();\n    fetchBtn.click();\n    expect(status.getText()).toMatch('0');\n    expect(data.getText()).toMatch('Request failed');\n  });\n</file>\n</example>\n     */\n    function $http(requestConfig) {\n      var config = {\n        method: 'get',\n        transformRequest: defaults.transformRequest,\n        transformResponse: defaults.transformResponse\n      };\n      var headers = mergeHeaders(requestConfig);\n\n      extend(config, requestConfig);\n      config.headers = headers;\n      config.method = uppercase(config.method);\n\n      var serverRequest = function(config) {\n        headers = config.headers;\n        var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);\n\n        // strip content-type if data is undefined\n        if (isUndefined(reqData)) {\n          forEach(headers, function(value, header) {\n            if (lowercase(header) === 'content-type') {\n                delete headers[header];\n            }\n          });\n        }\n\n        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {\n          config.withCredentials = defaults.withCredentials;\n        }\n\n        // send request\n        return sendReq(config, reqData, headers).then(transformResponse, transformResponse);\n      };\n\n      var chain = [serverRequest, undefined];\n      var promise = $q.when(config);\n\n      // apply interceptors\n      forEach(reversedInterceptors, function(interceptor) {\n        if (interceptor.request || interceptor.requestError) {\n          chain.unshift(interceptor.request, interceptor.requestError);\n        }\n        if (interceptor.response || interceptor.responseError) {\n          chain.push(interceptor.response, interceptor.responseError);\n        }\n      });\n\n      while(chain.length) {\n        var thenFn = chain.shift();\n        var rejectFn = chain.shift();\n\n        promise = promise.then(thenFn, rejectFn);\n      }\n\n      promise.success = function(fn) {\n        promise.then(function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      promise.error = function(fn) {\n        promise.then(null, function(response) {\n          fn(response.data, response.status, response.headers, config);\n        });\n        return promise;\n      };\n\n      return promise;\n\n      function transformResponse(response) {\n        // make a copy since the response must be cacheable\n        var resp = extend({}, response, {\n          data: transformData(response.data, response.headers, config.transformResponse)\n        });\n        return (isSuccess(response.status))\n          ? resp\n          : $q.reject(resp);\n      }\n\n      function mergeHeaders(config) {\n        var defHeaders = defaults.headers,\n            reqHeaders = extend({}, config.headers),\n            defHeaderName, lowercaseDefHeaderName, reqHeaderName;\n\n        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);\n\n        // using for-in instead of forEach to avoid unecessary iteration after header has been found\n        defaultHeadersIteration:\n        for (defHeaderName in defHeaders) {\n          lowercaseDefHeaderName = lowercase(defHeaderName);\n\n          for (reqHeaderName in reqHeaders) {\n            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {\n              continue defaultHeadersIteration;\n            }\n          }\n\n          reqHeaders[defHeaderName] = defHeaders[defHeaderName];\n        }\n\n        // execute if header value is a function for merged headers\n        execHeaders(reqHeaders);\n        return reqHeaders;\n\n        function execHeaders(headers) {\n          var headerContent;\n\n          forEach(headers, function(headerFn, header) {\n            if (isFunction(headerFn)) {\n              headerContent = headerFn();\n              if (headerContent != null) {\n                headers[header] = headerContent;\n              } else {\n                delete headers[header];\n              }\n            }\n          });\n        }\n      }\n    }\n\n    $http.pendingRequests = [];\n\n    /**\n     * @ngdoc method\n     * @name $http#get\n     *\n     * @description\n     * Shortcut method to perform `GET` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#delete\n     *\n     * @description\n     * Shortcut method to perform `DELETE` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#head\n     *\n     * @description\n     * Shortcut method to perform `HEAD` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#jsonp\n     *\n     * @description\n     * Shortcut method to perform `JSONP` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request.\n     *                     The name of the callback should be the string `JSON_CALLBACK`.\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethods('get', 'delete', 'head', 'jsonp');\n\n    /**\n     * @ngdoc method\n     * @name $http#post\n     *\n     * @description\n     * Shortcut method to perform `POST` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#put\n     *\n     * @description\n     * Shortcut method to perform `PUT` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n\n    /**\n     * @ngdoc method\n     * @name $http#patch\n     *\n     * @description\n     * Shortcut method to perform `PATCH` request.\n     *\n     * @param {string} url Relative or absolute URL specifying the destination of the request\n     * @param {*} data Request content\n     * @param {Object=} config Optional configuration object\n     * @returns {HttpPromise} Future object\n     */\n    createShortMethodsWithData('post', 'put', 'patch');\n\n    /**\n     * @ngdoc property\n     * @name $http#defaults\n     *\n     * @description\n     * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of\n     * default headers, withCredentials as well as request and response transformations.\n     *\n     * See \"Setting HTTP Headers\" and \"Transforming Requests and Responses\" sections above.\n     */\n    $http.defaults = defaults;\n\n\n    return $http;\n\n\n    function createShortMethods(names) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url\n          }));\n        };\n      });\n    }\n\n\n    function createShortMethodsWithData(name) {\n      forEach(arguments, function(name) {\n        $http[name] = function(url, data, config) {\n          return $http(extend(config || {}, {\n            method: name,\n            url: url,\n            data: data\n          }));\n        };\n      });\n    }\n\n\n    /**\n     * Makes the request.\n     *\n     * !!! ACCESSES CLOSURE VARS:\n     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests\n     */\n    function sendReq(config, reqData, reqHeaders) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          cache,\n          cachedResp,\n          url = buildUrl(config.url, config.params);\n\n      $http.pendingRequests.push(config);\n      promise.then(removePendingReq, removePendingReq);\n\n\n      if ((config.cache || defaults.cache) && config.cache !== false &&\n          (config.method === 'GET' || config.method === 'JSONP')) {\n        cache = isObject(config.cache) ? config.cache\n              : isObject(defaults.cache) ? defaults.cache\n              : defaultCache;\n      }\n\n      if (cache) {\n        cachedResp = cache.get(url);\n        if (isDefined(cachedResp)) {\n          if (isPromiseLike(cachedResp)) {\n            // cached request has already been sent, but there is no response yet\n            cachedResp.then(removePendingReq, removePendingReq);\n            return cachedResp;\n          } else {\n            // serving from cache\n            if (isArray(cachedResp)) {\n              resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);\n            } else {\n              resolvePromise(cachedResp, 200, {}, 'OK');\n            }\n          }\n        } else {\n          // put the promise for the non-transformed response into cache as a placeholder\n          cache.put(url, promise);\n        }\n      }\n\n\n      // if we won't have the response in cache, set the xsrf headers and\n      // send the request to the backend\n      if (isUndefined(cachedResp)) {\n        var xsrfValue = urlIsSameOrigin(config.url)\n            ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]\n            : undefined;\n        if (xsrfValue) {\n          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;\n        }\n\n        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,\n            config.withCredentials, config.responseType);\n      }\n\n      return promise;\n\n\n      /**\n       * Callback registered to $httpBackend():\n       *  - caches the response if desired\n       *  - resolves the raw $http promise\n       *  - calls $apply\n       */\n      function done(status, response, headersString, statusText) {\n        if (cache) {\n          if (isSuccess(status)) {\n            cache.put(url, [status, response, parseHeaders(headersString), statusText]);\n          } else {\n            // remove promise from the cache\n            cache.remove(url);\n          }\n        }\n\n        resolvePromise(response, status, headersString, statusText);\n        if (!$rootScope.$$phase) $rootScope.$apply();\n      }\n\n\n      /**\n       * Resolves the raw $http promise.\n       */\n      function resolvePromise(response, status, headers, statusText) {\n        // normalize internal statuses to 0\n        status = Math.max(status, 0);\n\n        (isSuccess(status) ? deferred.resolve : deferred.reject)({\n          data: response,\n          status: status,\n          headers: headersGetter(headers),\n          config: config,\n          statusText : statusText\n        });\n      }\n\n\n      function removePendingReq() {\n        var idx = indexOf($http.pendingRequests, config);\n        if (idx !== -1) $http.pendingRequests.splice(idx, 1);\n      }\n    }\n\n\n    function buildUrl(url, params) {\n      if (!params) return url;\n      var parts = [];\n      forEachSorted(params, function(value, key) {\n        if (value === null || isUndefined(value)) return;\n        if (!isArray(value)) value = [value];\n\n        forEach(value, function(v) {\n          if (isObject(v)) {\n            if (isDate(v)){\n              v = v.toISOString();\n            } else {\n              v = toJson(v);\n            }\n          }\n          parts.push(encodeUriQuery(key) + '=' +\n                     encodeUriQuery(v));\n        });\n      });\n      if(parts.length > 0) {\n        url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');\n      }\n      return url;\n    }\n  }];\n}\n\nfunction createXhr(method) {\n    //if IE and the method is not RFC2616 compliant, or if XMLHttpRequest\n    //is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest\n    //if it is available\n    if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) ||\n      !window.XMLHttpRequest)) {\n      return new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n    } else if (window.XMLHttpRequest) {\n      return new window.XMLHttpRequest();\n    }\n\n    throw minErr('$httpBackend')('noxhr', \"This browser does not support XMLHttpRequest.\");\n}\n\n/**\n * @ngdoc service\n * @name $httpBackend\n * @requires $window\n * @requires $document\n *\n * @description\n * HTTP backend used by the {@link ng.$http service} that delegates to\n * XMLHttpRequest object or JSONP and deals with browser incompatibilities.\n *\n * You should never need to use this service directly, instead use the higher-level abstractions:\n * {@link ng.$http $http} or {@link ngResource.$resource $resource}.\n *\n * During testing this implementation is swapped with {@link ngMock.$httpBackend mock\n * $httpBackend} which can be trained with responses.\n */\nfunction $HttpBackendProvider() {\n  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {\n    return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);\n  }];\n}\n\nfunction createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {\n  var ABORTED = -1;\n\n  // TODO(vojta): fix the signature\n  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {\n    var status;\n    $browser.$$incOutstandingRequestCount();\n    url = url || $browser.url();\n\n    if (lowercase(method) == 'jsonp') {\n      var callbackId = '_' + (callbacks.counter++).toString(36);\n      callbacks[callbackId] = function(data) {\n        callbacks[callbackId].data = data;\n        callbacks[callbackId].called = true;\n      };\n\n      var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),\n          callbackId, function(status, text) {\n        completeRequest(callback, status, callbacks[callbackId].data, \"\", text);\n        callbacks[callbackId] = noop;\n      });\n    } else {\n\n      var xhr = createXhr(method);\n\n      xhr.open(method, url, true);\n      forEach(headers, function(value, key) {\n        if (isDefined(value)) {\n            xhr.setRequestHeader(key, value);\n        }\n      });\n\n      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the\n      // response is in the cache. the promise api will ensure that to the app code the api is\n      // always async\n      xhr.onreadystatechange = function() {\n        // onreadystatechange might get called multiple times with readyState === 4 on mobile webkit caused by\n        // xhrs that are resolved while the app is in the background (see #5426).\n        // since calling completeRequest sets the `xhr` variable to null, we just check if it's not null before\n        // continuing\n        //\n        // we can't set xhr.onreadystatechange to undefined or delete it because that breaks IE8 (method=PATCH) and\n        // Safari respectively.\n        if (xhr && xhr.readyState == 4) {\n          var responseHeaders = null,\n              response = null,\n              statusText = '';\n\n          if(status !== ABORTED) {\n            responseHeaders = xhr.getAllResponseHeaders();\n\n            // responseText is the old-school way of retrieving response (supported by IE8 & 9)\n            // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)\n            response = ('response' in xhr) ? xhr.response : xhr.responseText;\n          }\n\n          // Accessing statusText on an aborted xhr object will\n          // throw an 'c00c023f error' in IE9 and lower, don't touch it.\n          if (!(status === ABORTED && msie < 10)) {\n            statusText = xhr.statusText;\n          }\n\n          completeRequest(callback,\n              status || xhr.status,\n              response,\n              responseHeaders,\n              statusText);\n        }\n      };\n\n      if (withCredentials) {\n        xhr.withCredentials = true;\n      }\n\n      if (responseType) {\n        try {\n          xhr.responseType = responseType;\n        } catch (e) {\n          // WebKit added support for the json responseType value on 09/03/2013\n          // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are\n          // known to throw when setting the value \"json\" as the response type. Other older\n          // browsers implementing the responseType\n          //\n          // The json response type can be ignored if not supported, because JSON payloads are\n          // parsed on the client-side regardless.\n          if (responseType !== 'json') {\n            throw e;\n          }\n        }\n      }\n\n      xhr.send(post || null);\n    }\n\n    if (timeout > 0) {\n      var timeoutId = $browserDefer(timeoutRequest, timeout);\n    } else if (isPromiseLike(timeout)) {\n      timeout.then(timeoutRequest);\n    }\n\n\n    function timeoutRequest() {\n      status = ABORTED;\n      jsonpDone && jsonpDone();\n      xhr && xhr.abort();\n    }\n\n    function completeRequest(callback, status, response, headersString, statusText) {\n      // cancel timeout and subsequent timeout promise resolution\n      timeoutId && $browserDefer.cancel(timeoutId);\n      jsonpDone = xhr = null;\n\n      // fix status code when it is 0 (0 status is undocumented).\n      // Occurs when accessing file resources or on Android 4.1 stock browser\n      // while retrieving files from application cache.\n      if (status === 0) {\n        status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;\n      }\n\n      // normalize IE bug (http://bugs.jquery.com/ticket/1450)\n      status = status === 1223 ? 204 : status;\n      statusText = statusText || '';\n\n      callback(status, response, headersString, statusText);\n      $browser.$$completeOutstandingRequest(noop);\n    }\n  };\n\n  function jsonpReq(url, callbackId, done) {\n    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:\n    // - fetches local scripts via XHR and evals them\n    // - adds and immediately removes script elements from the document\n    var script = rawDocument.createElement('script'), callback = null;\n    script.type = \"text/javascript\";\n    script.src = url;\n    script.async = true;\n\n    callback = function(event) {\n      removeEventListenerFn(script, \"load\", callback);\n      removeEventListenerFn(script, \"error\", callback);\n      rawDocument.body.removeChild(script);\n      script = null;\n      var status = -1;\n      var text = \"unknown\";\n\n      if (event) {\n        if (event.type === \"load\" && !callbacks[callbackId].called) {\n          event = { type: \"error\" };\n        }\n        text = event.type;\n        status = event.type === \"error\" ? 404 : 200;\n      }\n\n      if (done) {\n        done(status, text);\n      }\n    };\n\n    addEventListenerFn(script, \"load\", callback);\n    addEventListenerFn(script, \"error\", callback);\n\n    if (msie <= 8) {\n      script.onreadystatechange = function() {\n        if (isString(script.readyState) && /loaded|complete/.test(script.readyState)) {\n          script.onreadystatechange = null;\n          callback({\n            type: 'load'\n          });\n        }\n      };\n    }\n\n    rawDocument.body.appendChild(script);\n    return callback;\n  }\n}\n\nvar $interpolateMinErr = minErr('$interpolate');\n\n/**\n * @ngdoc provider\n * @name $interpolateProvider\n * @kind function\n *\n * @description\n *\n * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.\n *\n * @example\n<example module=\"customInterpolationApp\">\n<file name=\"index.html\">\n<script>\n  var customInterpolationApp = angular.module('customInterpolationApp', []);\n\n  customInterpolationApp.config(function($interpolateProvider) {\n    $interpolateProvider.startSymbol('//');\n    $interpolateProvider.endSymbol('//');\n  });\n\n\n  customInterpolationApp.controller('DemoController', function() {\n      this.label = \"This binding is brought you by // interpolation symbols.\";\n  });\n</script>\n<div ng-app=\"App\" ng-controller=\"DemoController as demo\">\n    //demo.label//\n</div>\n</file>\n<file name=\"protractor.js\" type=\"protractor\">\n  it('should interpolate binding with custom symbols', function() {\n    expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');\n  });\n</file>\n</example>\n */\nfunction $InterpolateProvider() {\n  var startSymbol = '{{';\n  var endSymbol = '}}';\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#startSymbol\n   * @description\n   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.\n   *\n   * @param {string=} value new value to set the starting symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.startSymbol = function(value){\n    if (value) {\n      startSymbol = value;\n      return this;\n    } else {\n      return startSymbol;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $interpolateProvider#endSymbol\n   * @description\n   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n   *\n   * @param {string=} value new value to set the ending symbol to.\n   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.\n   */\n  this.endSymbol = function(value){\n    if (value) {\n      endSymbol = value;\n      return this;\n    } else {\n      return endSymbol;\n    }\n  };\n\n\n  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {\n    var startSymbolLength = startSymbol.length,\n        endSymbolLength = endSymbol.length;\n\n    /**\n     * @ngdoc service\n     * @name $interpolate\n     * @kind function\n     *\n     * @requires $parse\n     * @requires $sce\n     *\n     * @description\n     *\n     * Compiles a string with markup into an interpolation function. This service is used by the\n     * HTML {@link ng.$compile $compile} service for data binding. See\n     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the\n     * interpolation markup.\n     *\n     *\n     * ```js\n     *   var $interpolate = ...; // injected\n     *   var exp = $interpolate('Hello {{name | uppercase}}!');\n     *   expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');\n     * ```\n     *\n     *\n     * @param {string} text The text with markup to interpolate.\n     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have\n     *    embedded expression in order to return an interpolation function. Strings with no\n     *    embedded expression will return null for the interpolation function.\n     * @param {string=} trustedContext when provided, the returned function passes the interpolated\n     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,\n     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that\n     *    provides Strict Contextual Escaping for details.\n     * @returns {function(context)} an interpolation function which is used to compute the\n     *    interpolated string. The function has these parameters:\n     *\n     *    * `context`: an object against which any expressions embedded in the strings are evaluated\n     *      against.\n     *\n     */\n    function $interpolate(text, mustHaveExpression, trustedContext) {\n      var startIndex,\n          endIndex,\n          index = 0,\n          parts = [],\n          length = text.length,\n          hasInterpolation = false,\n          fn,\n          exp,\n          concat = [];\n\n      while(index < length) {\n        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&\n             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {\n          (index != startIndex) && parts.push(text.substring(index, startIndex));\n          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));\n          fn.exp = exp;\n          index = endIndex + endSymbolLength;\n          hasInterpolation = true;\n        } else {\n          // we did not find anything, so we have to add the remainder to the parts array\n          (index != length) && parts.push(text.substring(index));\n          index = length;\n        }\n      }\n\n      if (!(length = parts.length)) {\n        // we added, nothing, must have been an empty string.\n        parts.push('');\n        length = 1;\n      }\n\n      // Concatenating expressions makes it hard to reason about whether some combination of\n      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a\n      // single expression be used for iframe[src], object[src], etc., we ensure that the value\n      // that's used is assigned or constructed by some JS code somewhere that is more testable or\n      // make it obvious that you bound the value to some user controlled value.  This helps reduce\n      // the load when auditing for XSS issues.\n      if (trustedContext && parts.length > 1) {\n          throw $interpolateMinErr('noconcat',\n              \"Error while interpolating: {0}\\nStrict Contextual Escaping disallows \" +\n              \"interpolations that concatenate multiple expressions when a trusted value is \" +\n              \"required.  See http://docs.angularjs.org/api/ng.$sce\", text);\n      }\n\n      if (!mustHaveExpression  || hasInterpolation) {\n        concat.length = length;\n        fn = function(context) {\n          try {\n            for(var i = 0, ii = length, part; i<ii; i++) {\n              if (typeof (part = parts[i]) == 'function') {\n                part = part(context);\n                if (trustedContext) {\n                  part = $sce.getTrusted(trustedContext, part);\n                } else {\n                  part = $sce.valueOf(part);\n                }\n                if (part == null) { // null || undefined\n                  part = '';\n                } else {\n                  switch (typeof part) {\n                    case 'string':\n                    {\n                      break;\n                    }\n                    case 'number':\n                    {\n                      part = '' + part;\n                      break;\n                    }\n                    default:\n                    {\n                      part = toJson(part);\n                    }\n                  }\n                }\n              }\n              concat[i] = part;\n            }\n            return concat.join('');\n          }\n          catch(err) {\n            var newErr = $interpolateMinErr('interr', \"Can't interpolate: {0}\\n{1}\", text,\n                err.toString());\n            $exceptionHandler(newErr);\n          }\n        };\n        fn.exp = text;\n        fn.parts = parts;\n        return fn;\n      }\n    }\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#startSymbol\n     * @description\n     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.\n     *\n     * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} start symbol.\n     */\n    $interpolate.startSymbol = function() {\n      return startSymbol;\n    };\n\n\n    /**\n     * @ngdoc method\n     * @name $interpolate#endSymbol\n     * @description\n     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.\n     *\n     * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change\n     * the symbol.\n     *\n     * @returns {string} end symbol.\n     */\n    $interpolate.endSymbol = function() {\n      return endSymbol;\n    };\n\n    return $interpolate;\n  }];\n}\n\nfunction $IntervalProvider() {\n  this.$get = ['$rootScope', '$window', '$q',\n       function($rootScope,   $window,   $q) {\n    var intervals = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $interval\n      *\n      * @description\n      * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`\n      * milliseconds.\n      *\n      * The return value of registering an interval function is a promise. This promise will be\n      * notified upon each tick of the interval, and will be resolved after `count` iterations, or\n      * run indefinitely if `count` is not defined. The value of the notification will be the\n      * number of iterations that have run.\n      * To cancel an interval, call `$interval.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to\n      * move forward by `millis` milliseconds and trigger any functions scheduled to run in that\n      * time.\n      *\n      * <div class=\"alert alert-warning\">\n      * **Note**: Intervals created by this service must be explicitly destroyed when you are finished\n      * with them.  In particular they are not automatically destroyed when a controller's scope or a\n      * directive's element are destroyed.\n      * You should take this into consideration and make sure to always cancel the interval at the\n      * appropriate moment.  See the example below for more details on how and when to do this.\n      * </div>\n      *\n      * @param {function()} fn A function that should be called repeatedly.\n      * @param {number} delay Number of milliseconds between each function call.\n      * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat\n      *   indefinitely.\n      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {promise} A promise which will be notified on each iteration.\n      *\n      * @example\n      * <example module=\"intervalExample\">\n      * <file name=\"index.html\">\n      *   <script>\n      *     angular.module('intervalExample', [])\n      *       .controller('ExampleController', ['$scope', '$interval',\n      *         function($scope, $interval) {\n      *           $scope.format = 'M/d/yy h:mm:ss a';\n      *           $scope.blood_1 = 100;\n      *           $scope.blood_2 = 120;\n      *\n      *           var stop;\n      *           $scope.fight = function() {\n      *             // Don't start a new fight if we are already fighting\n      *             if ( angular.isDefined(stop) ) return;\n      *\n      *             stop = $interval(function() {\n      *               if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {\n      *                 $scope.blood_1 = $scope.blood_1 - 3;\n      *                 $scope.blood_2 = $scope.blood_2 - 4;\n      *               } else {\n      *                 $scope.stopFight();\n      *               }\n      *             }, 100);\n      *           };\n      *\n      *           $scope.stopFight = function() {\n      *             if (angular.isDefined(stop)) {\n      *               $interval.cancel(stop);\n      *               stop = undefined;\n      *             }\n      *           };\n      *\n      *           $scope.resetFight = function() {\n      *             $scope.blood_1 = 100;\n      *             $scope.blood_2 = 120;\n      *           };\n      *\n      *           $scope.$on('$destroy', function() {\n      *             // Make sure that the interval is destroyed too\n      *             $scope.stopFight();\n      *           });\n      *         }])\n      *       // Register the 'myCurrentTime' directive factory method.\n      *       // We inject $interval and dateFilter service since the factory method is DI.\n      *       .directive('myCurrentTime', ['$interval', 'dateFilter',\n      *         function($interval, dateFilter) {\n      *           // return the directive link function. (compile function not needed)\n      *           return function(scope, element, attrs) {\n      *             var format,  // date format\n      *                 stopTime; // so that we can cancel the time updates\n      *\n      *             // used to update the UI\n      *             function updateTime() {\n      *               element.text(dateFilter(new Date(), format));\n      *             }\n      *\n      *             // watch the expression, and update the UI on change.\n      *             scope.$watch(attrs.myCurrentTime, function(value) {\n      *               format = value;\n      *               updateTime();\n      *             });\n      *\n      *             stopTime = $interval(updateTime, 1000);\n      *\n      *             // listen on DOM destroy (removal) event, and cancel the next UI update\n      *             // to prevent updating time after the DOM element was removed.\n      *             element.bind('$destroy', function() {\n      *               $interval.cancel(stopTime);\n      *             });\n      *           }\n      *         }]);\n      *   </script>\n      *\n      *   <div>\n      *     <div ng-controller=\"ExampleController\">\n      *       Date format: <input ng-model=\"format\"> <hr/>\n      *       Current time is: <span my-current-time=\"format\"></span>\n      *       <hr/>\n      *       Blood 1 : <font color='red'>{{blood_1}}</font>\n      *       Blood 2 : <font color='red'>{{blood_2}}</font>\n      *       <button type=\"button\" data-ng-click=\"fight()\">Fight</button>\n      *       <button type=\"button\" data-ng-click=\"stopFight()\">StopFight</button>\n      *       <button type=\"button\" data-ng-click=\"resetFight()\">resetFight</button>\n      *     </div>\n      *   </div>\n      *\n      * </file>\n      * </example>\n      */\n    function interval(fn, delay, count, invokeApply) {\n      var setInterval = $window.setInterval,\n          clearInterval = $window.clearInterval,\n          deferred = $q.defer(),\n          promise = deferred.promise,\n          iteration = 0,\n          skipApply = (isDefined(invokeApply) && !invokeApply);\n\n      count = isDefined(count) ? count : 0;\n\n      promise.then(null, null, fn);\n\n      promise.$$intervalId = setInterval(function tick() {\n        deferred.notify(iteration++);\n\n        if (count > 0 && iteration >= count) {\n          deferred.resolve(iteration);\n          clearInterval(promise.$$intervalId);\n          delete intervals[promise.$$intervalId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n\n      }, delay);\n\n      intervals[promise.$$intervalId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $interval#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`.\n      *\n      * @param {promise} promise returned by the `$interval` function.\n      * @returns {boolean} Returns `true` if the task was successfully canceled.\n      */\n    interval.cancel = function(promise) {\n      if (promise && promise.$$intervalId in intervals) {\n        intervals[promise.$$intervalId].reject('canceled');\n        $window.clearInterval(promise.$$intervalId);\n        delete intervals[promise.$$intervalId];\n        return true;\n      }\n      return false;\n    };\n\n    return interval;\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $locale\n *\n * @description\n * $locale service provides localization rules for various Angular components. As of right now the\n * only public api is:\n *\n * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)\n */\nfunction $LocaleProvider(){\n  this.$get = function() {\n    return {\n      id: 'en-us',\n\n      NUMBER_FORMATS: {\n        DECIMAL_SEP: '.',\n        GROUP_SEP: ',',\n        PATTERNS: [\n          { // Decimal Pattern\n            minInt: 1,\n            minFrac: 0,\n            maxFrac: 3,\n            posPre: '',\n            posSuf: '',\n            negPre: '-',\n            negSuf: '',\n            gSize: 3,\n            lgSize: 3\n          },{ //Currency Pattern\n            minInt: 1,\n            minFrac: 2,\n            maxFrac: 2,\n            posPre: '\\u00A4',\n            posSuf: '',\n            negPre: '(\\u00A4',\n            negSuf: ')',\n            gSize: 3,\n            lgSize: 3\n          }\n        ],\n        CURRENCY_SYM: '$'\n      },\n\n      DATETIME_FORMATS: {\n        MONTH:\n            'January,February,March,April,May,June,July,August,September,October,November,December'\n            .split(','),\n        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),\n        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),\n        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),\n        AMPMS: ['AM','PM'],\n        medium: 'MMM d, y h:mm:ss a',\n        short: 'M/d/yy h:mm a',\n        fullDate: 'EEEE, MMMM d, y',\n        longDate: 'MMMM d, y',\n        mediumDate: 'MMM d, y',\n        shortDate: 'M/d/yy',\n        mediumTime: 'h:mm:ss a',\n        shortTime: 'h:mm a'\n      },\n\n      pluralCat: function(num) {\n        if (num === 1) {\n          return 'one';\n        }\n        return 'other';\n      }\n    };\n  };\n}\n\nvar PATH_MATCH = /^([^\\?#]*)(\\?([^#]*))?(#(.*))?$/,\n    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};\nvar $locationMinErr = minErr('$location');\n\n\n/**\n * Encode path using encodeUriSegment, ignoring forward slashes\n *\n * @param {string} path Path to encode\n * @returns {string}\n */\nfunction encodePath(path) {\n  var segments = path.split('/'),\n      i = segments.length;\n\n  while (i--) {\n    segments[i] = encodeUriSegment(segments[i]);\n  }\n\n  return segments.join('/');\n}\n\nfunction parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {\n  var parsedUrl = urlResolve(absoluteUrl, appBase);\n\n  locationObj.$$protocol = parsedUrl.protocol;\n  locationObj.$$host = parsedUrl.hostname;\n  locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;\n}\n\n\nfunction parseAppUrl(relativeUrl, locationObj, appBase) {\n  var prefixed = (relativeUrl.charAt(0) !== '/');\n  if (prefixed) {\n    relativeUrl = '/' + relativeUrl;\n  }\n  var match = urlResolve(relativeUrl, appBase);\n  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?\n      match.pathname.substring(1) : match.pathname);\n  locationObj.$$search = parseKeyValue(match.search);\n  locationObj.$$hash = decodeURIComponent(match.hash);\n\n  // make sure path starts with '/';\n  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {\n    locationObj.$$path = '/' + locationObj.$$path;\n  }\n}\n\n\n/**\n *\n * @param {string} begin\n * @param {string} whole\n * @returns {string} returns text from whole after begin or undefined if it does not begin with\n *                   expected string.\n */\nfunction beginsWith(begin, whole) {\n  if (whole.indexOf(begin) === 0) {\n    return whole.substr(begin.length);\n  }\n}\n\n\nfunction stripHash(url) {\n  var index = url.indexOf('#');\n  return index == -1 ? url : url.substr(0, index);\n}\n\n\nfunction stripFile(url) {\n  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);\n}\n\n/* return the server only (scheme://host:port) */\nfunction serverBase(url) {\n  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));\n}\n\n\n/**\n * LocationHtml5Url represents an url\n * This object is exposed as $location service when HTML5 mode is enabled and supported\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} basePrefix url path prefix\n */\nfunction LocationHtml5Url(appBase, basePrefix) {\n  this.$$html5 = true;\n  basePrefix = basePrefix || '';\n  var appBaseNoFile = stripFile(appBase);\n  parseAbsoluteUrl(appBase, this, appBase);\n\n\n  /**\n   * Parse given html5 (regular) url string into properties\n   * @param {string} newAbsoluteUrl HTML5 url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var pathUrl = beginsWith(appBaseNoFile, url);\n    if (!isString(pathUrl)) {\n      throw $locationMinErr('ipthprfx', 'Invalid url \"{0}\", missing path prefix \"{1}\".', url,\n          appBaseNoFile);\n    }\n\n    parseAppUrl(pathUrl, this, appBase);\n\n    if (!this.$$path) {\n      this.$$path = '/';\n    }\n\n    this.$$compose();\n  };\n\n  /**\n   * Compose url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    var appUrl, prevAppUrl;\n    var rewrittenUrl;\n\n    if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {\n      prevAppUrl = appUrl;\n      if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {\n        rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);\n      } else {\n        rewrittenUrl = appBase + prevAppUrl;\n      }\n    } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {\n      rewrittenUrl = appBaseNoFile + appUrl;\n    } else if (appBaseNoFile == url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when developer doesn't opt into html5 mode.\n * It also serves as the base class for html5 mode fallback on legacy browsers.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangUrl(appBase, hashPrefix) {\n  var appBaseNoFile = stripFile(appBase);\n\n  parseAbsoluteUrl(appBase, this, appBase);\n\n\n  /**\n   * Parse given hashbang url into properties\n   * @param {string} url Hashbang url\n   * @private\n   */\n  this.$$parse = function(url) {\n    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);\n    var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'\n        ? beginsWith(hashPrefix, withoutBaseUrl)\n        : (this.$$html5)\n          ? withoutBaseUrl\n          : '';\n\n    if (!isString(withoutHashUrl)) {\n      throw $locationMinErr('ihshprfx', 'Invalid url \"{0}\", missing hash prefix \"{1}\".', url,\n          hashPrefix);\n    }\n    parseAppUrl(withoutHashUrl, this, appBase);\n\n    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);\n\n    this.$$compose();\n\n    /*\n     * In Windows, on an anchor node on documents loaded from\n     * the filesystem, the browser will return a pathname\n     * prefixed with the drive name ('/C:/path') when a\n     * pathname without a drive is set:\n     *  * a.setAttribute('href', '/foo')\n     *   * a.pathname === '/C:/foo' //true\n     *\n     * Inside of Angular, we're always using pathnames that\n     * do not include drive names for routing.\n     */\n    function removeWindowsDriveName (path, url, base) {\n      /*\n      Matches paths for file protocol on windows,\n      such as /C:/foo/bar, and captures only /foo/bar.\n      */\n      var windowsFilePathExp = /^\\/[A-Z]:(\\/.*)/;\n\n      var firstPathSegmentMatch;\n\n      //Get the relative path from the input URL.\n      if (url.indexOf(base) === 0) {\n        url = url.replace(base, '');\n      }\n\n      // The input URL intentionally contains a first path segment that ends with a colon.\n      if (windowsFilePathExp.exec(url)) {\n        return path;\n      }\n\n      firstPathSegmentMatch = windowsFilePathExp.exec(path);\n      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;\n    }\n  };\n\n  /**\n   * Compose hashbang url and update `absUrl` property\n   * @private\n   */\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');\n  };\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    if(stripHash(appBase) == stripHash(url)) {\n      this.$$parse(url);\n      return true;\n    }\n    return false;\n  };\n}\n\n\n/**\n * LocationHashbangUrl represents url\n * This object is exposed as $location service when html5 history api is enabled but the browser\n * does not support it.\n *\n * @constructor\n * @param {string} appBase application base URL\n * @param {string} hashPrefix hashbang prefix\n */\nfunction LocationHashbangInHtml5Url(appBase, hashPrefix) {\n  this.$$html5 = true;\n  LocationHashbangUrl.apply(this, arguments);\n\n  var appBaseNoFile = stripFile(appBase);\n\n  this.$$parseLinkUrl = function(url, relHref) {\n    var rewrittenUrl;\n    var appUrl;\n\n    if ( appBase == stripHash(url) ) {\n      rewrittenUrl = url;\n    } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {\n      rewrittenUrl = appBase + hashPrefix + appUrl;\n    } else if ( appBaseNoFile === url + '/') {\n      rewrittenUrl = appBaseNoFile;\n    }\n    if (rewrittenUrl) {\n      this.$$parse(rewrittenUrl);\n    }\n    return !!rewrittenUrl;\n  };\n\n  this.$$compose = function() {\n    var search = toKeyValue(this.$$search),\n        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';\n\n    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;\n    // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'\n    this.$$absUrl = appBase + hashPrefix + this.$$url;\n  };\n\n}\n\n\nLocationHashbangInHtml5Url.prototype =\n  LocationHashbangUrl.prototype =\n  LocationHtml5Url.prototype = {\n\n  /**\n   * Are we in html5 mode?\n   * @private\n   */\n  $$html5: false,\n\n  /**\n   * Has any change been replacing ?\n   * @private\n   */\n  $$replace: false,\n\n  /**\n   * @ngdoc method\n   * @name $location#absUrl\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return full url representation with all segments encoded according to rules specified in\n   * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).\n   *\n   * @return {string} full url\n   */\n  absUrl: locationGetter('$$absUrl'),\n\n  /**\n   * @ngdoc method\n   * @name $location#url\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.\n   *\n   * Change path, search and hash, when called with parameter and return `$location`.\n   *\n   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)\n   * @return {string} url\n   */\n  url: function(url) {\n    if (isUndefined(url))\n      return this.$$url;\n\n    var match = PATH_MATCH.exec(url);\n    if (match[1]) this.path(decodeURIComponent(match[1]));\n    if (match[2] || match[1]) this.search(match[3] || '');\n    this.hash(match[5] || '');\n\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#protocol\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return protocol of current url.\n   *\n   * @return {string} protocol of current url\n   */\n  protocol: locationGetter('$$protocol'),\n\n  /**\n   * @ngdoc method\n   * @name $location#host\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return host of current url.\n   *\n   * @return {string} host of current url.\n   */\n  host: locationGetter('$$host'),\n\n  /**\n   * @ngdoc method\n   * @name $location#port\n   *\n   * @description\n   * This method is getter only.\n   *\n   * Return port of current url.\n   *\n   * @return {Number} port\n   */\n  port: locationGetter('$$port'),\n\n  /**\n   * @ngdoc method\n   * @name $location#path\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return path of current url when called without any parameter.\n   *\n   * Change path when called with parameter and return `$location`.\n   *\n   * Note: Path should always begin with forward slash (/), this method will add the forward slash\n   * if it is missing.\n   *\n   * @param {(string|number)=} path New path\n   * @return {string} path\n   */\n  path: locationGetterSetter('$$path', function(path) {\n    path = path !== null ? path.toString() : '';\n    return path.charAt(0) == '/' ? path : '/' + path;\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#search\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return search part (as object) of current url when called without any parameter.\n   *\n   * Change search part when called with parameter and return `$location`.\n   *\n   *\n   * ```js\n   * // given url http://example.com/#/some/path?foo=bar&baz=xoxo\n   * var searchObject = $location.search();\n   * // => {foo: 'bar', baz: 'xoxo'}\n   *\n   *\n   * // set foo to 'yipee'\n   * $location.search('foo', 'yipee');\n   * // => $location\n   * ```\n   *\n   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or\n   * hash object.\n   *\n   * When called with a single argument the method acts as a setter, setting the `search` component\n   * of `$location` to the specified value.\n   *\n   * If the argument is a hash object containing an array of values, these values will be encoded\n   * as duplicate search parameters in the url.\n   *\n   * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`\n   * will override only a single search property.\n   *\n   * If `paramValue` is an array, it will override the property of the `search` component of\n   * `$location` specified via the first argument.\n   *\n   * If `paramValue` is `null`, the property specified via the first argument will be deleted.\n   *\n   * If `paramValue` is `true`, the property specified via the first argument will be added with no\n   * value nor trailing equal sign.\n   *\n   * @return {Object} If called with no arguments returns the parsed `search` object. If called with\n   * one or more arguments returns `$location` object itself.\n   */\n  search: function(search, paramValue) {\n    switch (arguments.length) {\n      case 0:\n        return this.$$search;\n      case 1:\n        if (isString(search) || isNumber(search)) {\n          search = search.toString();\n          this.$$search = parseKeyValue(search);\n        } else if (isObject(search)) {\n          // remove object undefined or null properties\n          forEach(search, function(value, key) {\n            if (value == null) delete search[key];\n          });\n\n          this.$$search = search;\n        } else {\n          throw $locationMinErr('isrcharg',\n              'The first argument of the `$location#search()` call must be a string or an object.');\n        }\n        break;\n      default:\n        if (isUndefined(paramValue) || paramValue === null) {\n          delete this.$$search[search];\n        } else {\n          this.$$search[search] = paramValue;\n        }\n    }\n\n    this.$$compose();\n    return this;\n  },\n\n  /**\n   * @ngdoc method\n   * @name $location#hash\n   *\n   * @description\n   * This method is getter / setter.\n   *\n   * Return hash fragment when called without any parameter.\n   *\n   * Change hash fragment when called with parameter and return `$location`.\n   *\n   * @param {(string|number)=} hash New hash fragment\n   * @return {string} hash\n   */\n  hash: locationGetterSetter('$$hash', function(hash) {\n    return hash !== null ? hash.toString() : '';\n  }),\n\n  /**\n   * @ngdoc method\n   * @name $location#replace\n   *\n   * @description\n   * If called, all changes to $location during current `$digest` will be replacing current history\n   * record, instead of adding new one.\n   */\n  replace: function() {\n    this.$$replace = true;\n    return this;\n  }\n};\n\nfunction locationGetter(property) {\n  return function() {\n    return this[property];\n  };\n}\n\n\nfunction locationGetterSetter(property, preprocess) {\n  return function(value) {\n    if (isUndefined(value))\n      return this[property];\n\n    this[property] = preprocess(value);\n    this.$$compose();\n\n    return this;\n  };\n}\n\n\n/**\n * @ngdoc service\n * @name $location\n *\n * @requires $rootElement\n *\n * @description\n * The $location service parses the URL in the browser address bar (based on the\n * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL\n * available to your application. Changes to the URL in the address bar are reflected into\n * $location service and changes to $location are reflected into the browser address bar.\n *\n * **The $location service:**\n *\n * - Exposes the current URL in the browser address bar, so you can\n *   - Watch and observe the URL.\n *   - Change the URL.\n * - Synchronizes the URL with the browser when the user\n *   - Changes the address bar.\n *   - Clicks the back or forward button (or clicks a History link).\n *   - Clicks on a link.\n * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).\n *\n * For more information see {@link guide/$location Developer Guide: Using $location}\n */\n\n/**\n * @ngdoc provider\n * @name $locationProvider\n * @description\n * Use the `$locationProvider` to configure how the application deep linking paths are stored.\n */\nfunction $LocationProvider(){\n  var hashPrefix = '',\n      html5Mode = false;\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#hashPrefix\n   * @description\n   * @param {string=} prefix Prefix for hash part (containing path and search)\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.hashPrefix = function(prefix) {\n    if (isDefined(prefix)) {\n      hashPrefix = prefix;\n      return this;\n    } else {\n      return hashPrefix;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name $locationProvider#html5Mode\n   * @description\n   * @param {boolean=} mode Use HTML5 strategy if available.\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.html5Mode = function(mode) {\n    if (isDefined(mode)) {\n      html5Mode = mode;\n      return this;\n    } else {\n      return html5Mode;\n    }\n  };\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeStart\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted before a URL will change. This change can be prevented by calling\n   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more\n   * details about event object. Upon successful change\n   * {@link ng.$location#events_$locationChangeSuccess $locationChangeSuccess} is fired.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   */\n\n  /**\n   * @ngdoc event\n   * @name $location#$locationChangeSuccess\n   * @eventType broadcast on root scope\n   * @description\n   * Broadcasted after a URL was changed.\n   *\n   * @param {Object} angularEvent Synthetic event object.\n   * @param {string} newUrl New URL\n   * @param {string=} oldUrl URL that was before it was changed.\n   */\n\n  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',\n      function( $rootScope,   $browser,   $sniffer,   $rootElement) {\n    var $location,\n        LocationMode,\n        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''\n        initialUrl = $browser.url(),\n        appBase;\n\n    if (html5Mode) {\n      appBase = serverBase(initialUrl) + (baseHref || '/');\n      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;\n    } else {\n      appBase = stripHash(initialUrl);\n      LocationMode = LocationHashbangUrl;\n    }\n    $location = new LocationMode(appBase, '#' + hashPrefix);\n    $location.$$parseLinkUrl(initialUrl, initialUrl);\n\n    var IGNORE_URI_REGEXP = /^\\s*(javascript|mailto):/i;\n\n    $rootElement.on('click', function(event) {\n      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)\n      // currently we open nice url link and redirect then\n\n      if (event.ctrlKey || event.metaKey || event.which == 2) return;\n\n      var elm = jqLite(event.target);\n\n      // traverse the DOM up to find first A tag\n      while (lowercase(elm[0].nodeName) !== 'a') {\n        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)\n        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;\n      }\n\n      var absHref = elm.prop('href');\n      // get the actual href attribute - see\n      // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx\n      var relHref = elm.attr('href') || elm.attr('xlink:href');\n\n      if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {\n        // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during\n        // an animation.\n        absHref = urlResolve(absHref.animVal).href;\n      }\n\n      // Ignore when url is started with javascript: or mailto:\n      if (IGNORE_URI_REGEXP.test(absHref)) return;\n\n      if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {\n        if ($location.$$parseLinkUrl(absHref, relHref)) {\n          // We do a preventDefault for all urls that are part of the angular application,\n          // in html5mode and also without, so that we are able to abort navigation without\n          // getting double entries in the location history.\n          event.preventDefault();\n          // update location manually\n          if ($location.absUrl() != $browser.url()) {\n            $rootScope.$apply();\n            // hack to work around FF6 bug 684208 when scenario runner clicks on links\n            window.angular['ff-684208-preventDefault'] = true;\n          }\n        }\n      }\n    });\n\n\n    // rewrite hashbang url <> html5 url\n    if ($location.absUrl() != initialUrl) {\n      $browser.url($location.absUrl(), true);\n    }\n\n    // update $location when $browser url changes\n    $browser.onUrlChange(function(newUrl) {\n      if ($location.absUrl() != newUrl) {\n        $rootScope.$evalAsync(function() {\n          var oldUrl = $location.absUrl();\n\n          $location.$$parse(newUrl);\n          if ($rootScope.$broadcast('$locationChangeStart', newUrl,\n                                    oldUrl).defaultPrevented) {\n            $location.$$parse(oldUrl);\n            $browser.url(oldUrl);\n          } else {\n            afterLocationChange(oldUrl);\n          }\n        });\n        if (!$rootScope.$$phase) $rootScope.$digest();\n      }\n    });\n\n    // update browser\n    var changeCounter = 0;\n    $rootScope.$watch(function $locationWatch() {\n      var oldUrl = $browser.url();\n      var currentReplace = $location.$$replace;\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n        changeCounter++;\n        $rootScope.$evalAsync(function() {\n          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n              defaultPrevented) {\n            $location.$$parse(oldUrl);\n          } else {\n            $browser.url($location.absUrl(), currentReplace);\n            afterLocationChange(oldUrl);\n          }\n        });\n      }\n      $location.$$replace = false;\n\n      return changeCounter;\n    });\n\n    return $location;\n\n    function afterLocationChange(oldUrl) {\n      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);\n    }\n}];\n}\n\n/**\n * @ngdoc service\n * @name $log\n * @requires $window\n *\n * @description\n * Simple service for logging. Default implementation safely writes the message\n * into the browser's console (if present).\n *\n * The main purpose of this service is to simplify debugging and troubleshooting.\n *\n * The default is to log `debug` messages. You can use\n * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.\n *\n * @example\n   <example module=\"logExample\">\n     <file name=\"script.js\">\n       angular.module('logExample', [])\n         .controller('LogController', ['$scope', '$log', function($scope, $log) {\n           $scope.$log = $log;\n           $scope.message = 'Hello World!';\n         }]);\n     </file>\n     <file name=\"index.html\">\n       <div ng-controller=\"LogController\">\n         <p>Reload this page with open console, enter text and hit the log button...</p>\n         Message:\n         <input type=\"text\" ng-model=\"message\"/>\n         <button ng-click=\"$log.log(message)\">log</button>\n         <button ng-click=\"$log.warn(message)\">warn</button>\n         <button ng-click=\"$log.info(message)\">info</button>\n         <button ng-click=\"$log.error(message)\">error</button>\n       </div>\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc provider\n * @name $logProvider\n * @description\n * Use the `$logProvider` to configure how the application logs messages\n */\nfunction $LogProvider(){\n  var debug = true,\n      self = this;\n\n  /**\n   * @ngdoc method\n   * @name $logProvider#debugEnabled\n   * @description\n   * @param {boolean=} flag enable or disable debug level messages\n   * @returns {*} current value if used as getter or itself (chaining) if used as setter\n   */\n  this.debugEnabled = function(flag) {\n    if (isDefined(flag)) {\n      debug = flag;\n    return this;\n    } else {\n      return debug;\n    }\n  };\n\n  this.$get = ['$window', function($window){\n    return {\n      /**\n       * @ngdoc method\n       * @name $log#log\n       *\n       * @description\n       * Write a log message\n       */\n      log: consoleLog('log'),\n\n      /**\n       * @ngdoc method\n       * @name $log#info\n       *\n       * @description\n       * Write an information message\n       */\n      info: consoleLog('info'),\n\n      /**\n       * @ngdoc method\n       * @name $log#warn\n       *\n       * @description\n       * Write a warning message\n       */\n      warn: consoleLog('warn'),\n\n      /**\n       * @ngdoc method\n       * @name $log#error\n       *\n       * @description\n       * Write an error message\n       */\n      error: consoleLog('error'),\n\n      /**\n       * @ngdoc method\n       * @name $log#debug\n       *\n       * @description\n       * Write a debug message\n       */\n      debug: (function () {\n        var fn = consoleLog('debug');\n\n        return function() {\n          if (debug) {\n            fn.apply(self, arguments);\n          }\n        };\n      }())\n    };\n\n    function formatError(arg) {\n      if (arg instanceof Error) {\n        if (arg.stack) {\n          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)\n              ? 'Error: ' + arg.message + '\\n' + arg.stack\n              : arg.stack;\n        } else if (arg.sourceURL) {\n          arg = arg.message + '\\n' + arg.sourceURL + ':' + arg.line;\n        }\n      }\n      return arg;\n    }\n\n    function consoleLog(type) {\n      var console = $window.console || {},\n          logFn = console[type] || console.log || noop,\n          hasApply = false;\n\n      // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.\n      // The reason behind this is that console.log has type \"object\" in IE8...\n      try {\n        hasApply = !!logFn.apply;\n      } catch (e) {}\n\n      if (hasApply) {\n        return function() {\n          var args = [];\n          forEach(arguments, function(arg) {\n            args.push(formatError(arg));\n          });\n          return logFn.apply(console, args);\n        };\n      }\n\n      // we are IE which either doesn't have window.console => this is noop and we do nothing,\n      // or we are IE where console.log doesn't have apply so we log at least first 2 args\n      return function(arg1, arg2) {\n        logFn(arg1, arg2 == null ? '' : arg2);\n      };\n    }\n  }];\n}\n\nvar $parseMinErr = minErr('$parse');\nvar promiseWarningCache = {};\nvar promiseWarning;\n\n// Sandboxing Angular Expressions\n// ------------------------------\n// Angular expressions are generally considered safe because these expressions only have direct\n// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by\n// obtaining a reference to native JS functions such as the Function constructor.\n//\n// As an example, consider the following Angular expression:\n//\n//   {}.toString.constructor('alert(\"evil JS code\")')\n//\n// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits\n// against the expression language, but not to prevent exploits that were enabled by exposing\n// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good\n// practice and therefore we are not even trying to protect against interaction with an object\n// explicitly exposed in this way.\n//\n// In general, it is not possible to access a Window object from an angular expression unless a\n// window or some DOM object that has a reference to window is published onto a Scope.\n// Similarly we prevent invocations of function known to be dangerous, as well as assignments to\n// native objects.\n//\n// See https://docs.angularjs.org/guide/security\n\n\nfunction ensureSafeMemberName(name, fullExpression) {\n  if (name === \"__defineGetter__\" || name === \"__defineSetter__\"\n      || name === \"__lookupGetter__\" || name === \"__lookupSetter__\"\n      || name === \"__proto__\") {\n    throw $parseMinErr('isecfld',\n        'Attempting to access a disallowed field in Angular expressions! '\n        +'Expression: {0}', fullExpression);\n  }\n  return name;\n}\n\nfunction ensureSafeObject(obj, fullExpression) {\n  // nifty check if obj is Function that is fast and works across iframes and other contexts\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n          'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isWindow(obj)\n        obj.document && obj.location && obj.alert && obj.setInterval) {\n      throw $parseMinErr('isecwindow',\n          'Referencing the Window in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// isElement(obj)\n        obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {\n      throw $parseMinErr('isecdom',\n          'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    } else if (// block Object so that we can't get hold of dangerous Object.* methods\n        obj === Object) {\n      throw $parseMinErr('isecobj',\n          'Referencing Object in Angular expressions is disallowed! Expression: {0}',\n          fullExpression);\n    }\n  }\n  return obj;\n}\n\nvar CALL = Function.prototype.call;\nvar APPLY = Function.prototype.apply;\nvar BIND = Function.prototype.bind;\n\nfunction ensureSafeFunction(obj, fullExpression) {\n  if (obj) {\n    if (obj.constructor === obj) {\n      throw $parseMinErr('isecfn',\n        'Referencing Function in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    } else if (obj === CALL || obj === APPLY || (BIND && obj === BIND)) {\n      throw $parseMinErr('isecff',\n        'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',\n        fullExpression);\n    }\n  }\n}\n\nvar OPERATORS = {\n    /* jshint bitwise : false */\n    'null':function(){return null;},\n    'true':function(){return true;},\n    'false':function(){return false;},\n    undefined:noop,\n    '+':function(self, locals, a,b){\n      a=a(self, locals); b=b(self, locals);\n      if (isDefined(a)) {\n        if (isDefined(b)) {\n          return a + b;\n        }\n        return a;\n      }\n      return isDefined(b)?b:undefined;},\n    '-':function(self, locals, a,b){\n          a=a(self, locals); b=b(self, locals);\n          return (isDefined(a)?a:0)-(isDefined(b)?b:0);\n        },\n    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},\n    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},\n    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},\n    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},\n    '=':noop,\n    '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},\n    '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},\n    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},\n    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},\n    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},\n    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},\n    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},\n    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},\n    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},\n    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},\n    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},\n//    '|':function(self, locals, a,b){return a|b;},\n    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},\n    '!':function(self, locals, a){return !a(self, locals);}\n};\n/* jshint bitwise: true */\nvar ESCAPE = {\"n\":\"\\n\", \"f\":\"\\f\", \"r\":\"\\r\", \"t\":\"\\t\", \"v\":\"\\v\", \"'\":\"'\", '\"':'\"'};\n\n\n/////////////////////////////////////////\n\n\n/**\n * @constructor\n */\nvar Lexer = function (options) {\n  this.options = options;\n};\n\nLexer.prototype = {\n  constructor: Lexer,\n\n  lex: function (text) {\n    this.text = text;\n\n    this.index = 0;\n    this.ch = undefined;\n    this.lastCh = ':'; // can start regexp\n\n    this.tokens = [];\n\n    while (this.index < this.text.length) {\n      this.ch = this.text.charAt(this.index);\n      if (this.is('\"\\'')) {\n        this.readString(this.ch);\n      } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) {\n        this.readNumber();\n      } else if (this.isIdent(this.ch)) {\n        this.readIdent();\n      } else if (this.is('(){}[].,;:?')) {\n        this.tokens.push({\n          index: this.index,\n          text: this.ch\n        });\n        this.index++;\n      } else if (this.isWhitespace(this.ch)) {\n        this.index++;\n        continue;\n      } else {\n        var ch2 = this.ch + this.peek();\n        var ch3 = ch2 + this.peek(2);\n        var fn = OPERATORS[this.ch];\n        var fn2 = OPERATORS[ch2];\n        var fn3 = OPERATORS[ch3];\n        if (fn3) {\n          this.tokens.push({index: this.index, text: ch3, fn: fn3});\n          this.index += 3;\n        } else if (fn2) {\n          this.tokens.push({index: this.index, text: ch2, fn: fn2});\n          this.index += 2;\n        } else if (fn) {\n          this.tokens.push({\n            index: this.index,\n            text: this.ch,\n            fn: fn\n          });\n          this.index += 1;\n        } else {\n          this.throwError('Unexpected next character ', this.index, this.index + 1);\n        }\n      }\n      this.lastCh = this.ch;\n    }\n    return this.tokens;\n  },\n\n  is: function(chars) {\n    return chars.indexOf(this.ch) !== -1;\n  },\n\n  was: function(chars) {\n    return chars.indexOf(this.lastCh) !== -1;\n  },\n\n  peek: function(i) {\n    var num = i || 1;\n    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;\n  },\n\n  isNumber: function(ch) {\n    return ('0' <= ch && ch <= '9');\n  },\n\n  isWhitespace: function(ch) {\n    // IE treats non-breaking space as \\u00A0\n    return (ch === ' ' || ch === '\\r' || ch === '\\t' ||\n            ch === '\\n' || ch === '\\v' || ch === '\\u00A0');\n  },\n\n  isIdent: function(ch) {\n    return ('a' <= ch && ch <= 'z' ||\n            'A' <= ch && ch <= 'Z' ||\n            '_' === ch || ch === '$');\n  },\n\n  isExpOperator: function(ch) {\n    return (ch === '-' || ch === '+' || this.isNumber(ch));\n  },\n\n  throwError: function(error, start, end) {\n    end = end || this.index;\n    var colStr = (isDefined(start)\n            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'\n            : ' ' + end);\n    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',\n        error, colStr, this.text);\n  },\n\n  readNumber: function() {\n    var number = '';\n    var start = this.index;\n    while (this.index < this.text.length) {\n      var ch = lowercase(this.text.charAt(this.index));\n      if (ch == '.' || this.isNumber(ch)) {\n        number += ch;\n      } else {\n        var peekCh = this.peek();\n        if (ch == 'e' && this.isExpOperator(peekCh)) {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            peekCh && this.isNumber(peekCh) &&\n            number.charAt(number.length - 1) == 'e') {\n          number += ch;\n        } else if (this.isExpOperator(ch) &&\n            (!peekCh || !this.isNumber(peekCh)) &&\n            number.charAt(number.length - 1) == 'e') {\n          this.throwError('Invalid exponent');\n        } else {\n          break;\n        }\n      }\n      this.index++;\n    }\n    number = 1 * number;\n    this.tokens.push({\n      index: start,\n      text: number,\n      literal: true,\n      constant: true,\n      fn: function() { return number; }\n    });\n  },\n\n  readIdent: function() {\n    var parser = this;\n\n    var ident = '';\n    var start = this.index;\n\n    var lastDot, peekIndex, methodName, ch;\n\n    while (this.index < this.text.length) {\n      ch = this.text.charAt(this.index);\n      if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) {\n        if (ch === '.') lastDot = this.index;\n        ident += ch;\n      } else {\n        break;\n      }\n      this.index++;\n    }\n\n    //check if this is not a method invocation and if it is back out to last dot\n    if (lastDot) {\n      peekIndex = this.index;\n      while (peekIndex < this.text.length) {\n        ch = this.text.charAt(peekIndex);\n        if (ch === '(') {\n          methodName = ident.substr(lastDot - start + 1);\n          ident = ident.substr(0, lastDot - start);\n          this.index = peekIndex;\n          break;\n        }\n        if (this.isWhitespace(ch)) {\n          peekIndex++;\n        } else {\n          break;\n        }\n      }\n    }\n\n\n    var token = {\n      index: start,\n      text: ident\n    };\n\n    // OPERATORS is our own object so we don't need to use special hasOwnPropertyFn\n    if (OPERATORS.hasOwnProperty(ident)) {\n      token.fn = OPERATORS[ident];\n      token.literal = true;\n      token.constant = true;\n    } else {\n      var getter = getterFn(ident, this.options, this.text);\n      token.fn = extend(function(self, locals) {\n        return (getter(self, locals));\n      }, {\n        assign: function(self, value) {\n          return setter(self, ident, value, parser.text, parser.options);\n        }\n      });\n    }\n\n    this.tokens.push(token);\n\n    if (methodName) {\n      this.tokens.push({\n        index:lastDot,\n        text: '.'\n      });\n      this.tokens.push({\n        index: lastDot + 1,\n        text: methodName\n      });\n    }\n  },\n\n  readString: function(quote) {\n    var start = this.index;\n    this.index++;\n    var string = '';\n    var rawString = quote;\n    var escape = false;\n    while (this.index < this.text.length) {\n      var ch = this.text.charAt(this.index);\n      rawString += ch;\n      if (escape) {\n        if (ch === 'u') {\n          var hex = this.text.substring(this.index + 1, this.index + 5);\n          if (!hex.match(/[\\da-f]{4}/i))\n            this.throwError('Invalid unicode escape [\\\\u' + hex + ']');\n          this.index += 4;\n          string += String.fromCharCode(parseInt(hex, 16));\n        } else {\n          var rep = ESCAPE[ch];\n          string = string + (rep || ch);\n        }\n        escape = false;\n      } else if (ch === '\\\\') {\n        escape = true;\n      } else if (ch === quote) {\n        this.index++;\n        this.tokens.push({\n          index: start,\n          text: rawString,\n          string: string,\n          literal: true,\n          constant: true,\n          fn: function() { return string; }\n        });\n        return;\n      } else {\n        string += ch;\n      }\n      this.index++;\n    }\n    this.throwError('Unterminated quote', start);\n  }\n};\n\n\n/**\n * @constructor\n */\nvar Parser = function (lexer, $filter, options) {\n  this.lexer = lexer;\n  this.$filter = $filter;\n  this.options = options;\n};\n\nParser.ZERO = extend(function () {\n  return 0;\n}, {\n  constant: true\n});\n\nParser.prototype = {\n  constructor: Parser,\n\n  parse: function (text) {\n    this.text = text;\n\n    this.tokens = this.lexer.lex(text);\n\n    var value = this.statements();\n\n    if (this.tokens.length !== 0) {\n      this.throwError('is an unexpected token', this.tokens[0]);\n    }\n\n    value.literal = !!value.literal;\n    value.constant = !!value.constant;\n\n    return value;\n  },\n\n  primary: function () {\n    var primary;\n    if (this.expect('(')) {\n      primary = this.filterChain();\n      this.consume(')');\n    } else if (this.expect('[')) {\n      primary = this.arrayDeclaration();\n    } else if (this.expect('{')) {\n      primary = this.object();\n    } else {\n      var token = this.expect();\n      primary = token.fn;\n      if (!primary) {\n        this.throwError('not a primary expression', token);\n      }\n      primary.literal = !!token.literal;\n      primary.constant = !!token.constant;\n    }\n\n    var next, context;\n    while ((next = this.expect('(', '[', '.'))) {\n      if (next.text === '(') {\n        primary = this.functionCall(primary, context);\n        context = null;\n      } else if (next.text === '[') {\n        context = primary;\n        primary = this.objectIndex(primary);\n      } else if (next.text === '.') {\n        context = primary;\n        primary = this.fieldAccess(primary);\n      } else {\n        this.throwError('IMPOSSIBLE');\n      }\n    }\n    return primary;\n  },\n\n  throwError: function(msg, token) {\n    throw $parseMinErr('syntax',\n        'Syntax Error: Token \\'{0}\\' {1} at column {2} of the expression [{3}] starting at [{4}].',\n          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));\n  },\n\n  peekToken: function() {\n    if (this.tokens.length === 0)\n      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);\n    return this.tokens[0];\n  },\n\n  peek: function(e1, e2, e3, e4) {\n    if (this.tokens.length > 0) {\n      var token = this.tokens[0];\n      var t = token.text;\n      if (t === e1 || t === e2 || t === e3 || t === e4 ||\n          (!e1 && !e2 && !e3 && !e4)) {\n        return token;\n      }\n    }\n    return false;\n  },\n\n  expect: function(e1, e2, e3, e4){\n    var token = this.peek(e1, e2, e3, e4);\n    if (token) {\n      this.tokens.shift();\n      return token;\n    }\n    return false;\n  },\n\n  consume: function(e1){\n    if (!this.expect(e1)) {\n      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());\n    }\n  },\n\n  unaryFn: function(fn, right) {\n    return extend(function(self, locals) {\n      return fn(self, locals, right);\n    }, {\n      constant:right.constant\n    });\n  },\n\n  ternaryFn: function(left, middle, right){\n    return extend(function(self, locals){\n      return left(self, locals) ? middle(self, locals) : right(self, locals);\n    }, {\n      constant: left.constant && middle.constant && right.constant\n    });\n  },\n\n  binaryFn: function(left, fn, right) {\n    return extend(function(self, locals) {\n      return fn(self, locals, left, right);\n    }, {\n      constant:left.constant && right.constant\n    });\n  },\n\n  statements: function() {\n    var statements = [];\n    while (true) {\n      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))\n        statements.push(this.filterChain());\n      if (!this.expect(';')) {\n        // optimize for the common case where there is only one statement.\n        // TODO(size): maybe we should not support multiple statements?\n        return (statements.length === 1)\n            ? statements[0]\n            : function(self, locals) {\n                var value;\n                for (var i = 0; i < statements.length; i++) {\n                  var statement = statements[i];\n                  if (statement) {\n                    value = statement(self, locals);\n                  }\n                }\n                return value;\n              };\n      }\n    }\n  },\n\n  filterChain: function() {\n    var left = this.expression();\n    var token;\n    while (true) {\n      if ((token = this.expect('|'))) {\n        left = this.binaryFn(left, token.fn, this.filter());\n      } else {\n        return left;\n      }\n    }\n  },\n\n  filter: function() {\n    var token = this.expect();\n    var fn = this.$filter(token.text);\n    var argsFn = [];\n    while (true) {\n      if ((token = this.expect(':'))) {\n        argsFn.push(this.expression());\n      } else {\n        var fnInvoke = function(self, locals, input) {\n          var args = [input];\n          for (var i = 0; i < argsFn.length; i++) {\n            args.push(argsFn[i](self, locals));\n          }\n          return fn.apply(self, args);\n        };\n        return function() {\n          return fnInvoke;\n        };\n      }\n    }\n  },\n\n  expression: function() {\n    return this.assignment();\n  },\n\n  assignment: function() {\n    var left = this.ternary();\n    var right;\n    var token;\n    if ((token = this.expect('='))) {\n      if (!left.assign) {\n        this.throwError('implies assignment but [' +\n            this.text.substring(0, token.index) + '] can not be assigned to', token);\n      }\n      right = this.ternary();\n      return function(scope, locals) {\n        return left.assign(scope, right(scope, locals), locals);\n      };\n    }\n    return left;\n  },\n\n  ternary: function() {\n    var left = this.logicalOR();\n    var middle;\n    var token;\n    if ((token = this.expect('?'))) {\n      middle = this.assignment();\n      if ((token = this.expect(':'))) {\n        return this.ternaryFn(left, middle, this.assignment());\n      } else {\n        this.throwError('expected :', token);\n      }\n    } else {\n      return left;\n    }\n  },\n\n  logicalOR: function() {\n    var left = this.logicalAND();\n    var token;\n    while (true) {\n      if ((token = this.expect('||'))) {\n        left = this.binaryFn(left, token.fn, this.logicalAND());\n      } else {\n        return left;\n      }\n    }\n  },\n\n  logicalAND: function() {\n    var left = this.equality();\n    var token;\n    if ((token = this.expect('&&'))) {\n      left = this.binaryFn(left, token.fn, this.logicalAND());\n    }\n    return left;\n  },\n\n  equality: function() {\n    var left = this.relational();\n    var token;\n    if ((token = this.expect('==','!=','===','!=='))) {\n      left = this.binaryFn(left, token.fn, this.equality());\n    }\n    return left;\n  },\n\n  relational: function() {\n    var left = this.additive();\n    var token;\n    if ((token = this.expect('<', '>', '<=', '>='))) {\n      left = this.binaryFn(left, token.fn, this.relational());\n    }\n    return left;\n  },\n\n  additive: function() {\n    var left = this.multiplicative();\n    var token;\n    while ((token = this.expect('+','-'))) {\n      left = this.binaryFn(left, token.fn, this.multiplicative());\n    }\n    return left;\n  },\n\n  multiplicative: function() {\n    var left = this.unary();\n    var token;\n    while ((token = this.expect('*','/','%'))) {\n      left = this.binaryFn(left, token.fn, this.unary());\n    }\n    return left;\n  },\n\n  unary: function() {\n    var token;\n    if (this.expect('+')) {\n      return this.primary();\n    } else if ((token = this.expect('-'))) {\n      return this.binaryFn(Parser.ZERO, token.fn, this.unary());\n    } else if ((token = this.expect('!'))) {\n      return this.unaryFn(token.fn, this.unary());\n    } else {\n      return this.primary();\n    }\n  },\n\n  fieldAccess: function(object) {\n    var parser = this;\n    var field = this.expect().text;\n    var getter = getterFn(field, this.options, this.text);\n\n    return extend(function(scope, locals, self) {\n      return getter(self || object(scope, locals));\n    }, {\n      assign: function(scope, value, locals) {\n        var o = object(scope, locals);\n        if (!o) object.assign(scope, o = {});\n        return setter(o, field, value, parser.text, parser.options);\n      }\n    });\n  },\n\n  objectIndex: function(obj) {\n    var parser = this;\n\n    var indexFn = this.expression();\n    this.consume(']');\n\n    return extend(function(self, locals) {\n      var o = obj(self, locals),\n          i = indexFn(self, locals),\n          v, p;\n\n      ensureSafeMemberName(i, parser.text);\n      if (!o) return undefined;\n      v = ensureSafeObject(o[i], parser.text);\n      if (v && v.then && parser.options.unwrapPromises) {\n        p = v;\n        if (!('$$v' in v)) {\n          p.$$v = undefined;\n          p.then(function(val) { p.$$v = val; });\n        }\n        v = v.$$v;\n      }\n      return v;\n    }, {\n      assign: function(self, value, locals) {\n        var key = ensureSafeMemberName(indexFn(self, locals), parser.text);\n        // prevent overwriting of Function.constructor which would break ensureSafeObject check\n        var o = ensureSafeObject(obj(self, locals), parser.text);\n        if (!o) obj.assign(self, o = {});\n        return o[key] = value;\n      }\n    });\n  },\n\n  functionCall: function(fn, contextGetter) {\n    var argsFn = [];\n    if (this.peekToken().text !== ')') {\n      do {\n        argsFn.push(this.expression());\n      } while (this.expect(','));\n    }\n    this.consume(')');\n\n    var parser = this;\n\n    return function(scope, locals) {\n      var args = [];\n      var context = contextGetter ? contextGetter(scope, locals) : scope;\n\n      for (var i = 0; i < argsFn.length; i++) {\n        args.push(ensureSafeObject(argsFn[i](scope, locals), parser.text));\n      }\n      var fnPtr = fn(scope, locals, context) || noop;\n\n      ensureSafeObject(context, parser.text);\n      ensureSafeFunction(fnPtr, parser.text);\n\n      // IE doesn't have apply for some native functions\n      var v = fnPtr.apply\n            ? fnPtr.apply(context, args)\n            : fnPtr(args[0], args[1], args[2], args[3], args[4]);\n\n      return ensureSafeObject(v, parser.text);\n    };\n  },\n\n  // This is used with json array declaration\n  arrayDeclaration: function () {\n    var elementFns = [];\n    var allConstant = true;\n    if (this.peekToken().text !== ']') {\n      do {\n        if (this.peek(']')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        var elementFn = this.expression();\n        elementFns.push(elementFn);\n        if (!elementFn.constant) {\n          allConstant = false;\n        }\n      } while (this.expect(','));\n    }\n    this.consume(']');\n\n    return extend(function(self, locals) {\n      var array = [];\n      for (var i = 0; i < elementFns.length; i++) {\n        array.push(elementFns[i](self, locals));\n      }\n      return array;\n    }, {\n      literal: true,\n      constant: allConstant\n    });\n  },\n\n  object: function () {\n    var keyValues = [];\n    var allConstant = true;\n    if (this.peekToken().text !== '}') {\n      do {\n        if (this.peek('}')) {\n          // Support trailing commas per ES5.1.\n          break;\n        }\n        var token = this.expect(),\n        key = token.string || token.text;\n        this.consume(':');\n        var value = this.expression();\n        keyValues.push({key: key, value: value});\n        if (!value.constant) {\n          allConstant = false;\n        }\n      } while (this.expect(','));\n    }\n    this.consume('}');\n\n    return extend(function(self, locals) {\n      var object = {};\n      for (var i = 0; i < keyValues.length; i++) {\n        var keyValue = keyValues[i];\n        object[keyValue.key] = keyValue.value(self, locals);\n      }\n      return object;\n    }, {\n      literal: true,\n      constant: allConstant\n    });\n  }\n};\n\n\n//////////////////////////////////////////////////\n// Parser helper functions\n//////////////////////////////////////////////////\n\nfunction setter(obj, path, setValue, fullExp, options) {\n  ensureSafeObject(obj, fullExp);\n\n  //needed?\n  options = options || {};\n\n  var element = path.split('.'), key;\n  for (var i = 0; element.length > 1; i++) {\n    key = ensureSafeMemberName(element.shift(), fullExp);\n    var propertyObj = ensureSafeObject(obj[key], fullExp);\n    if (!propertyObj) {\n      propertyObj = {};\n      obj[key] = propertyObj;\n    }\n    obj = propertyObj;\n    if (obj.then && options.unwrapPromises) {\n      promiseWarning(fullExp);\n      if (!(\"$$v\" in obj)) {\n        (function(promise) {\n          promise.then(function(val) { promise.$$v = val; }); }\n        )(obj);\n      }\n      if (obj.$$v === undefined) {\n        obj.$$v = {};\n      }\n      obj = obj.$$v;\n    }\n  }\n  key = ensureSafeMemberName(element.shift(), fullExp);\n  ensureSafeObject(obj[key], fullExp);\n  obj[key] = setValue;\n  return setValue;\n}\n\nvar getterFnCacheDefault = {};\nvar getterFnCacheExpensive = {};\n\nfunction isPossiblyDangerousMemberName(name) {\n  return name == 'constructor';\n}\n\n/**\n * Implementation of the \"Black Hole\" variant from:\n * - http://jsperf.com/angularjs-parse-getter/4\n * - http://jsperf.com/path-evaluation-simplified/7\n */\nfunction cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {\n  ensureSafeMemberName(key0, fullExp);\n  ensureSafeMemberName(key1, fullExp);\n  ensureSafeMemberName(key2, fullExp);\n  ensureSafeMemberName(key3, fullExp);\n  ensureSafeMemberName(key4, fullExp);\n  var eso = function(o) {\n    return ensureSafeObject(o, fullExp);\n  };\n  var expensiveChecks = options.expensiveChecks;\n  var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity;\n  var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity;\n  var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity;\n  var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity;\n  var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity;\n\n  return !options.unwrapPromises\n      ? function cspSafeGetter(scope, locals) {\n          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;\n\n          if (pathVal == null) return pathVal;\n          pathVal = eso0(pathVal[key0]);\n\n          if (!key1) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso1(pathVal[key1]);\n\n          if (!key2) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso2(pathVal[key2]);\n\n          if (!key3) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso3(pathVal[key3]);\n\n          if (!key4) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso4(pathVal[key4]);\n\n          return pathVal;\n        }\n      : function cspSafePromiseEnabledGetter(scope, locals) {\n          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,\n              promise;\n\n          if (pathVal == null) return pathVal;\n\n          pathVal = eso0(pathVal[key0]);\n          if (pathVal && pathVal.then) {\n            promiseWarning(fullExp);\n            if (!(\"$$v\" in pathVal)) {\n              promise = pathVal;\n              promise.$$v = undefined;\n              promise.then(function(val) { promise.$$v = eso0(val); });\n            }\n            pathVal = eso0(pathVal.$$v);\n          }\n\n          if (!key1) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso1(pathVal[key1]);\n          if (pathVal && pathVal.then) {\n            promiseWarning(fullExp);\n            if (!(\"$$v\" in pathVal)) {\n              promise = pathVal;\n              promise.$$v = undefined;\n              promise.then(function(val) { promise.$$v = eso1(val); });\n            }\n            pathVal = eso1(pathVal.$$v);\n          }\n\n          if (!key2) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso2(pathVal[key2]);\n          if (pathVal && pathVal.then) {\n            promiseWarning(fullExp);\n            if (!(\"$$v\" in pathVal)) {\n              promise = pathVal;\n              promise.$$v = undefined;\n              promise.then(function(val) { promise.$$v = eso2(val); });\n            }\n            pathVal = eso2(pathVal.$$v);\n          }\n\n          if (!key3) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso3(pathVal[key3]);\n          if (pathVal && pathVal.then) {\n            promiseWarning(fullExp);\n            if (!(\"$$v\" in pathVal)) {\n              promise = pathVal;\n              promise.$$v = undefined;\n              promise.then(function(val) { promise.$$v = eso3(val); });\n            }\n            pathVal = eso3(pathVal.$$v);\n          }\n\n          if (!key4) return pathVal;\n          if (pathVal == null) return undefined;\n          pathVal = eso4(pathVal[key4]);\n          if (pathVal && pathVal.then) {\n            promiseWarning(fullExp);\n            if (!(\"$$v\" in pathVal)) {\n              promise = pathVal;\n              promise.$$v = undefined;\n              promise.then(function(val) { promise.$$v = eso4(val); });\n            }\n            pathVal = eso4(pathVal.$$v);\n          }\n          return pathVal;\n        };\n}\n\nfunction getterFnWithExtraArgs(fn, fullExpression) {\n  return function(s, l) {\n    return fn(s, l, promiseWarning, ensureSafeObject, fullExpression);\n  };\n}\n\nfunction getterFn(path, options, fullExp) {\n  var expensiveChecks = options.expensiveChecks;\n  var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault);\n  // Check whether the cache has this getter already.\n  // We can use hasOwnProperty directly on the cache because we ensure,\n  // see below, that the cache never stores a path called 'hasOwnProperty'\n  if (getterFnCache.hasOwnProperty(path)) {\n    return getterFnCache[path];\n  }\n\n  var pathKeys = path.split('.'),\n      pathKeysLength = pathKeys.length,\n      fn;\n\n  // http://jsperf.com/angularjs-parse-getter/6\n  if (options.csp) {\n    if (pathKeysLength < 6) {\n      fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,\n                          options);\n    } else {\n      fn = function(scope, locals) {\n        var i = 0, val;\n        do {\n          val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],\n                                pathKeys[i++], fullExp, options)(scope, locals);\n\n          locals = undefined; // clear after first iteration\n          scope = val;\n        } while (i < pathKeysLength);\n        return val;\n      };\n    }\n  } else {\n    var code = 'var p;\\n';\n    if (expensiveChecks) {\n      code += 's = eso(s, fe);\\nl = eso(l, fe);\\n';\n    }\n    var needsEnsureSafeObject = expensiveChecks;\n    forEach(pathKeys, function(key, index) {\n      ensureSafeMemberName(key, fullExp);\n      var lookupJs = (index\n                      // we simply dereference 's' on any .dot notation\n                      ? 's'\n                      // but if we are first then we check locals first, and if so read it first\n                      : '((l&&l.hasOwnProperty(\"' + key + '\"))?l:s)') + '[\"' + key + '\"]';\n      var wrapWithEso = expensiveChecks || isPossiblyDangerousMemberName(key);\n      if (wrapWithEso) {\n        lookupJs = 'eso(' + lookupJs + ', fe)';\n        needsEnsureSafeObject = true;\n      }\n      code += 'if(s == null) return undefined;\\n' +\n              's=' + lookupJs + ';\\n';\n      if (options.unwrapPromises) {\n        code += 'if (s && s.then) {\\n' +\n                  ' pw(\"' + fullExp.replace(/([\"\\r\\n])/g, '\\\\$1') + '\");\\n' +\n                  ' if (!(\"$$v\" in s)) {\\n' +\n                    ' p=s;\\n' +\n                    ' p.$$v = undefined;\\n' +\n                    ' p.then(function(v) {p.$$v=' + (wrapWithEso ? 'eso(v)' : 'v') + ';});\\n' +\n                    '}\\n' +\n                  ' s=' + (wrapWithEso ? 'eso(s.$$v)' : 's.$$v') + '\\n' +\n                '}\\n';\n\n      }\n    });\n    code += 'return s;';\n\n    /* jshint -W054 */\n    // s=scope, l=locals, pw=promiseWarning, eso=ensureSafeObject, fe=fullExpression\n    var evaledFnGetter = new Function('s', 'l', 'pw', 'eso', 'fe', code);\n    /* jshint +W054 */\n    evaledFnGetter.toString = valueFn(code);\n    if (needsEnsureSafeObject || options.unwrapPromises) {\n      evaledFnGetter = getterFnWithExtraArgs(evaledFnGetter, fullExp);\n    }\n    fn = evaledFnGetter;\n  }\n\n  // Only cache the value if it's not going to mess up the cache object\n  // This is more performant that using Object.prototype.hasOwnProperty.call\n  if (path !== 'hasOwnProperty') {\n    getterFnCache[path] = fn;\n  }\n  return fn;\n}\n\n///////////////////////////////////\n\n/**\n * @ngdoc service\n * @name $parse\n * @kind function\n *\n * @description\n *\n * Converts Angular {@link guide/expression expression} into a function.\n *\n * ```js\n *   var getter = $parse('user.name');\n *   var setter = getter.assign;\n *   var context = {user:{name:'angular'}};\n *   var locals = {user:{name:'local'}};\n *\n *   expect(getter(context)).toEqual('angular');\n *   setter(context, 'newValue');\n *   expect(context.user.name).toEqual('newValue');\n *   expect(getter(context, locals)).toEqual('local');\n * ```\n *\n *\n * @param {string} expression String expression to compile.\n * @returns {function(context, locals)} a function which represents the compiled expression:\n *\n *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n *      are evaluated against (typically a scope object).\n *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n *      `context`.\n *\n *    The returned function also has the following properties:\n *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript\n *        literal.\n *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript\n *        constant literals.\n *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be\n *        set to a function to change its value on the given context.\n *\n */\n\n\n/**\n * @ngdoc provider\n * @name $parseProvider\n * @kind function\n *\n * @description\n * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}\n *  service.\n */\nfunction $ParseProvider() {\n  var cacheDefault = {};\n  var cacheExpensive = {};\n\n  var $parseOptions = {\n    csp: false,\n    unwrapPromises: false,\n    logPromiseWarnings: true,\n    expensiveChecks: false\n  };\n\n\n  /**\n   * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.\n   *\n   * @ngdoc method\n   * @name $parseProvider#unwrapPromises\n   * @description\n   *\n   * **This feature is deprecated, see deprecation notes below for more info**\n   *\n   * If set to true (default is false), $parse will unwrap promises automatically when a promise is\n   * found at any part of the expression. In other words, if set to true, the expression will always\n   * result in a non-promise value.\n   *\n   * While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled,\n   * the fulfillment value is used in place of the promise while evaluating the expression.\n   *\n   * **Deprecation notice**\n   *\n   * This is a feature that didn't prove to be wildly useful or popular, primarily because of the\n   * dichotomy between data access in templates (accessed as raw values) and controller code\n   * (accessed as promises).\n   *\n   * In most code we ended up resolving promises manually in controllers anyway and thus unifying\n   * the model access there.\n   *\n   * Other downsides of automatic promise unwrapping:\n   *\n   * - when building components it's often desirable to receive the raw promises\n   * - adds complexity and slows down expression evaluation\n   * - makes expression code pre-generation unattractive due to the amount of code that needs to be\n   *   generated\n   * - makes IDE auto-completion and tool support hard\n   *\n   * **Warning Logs**\n   *\n   * If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a\n   * promise (to reduce the noise, each expression is logged only once). To disable this logging use\n   * `$parseProvider.logPromiseWarnings(false)` api.\n   *\n   *\n   * @param {boolean=} value New value.\n   * @returns {boolean|self} Returns the current setting when used as getter and self if used as\n   *                         setter.\n   */\n  this.unwrapPromises = function(value) {\n    if (isDefined(value)) {\n      $parseOptions.unwrapPromises = !!value;\n      return this;\n    } else {\n      return $parseOptions.unwrapPromises;\n    }\n  };\n\n\n  /**\n   * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.\n   *\n   * @ngdoc method\n   * @name $parseProvider#logPromiseWarnings\n   * @description\n   *\n   * Controls whether Angular should log a warning on any encounter of a promise in an expression.\n   *\n   * The default is set to `true`.\n   *\n   * This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well.\n   *\n   * @param {boolean=} value New value.\n   * @returns {boolean|self} Returns the current setting when used as getter and self if used as\n   *                         setter.\n   */\n this.logPromiseWarnings = function(value) {\n    if (isDefined(value)) {\n      $parseOptions.logPromiseWarnings = value;\n      return this;\n    } else {\n      return $parseOptions.logPromiseWarnings;\n    }\n  };\n\n\n  this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {\n    $parseOptions.csp = $sniffer.csp;\n    var $parseOptionsExpensive = {\n      csp: $parseOptions.csp,\n      unwrapPromises: $parseOptions.unwrapPromises,\n      logPromiseWarnings: $parseOptions.logPromiseWarnings,\n      expensiveChecks: true\n    };\n\n    promiseWarning = function promiseWarningFn(fullExp) {\n      if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return;\n      promiseWarningCache[fullExp] = true;\n      $log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' +\n          'Automatic unwrapping of promises in Angular expressions is deprecated.');\n    };\n\n    return function(exp, expensiveChecks) {\n      var parsedExpression;\n\n      switch (typeof exp) {\n        case 'string':\n\n          var cache = (expensiveChecks ? cacheExpensive : cacheDefault);\n          if (cache.hasOwnProperty(exp)) {\n            return cache[exp];\n          }\n\n          var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;\n          var lexer = new Lexer(parseOptions);\n          var parser = new Parser(lexer, $filter, parseOptions);\n          parsedExpression = parser.parse(exp);\n\n          if (exp !== 'hasOwnProperty') {\n            // Only cache the value if it's not going to mess up the cache object\n            // This is more performant that using Object.prototype.hasOwnProperty.call\n            cache[exp] = parsedExpression;\n          }\n\n          return parsedExpression;\n\n        case 'function':\n          return exp;\n\n        default:\n          return noop;\n      }\n    };\n  }];\n}\n\n/**\n * @ngdoc service\n * @name $q\n * @requires $rootScope\n *\n * @description\n * A service that helps you run functions asynchronously, and use their return values (or exceptions)\n * when they are done processing.\n *\n * This is an implementation of promises/deferred objects inspired by\n * [Kris Kowal's Q](https://github.com/kriskowal/q).\n *\n * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an\n * interface for interacting with an object that represents the result of an action that is\n * performed asynchronously, and may or may not be finished at any given point in time.\n *\n * From the perspective of dealing with error handling, deferred and promise APIs are to\n * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.\n *\n * ```js\n *   // for the purpose of this example let's assume that variables `$q`, `scope` and `okToGreet`\n *   // are available in the current lexical scope (they could have been injected or passed in).\n *\n *   function asyncGreet(name) {\n *     var deferred = $q.defer();\n *\n *     setTimeout(function() {\n *       deferred.notify('About to greet ' + name + '.');\n *\n *       if (okToGreet(name)) {\n *         deferred.resolve('Hello, ' + name + '!');\n *       } else {\n *         deferred.reject('Greeting ' + name + ' is not allowed.');\n *       }\n *     }, 1000);\n *\n *     return deferred.promise;\n *   }\n *\n *   var promise = asyncGreet('Robin Hood');\n *   promise.then(function(greeting) {\n *     alert('Success: ' + greeting);\n *   }, function(reason) {\n *     alert('Failed: ' + reason);\n *   }, function(update) {\n *     alert('Got notification: ' + update);\n *   });\n * ```\n *\n * At first it might not be obvious why this extra complexity is worth the trouble. The payoff\n * comes in the way of guarantees that promise and deferred APIs make, see\n * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.\n *\n * Additionally the promise api allows for composition that is very hard to do with the\n * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.\n * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the\n * section on serial or parallel joining of promises.\n *\n *\n * # The Deferred API\n *\n * A new instance of deferred is constructed by calling `$q.defer()`.\n *\n * The purpose of the deferred object is to expose the associated Promise instance as well as APIs\n * that can be used for signaling the successful or unsuccessful completion, as well as the status\n * of the task.\n *\n * **Methods**\n *\n * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection\n *   constructed via `$q.reject`, the promise will be rejected instead.\n * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to\n *   resolving it with a rejection constructed via `$q.reject`.\n * - `notify(value)` - provides updates on the status of the promise's execution. This may be called\n *   multiple times before the promise is either resolved or rejected.\n *\n * **Properties**\n *\n * - promise – `{Promise}` – promise object associated with this deferred.\n *\n *\n * # The Promise API\n *\n * A new promise instance is created when a deferred instance is created and can be retrieved by\n * calling `deferred.promise`.\n *\n * The purpose of the promise object is to allow for interested parties to get access to the result\n * of the deferred task when it completes.\n *\n * **Methods**\n *\n * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or\n *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously\n *   as soon as the result is available. The callbacks are called with a single argument: the result\n *   or rejection reason. Additionally, the notify callback may be called zero or more times to\n *   provide a progress indication, before the promise is resolved or rejected.\n *\n *   This method *returns a new promise* which is resolved or rejected via the return value of the\n *   `successCallback`, `errorCallback`. It also notifies via the return value of the\n *   `notifyCallback` method. The promise can not be resolved or rejected from the notifyCallback\n *   method.\n *\n * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`\n *\n *   Because `catch` is a reserved word in JavaScript and reserved keywords are not supported as\n *   property names by ES3, you'll need to invoke the method like `promise['catch'](callback)` or\n *  `promise.then(null, errorCallback)` to make your code IE8 and Android 2.x compatible.\n *\n * - `finally(callback)` – allows you to observe either the fulfillment or rejection of a promise,\n *   but to do so without modifying the final value. This is useful to release resources or do some\n *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full\n *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for\n *   more information.\n *\n *   Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as\n *   property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to\n *   make your code IE8 and Android 2.x compatible.\n *\n * # Chaining promises\n *\n * Because calling the `then` method of a promise returns a new derived promise, it is easily\n * possible to create a chain of promises:\n *\n * ```js\n *   promiseB = promiseA.then(function(result) {\n *     return result + 1;\n *   });\n *\n *   // promiseB will be resolved immediately after promiseA is resolved and its value\n *   // will be the result of promiseA incremented by 1\n * ```\n *\n * It is possible to create chains of any length and since a promise can be resolved with another\n * promise (which will defer its resolution further), it is possible to pause/defer resolution of\n * the promises at any point in the chain. This makes it possible to implement powerful APIs like\n * $http's response interceptors.\n *\n *\n * # Differences between Kris Kowal's Q and $q\n *\n *  There are two main differences:\n *\n * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation\n *   mechanism in angular, which means faster propagation of resolution or rejection into your\n *   models and avoiding unnecessary browser repaints, which would result in flickering UI.\n * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains\n *   all the important functionality needed for common async tasks.\n *\n *  # Testing\n *\n *  ```js\n *    it('should simulate promise', inject(function($q, $rootScope) {\n *      var deferred = $q.defer();\n *      var promise = deferred.promise;\n *      var resolvedValue;\n *\n *      promise.then(function(value) { resolvedValue = value; });\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Simulate resolving of promise\n *      deferred.resolve(123);\n *      // Note that the 'then' function does not get called synchronously.\n *      // This is because we want the promise API to always be async, whether or not\n *      // it got called synchronously or asynchronously.\n *      expect(resolvedValue).toBeUndefined();\n *\n *      // Propagate promise resolution to 'then' functions using $apply().\n *      $rootScope.$apply();\n *      expect(resolvedValue).toEqual(123);\n *    }));\n *  ```\n */\nfunction $QProvider() {\n\n  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {\n    return qFactory(function(callback) {\n      $rootScope.$evalAsync(callback);\n    }, $exceptionHandler);\n  }];\n}\n\n\n/**\n * Constructs a promise manager.\n *\n * @param {function(Function)} nextTick Function for executing functions in the next turn.\n * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for\n *     debugging purposes.\n * @returns {object} Promise manager.\n */\nfunction qFactory(nextTick, exceptionHandler) {\n\n  /**\n   * @ngdoc method\n   * @name $q#defer\n   * @kind function\n   *\n   * @description\n   * Creates a `Deferred` object which represents a task which will finish in the future.\n   *\n   * @returns {Deferred} Returns a new instance of deferred.\n   */\n  var defer = function() {\n    var pending = [],\n        value, deferred;\n\n    deferred = {\n\n      resolve: function(val) {\n        if (pending) {\n          var callbacks = pending;\n          pending = undefined;\n          value = ref(val);\n\n          if (callbacks.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                value.then(callback[0], callback[1], callback[2]);\n              }\n            });\n          }\n        }\n      },\n\n\n      reject: function(reason) {\n        deferred.resolve(createInternalRejectedPromise(reason));\n      },\n\n\n      notify: function(progress) {\n        if (pending) {\n          var callbacks = pending;\n\n          if (pending.length) {\n            nextTick(function() {\n              var callback;\n              for (var i = 0, ii = callbacks.length; i < ii; i++) {\n                callback = callbacks[i];\n                callback[2](progress);\n              }\n            });\n          }\n        }\n      },\n\n\n      promise: {\n        then: function(callback, errback, progressback) {\n          var result = defer();\n\n          var wrappedCallback = function(value) {\n            try {\n              result.resolve((isFunction(callback) ? callback : defaultCallback)(value));\n            } catch(e) {\n              result.reject(e);\n              exceptionHandler(e);\n            }\n          };\n\n          var wrappedErrback = function(reason) {\n            try {\n              result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));\n            } catch(e) {\n              result.reject(e);\n              exceptionHandler(e);\n            }\n          };\n\n          var wrappedProgressback = function(progress) {\n            try {\n              result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));\n            } catch(e) {\n              exceptionHandler(e);\n            }\n          };\n\n          if (pending) {\n            pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);\n          } else {\n            value.then(wrappedCallback, wrappedErrback, wrappedProgressback);\n          }\n\n          return result.promise;\n        },\n\n        \"catch\": function(callback) {\n          return this.then(null, callback);\n        },\n\n        \"finally\": function(callback) {\n\n          function makePromise(value, resolved) {\n            var result = defer();\n            if (resolved) {\n              result.resolve(value);\n            } else {\n              result.reject(value);\n            }\n            return result.promise;\n          }\n\n          function handleCallback(value, isResolved) {\n            var callbackOutput = null;\n            try {\n              callbackOutput = (callback ||defaultCallback)();\n            } catch(e) {\n              return makePromise(e, false);\n            }\n            if (isPromiseLike(callbackOutput)) {\n              return callbackOutput.then(function() {\n                return makePromise(value, isResolved);\n              }, function(error) {\n                return makePromise(error, false);\n              });\n            } else {\n              return makePromise(value, isResolved);\n            }\n          }\n\n          return this.then(function(value) {\n            return handleCallback(value, true);\n          }, function(error) {\n            return handleCallback(error, false);\n          });\n        }\n      }\n    };\n\n    return deferred;\n  };\n\n\n  var ref = function(value) {\n    if (isPromiseLike(value)) return value;\n    return {\n      then: function(callback) {\n        var result = defer();\n        nextTick(function() {\n          result.resolve(callback(value));\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $q#reject\n   * @kind function\n   *\n   * @description\n   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be\n   * used to forward rejection in a chain of promises. If you are dealing with the last promise in\n   * a promise chain, you don't need to worry about it.\n   *\n   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of\n   * `reject` as the `throw` keyword in JavaScript. This also means that if you \"catch\" an error via\n   * a promise error callback and you want to forward the error to the promise derived from the\n   * current promise, you have to \"rethrow\" the error by returning a rejection constructed via\n   * `reject`.\n   *\n   * ```js\n   *   promiseB = promiseA.then(function(result) {\n   *     // success: do something and resolve promiseB\n   *     //          with the old or a new result\n   *     return result;\n   *   }, function(reason) {\n   *     // error: handle the error if possible and\n   *     //        resolve promiseB with newPromiseOrValue,\n   *     //        otherwise forward the rejection to promiseB\n   *     if (canHandle(reason)) {\n   *      // handle the error and recover\n   *      return newPromiseOrValue;\n   *     }\n   *     return $q.reject(reason);\n   *   });\n   * ```\n   *\n   * @param {*} reason Constant, message, exception or an object representing the rejection reason.\n   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.\n   */\n  var reject = function(reason) {\n    var result = defer();\n    result.reject(reason);\n    return result.promise;\n  };\n\n  var createInternalRejectedPromise = function(reason) {\n    return {\n      then: function(callback, errback) {\n        var result = defer();\n        nextTick(function() {\n          try {\n            result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));\n          } catch(e) {\n            result.reject(e);\n            exceptionHandler(e);\n          }\n        });\n        return result.promise;\n      }\n    };\n  };\n\n\n  /**\n   * @ngdoc method\n   * @name $q#when\n   * @kind function\n   *\n   * @description\n   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.\n   * This is useful when you are dealing with an object that might or might not be a promise, or if\n   * the promise comes from a source that can't be trusted.\n   *\n   * @param {*} value Value or a promise\n   * @returns {Promise} Returns a promise of the passed value or promise\n   */\n  var when = function(value, callback, errback, progressback) {\n    var result = defer(),\n        done;\n\n    var wrappedCallback = function(value) {\n      try {\n        return (isFunction(callback) ? callback : defaultCallback)(value);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedErrback = function(reason) {\n      try {\n        return (isFunction(errback) ? errback : defaultErrback)(reason);\n      } catch (e) {\n        exceptionHandler(e);\n        return reject(e);\n      }\n    };\n\n    var wrappedProgressback = function(progress) {\n      try {\n        return (isFunction(progressback) ? progressback : defaultCallback)(progress);\n      } catch (e) {\n        exceptionHandler(e);\n      }\n    };\n\n    nextTick(function() {\n      ref(value).then(function(value) {\n        if (done) return;\n        done = true;\n        result.resolve(ref(value).then(wrappedCallback, wrappedErrback, wrappedProgressback));\n      }, function(reason) {\n        if (done) return;\n        done = true;\n        result.resolve(wrappedErrback(reason));\n      }, function(progress) {\n        if (done) return;\n        result.notify(wrappedProgressback(progress));\n      });\n    });\n\n    return result.promise;\n  };\n\n\n  function defaultCallback(value) {\n    return value;\n  }\n\n\n  function defaultErrback(reason) {\n    return reject(reason);\n  }\n\n\n  /**\n   * @ngdoc method\n   * @name $q#all\n   * @kind function\n   *\n   * @description\n   * Combines multiple promises into a single promise that is resolved when all of the input\n   * promises are resolved.\n   *\n   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.\n   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,\n   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.\n   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected\n   *   with the same rejection value.\n   */\n  function all(promises) {\n    var deferred = defer(),\n        counter = 0,\n        results = isArray(promises) ? [] : {};\n\n    forEach(promises, function(promise, key) {\n      counter++;\n      ref(promise).then(function(value) {\n        if (results.hasOwnProperty(key)) return;\n        results[key] = value;\n        if (!(--counter)) deferred.resolve(results);\n      }, function(reason) {\n        if (results.hasOwnProperty(key)) return;\n        deferred.reject(reason);\n      });\n    });\n\n    if (counter === 0) {\n      deferred.resolve(results);\n    }\n\n    return deferred.promise;\n  }\n\n  return {\n    defer: defer,\n    reject: reject,\n    when: when,\n    all: all\n  };\n}\n\nfunction $$RAFProvider(){ //rAF\n  this.$get = ['$window', '$timeout', function($window, $timeout) {\n    var requestAnimationFrame = $window.requestAnimationFrame ||\n                                $window.webkitRequestAnimationFrame ||\n                                $window.mozRequestAnimationFrame;\n\n    var cancelAnimationFrame = $window.cancelAnimationFrame ||\n                               $window.webkitCancelAnimationFrame ||\n                               $window.mozCancelAnimationFrame ||\n                               $window.webkitCancelRequestAnimationFrame;\n\n    var rafSupported = !!requestAnimationFrame;\n    var raf = rafSupported\n      ? function(fn) {\n          var id = requestAnimationFrame(fn);\n          return function() {\n            cancelAnimationFrame(id);\n          };\n        }\n      : function(fn) {\n          var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n          return function() {\n            $timeout.cancel(timer);\n          };\n        };\n\n    raf.supported = rafSupported;\n\n    return raf;\n  }];\n}\n\n/**\n * DESIGN NOTES\n *\n * The design decisions behind the scope are heavily favored for speed and memory consumption.\n *\n * The typical use of scope is to watch the expressions, which most of the time return the same\n * value as last time so we optimize the operation.\n *\n * Closures construction is expensive in terms of speed as well as memory:\n *   - No closures, instead use prototypical inheritance for API\n *   - Internal state needs to be stored on scope directly, which means that private state is\n *     exposed as $$____ properties\n *\n * Loop operations are optimized by using while(count--) { ... }\n *   - this means that in order to keep the same order of execution as addition we have to add\n *     items to the array at the beginning (unshift) instead of at the end (push)\n *\n * Child scopes are created and removed often\n *   - Using an array would be slow since inserts in middle are expensive so we use linked list\n *\n * There are few watches then a lot of observers. This is why you don't want the observer to be\n * implemented in the same way as watch. Watch requires return of initialization function which\n * are expensive to construct.\n */\n\n\n/**\n * @ngdoc provider\n * @name $rootScopeProvider\n * @description\n *\n * Provider for the $rootScope service.\n */\n\n/**\n * @ngdoc method\n * @name $rootScopeProvider#digestTtl\n * @description\n *\n * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and\n * assuming that the model is unstable.\n *\n * The current default is 10 iterations.\n *\n * In complex applications it's possible that the dependencies between `$watch`s will result in\n * several digest iterations. However if an application needs more than the default 10 digest\n * iterations for its model to stabilize then you should investigate what is causing the model to\n * continuously change during the digest.\n *\n * Increasing the TTL could have performance implications, so you should not change it without\n * proper justification.\n *\n * @param {number} limit The number of digest iterations.\n */\n\n\n/**\n * @ngdoc service\n * @name $rootScope\n * @description\n *\n * Every application has a single root {@link ng.$rootScope.Scope scope}.\n * All other scopes are descendant scopes of the root scope. Scopes provide separation\n * between the model and the view, via a mechanism for watching the model for changes.\n * They also provide an event emission/broadcast and subscription facility. See the\n * {@link guide/scope developer guide on scopes}.\n */\nfunction $RootScopeProvider(){\n  var TTL = 10;\n  var $rootScopeMinErr = minErr('$rootScope');\n  var lastDirtyWatch = null;\n\n  this.digestTtl = function(value) {\n    if (arguments.length) {\n      TTL = value;\n    }\n    return TTL;\n  };\n\n  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',\n      function( $injector,   $exceptionHandler,   $parse,   $browser) {\n\n    /**\n     * @ngdoc type\n     * @name $rootScope.Scope\n     *\n     * @description\n     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the\n     * {@link auto.$injector $injector}. Child scopes are created using the\n     * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when\n     * compiled HTML template is executed.)\n     *\n     * Here is a simple scope snippet to show how you can interact with the scope.\n     * ```html\n     * <file src=\"./test/ng/rootScopeSpec.js\" tag=\"docs1\" />\n     * ```\n     *\n     * # Inheritance\n     * A scope can inherit from a parent scope, as in this example:\n     * ```js\n         var parent = $rootScope;\n         var child = parent.$new();\n\n         parent.salutation = \"Hello\";\n         child.name = \"World\";\n         expect(child.salutation).toEqual('Hello');\n\n         child.salutation = \"Welcome\";\n         expect(child.salutation).toEqual('Welcome');\n         expect(parent.salutation).toEqual('Hello');\n     * ```\n     *\n     *\n     * @param {Object.<string, function()>=} providers Map of service factory which need to be\n     *                                       provided for the current scope. Defaults to {@link ng}.\n     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should\n     *                              append/override services provided by `providers`. This is handy\n     *                              when unit-testing and having the need to override a default\n     *                              service.\n     * @returns {Object} Newly created scope.\n     *\n     */\n    function Scope() {\n      this.$id = nextUid();\n      this.$$phase = this.$parent = this.$$watchers =\n                     this.$$nextSibling = this.$$prevSibling =\n                     this.$$childHead = this.$$childTail = null;\n      this['this'] = this.$root =  this;\n      this.$$destroyed = false;\n      this.$$asyncQueue = [];\n      this.$$postDigestQueue = [];\n      this.$$listeners = {};\n      this.$$listenerCount = {};\n      this.$$isolateBindings = {};\n    }\n\n    /**\n     * @ngdoc property\n     * @name $rootScope.Scope#$id\n     *\n     * @description\n     * Unique scope ID (monotonically increasing) useful for debugging.\n     */\n\n     /**\n      * @ngdoc property\n      * @name $rootScope.Scope#$parent\n      *\n      * @description\n      * Reference to the parent scope.\n      */\n\n      /**\n       * @ngdoc property\n       * @name $rootScope.Scope#$root\n       *\n       * @description\n       * Reference to the root scope.\n       */\n\n    Scope.prototype = {\n      constructor: Scope,\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$new\n       * @kind function\n       *\n       * @description\n       * Creates a new child {@link ng.$rootScope.Scope scope}.\n       *\n       * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.\n       * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.\n       *\n       * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is\n       * desired for the scope and its child scopes to be permanently detached from the parent and\n       * thus stop participating in model change detection and listener notification by invoking.\n       *\n       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the\n       *         parent scope. The scope is isolated, as it can not see parent scope properties.\n       *         When creating widgets, it is useful for the widget to not accidentally read parent\n       *         state.\n       *\n       * @returns {Object} The newly created child scope.\n       *\n       */\n      $new: function(isolate) {\n        var ChildScope,\n            child;\n\n        if (isolate) {\n          child = new Scope();\n          child.$root = this.$root;\n          // ensure that there is just one async queue per $rootScope and its children\n          child.$$asyncQueue = this.$$asyncQueue;\n          child.$$postDigestQueue = this.$$postDigestQueue;\n        } else {\n          // Only create a child scope class if somebody asks for one,\n          // but cache it to allow the VM to optimize lookups.\n          if (!this.$$childScopeClass) {\n            this.$$childScopeClass = function() {\n              this.$$watchers = this.$$nextSibling =\n                  this.$$childHead = this.$$childTail = null;\n              this.$$listeners = {};\n              this.$$listenerCount = {};\n              this.$id = nextUid();\n              this.$$childScopeClass = null;\n            };\n            this.$$childScopeClass.prototype = this;\n          }\n          child = new this.$$childScopeClass();\n        }\n        child['this'] = child;\n        child.$parent = this;\n        child.$$prevSibling = this.$$childTail;\n        if (this.$$childHead) {\n          this.$$childTail.$$nextSibling = child;\n          this.$$childTail = child;\n        } else {\n          this.$$childHead = this.$$childTail = child;\n        }\n        return child;\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watch\n       * @kind function\n       *\n       * @description\n       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.\n       *\n       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest\n       *   $digest()} and should return the value that will be watched. (Since\n       *   {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the\n       *   `watchExpression` can execute multiple times per\n       *   {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)\n       * - The `listener` is called only when the value from the current `watchExpression` and the\n       *   previous call to `watchExpression` are not equal (with the exception of the initial run,\n       *   see below). Inequality is determined according to reference inequality,\n       *   [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)\n       *    via the `!==` Javascript operator, unless `objectEquality == true`\n       *   (see next point)\n       * - When `objectEquality == true`, inequality of the `watchExpression` is determined\n       *   according to the {@link angular.equals} function. To save the value of the object for\n       *   later comparison, the {@link angular.copy} function is used. This therefore means that\n       *   watching complex objects will have adverse memory and performance implications.\n       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.\n       *   This is achieved by rerunning the watchers until no changes are detected. The rerun\n       *   iteration limit is 10 to prevent an infinite loop deadlock.\n       *\n       *\n       * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,\n       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`\n       * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a\n       * change is detected, be prepared for multiple calls to your listener.)\n       *\n       * After a watcher is registered with the scope, the `listener` fn is called asynchronously\n       * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the\n       * watcher. In rare cases, this is undesirable because the listener is called when the result\n       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you\n       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the\n       * listener was called due to initialization.\n       *\n       * The example below contains an illustration of using a function as your $watch listener\n       *\n       *\n       * # Example\n       * ```js\n           // let's assume that scope was dependency injected as the $rootScope\n           var scope = $rootScope;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n\n\n\n           // Using a listener function\n           var food;\n           scope.foodCounter = 0;\n           expect(scope.foodCounter).toEqual(0);\n           scope.$watch(\n             // This is the listener function\n             function() { return food; },\n             // This is the change handler\n             function(newValue, oldValue) {\n               if ( newValue !== oldValue ) {\n                 // Only increment the counter if the value changed\n                 scope.foodCounter = scope.foodCounter + 1;\n               }\n             }\n           );\n           // No digest has been run so the counter will be zero\n           expect(scope.foodCounter).toEqual(0);\n\n           // Run the digest but since food has not changed count will still be zero\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(0);\n\n           // Update food and run digest.  Now the counter will increment\n           food = 'cheeseburger';\n           scope.$digest();\n           expect(scope.foodCounter).toEqual(1);\n\n       * ```\n       *\n       *\n       *\n       * @param {(function()|string)} watchExpression Expression that is evaluated on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers\n       *    a call to the `listener`.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(scope)`: called with current `scope` as a parameter.\n       * @param {(function()|string)=} listener Callback called whenever the return value of\n       *   the `watchExpression` changes.\n       *\n       *    - `string`: Evaluated as {@link guide/expression expression}\n       *    - `function(newValue, oldValue, scope)`: called with current and previous values as\n       *      parameters.\n       *\n       * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of\n       *     comparing for reference equality.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $watch: function(watchExp, listener, objectEquality) {\n        var scope = this,\n            get = compileToFn(watchExp, 'watch'),\n            array = scope.$$watchers,\n            watcher = {\n              fn: listener,\n              last: initWatchVal,\n              get: get,\n              exp: watchExp,\n              eq: !!objectEquality\n            };\n\n        lastDirtyWatch = null;\n\n        // in the case user pass string, we need to compile it, do we really need this ?\n        if (!isFunction(listener)) {\n          var listenFn = compileToFn(listener || noop, 'listener');\n          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};\n        }\n\n        if (typeof watchExp == 'string' && get.constant) {\n          var originalFn = watcher.fn;\n          watcher.fn = function(newVal, oldVal, scope) {\n            originalFn.call(this, newVal, oldVal, scope);\n            arrayRemove(array, watcher);\n          };\n        }\n\n        if (!array) {\n          array = scope.$$watchers = [];\n        }\n        // we use unshift since we use a while loop in $digest for speed.\n        // the while loop reads in reverse order.\n        array.unshift(watcher);\n\n        return function deregisterWatch() {\n          arrayRemove(array, watcher);\n          lastDirtyWatch = null;\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$watchCollection\n       * @kind function\n       *\n       * @description\n       * Shallow watches the properties of an object and fires whenever any of the properties change\n       * (for arrays, this implies watching the array items; for object maps, this implies watching\n       * the properties). If a change is detected, the `listener` callback is fired.\n       *\n       * - The `obj` collection is observed via standard $watch operation and is examined on every\n       *   call to $digest() to see if any items have been added, removed, or moved.\n       * - The `listener` is called whenever anything within the `obj` has changed. Examples include\n       *   adding, removing, and moving items belonging to an object or array.\n       *\n       *\n       * # Example\n       * ```js\n          $scope.names = ['igor', 'matias', 'misko', 'james'];\n          $scope.dataCount = 4;\n\n          $scope.$watchCollection('names', function(newNames, oldNames) {\n            $scope.dataCount = newNames.length;\n          });\n\n          expect($scope.dataCount).toEqual(4);\n          $scope.$digest();\n\n          //still at 4 ... no changes\n          expect($scope.dataCount).toEqual(4);\n\n          $scope.names.pop();\n          $scope.$digest();\n\n          //now there's been a change\n          expect($scope.dataCount).toEqual(3);\n       * ```\n       *\n       *\n       * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The\n       *    expression value should evaluate to an object or an array which is observed on each\n       *    {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the\n       *    collection will trigger a call to the `listener`.\n       *\n       * @param {function(newCollection, oldCollection, scope)} listener a callback function called\n       *    when a change is detected.\n       *    - The `newCollection` object is the newly modified data obtained from the `obj` expression\n       *    - The `oldCollection` object is a copy of the former collection data.\n       *      Due to performance considerations, the`oldCollection` value is computed only if the\n       *      `listener` function declares two or more arguments.\n       *    - The `scope` argument refers to the current scope.\n       *\n       * @returns {function()} Returns a de-registration function for this listener. When the\n       *    de-registration function is executed, the internal watch operation is terminated.\n       */\n      $watchCollection: function(obj, listener) {\n        var self = this;\n        // the current value, updated on each dirty-check run\n        var newValue;\n        // a shallow copy of the newValue from the last dirty-check run,\n        // updated to match newValue during dirty-check run\n        var oldValue;\n        // a shallow copy of the newValue from when the last change happened\n        var veryOldValue;\n        // only track veryOldValue if the listener is asking for it\n        var trackVeryOldValue = (listener.length > 1);\n        var changeDetected = 0;\n        var objGetter = $parse(obj);\n        var internalArray = [];\n        var internalObject = {};\n        var initRun = true;\n        var oldLength = 0;\n\n        function $watchCollectionWatch() {\n          newValue = objGetter(self);\n          var newLength, key, bothNaN;\n\n          if (!isObject(newValue)) { // if primitive\n            if (oldValue !== newValue) {\n              oldValue = newValue;\n              changeDetected++;\n            }\n          } else if (isArrayLike(newValue)) {\n            if (oldValue !== internalArray) {\n              // we are transitioning from something which was not an array into array.\n              oldValue = internalArray;\n              oldLength = oldValue.length = 0;\n              changeDetected++;\n            }\n\n            newLength = newValue.length;\n\n            if (oldLength !== newLength) {\n              // if lengths do not match we need to trigger change notification\n              changeDetected++;\n              oldValue.length = oldLength = newLength;\n            }\n            // copy the items to oldValue and look for changes.\n            for (var i = 0; i < newLength; i++) {\n              bothNaN = (oldValue[i] !== oldValue[i]) &&\n                  (newValue[i] !== newValue[i]);\n              if (!bothNaN && (oldValue[i] !== newValue[i])) {\n                changeDetected++;\n                oldValue[i] = newValue[i];\n              }\n            }\n          } else {\n            if (oldValue !== internalObject) {\n              // we are transitioning from something which was not an object into object.\n              oldValue = internalObject = {};\n              oldLength = 0;\n              changeDetected++;\n            }\n            // copy the items to oldValue and look for changes.\n            newLength = 0;\n            for (key in newValue) {\n              if (newValue.hasOwnProperty(key)) {\n                newLength++;\n                if (oldValue.hasOwnProperty(key)) {\n                  bothNaN = (oldValue[key] !== oldValue[key]) &&\n                      (newValue[key] !== newValue[key]);\n                  if (!bothNaN && (oldValue[key] !== newValue[key])) {\n                    changeDetected++;\n                    oldValue[key] = newValue[key];\n                  }\n                } else {\n                  oldLength++;\n                  oldValue[key] = newValue[key];\n                  changeDetected++;\n                }\n              }\n            }\n            if (oldLength > newLength) {\n              // we used to have more keys, need to find them and destroy them.\n              changeDetected++;\n              for(key in oldValue) {\n                if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) {\n                  oldLength--;\n                  delete oldValue[key];\n                }\n              }\n            }\n          }\n          return changeDetected;\n        }\n\n        function $watchCollectionAction() {\n          if (initRun) {\n            initRun = false;\n            listener(newValue, newValue, self);\n          } else {\n            listener(newValue, veryOldValue, self);\n          }\n\n          // make a copy for the next time a collection is changed\n          if (trackVeryOldValue) {\n            if (!isObject(newValue)) {\n              //primitive\n              veryOldValue = newValue;\n            } else if (isArrayLike(newValue)) {\n              veryOldValue = new Array(newValue.length);\n              for (var i = 0; i < newValue.length; i++) {\n                veryOldValue[i] = newValue[i];\n              }\n            } else { // if object\n              veryOldValue = {};\n              for (var key in newValue) {\n                if (hasOwnProperty.call(newValue, key)) {\n                  veryOldValue[key] = newValue[key];\n                }\n              }\n            }\n          }\n        }\n\n        return this.$watch($watchCollectionWatch, $watchCollectionAction);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$digest\n       * @kind function\n       *\n       * @description\n       * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and\n       * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change\n       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}\n       * until no more listeners are firing. This means that it is possible to get into an infinite\n       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of\n       * iterations exceeds 10.\n       *\n       * Usually, you don't call `$digest()` directly in\n       * {@link ng.directive:ngController controllers} or in\n       * {@link ng.$compileProvider#directive directives}.\n       * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within\n       * a {@link ng.$compileProvider#directive directives}), which will force a `$digest()`.\n       *\n       * If you want to be notified whenever `$digest()` is called,\n       * you can register a `watchExpression` function with\n       * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.\n       *\n       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.\n       *\n       * # Example\n       * ```js\n           var scope = ...;\n           scope.name = 'misko';\n           scope.counter = 0;\n\n           expect(scope.counter).toEqual(0);\n           scope.$watch('name', function(newValue, oldValue) {\n             scope.counter = scope.counter + 1;\n           });\n           expect(scope.counter).toEqual(0);\n\n           scope.$digest();\n           // the listener is always called during the first $digest loop after it was registered\n           expect(scope.counter).toEqual(1);\n\n           scope.$digest();\n           // but now it will not be called unless the value changes\n           expect(scope.counter).toEqual(1);\n\n           scope.name = 'adam';\n           scope.$digest();\n           expect(scope.counter).toEqual(2);\n       * ```\n       *\n       */\n      $digest: function() {\n        var watch, value, last,\n            watchers,\n            asyncQueue = this.$$asyncQueue,\n            postDigestQueue = this.$$postDigestQueue,\n            length,\n            dirty, ttl = TTL,\n            next, current, target = this,\n            watchLog = [],\n            logIdx, logMsg, asyncTask;\n\n        beginPhase('$digest');\n        // Check for changes to browser url that happened in sync before the call to $digest\n        $browser.$$checkUrlChange();\n\n        lastDirtyWatch = null;\n\n        do { // \"while dirty\" loop\n          dirty = false;\n          current = target;\n\n          while(asyncQueue.length) {\n            try {\n              asyncTask = asyncQueue.shift();\n              asyncTask.scope.$eval(asyncTask.expression);\n            } catch (e) {\n              clearPhase();\n              $exceptionHandler(e);\n            }\n            lastDirtyWatch = null;\n          }\n\n          traverseScopesLoop:\n          do { // \"traverse the scopes\" loop\n            if ((watchers = current.$$watchers)) {\n              // process our watches\n              length = watchers.length;\n              while (length--) {\n                try {\n                  watch = watchers[length];\n                  // Most common watches are on primitives, in which case we can short\n                  // circuit it with === operator, only when === fails do we use .equals\n                  if (watch) {\n                    if ((value = watch.get(current)) !== (last = watch.last) &&\n                        !(watch.eq\n                            ? equals(value, last)\n                            : (typeof value === 'number' && typeof last === 'number'\n                               && isNaN(value) && isNaN(last)))) {\n                      dirty = true;\n                      lastDirtyWatch = watch;\n                      watch.last = watch.eq ? copy(value, null) : value;\n                      watch.fn(value, ((last === initWatchVal) ? value : last), current);\n                      if (ttl < 5) {\n                        logIdx = 4 - ttl;\n                        if (!watchLog[logIdx]) watchLog[logIdx] = [];\n                        logMsg = (isFunction(watch.exp))\n                            ? 'fn: ' + (watch.exp.name || watch.exp.toString())\n                            : watch.exp;\n                        logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);\n                        watchLog[logIdx].push(logMsg);\n                      }\n                    } else if (watch === lastDirtyWatch) {\n                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers\n                      // have already been tested.\n                      dirty = false;\n                      break traverseScopesLoop;\n                    }\n                  }\n                } catch (e) {\n                  clearPhase();\n                  $exceptionHandler(e);\n                }\n              }\n            }\n\n            // Insanity Warning: scope depth-first traversal\n            // yes, this code is a bit crazy, but it works and we have tests to prove it!\n            // this piece should be kept in sync with the traversal in $broadcast\n            if (!(next = (current.$$childHead ||\n                (current !== target && current.$$nextSibling)))) {\n              while(current !== target && !(next = current.$$nextSibling)) {\n                current = current.$parent;\n              }\n            }\n          } while ((current = next));\n\n          // `break traverseScopesLoop;` takes us to here\n\n          if((dirty || asyncQueue.length) && !(ttl--)) {\n            clearPhase();\n            throw $rootScopeMinErr('infdig',\n                '{0} $digest() iterations reached. Aborting!\\n' +\n                'Watchers fired in the last 5 iterations: {1}',\n                TTL, toJson(watchLog));\n          }\n\n        } while (dirty || asyncQueue.length);\n\n        clearPhase();\n\n        while(postDigestQueue.length) {\n          try {\n            postDigestQueue.shift()();\n          } catch (e) {\n            $exceptionHandler(e);\n          }\n        }\n      },\n\n\n      /**\n       * @ngdoc event\n       * @name $rootScope.Scope#$destroy\n       * @eventType broadcast on scope being destroyed\n       *\n       * @description\n       * Broadcasted when a scope and its children are being destroyed.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$destroy\n       * @kind function\n       *\n       * @description\n       * Removes the current scope (and all of its children) from the parent scope. Removal implies\n       * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer\n       * propagate to the current scope and its children. Removal also implies that the current\n       * scope is eligible for garbage collection.\n       *\n       * The `$destroy()` is usually used by directives such as\n       * {@link ng.directive:ngRepeat ngRepeat} for managing the\n       * unrolling of the loop.\n       *\n       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.\n       * Application code can register a `$destroy` event handler that will give it a chance to\n       * perform any necessary cleanup.\n       *\n       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to\n       * clean up DOM bindings before an element is removed from the DOM.\n       */\n      $destroy: function() {\n        // we can't destroy the root scope or a scope that has been already destroyed\n        if (this.$$destroyed) return;\n        var parent = this.$parent;\n\n        this.$broadcast('$destroy');\n        this.$$destroyed = true;\n        if (this === $rootScope) return;\n\n        forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));\n\n        // sever all the references to parent scopes (after this cleanup, the current scope should\n        // not be retained by any of our references and should be eligible for garbage collection)\n        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;\n        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;\n        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;\n        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;\n\n\n        // All of the code below is bogus code that works around V8's memory leak via optimized code\n        // and inline caches.\n        //\n        // see:\n        // - https://code.google.com/p/v8/issues/detail?id=2073#c26\n        // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909\n        // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451\n\n        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =\n            this.$$childTail = this.$root = null;\n\n        // don't reset these to null in case some async task tries to register a listener/watch/task\n        this.$$listeners = {};\n        this.$$watchers = this.$$asyncQueue = this.$$postDigestQueue = [];\n\n        // prevent NPEs since these methods have references to properties we nulled out\n        this.$destroy = this.$digest = this.$apply = noop;\n        this.$on = this.$watch = function() { return noop; };\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$eval\n       * @kind function\n       *\n       * @description\n       * Executes the `expression` on the current scope and returns the result. Any exceptions in\n       * the expression are propagated (uncaught). This is useful when evaluating Angular\n       * expressions.\n       *\n       * # Example\n       * ```js\n           var scope = ng.$rootScope.Scope();\n           scope.a = 1;\n           scope.b = 2;\n\n           expect(scope.$eval('a+b')).toEqual(3);\n           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);\n       * ```\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       * @param {(object)=} locals Local variables object, useful for overriding values in scope.\n       * @returns {*} The result of evaluating the expression.\n       */\n      $eval: function(expr, locals) {\n        return $parse(expr)(this, locals);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$evalAsync\n       * @kind function\n       *\n       * @description\n       * Executes the expression on the current scope at a later point in time.\n       *\n       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only\n       * that:\n       *\n       *   - it will execute after the function that scheduled the evaluation (preferably before DOM\n       *     rendering).\n       *   - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after\n       *     `expression` execution.\n       *\n       * Any exceptions from the execution of the expression are forwarded to the\n       * {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle\n       * will be scheduled. However, it is encouraged to always call code that changes the model\n       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.\n       *\n       * @param {(string|function())=} expression An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with the current `scope` parameter.\n       *\n       */\n      $evalAsync: function(expr) {\n        // if we are outside of an $digest loop and this is the first time we are scheduling async\n        // task also schedule async auto-flush\n        if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {\n          $browser.defer(function() {\n            if ($rootScope.$$asyncQueue.length) {\n              $rootScope.$digest();\n            }\n          });\n        }\n\n        this.$$asyncQueue.push({scope: this, expression: expr});\n      },\n\n      $$postDigest : function(fn) {\n        this.$$postDigestQueue.push(fn);\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$apply\n       * @kind function\n       *\n       * @description\n       * `$apply()` is used to execute an expression in angular from outside of the angular\n       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).\n       * Because we are calling into the angular framework we need to perform proper scope life\n       * cycle of {@link ng.$exceptionHandler exception handling},\n       * {@link ng.$rootScope.Scope#$digest executing watches}.\n       *\n       * ## Life cycle\n       *\n       * # Pseudo-Code of `$apply()`\n       * ```js\n           function $apply(expr) {\n             try {\n               return $eval(expr);\n             } catch (e) {\n               $exceptionHandler(e);\n             } finally {\n               $root.$digest();\n             }\n           }\n       * ```\n       *\n       *\n       * Scope's `$apply()` method transitions through the following stages:\n       *\n       * 1. The {@link guide/expression expression} is executed using the\n       *    {@link ng.$rootScope.Scope#$eval $eval()} method.\n       * 2. Any exceptions from the execution of the expression are forwarded to the\n       *    {@link ng.$exceptionHandler $exceptionHandler} service.\n       * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the\n       *    expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.\n       *\n       *\n       * @param {(string|function())=} exp An angular expression to be executed.\n       *\n       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.\n       *    - `function(scope)`: execute the function with current `scope` parameter.\n       *\n       * @returns {*} The result of evaluating the expression.\n       */\n      $apply: function(expr) {\n        try {\n          beginPhase('$apply');\n          return this.$eval(expr);\n        } catch (e) {\n          $exceptionHandler(e);\n        } finally {\n          clearPhase();\n          try {\n            $rootScope.$digest();\n          } catch (e) {\n            $exceptionHandler(e);\n            throw e;\n          }\n        }\n      },\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$on\n       * @kind function\n       *\n       * @description\n       * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for\n       * discussion of event life cycle.\n       *\n       * The event listener function format is: `function(event, args...)`. The `event` object\n       * passed into the listener has the following attributes:\n       *\n       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or\n       *     `$broadcast`-ed.\n       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.\n       *   - `name` - `{string}`: name of the event.\n       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel\n       *     further event propagation (available only for events that were `$emit`-ed).\n       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag\n       *     to true.\n       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.\n       *\n       * @param {string} name Event name to listen on.\n       * @param {function(event, ...args)} listener Function to call when the event is emitted.\n       * @returns {function()} Returns a deregistration function for this listener.\n       */\n      $on: function(name, listener) {\n        var namedListeners = this.$$listeners[name];\n        if (!namedListeners) {\n          this.$$listeners[name] = namedListeners = [];\n        }\n        namedListeners.push(listener);\n\n        var current = this;\n        do {\n          if (!current.$$listenerCount[name]) {\n            current.$$listenerCount[name] = 0;\n          }\n          current.$$listenerCount[name]++;\n        } while ((current = current.$parent));\n\n        var self = this;\n        return function() {\n          var indexOfListener = indexOf(namedListeners, listener);\n          if (indexOfListener !== -1) {\n            namedListeners[indexOfListener] = null;\n            decrementListenerCount(self, 1, name);\n          }\n        };\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$emit\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` upwards through the scope hierarchy notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$emit` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event traverses upwards toward the root scope and calls all\n       * registered listeners along the way. The event will stop propagating if one of the listeners\n       * cancels it.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to emit.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).\n       */\n      $emit: function(name, args) {\n        var empty = [],\n            namedListeners,\n            scope = this,\n            stopPropagation = false,\n            event = {\n              name: name,\n              targetScope: scope,\n              stopPropagation: function() {stopPropagation = true;},\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            i, length;\n\n        do {\n          namedListeners = scope.$$listeners[name] || empty;\n          event.currentScope = scope;\n          for (i=0, length=namedListeners.length; i<length; i++) {\n\n            // if listeners were deregistered, defragment the array\n            if (!namedListeners[i]) {\n              namedListeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n            try {\n              //allow all listeners attached to the current scope to run\n              namedListeners[i].apply(null, listenerArgs);\n            } catch (e) {\n              $exceptionHandler(e);\n            }\n          }\n          //if any listener on the current scope stops propagation, prevent bubbling\n          if (stopPropagation) return event;\n          //traverse upwards\n          scope = scope.$parent;\n        } while (scope);\n\n        return event;\n      },\n\n\n      /**\n       * @ngdoc method\n       * @name $rootScope.Scope#$broadcast\n       * @kind function\n       *\n       * @description\n       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the\n       * registered {@link ng.$rootScope.Scope#$on} listeners.\n       *\n       * The event life cycle starts at the scope on which `$broadcast` was called. All\n       * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get\n       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current\n       * scope and calls all registered listeners along the way. The event cannot be canceled.\n       *\n       * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed\n       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.\n       *\n       * @param {string} name Event name to broadcast.\n       * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.\n       * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}\n       */\n      $broadcast: function(name, args) {\n        var target = this,\n            current = target,\n            next = target,\n            event = {\n              name: name,\n              targetScope: target,\n              preventDefault: function() {\n                event.defaultPrevented = true;\n              },\n              defaultPrevented: false\n            },\n            listenerArgs = concat([event], arguments, 1),\n            listeners, i, length;\n\n        //down while you can, then up and next sibling or up and next sibling until back at root\n        while ((current = next)) {\n          event.currentScope = current;\n          listeners = current.$$listeners[name] || [];\n          for (i=0, length = listeners.length; i<length; i++) {\n            // if listeners were deregistered, defragment the array\n            if (!listeners[i]) {\n              listeners.splice(i, 1);\n              i--;\n              length--;\n              continue;\n            }\n\n            try {\n              listeners[i].apply(null, listenerArgs);\n            } catch(e) {\n              $exceptionHandler(e);\n            }\n          }\n\n          // Insanity Warning: scope depth-first traversal\n          // yes, this code is a bit crazy, but it works and we have tests to prove it!\n          // this piece should be kept in sync with the traversal in $digest\n          // (though it differs due to having the extra check for $$listenerCount)\n          if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||\n              (current !== target && current.$$nextSibling)))) {\n            while(current !== target && !(next = current.$$nextSibling)) {\n              current = current.$parent;\n            }\n          }\n        }\n\n        return event;\n      }\n    };\n\n    var $rootScope = new Scope();\n\n    return $rootScope;\n\n\n    function beginPhase(phase) {\n      if ($rootScope.$$phase) {\n        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);\n      }\n\n      $rootScope.$$phase = phase;\n    }\n\n    function clearPhase() {\n      $rootScope.$$phase = null;\n    }\n\n    function compileToFn(exp, name) {\n      var fn = $parse(exp);\n      assertArgFn(fn, name);\n      return fn;\n    }\n\n    function decrementListenerCount(current, count, name) {\n      do {\n        current.$$listenerCount[name] -= count;\n\n        if (current.$$listenerCount[name] === 0) {\n          delete current.$$listenerCount[name];\n        }\n      } while ((current = current.$parent));\n    }\n\n    /**\n     * function used as an initial value for watchers.\n     * because it's unique we can easily tell it apart from other values\n     */\n    function initWatchVal() {}\n  }];\n}\n\n/**\n * @description\n * Private service to sanitize uris for links and images. Used by $compile and $sanitize.\n */\nfunction $$SanitizeUriProvider() {\n  var aHrefSanitizationWhitelist = /^\\s*(https?|ftp|mailto|tel|file):/,\n    imgSrcSanitizationWhitelist = /^\\s*((https?|ftp|file):|data:image\\/)/;\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during a[href] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.aHrefSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      aHrefSanitizationWhitelist = regexp;\n      return this;\n    }\n    return aHrefSanitizationWhitelist;\n  };\n\n\n  /**\n   * @description\n   * Retrieves or overrides the default regular expression that is used for whitelisting of safe\n   * urls during img[src] sanitization.\n   *\n   * The sanitization is a security measure aimed at prevent XSS attacks via html links.\n   *\n   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into\n   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`\n   * regular expression. If a match is found, the original url is written into the dom. Otherwise,\n   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.\n   *\n   * @param {RegExp=} regexp New regexp to whitelist urls with.\n   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for\n   *    chaining otherwise.\n   */\n  this.imgSrcSanitizationWhitelist = function(regexp) {\n    if (isDefined(regexp)) {\n      imgSrcSanitizationWhitelist = regexp;\n      return this;\n    }\n    return imgSrcSanitizationWhitelist;\n  };\n\n  this.$get = function() {\n    return function sanitizeUri(uri, isImage) {\n      var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;\n      var normalizedVal;\n      // NOTE: urlResolve() doesn't support IE < 8 so we don't sanitize for that case.\n      if (!msie || msie >= 8 ) {\n        normalizedVal = urlResolve(uri).href;\n        if (normalizedVal !== '' && !normalizedVal.match(regex)) {\n          return 'unsafe:'+normalizedVal;\n        }\n      }\n      return uri;\n    };\n  };\n}\n\nvar $sceMinErr = minErr('$sce');\n\nvar SCE_CONTEXTS = {\n  HTML: 'html',\n  CSS: 'css',\n  URL: 'url',\n  // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a\n  // url.  (e.g. ng-include, script src, templateUrl)\n  RESOURCE_URL: 'resourceUrl',\n  JS: 'js'\n};\n\n// Helper functions follow.\n\n// Copied from:\n// http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962\n// Prereq: s is a string.\nfunction escapeForRegexp(s) {\n  return s.replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1').\n           replace(/\\x08/g, '\\\\x08');\n}\n\n\nfunction adjustMatcher(matcher) {\n  if (matcher === 'self') {\n    return matcher;\n  } else if (isString(matcher)) {\n    // Strings match exactly except for 2 wildcards - '*' and '**'.\n    // '*' matches any character except those from the set ':/.?&'.\n    // '**' matches any character (like .* in a RegExp).\n    // More than 2 *'s raises an error as it's ill defined.\n    if (matcher.indexOf('***') > -1) {\n      throw $sceMinErr('iwcard',\n          'Illegal sequence *** in string matcher.  String: {0}', matcher);\n    }\n    matcher = escapeForRegexp(matcher).\n                  replace('\\\\*\\\\*', '.*').\n                  replace('\\\\*', '[^:/.?&;]*');\n    return new RegExp('^' + matcher + '$');\n  } else if (isRegExp(matcher)) {\n    // The only other type of matcher allowed is a Regexp.\n    // Match entire URL / disallow partial matches.\n    // Flags are reset (i.e. no global, ignoreCase or multiline)\n    return new RegExp('^' + matcher.source + '$');\n  } else {\n    throw $sceMinErr('imatcher',\n        'Matchers may only be \"self\", string patterns or RegExp objects');\n  }\n}\n\n\nfunction adjustMatchers(matchers) {\n  var adjustedMatchers = [];\n  if (isDefined(matchers)) {\n    forEach(matchers, function(matcher) {\n      adjustedMatchers.push(adjustMatcher(matcher));\n    });\n  }\n  return adjustedMatchers;\n}\n\n\n/**\n * @ngdoc service\n * @name $sceDelegate\n * @kind function\n *\n * @description\n *\n * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict\n * Contextual Escaping (SCE)} services to AngularJS.\n *\n * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of\n * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is\n * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to\n * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things\n * work because `$sce` delegates to `$sceDelegate` for these operations.\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.\n *\n * The default instance of `$sceDelegate` should work out of the box with little pain.  While you\n * can override it completely to change the behavior of `$sce`, the common case would\n * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting\n * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as\n * templates.  Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist\n * $sceDelegateProvider.resourceUrlWhitelist} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n */\n\n/**\n * @ngdoc provider\n * @name $sceDelegateProvider\n * @description\n *\n * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate\n * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure\n * that the URLs used for sourcing Angular templates are safe.  Refer {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and\n * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}\n *\n * For the general details about this service in Angular, read the main page for {@link ng.$sce\n * Strict Contextual Escaping (SCE)}.\n *\n * **Example**:  Consider the following case. <a name=\"example\"></a>\n *\n * - your app is hosted at url `http://myapp.example.com/`\n * - but some of your templates are hosted on other domains you control such as\n *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.\n * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.\n *\n * Here is what a secure configuration for this scenario might look like:\n *\n * ```\n *  angular.module('myApp', []).config(function($sceDelegateProvider) {\n *    $sceDelegateProvider.resourceUrlWhitelist([\n *      // Allow same origin resource loads.\n *      'self',\n *      // Allow loading from our assets domain.  Notice the difference between * and **.\n *      'http://srv*.assets.example.com/**'\n *    ]);\n *\n *    // The blacklist overrides the whitelist so the open redirect here is blocked.\n *    $sceDelegateProvider.resourceUrlBlacklist([\n *      'http://myapp.example.com/clickThru**'\n *    ]);\n *  });\n * ```\n */\n\nfunction $SceDelegateProvider() {\n  this.SCE_CONTEXTS = SCE_CONTEXTS;\n\n  // Resource URLs can also be trusted by policy.\n  var resourceUrlWhitelist = ['self'],\n      resourceUrlBlacklist = [];\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlWhitelist\n   * @kind function\n   *\n   * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     Note: **an empty whitelist array will block all URLs**!\n   *\n   * @return {Array} the currently set whitelist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is `['self']` allowing only\n   * same origin resource requests.\n   *\n   * @description\n   * Sets/Gets the whitelist of trusted resource URLs.\n   */\n  this.resourceUrlWhitelist = function (value) {\n    if (arguments.length) {\n      resourceUrlWhitelist = adjustMatchers(value);\n    }\n    return resourceUrlWhitelist;\n  };\n\n  /**\n   * @ngdoc method\n   * @name $sceDelegateProvider#resourceUrlBlacklist\n   * @kind function\n   *\n   * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value\n   *     provided.  This must be an array or null.  A snapshot of this array is used so further\n   *     changes to the array are ignored.\n   *\n   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items\n   *     allowed in this array.\n   *\n   *     The typical usage for the blacklist is to **block\n   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as\n   *     these would otherwise be trusted but actually return content from the redirected domain.\n   *\n   *     Finally, **the blacklist overrides the whitelist** and has the final say.\n   *\n   * @return {Array} the currently set blacklist array.\n   *\n   * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there\n   * is no blacklist.)\n   *\n   * @description\n   * Sets/Gets the blacklist of trusted resource URLs.\n   */\n\n  this.resourceUrlBlacklist = function (value) {\n    if (arguments.length) {\n      resourceUrlBlacklist = adjustMatchers(value);\n    }\n    return resourceUrlBlacklist;\n  };\n\n  this.$get = ['$injector', function($injector) {\n\n    var htmlSanitizer = function htmlSanitizer(html) {\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    };\n\n    if ($injector.has('$sanitize')) {\n      htmlSanitizer = $injector.get('$sanitize');\n    }\n\n\n    function matchUrl(matcher, parsedUrl) {\n      if (matcher === 'self') {\n        return urlIsSameOrigin(parsedUrl);\n      } else {\n        // definitely a regex.  See adjustMatchers()\n        return !!matcher.exec(parsedUrl.href);\n      }\n    }\n\n    function isResourceUrlAllowedByPolicy(url) {\n      var parsedUrl = urlResolve(url.toString());\n      var i, n, allowed = false;\n      // Ensure that at least one item from the whitelist allows this url.\n      for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {\n        if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {\n          allowed = true;\n          break;\n        }\n      }\n      if (allowed) {\n        // Ensure that no item from the blacklist blocked this url.\n        for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {\n          if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {\n            allowed = false;\n            break;\n          }\n        }\n      }\n      return allowed;\n    }\n\n    function generateHolderType(Base) {\n      var holderType = function TrustedValueHolderType(trustedValue) {\n        this.$$unwrapTrustedValue = function() {\n          return trustedValue;\n        };\n      };\n      if (Base) {\n        holderType.prototype = new Base();\n      }\n      holderType.prototype.valueOf = function sceValueOf() {\n        return this.$$unwrapTrustedValue();\n      };\n      holderType.prototype.toString = function sceToString() {\n        return this.$$unwrapTrustedValue().toString();\n      };\n      return holderType;\n    }\n\n    var trustedValueHolderBase = generateHolderType(),\n        byType = {};\n\n    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);\n    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#trustAs\n     *\n     * @description\n     * Returns an object that is trusted by angular for use in specified strict\n     * contextual escaping contexts (such as ng-bind-html, ng-include, any src\n     * attribute interpolation, any dom event binding attribute interpolation\n     * such as for onclick,  etc.) that uses the provided value.\n     * See {@link ng.$sce $sce} for enabling strict contextual escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resourceUrl, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n    function trustAs(type, trustedValue) {\n      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (!Constructor) {\n        throw $sceMinErr('icontext',\n            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',\n            type, trustedValue);\n      }\n      if (trustedValue === null || trustedValue === undefined || trustedValue === '') {\n        return trustedValue;\n      }\n      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting\n      // mutable objects, we ensure here that the value passed in is actually a string.\n      if (typeof trustedValue !== 'string') {\n        throw $sceMinErr('itype',\n            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',\n            type);\n      }\n      return new Constructor(trustedValue);\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#valueOf\n     *\n     * @description\n     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs\n     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.\n     *\n     * If the passed parameter is not a value that had been returned by {@link\n     * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.\n     *\n     * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}\n     *      call or anything else.\n     * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns\n     *     `value` unchanged.\n     */\n    function valueOf(maybeTrusted) {\n      if (maybeTrusted instanceof trustedValueHolderBase) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      } else {\n        return maybeTrusted;\n      }\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sceDelegate#getTrusted\n     *\n     * @description\n     * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and\n     * returns the originally supplied value if the queried context type is a supertype of the\n     * created type.  If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} call.\n     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs\n     *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.\n     */\n    function getTrusted(type, maybeTrusted) {\n      if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {\n        return maybeTrusted;\n      }\n      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);\n      if (constructor && maybeTrusted instanceof constructor) {\n        return maybeTrusted.$$unwrapTrustedValue();\n      }\n      // If we get here, then we may only take one of two actions.\n      // 1. sanitize the value for the requested type, or\n      // 2. throw an exception.\n      if (type === SCE_CONTEXTS.RESOURCE_URL) {\n        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {\n          return maybeTrusted;\n        } else {\n          throw $sceMinErr('insecurl',\n              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',\n              maybeTrusted.toString());\n        }\n      } else if (type === SCE_CONTEXTS.HTML) {\n        return htmlSanitizer(maybeTrusted);\n      }\n      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');\n    }\n\n    return { trustAs: trustAs,\n             getTrusted: getTrusted,\n             valueOf: valueOf };\n  }];\n}\n\n\n/**\n * @ngdoc provider\n * @name $sceProvider\n * @description\n *\n * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.\n * -   enable/disable Strict Contextual Escaping (SCE) in a module\n * -   override the default implementation with a custom delegate\n *\n * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.\n */\n\n/* jshint maxlen: false*/\n\n/**\n * @ngdoc service\n * @name $sce\n * @kind function\n *\n * @description\n *\n * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.\n *\n * # Strict Contextual Escaping\n *\n * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain\n * contexts to result in a value that is marked as safe to use for that context.  One example of\n * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer\n * to these contexts as privileged or SCE contexts.\n *\n * As of version 1.2, Angular ships with SCE enabled by default.\n *\n * Note:  When enabled (the default), IE8 in quirks mode is not supported.  In this mode, IE8 allows\n * one to execute arbitrary javascript by the use of the expression() syntax.  Refer\n * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.\n * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`\n * to the top of your HTML document.\n *\n * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for\n * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.\n *\n * Here's an example of a binding in a privileged context:\n *\n * ```\n * <input ng-model=\"userHtml\">\n * <div ng-bind-html=\"userHtml\"></div>\n * ```\n *\n * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE\n * disabled, this application allows the user to render arbitrary HTML into the DIV.\n * In a more realistic example, one may be rendering user comments, blog articles, etc. via\n * bindings.  (HTML is just one example of a context where rendering user controlled input creates\n * security vulnerabilities.)\n *\n * For the case of HTML, you might use a library, either on the client side, or on the server side,\n * to sanitize unsafe HTML before binding to the value and rendering it in the document.\n *\n * How would you ensure that every place that used these types of bindings was bound to a value that\n * was sanitized by your library (or returned as safe for rendering by your server?)  How can you\n * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some\n * properties/fields and forgot to update the binding to the sanitized value?\n *\n * To be secure by default, you want to ensure that any such bindings are disallowed unless you can\n * determine that something explicitly says it's safe to use a value for binding in that\n * context.  You can then audit your code (a simple grep would do) to ensure that this is only done\n * for those values that you can easily tell are safe - because they were received from your server,\n * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps\n * allowing only the files in a specific directory to do this.  Ensuring that the internal API\n * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.\n *\n * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}\n * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to\n * obtain values that will be accepted by SCE / privileged contexts.\n *\n *\n * ## How does it work?\n *\n * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted\n * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link\n * ng.$sce#parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the\n * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.\n *\n * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link\n * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly\n * simplified):\n *\n * ```\n * var ngBindHtmlDirective = ['$sce', function($sce) {\n *   return function(scope, element, attr) {\n *     scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {\n *       element.html(value || '');\n *     });\n *   };\n * }];\n * ```\n *\n * ## Impact on loading templates\n *\n * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as\n * `templateUrl`'s specified by {@link guide/directive directives}.\n *\n * By default, Angular only loads templates from the same domain and protocol as the application\n * document.  This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or\n * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist\n * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.\n *\n * *Please note*:\n * The browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy apply in addition to this and may further restrict whether the template is successfully\n * loaded.  This means that without the right CORS policy, loading templates from a different domain\n * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some\n * browsers.\n *\n * ## This feels like too much overhead for the developer?\n *\n * It's important to remember that SCE only applies to interpolation expressions.\n *\n * If your expressions are constant literals, they're automatically trusted and you don't need to\n * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.\n * `<div ng-bind-html=\"'<b>implicitly trusted</b>'\"></div>`) just works.\n *\n * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them\n * through {@link ng.$sce#getTrusted $sce.getTrusted}.  SCE doesn't play a role here.\n *\n * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load\n * templates in `ng-include` from your application's domain without having to even know about SCE.\n * It blocks loading templates from other domains or loading templates over http from an https\n * served document.  You can change these by setting your own custom {@link\n * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link\n * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.\n *\n * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an\n * application that's secure and can be audited to verify that with much more ease than bolting\n * security onto an application later.\n *\n * <a name=\"contexts\"></a>\n * ## What trusted context types are supported?\n *\n * | Context             | Notes          |\n * |---------------------|----------------|\n * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |\n * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |\n * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |\n * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |\n * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |\n *\n * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name=\"resourceUrlPatternItem\"></a>\n *\n *  Each element in these arrays must be one of the following:\n *\n *  - **'self'**\n *    - The special **string**, `'self'`, can be used to match against all URLs of the **same\n *      domain** as the application document using the **same protocol**.\n *  - **String** (except the special value `'self'`)\n *    - The string is matched against the full *normalized / absolute URL* of the resource\n *      being tested (substring matches are not good enough.)\n *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters\n *      match themselves.\n *    - `*`: matches zero or more occurrences of any character other than one of the following 6\n *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'.  It's a useful wildcard for use\n *      in a whitelist.\n *    - `**`: matches zero or more occurrences of *any* character.  As such, it's not\n *      not appropriate to use in for a scheme, domain, etc. as it would match too much.  (e.g.\n *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might\n *      not have been the intention.)  Its usage at the very end of the path is ok.  (e.g.\n *      http://foo.example.com/templates/**).\n *  - **RegExp** (*see caveat below*)\n *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax\n *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to\n *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should\n *      have good test coverage.).  For instance, the use of `.` in the regex is correct only in a\n *      small number of cases.  A `.` character in the regex used when matching the scheme or a\n *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It\n *      is highly recommended to use the string patterns and only fall back to regular expressions\n *      if they as a last resort.\n *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is\n *      matched against the **entire** *normalized / absolute URL* of the resource being tested\n *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags\n *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.\n *    - If you are generating your JavaScript from some other templating engine (not\n *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),\n *      remember to escape your regular expression (and be aware that you might need more than\n *      one level of escaping depending on your templating engine and the way you interpolated\n *      the value.)  Do make use of your platform's escaping mechanism as it might be good\n *      enough before coding your own.  e.g. Ruby has\n *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)\n *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).\n *      Javascript lacks a similar built in function for escaping.  Take a look at Google\n *      Closure library's [goog.string.regExpEscape(s)](\n *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).\n *\n * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.\n *\n * ## Show me an example using SCE.\n *\n * <example module=\"mySceApp\" deps=\"angular-sanitize.js\">\n * <file name=\"index.html\">\n *   <div ng-controller=\"myAppController as myCtrl\">\n *     <i ng-bind-html=\"myCtrl.explicitlyTrustedHtml\" id=\"explicitlyTrustedHtml\"></i><br><br>\n *     <b>User comments</b><br>\n *     By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when\n *     $sanitize is available.  If $sanitize isn't available, this results in an error instead of an\n *     exploit.\n *     <div class=\"well\">\n *       <div ng-repeat=\"userComment in myCtrl.userComments\">\n *         <b>{{userComment.name}}</b>:\n *         <span ng-bind-html=\"userComment.htmlComment\" class=\"htmlComment\"></span>\n *         <br>\n *       </div>\n *     </div>\n *   </div>\n * </file>\n *\n * <file name=\"script.js\">\n *   var mySceApp = angular.module('mySceApp', ['ngSanitize']);\n *\n *   mySceApp.controller(\"myAppController\", function myAppController($http, $templateCache, $sce) {\n *     var self = this;\n *     $http.get(\"test_data.json\", {cache: $templateCache}).success(function(userComments) {\n *       self.userComments = userComments;\n *     });\n *     self.explicitlyTrustedHtml = $sce.trustAsHtml(\n *         '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *         'sanitization.&quot;\">Hover over this text.</span>');\n *   });\n * </file>\n *\n * <file name=\"test_data.json\">\n * [\n *   { \"name\": \"Alice\",\n *     \"htmlComment\":\n *         \"<span onmouseover='this.textContent=\\\"PWN3D!\\\"'>Is <i>anyone</i> reading this?</span>\"\n *   },\n *   { \"name\": \"Bob\",\n *     \"htmlComment\": \"<i>Yes!</i>  Am I the only other one?\"\n *   }\n * ]\n * </file>\n *\n * <file name=\"protractor.js\" type=\"protractor\">\n *   describe('SCE doc demo', function() {\n *     it('should sanitize untrusted values', function() {\n *       expect(element.all(by.css('.htmlComment')).first().getInnerHtml())\n *           .toBe('<span>Is <i>anyone</i> reading this?</span>');\n *     });\n *\n *     it('should NOT sanitize explicitly trusted values', function() {\n *       expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(\n *           '<span onmouseover=\"this.textContent=&quot;Explicitly trusted HTML bypasses ' +\n *           'sanitization.&quot;\">Hover over this text.</span>');\n *     });\n *   });\n * </file>\n * </example>\n *\n *\n *\n * ## Can I disable SCE completely?\n *\n * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits\n * for little coding overhead.  It will be much harder to take an SCE disabled application and\n * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE\n * for cases where you have a lot of existing code that was written before SCE was introduced and\n * you're migrating them a module at a time.\n *\n * That said, here's how you can completely disable SCE:\n *\n * ```\n * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {\n *   // Completely disable SCE.  For demonstration purposes only!\n *   // Do not use in new projects.\n *   $sceProvider.enabled(false);\n * });\n * ```\n *\n */\n/* jshint maxlen: 100 */\n\nfunction $SceProvider() {\n  var enabled = true;\n\n  /**\n   * @ngdoc method\n   * @name $sceProvider#enabled\n   * @kind function\n   *\n   * @param {boolean=} value If provided, then enables/disables SCE.\n   * @return {boolean} true if SCE is enabled, false otherwise.\n   *\n   * @description\n   * Enables/disables SCE and returns the current value.\n   */\n  this.enabled = function (value) {\n    if (arguments.length) {\n      enabled = !!value;\n    }\n    return enabled;\n  };\n\n\n  /* Design notes on the default implementation for SCE.\n   *\n   * The API contract for the SCE delegate\n   * -------------------------------------\n   * The SCE delegate object must provide the following 3 methods:\n   *\n   * - trustAs(contextEnum, value)\n   *     This method is used to tell the SCE service that the provided value is OK to use in the\n   *     contexts specified by contextEnum.  It must return an object that will be accepted by\n   *     getTrusted() for a compatible contextEnum and return this value.\n   *\n   * - valueOf(value)\n   *     For values that were not produced by trustAs(), return them as is.  For values that were\n   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if\n   *     trustAs is wrapping the given values into some type, this operation unwraps it when given\n   *     such a value.\n   *\n   * - getTrusted(contextEnum, value)\n   *     This function should return the a value that is safe to use in the context specified by\n   *     contextEnum or throw and exception otherwise.\n   *\n   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be\n   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For\n   * instance, an implementation could maintain a registry of all trusted objects by context.  In\n   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would\n   * return the same object passed in if it was found in the registry under a compatible context or\n   * throw an exception otherwise.  An implementation might only wrap values some of the time based\n   * on some criteria.  getTrusted() might return a value and not throw an exception for special\n   * constants or objects even if not wrapped.  All such implementations fulfill this contract.\n   *\n   *\n   * A note on the inheritance model for SCE contexts\n   * ------------------------------------------------\n   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This\n   * is purely an implementation details.\n   *\n   * The contract is simply this:\n   *\n   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)\n   *     will also succeed.\n   *\n   * Inheritance happens to capture this in a natural way.  In some future, we\n   * may not use inheritance anymore.  That is OK because no code outside of\n   * sce.js and sceSpecs.js would need to be aware of this detail.\n   */\n\n  this.$get = ['$parse', '$sniffer', '$sceDelegate', function(\n                $parse,   $sniffer,   $sceDelegate) {\n    // Prereq: Ensure that we're not running in IE8 quirks mode.  In that mode, IE allows\n    // the \"expression(javascript expression)\" syntax which is insecure.\n    if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) {\n      throw $sceMinErr('iequirks',\n        'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +\n        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +\n        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');\n    }\n\n    var sce = shallowCopy(SCE_CONTEXTS);\n\n    /**\n     * @ngdoc method\n     * @name $sce#isEnabled\n     * @kind function\n     *\n     * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you\n     * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.\n     *\n     * @description\n     * Returns a boolean indicating if SCE is enabled.\n     */\n    sce.isEnabled = function () {\n      return enabled;\n    };\n    sce.trustAs = $sceDelegate.trustAs;\n    sce.getTrusted = $sceDelegate.getTrusted;\n    sce.valueOf = $sceDelegate.valueOf;\n\n    if (!enabled) {\n      sce.trustAs = sce.getTrusted = function(type, value) { return value; };\n      sce.valueOf = identity;\n    }\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAs\n     *\n     * @description\n     * Converts Angular {@link guide/expression expression} into a function.  This is like {@link\n     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it\n     * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,\n     * *result*)}\n     *\n     * @param {string} type The kind of SCE context in which this result will be used.\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n    sce.parseAs = function sceParseAs(type, expr) {\n      var parsed = $parse(expr);\n      if (parsed.literal && parsed.constant) {\n        return parsed;\n      } else {\n        return function sceParseAsTrusted(self, locals) {\n          return sce.getTrusted(type, parsed(self, locals));\n        };\n      }\n    };\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAs\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.  As such,\n     * returns an object that is trusted by angular for use in specified strict contextual\n     * escaping contexts (such as ng-bind-html, ng-include, any src attribute\n     * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)\n     * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual\n     * escaping.\n     *\n     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,\n     *   resource_url, html, js and css.\n     * @param {*} value The value that that should be considered trusted/safe.\n     * @returns {*} A value that can be used to stand in for the provided `value` in places\n     * where Angular expects a $sce.trustAs() return value.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsHtml(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml\n     *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl\n     *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl\n     *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the return\n     *     value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#trustAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.trustAsJs(value)` →\n     *     {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}\n     *\n     * @param {*} value The value to trustAs.\n     * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs\n     *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives\n     *     only accept expressions that are either literal constants or are the\n     *     return value of {@link ng.$sce#trustAs $sce.trustAs}.)\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrusted\n     *\n     * @description\n     * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}.  As such,\n     * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the\n     * originally supplied value if the queried context type is a supertype of the created type.\n     * If this condition isn't satisfied, throws an exception.\n     *\n     * @param {string} type The kind of context in which this value is to be used.\n     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}\n     *                         call.\n     * @returns {*} The value the was originally provided to\n     *              {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.\n     *              Otherwise, throws an exception.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedHtml(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedCss\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedCss(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}\n     *\n     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#getTrustedJs\n     *\n     * @description\n     * Shorthand method.  `$sce.getTrustedJs(value)` →\n     *     {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}\n     *\n     * @param {*} value The value to pass to `$sce.getTrusted`.\n     * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsHtml\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsHtml(expression string)` →\n     *     {@link ng.$sce#parse `$sce.parseAs($sce.HTML, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsCss\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsCss(value)` →\n     *     {@link ng.$sce#parse `$sce.parseAs($sce.CSS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsUrl(value)` →\n     *     {@link ng.$sce#parse `$sce.parseAs($sce.URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsResourceUrl\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →\n     *     {@link ng.$sce#parse `$sce.parseAs($sce.RESOURCE_URL, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    /**\n     * @ngdoc method\n     * @name $sce#parseAsJs\n     *\n     * @description\n     * Shorthand method.  `$sce.parseAsJs(value)` →\n     *     {@link ng.$sce#parse `$sce.parseAs($sce.JS, value)`}\n     *\n     * @param {string} expression String expression to compile.\n     * @returns {function(context, locals)} a function which represents the compiled expression:\n     *\n     *    * `context` – `{object}` – an object against which any expressions embedded in the strings\n     *      are evaluated against (typically a scope object).\n     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in\n     *      `context`.\n     */\n\n    // Shorthand delegations.\n    var parse = sce.parseAs,\n        getTrusted = sce.getTrusted,\n        trustAs = sce.trustAs;\n\n    forEach(SCE_CONTEXTS, function (enumValue, name) {\n      var lName = lowercase(name);\n      sce[camelCase(\"parse_as_\" + lName)] = function (expr) {\n        return parse(enumValue, expr);\n      };\n      sce[camelCase(\"get_trusted_\" + lName)] = function (value) {\n        return getTrusted(enumValue, value);\n      };\n      sce[camelCase(\"trust_as_\" + lName)] = function (value) {\n        return trustAs(enumValue, value);\n      };\n    });\n\n    return sce;\n  }];\n}\n\n/**\n * !!! This is an undocumented \"private\" service !!!\n *\n * @name $sniffer\n * @requires $window\n * @requires $document\n *\n * @property {boolean} history Does the browser support html5 history api ?\n * @property {boolean} hashchange Does the browser support hashchange event ?\n * @property {boolean} transitions Does the browser support CSS transition events ?\n * @property {boolean} animations Does the browser support CSS animation events ?\n *\n * @description\n * This is very simple implementation of testing browser's features.\n */\nfunction $SnifferProvider() {\n  this.$get = ['$window', '$document', function($window, $document) {\n    var eventSupport = {},\n        android =\n          int((/android (\\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),\n        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),\n        document = $document[0] || {},\n        documentMode = document.documentMode,\n        vendorPrefix,\n        vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,\n        bodyStyle = document.body && document.body.style,\n        transitions = false,\n        animations = false,\n        match;\n\n    if (bodyStyle) {\n      for(var prop in bodyStyle) {\n        if(match = vendorRegex.exec(prop)) {\n          vendorPrefix = match[0];\n          vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);\n          break;\n        }\n      }\n\n      if(!vendorPrefix) {\n        vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';\n      }\n\n      transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));\n      animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));\n\n      if (android && (!transitions||!animations)) {\n        transitions = isString(document.body.style.webkitTransition);\n        animations = isString(document.body.style.webkitAnimation);\n      }\n    }\n\n\n    return {\n      // Android has history.pushState, but it does not update location correctly\n      // so let's not use the history API at all.\n      // http://code.google.com/p/android/issues/detail?id=17471\n      // https://github.com/angular/angular.js/issues/904\n\n      // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has\n      // so let's not use the history API also\n      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined\n      // jshint -W018\n      history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),\n      // jshint +W018\n      hashchange: 'onhashchange' in $window &&\n                  // IE8 compatible mode lies\n                  (!documentMode || documentMode > 7),\n      hasEvent: function(event) {\n        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have\n        // it. In particular the event is not fired when backspace or delete key are pressed or\n        // when cut operation is performed.\n        if (event == 'input' && msie == 9) return false;\n\n        if (isUndefined(eventSupport[event])) {\n          var divElm = document.createElement('div');\n          eventSupport[event] = 'on' + event in divElm;\n        }\n\n        return eventSupport[event];\n      },\n      csp: csp(),\n      vendorPrefix: vendorPrefix,\n      transitions : transitions,\n      animations : animations,\n      android: android,\n      msie : msie,\n      msieDocumentMode: documentMode\n    };\n  }];\n}\n\nfunction $TimeoutProvider() {\n  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',\n       function($rootScope,   $browser,   $q,   $exceptionHandler) {\n    var deferreds = {};\n\n\n     /**\n      * @ngdoc service\n      * @name $timeout\n      *\n      * @description\n      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch\n      * block and delegates any exceptions to\n      * {@link ng.$exceptionHandler $exceptionHandler} service.\n      *\n      * The return value of registering a timeout function is a promise, which will be resolved when\n      * the timeout is reached and the timeout function is executed.\n      *\n      * To cancel a timeout request, call `$timeout.cancel(promise)`.\n      *\n      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to\n      * synchronously flush the queue of deferred functions.\n      *\n      * @param {function()} fn A function, whose execution should be delayed.\n      * @param {number=} [delay=0] Delay in milliseconds.\n      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise\n      *   will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.\n      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this\n      *   promise will be resolved with is the return value of the `fn` function.\n      *\n      */\n    function timeout(fn, delay, invokeApply) {\n      var deferred = $q.defer(),\n          promise = deferred.promise,\n          skipApply = (isDefined(invokeApply) && !invokeApply),\n          timeoutId;\n\n      timeoutId = $browser.defer(function() {\n        try {\n          deferred.resolve(fn());\n        } catch(e) {\n          deferred.reject(e);\n          $exceptionHandler(e);\n        }\n        finally {\n          delete deferreds[promise.$$timeoutId];\n        }\n\n        if (!skipApply) $rootScope.$apply();\n      }, delay);\n\n      promise.$$timeoutId = timeoutId;\n      deferreds[timeoutId] = deferred;\n\n      return promise;\n    }\n\n\n     /**\n      * @ngdoc method\n      * @name $timeout#cancel\n      *\n      * @description\n      * Cancels a task associated with the `promise`. As a result of this, the promise will be\n      * resolved with a rejection.\n      *\n      * @param {Promise=} promise Promise returned by the `$timeout` function.\n      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully\n      *   canceled.\n      */\n    timeout.cancel = function(promise) {\n      if (promise && promise.$$timeoutId in deferreds) {\n        deferreds[promise.$$timeoutId].reject('canceled');\n        delete deferreds[promise.$$timeoutId];\n        return $browser.defer.cancel(promise.$$timeoutId);\n      }\n      return false;\n    };\n\n    return timeout;\n  }];\n}\n\n// NOTE:  The usage of window and document instead of $window and $document here is\n// deliberate.  This service depends on the specific behavior of anchor nodes created by the\n// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and\n// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it\n// doesn't know about mocked locations and resolves URLs to the real document - which is\n// exactly the behavior needed here.  There is little value is mocking these out for this\n// service.\nvar urlParsingNode = document.createElement(\"a\");\nvar originUrl = urlResolve(window.location.href, true);\n\n\n/**\n *\n * Implementation Notes for non-IE browsers\n * ----------------------------------------\n * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,\n * results both in the normalizing and parsing of the URL.  Normalizing means that a relative\n * URL will be resolved into an absolute URL in the context of the application document.\n * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related\n * properties are all populated to reflect the normalized URL.  This approach has wide\n * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See\n * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *\n * Implementation Notes for IE\n * ---------------------------\n * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other\n * browsers.  However, the parsed components will not be set if the URL assigned did not specify\n * them.  (e.g. if you assign a.href = \"foo\", then a.protocol, a.host, etc. will be empty.)  We\n * work around that by performing the parsing in a 2nd step by taking a previously normalized\n * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the\n * properties such as protocol, hostname, port, etc.\n *\n * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one\n * uses the inner HTML approach to assign the URL as part of an HTML snippet -\n * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL.\n * Unfortunately, setting img[src] to something like \"javascript:foo\" on IE throws an exception.\n * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that\n * method and IE < 8 is unsupported.\n *\n * References:\n *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement\n *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html\n *   http://url.spec.whatwg.org/#urlutils\n *   https://github.com/angular/angular.js/pull/2902\n *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/\n *\n * @kind function\n * @param {string} url The URL to be parsed.\n * @description Normalizes and parses a URL.\n * @returns {object} Returns the normalized URL as a dictionary.\n *\n *   | member name   | Description    |\n *   |---------------|----------------|\n *   | href          | A normalized version of the provided URL if it was not an absolute URL |\n *   | protocol      | The protocol including the trailing colon                              |\n *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |\n *   | search        | The search params, minus the question mark                             |\n *   | hash          | The hash string, minus the hash symbol\n *   | hostname      | The hostname\n *   | port          | The port, without \":\"\n *   | pathname      | The pathname, beginning with \"/\"\n *\n */\nfunction urlResolve(url, base) {\n  var href = url;\n\n  if (msie) {\n    // Normalize before parse.  Refer Implementation Notes on why this is\n    // done in two steps on IE.\n    urlParsingNode.setAttribute(\"href\", href);\n    href = urlParsingNode.href;\n  }\n\n  urlParsingNode.setAttribute('href', href);\n\n  // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n  return {\n    href: urlParsingNode.href,\n    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n    host: urlParsingNode.host,\n    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n    hostname: urlParsingNode.hostname,\n    port: urlParsingNode.port,\n    pathname: (urlParsingNode.pathname.charAt(0) === '/')\n      ? urlParsingNode.pathname\n      : '/' + urlParsingNode.pathname\n  };\n}\n\n/**\n * Parse a request URL and determine whether this is a same-origin request as the application document.\n *\n * @param {string|object} requestUrl The url of the request as a string that will be resolved\n * or a parsed URL object.\n * @returns {boolean} Whether the request is for the same origin as the application document.\n */\nfunction urlIsSameOrigin(requestUrl) {\n  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;\n  return (parsed.protocol === originUrl.protocol &&\n          parsed.host === originUrl.host);\n}\n\n/**\n * @ngdoc service\n * @name $window\n *\n * @description\n * A reference to the browser's `window` object. While `window`\n * is globally available in JavaScript, it causes testability problems, because\n * it is a global variable. In angular we always refer to it through the\n * `$window` service, so it may be overridden, removed or mocked for testing.\n *\n * Expressions, like the one defined for the `ngClick` directive in the example\n * below, are evaluated with respect to the current scope.  Therefore, there is\n * no risk of inadvertently coding in a dependency on a global value in such an\n * expression.\n *\n * @example\n   <example module=\"windowExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('windowExample', [])\n           .controller('ExampleController', ['$scope', '$window', function ($scope, $window) {\n             $scope.greeting = 'Hello, World!';\n             $scope.doGreeting = function(greeting) {\n               $window.alert(greeting);\n             };\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"text\" ng-model=\"greeting\" />\n         <button ng-click=\"doGreeting(greeting)\">ALERT</button>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n      it('should display the greeting in the input box', function() {\n       element(by.model('greeting')).sendKeys('Hello, E2E Tests');\n       // If we click the button it will block the test runner\n       // element(':button').click();\n      });\n     </file>\n   </example>\n */\nfunction $WindowProvider(){\n  this.$get = valueFn(window);\n}\n\n/* global currencyFilter: true,\n dateFilter: true,\n filterFilter: true,\n jsonFilter: true,\n limitToFilter: true,\n lowercaseFilter: true,\n numberFilter: true,\n orderByFilter: true,\n uppercaseFilter: true,\n */\n\n/**\n * @ngdoc provider\n * @name $filterProvider\n * @description\n *\n * Filters are just functions which transform input to an output. However filters need to be\n * Dependency Injected. To achieve this a filter definition consists of a factory function which is\n * annotated with dependencies and is responsible for creating a filter function.\n *\n * ```js\n *   // Filter registration\n *   function MyModule($provide, $filterProvider) {\n *     // create a service to demonstrate injection (not always needed)\n *     $provide.value('greet', function(name){\n *       return 'Hello ' + name + '!';\n *     });\n *\n *     // register a filter factory which uses the\n *     // greet service to demonstrate DI.\n *     $filterProvider.register('greet', function(greet){\n *       // return the filter function which uses the greet service\n *       // to generate salutation\n *       return function(text) {\n *         // filters need to be forgiving so check input validity\n *         return text && greet(text) || text;\n *       };\n *     });\n *   }\n * ```\n *\n * The filter function is registered with the `$injector` under the filter name suffix with\n * `Filter`.\n *\n * ```js\n *   it('should be the same instance', inject(\n *     function($filterProvider) {\n *       $filterProvider.register('reverse', function(){\n *         return ...;\n *       });\n *     },\n *     function($filter, reverseFilter) {\n *       expect($filter('reverse')).toBe(reverseFilter);\n *     });\n * ```\n *\n *\n * For more information about how angular filters work, and how to create your own filters, see\n * {@link guide/filter Filters} in the Angular Developer Guide.\n */\n\n/**\n * @ngdoc service\n * @name $filter\n * @kind function\n * @description\n * Filters are used for formatting data displayed to the user.\n *\n * The general syntax in templates is as follows:\n *\n *         {{ expression [| filter_name[:parameter_value] ... ] }}\n *\n * @param {String} name Name of the filter function to retrieve\n * @return {Function} the filter function\n * @example\n   <example name=\"$filter\" module=\"filterExample\">\n     <file name=\"index.html\">\n       <div ng-controller=\"MainCtrl\">\n        <h3>{{ originalText }}</h3>\n        <h3>{{ filteredText }}</h3>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n      angular.module('filterExample', [])\n      .controller('MainCtrl', function($scope, $filter) {\n        $scope.originalText = 'hello';\n        $scope.filteredText = $filter('uppercase')($scope.originalText);\n      });\n     </file>\n   </example>\n  */\n$FilterProvider.$inject = ['$provide'];\nfunction $FilterProvider($provide) {\n  var suffix = 'Filter';\n\n  /**\n   * @ngdoc method\n   * @name $filterProvider#register\n   * @param {string|Object} name Name of the filter function, or an object map of filters where\n   *    the keys are the filter names and the values are the filter factories.\n   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map\n   *    of the registered filter instances.\n   */\n  function register(name, factory) {\n    if(isObject(name)) {\n      var filters = {};\n      forEach(name, function(filter, key) {\n        filters[key] = register(key, filter);\n      });\n      return filters;\n    } else {\n      return $provide.factory(name + suffix, factory);\n    }\n  }\n  this.register = register;\n\n  this.$get = ['$injector', function($injector) {\n    return function(name) {\n      return $injector.get(name + suffix);\n    };\n  }];\n\n  ////////////////////////////////////////\n\n  /* global\n    currencyFilter: false,\n    dateFilter: false,\n    filterFilter: false,\n    jsonFilter: false,\n    limitToFilter: false,\n    lowercaseFilter: false,\n    numberFilter: false,\n    orderByFilter: false,\n    uppercaseFilter: false,\n  */\n\n  register('currency', currencyFilter);\n  register('date', dateFilter);\n  register('filter', filterFilter);\n  register('json', jsonFilter);\n  register('limitTo', limitToFilter);\n  register('lowercase', lowercaseFilter);\n  register('number', numberFilter);\n  register('orderBy', orderByFilter);\n  register('uppercase', uppercaseFilter);\n}\n\n/**\n * @ngdoc filter\n * @name filter\n * @kind function\n *\n * @description\n * Selects a subset of items from `array` and returns it as a new array.\n *\n * @param {Array} array The source array.\n * @param {string|Object|function()} expression The predicate to be used for selecting items from\n *   `array`.\n *\n *   Can be one of:\n *\n *   - `string`: The string is evaluated as an expression and the resulting value is used for substring match against\n *     the contents of the `array`. All strings or objects with string properties in `array` that contain this string\n *     will be returned. The predicate can be negated by prefixing the string with `!`.\n *\n *   - `Object`: A pattern object can be used to filter specific properties on objects contained\n *     by `array`. For example `{name:\"M\", phone:\"1\"}` predicate will return an array of items\n *     which have property `name` containing \"M\" and property `phone` containing \"1\". A special\n *     property name `$` can be used (as in `{$:\"text\"}`) to accept a match against any\n *     property of the object. That's equivalent to the simple substring match with a `string`\n *     as described above. The predicate can be negated by prefixing the string with `!`.\n *     For Example `{name: \"!M\"}` predicate will return an array of items which have property `name`\n *     not containing \"M\".\n *\n *   - `function(value)`: A predicate function can be used to write arbitrary filters. The function is\n *     called for each element of `array`. The final result is an array of those elements that\n *     the predicate returned true for.\n *\n * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in\n *     determining if the expected value (from the filter expression) and actual value (from\n *     the object in the array) should be considered a match.\n *\n *   Can be one of:\n *\n *   - `function(actual, expected)`:\n *     The function will be given the object value and the predicate value to compare and\n *     should return true if the item should be included in filtered result.\n *\n *   - `true`: A shorthand for `function(actual, expected) { return angular.equals(expected, actual)}`.\n *     this is essentially strict comparison of expected and actual.\n *\n *   - `false|undefined`: A short hand for a function which will look for a substring match in case\n *     insensitive way.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <div ng-init=\"friends = [{name:'John', phone:'555-1276'},\n                                {name:'Mary', phone:'800-BIG-MARY'},\n                                {name:'Mike', phone:'555-4321'},\n                                {name:'Adam', phone:'555-5678'},\n                                {name:'Julie', phone:'555-8765'},\n                                {name:'Juliette', phone:'555-5678'}]\"></div>\n\n       Search: <input ng-model=\"searchText\">\n       <table id=\"searchTextResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friend in friends | filter:searchText\">\n           <td>{{friend.name}}</td>\n           <td>{{friend.phone}}</td>\n         </tr>\n       </table>\n       <hr>\n       Any: <input ng-model=\"search.$\"> <br>\n       Name only <input ng-model=\"search.name\"><br>\n       Phone only <input ng-model=\"search.phone\"><br>\n       Equality <input type=\"checkbox\" ng-model=\"strict\"><br>\n       <table id=\"searchObjResults\">\n         <tr><th>Name</th><th>Phone</th></tr>\n         <tr ng-repeat=\"friendObj in friends | filter:search:strict\">\n           <td>{{friendObj.name}}</td>\n           <td>{{friendObj.phone}}</td>\n         </tr>\n       </table>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var expectFriendNames = function(expectedNames, key) {\n         element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {\n           arr.forEach(function(wd, i) {\n             expect(wd.getText()).toMatch(expectedNames[i]);\n           });\n         });\n       };\n\n       it('should search across all fields when filtering with a string', function() {\n         var searchText = element(by.model('searchText'));\n         searchText.clear();\n         searchText.sendKeys('m');\n         expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');\n\n         searchText.clear();\n         searchText.sendKeys('76');\n         expectFriendNames(['John', 'Julie'], 'friend');\n       });\n\n       it('should search in specific fields when filtering with a predicate object', function() {\n         var searchAny = element(by.model('search.$'));\n         searchAny.clear();\n         searchAny.sendKeys('i');\n         expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');\n       });\n       it('should use a equal comparison when comparator is true', function() {\n         var searchName = element(by.model('search.name'));\n         var strict = element(by.model('strict'));\n         searchName.clear();\n         searchName.sendKeys('Julie');\n         strict.click();\n         expectFriendNames(['Julie'], 'friendObj');\n       });\n     </file>\n   </example>\n */\nfunction filterFilter() {\n  return function(array, expression, comparator) {\n    if (!isArray(array)) return array;\n\n    var comparatorType = typeof(comparator),\n        predicates = [];\n\n    predicates.check = function(value) {\n      for (var j = 0; j < predicates.length; j++) {\n        if(!predicates[j](value)) {\n          return false;\n        }\n      }\n      return true;\n    };\n\n    if (comparatorType !== 'function') {\n      if (comparatorType === 'boolean' && comparator) {\n        comparator = function(obj, text) {\n          return angular.equals(obj, text);\n        };\n      } else {\n        comparator = function(obj, text) {\n          if (obj && text && typeof obj === 'object' && typeof text === 'object') {\n            for (var objKey in obj) {\n              if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&\n                  comparator(obj[objKey], text[objKey])) {\n                return true;\n              }\n            }\n            return false;\n          }\n          text = (''+text).toLowerCase();\n          return (''+obj).toLowerCase().indexOf(text) > -1;\n        };\n      }\n    }\n\n    var search = function(obj, text){\n      if (typeof text === 'string' && text.charAt(0) === '!') {\n        return !search(obj, text.substr(1));\n      }\n      switch (typeof obj) {\n        case 'boolean':\n        case 'number':\n        case 'string':\n          return comparator(obj, text);\n        case 'object':\n          switch (typeof text) {\n            case 'object':\n              return comparator(obj, text);\n            default:\n              for ( var objKey in obj) {\n                if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {\n                  return true;\n                }\n              }\n              break;\n          }\n          return false;\n        case 'array':\n          for ( var i = 0; i < obj.length; i++) {\n            if (search(obj[i], text)) {\n              return true;\n            }\n          }\n          return false;\n        default:\n          return false;\n      }\n    };\n    switch (typeof expression) {\n      case 'boolean':\n      case 'number':\n      case 'string':\n        // Set up expression object and fall through\n        expression = {$:expression};\n        // jshint -W086\n      case 'object':\n        // jshint +W086\n        for (var key in expression) {\n          (function(path) {\n            if (typeof expression[path] === 'undefined') return;\n            predicates.push(function(value) {\n              return search(path == '$' ? value : (value && value[path]), expression[path]);\n            });\n          })(key);\n        }\n        break;\n      case 'function':\n        predicates.push(expression);\n        break;\n      default:\n        return array;\n    }\n    var filtered = [];\n    for ( var j = 0; j < array.length; j++) {\n      var value = array[j];\n      if (predicates.check(value)) {\n        filtered.push(value);\n      }\n    }\n    return filtered;\n  };\n}\n\n/**\n * @ngdoc filter\n * @name currency\n * @kind function\n *\n * @description\n * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default\n * symbol for current locale is used.\n *\n * @param {number} amount Input to filter.\n * @param {string=} symbol Currency symbol or identifier to be displayed.\n * @returns {string} Formatted number.\n *\n *\n * @example\n   <example module=\"currencyExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('currencyExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.amount = 1234.56;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input type=\"number\" ng-model=\"amount\"> <br>\n         default currency symbol ($): <span id=\"currency-default\">{{amount | currency}}</span><br>\n         custom currency identifier (USD$): <span>{{amount | currency:\"USD$\"}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should init with 1234.56', function() {\n         expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');\n         expect(element(by.binding('amount | currency:\"USD$\"')).getText()).toBe('USD$1,234.56');\n       });\n       it('should update', function() {\n         if (browser.params.browser == 'safari') {\n           // Safari does not understand the minus key. See\n           // https://github.com/angular/protractor/issues/481\n           return;\n         }\n         element(by.model('amount')).clear();\n         element(by.model('amount')).sendKeys('-1234');\n         expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');\n         expect(element(by.binding('amount | currency:\"USD$\"')).getText()).toBe('(USD$1,234.00)');\n       });\n     </file>\n   </example>\n */\ncurrencyFilter.$inject = ['$locale'];\nfunction currencyFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(amount, currencySymbol){\n    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;\n    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).\n                replace(/\\u00A4/g, currencySymbol);\n  };\n}\n\n/**\n * @ngdoc filter\n * @name number\n * @kind function\n *\n * @description\n * Formats a number as text.\n *\n * If the input is not a number an empty string is returned.\n *\n * @param {number|string} number Number to format.\n * @param {(number|string)=} fractionSize Number of decimal places to round the number to.\n * If this is not provided then the fraction size is computed from the current locale's number\n * formatting pattern. In the case of the default locale, it will be 3.\n * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.\n *\n * @example\n   <example module=\"numberFilterExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('numberFilterExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.val = 1234.56789;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter number: <input ng-model='val'><br>\n         Default formatting: <span id='number-default'>{{val | number}}</span><br>\n         No fractions: <span>{{val | number:0}}</span><br>\n         Negative number: <span>{{-val | number:4}}</span>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format numbers', function() {\n         expect(element(by.id('number-default')).getText()).toBe('1,234.568');\n         expect(element(by.binding('val | number:0')).getText()).toBe('1,235');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');\n       });\n\n       it('should update', function() {\n         element(by.model('val')).clear();\n         element(by.model('val')).sendKeys('3374.333');\n         expect(element(by.id('number-default')).getText()).toBe('3,374.333');\n         expect(element(by.binding('val | number:0')).getText()).toBe('3,374');\n         expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');\n      });\n     </file>\n   </example>\n */\n\n\nnumberFilter.$inject = ['$locale'];\nfunction numberFilter($locale) {\n  var formats = $locale.NUMBER_FORMATS;\n  return function(number, fractionSize) {\n    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,\n      fractionSize);\n  };\n}\n\nvar DECIMAL_SEP = '.';\nfunction formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {\n  if (number == null || !isFinite(number) || isObject(number)) return '';\n\n  var isNegative = number < 0;\n  number = Math.abs(number);\n  var numStr = number + '',\n      formatedText = '',\n      parts = [];\n\n  var hasExponent = false;\n  if (numStr.indexOf('e') !== -1) {\n    var match = numStr.match(/([\\d\\.]+)e(-?)(\\d+)/);\n    if (match && match[2] == '-' && match[3] > fractionSize + 1) {\n      numStr = '0';\n      number = 0;\n    } else {\n      formatedText = numStr;\n      hasExponent = true;\n    }\n  }\n\n  if (!hasExponent) {\n    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;\n\n    // determine fractionSize if it is not specified\n    if (isUndefined(fractionSize)) {\n      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);\n    }\n\n    // safely round numbers in JS without hitting imprecisions of floating-point arithmetics\n    // inspired by:\n    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round\n    number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);\n\n    if (number === 0) {\n      isNegative = false;\n    }\n\n    var fraction = ('' + number).split(DECIMAL_SEP);\n    var whole = fraction[0];\n    fraction = fraction[1] || '';\n\n    var i, pos = 0,\n        lgroup = pattern.lgSize,\n        group = pattern.gSize;\n\n    if (whole.length >= (lgroup + group)) {\n      pos = whole.length - lgroup;\n      for (i = 0; i < pos; i++) {\n        if ((pos - i)%group === 0 && i !== 0) {\n          formatedText += groupSep;\n        }\n        formatedText += whole.charAt(i);\n      }\n    }\n\n    for (i = pos; i < whole.length; i++) {\n      if ((whole.length - i)%lgroup === 0 && i !== 0) {\n        formatedText += groupSep;\n      }\n      formatedText += whole.charAt(i);\n    }\n\n    // format fraction part.\n    while(fraction.length < fractionSize) {\n      fraction += '0';\n    }\n\n    if (fractionSize && fractionSize !== \"0\") formatedText += decimalSep + fraction.substr(0, fractionSize);\n  } else {\n\n    if (fractionSize > 0 && number > -1 && number < 1) {\n      formatedText = number.toFixed(fractionSize);\n    }\n  }\n\n  parts.push(isNegative ? pattern.negPre : pattern.posPre);\n  parts.push(formatedText);\n  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);\n  return parts.join('');\n}\n\nfunction padNumber(num, digits, trim) {\n  var neg = '';\n  if (num < 0) {\n    neg =  '-';\n    num = -num;\n  }\n  num = '' + num;\n  while(num.length < digits) num = '0' + num;\n  if (trim)\n    num = num.substr(num.length - digits);\n  return neg + num;\n}\n\n\nfunction dateGetter(name, size, offset, trim) {\n  offset = offset || 0;\n  return function(date) {\n    var value = date['get' + name]();\n    if (offset > 0 || value > -offset)\n      value += offset;\n    if (value === 0 && offset == -12 ) value = 12;\n    return padNumber(value, size, trim);\n  };\n}\n\nfunction dateStrGetter(name, shortForm) {\n  return function(date, formats) {\n    var value = date['get' + name]();\n    var get = uppercase(shortForm ? ('SHORT' + name) : name);\n\n    return formats[get][value];\n  };\n}\n\nfunction timeZoneGetter(date) {\n  var zone = -1 * date.getTimezoneOffset();\n  var paddedZone = (zone >= 0) ? \"+\" : \"\";\n\n  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +\n                padNumber(Math.abs(zone % 60), 2);\n\n  return paddedZone;\n}\n\nfunction ampmGetter(date, formats) {\n  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];\n}\n\nvar DATE_FORMATS = {\n  yyyy: dateGetter('FullYear', 4),\n    yy: dateGetter('FullYear', 2, 0, true),\n     y: dateGetter('FullYear', 1),\n  MMMM: dateStrGetter('Month'),\n   MMM: dateStrGetter('Month', true),\n    MM: dateGetter('Month', 2, 1),\n     M: dateGetter('Month', 1, 1),\n    dd: dateGetter('Date', 2),\n     d: dateGetter('Date', 1),\n    HH: dateGetter('Hours', 2),\n     H: dateGetter('Hours', 1),\n    hh: dateGetter('Hours', 2, -12),\n     h: dateGetter('Hours', 1, -12),\n    mm: dateGetter('Minutes', 2),\n     m: dateGetter('Minutes', 1),\n    ss: dateGetter('Seconds', 2),\n     s: dateGetter('Seconds', 1),\n     // while ISO 8601 requires fractions to be prefixed with `.` or `,`\n     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions\n   sss: dateGetter('Milliseconds', 3),\n  EEEE: dateStrGetter('Day'),\n   EEE: dateStrGetter('Day', true),\n     a: ampmGetter,\n     Z: timeZoneGetter\n};\n\nvar DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,\n    NUMBER_STRING = /^\\-?\\d+$/;\n\n/**\n * @ngdoc filter\n * @name date\n * @kind function\n *\n * @description\n *   Formats `date` to a string based on the requested `format`.\n *\n *   `format` string can be composed of the following elements:\n *\n *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)\n *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)\n *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)\n *   * `'MMMM'`: Month in year (January-December)\n *   * `'MMM'`: Month in year (Jan-Dec)\n *   * `'MM'`: Month in year, padded (01-12)\n *   * `'M'`: Month in year (1-12)\n *   * `'dd'`: Day in month, padded (01-31)\n *   * `'d'`: Day in month (1-31)\n *   * `'EEEE'`: Day in Week,(Sunday-Saturday)\n *   * `'EEE'`: Day in Week, (Sun-Sat)\n *   * `'HH'`: Hour in day, padded (00-23)\n *   * `'H'`: Hour in day (0-23)\n *   * `'hh'`: Hour in am/pm, padded (01-12)\n *   * `'h'`: Hour in am/pm, (1-12)\n *   * `'mm'`: Minute in hour, padded (00-59)\n *   * `'m'`: Minute in hour (0-59)\n *   * `'ss'`: Second in minute, padded (00-59)\n *   * `'s'`: Second in minute (0-59)\n *   * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)\n *   * `'a'`: am/pm marker\n *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)\n *\n *   `format` string can also be one of the following predefined\n *   {@link guide/i18n localizable formats}:\n *\n *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale\n *     (e.g. Sep 3, 2010 12:05:08 pm)\n *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)\n *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale\n *     (e.g. Friday, September 3, 2010)\n *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)\n *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)\n *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)\n *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)\n *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)\n *\n *   `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.\n *   `\"h 'in the morning'\"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence\n *   (e.g. `\"h 'o''clock'\"`).\n *\n * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or\n *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its\n *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is\n *    specified in the string input, the time is considered to be in the local timezone.\n * @param {string=} format Formatting rules (see Description). If not specified,\n *    `mediumDate` is used.\n * @returns {string} Formatted string or the input if input is not recognized as date/millis.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:\n           <span>{{1288323623006 | date:'medium'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:\n          <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:\n          <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>\n       <span ng-non-bindable>{{1288323623006 | date:\"MM/dd/yyyy 'at' h:mma\"}}</span>:\n          <span>{{'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"}}</span><br>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should format date', function() {\n         expect(element(by.binding(\"1288323623006 | date:'medium'\")).getText()).\n            toMatch(/Oct 2\\d, 2010 \\d{1,2}:\\d{2}:\\d{2} (AM|PM)/);\n         expect(element(by.binding(\"1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'\")).getText()).\n            toMatch(/2010\\-10\\-2\\d \\d{2}:\\d{2}:\\d{2} (\\-|\\+)?\\d{4}/);\n         expect(element(by.binding(\"'1288323623006' | date:'MM/dd/yyyy @ h:mma'\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 @ \\d{1,2}:\\d{2}(AM|PM)/);\n         expect(element(by.binding(\"'1288323623006' | date:\\\"MM/dd/yyyy 'at' h:mma\\\"\")).getText()).\n            toMatch(/10\\/2\\d\\/2010 at \\d{1,2}:\\d{2}(AM|PM)/);\n       });\n     </file>\n   </example>\n */\ndateFilter.$inject = ['$locale'];\nfunction dateFilter($locale) {\n\n\n  var R_ISO8601_STR = /^(\\d{4})-?(\\d\\d)-?(\\d\\d)(?:T(\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(?:\\.(\\d+))?)?)?(Z|([+-])(\\d\\d):?(\\d\\d))?)?$/;\n                     // 1        2       3         4          5          6          7          8  9     10      11\n  function jsonStringToDate(string) {\n    var match;\n    if (match = string.match(R_ISO8601_STR)) {\n      var date = new Date(0),\n          tzHour = 0,\n          tzMin  = 0,\n          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,\n          timeSetter = match[8] ? date.setUTCHours : date.setHours;\n\n      if (match[9]) {\n        tzHour = int(match[9] + match[10]);\n        tzMin = int(match[9] + match[11]);\n      }\n      dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));\n      var h = int(match[4]||0) - tzHour;\n      var m = int(match[5]||0) - tzMin;\n      var s = int(match[6]||0);\n      var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);\n      timeSetter.call(date, h, m, s, ms);\n      return date;\n    }\n    return string;\n  }\n\n\n  return function(date, format) {\n    var text = '',\n        parts = [],\n        fn, match;\n\n    format = format || 'mediumDate';\n    format = $locale.DATETIME_FORMATS[format] || format;\n    if (isString(date)) {\n      date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date);\n    }\n\n    if (isNumber(date)) {\n      date = new Date(date);\n    }\n\n    if (!isDate(date)) {\n      return date;\n    }\n\n    while(format) {\n      match = DATE_FORMATS_SPLIT.exec(format);\n      if (match) {\n        parts = concat(parts, match, 1);\n        format = parts.pop();\n      } else {\n        parts.push(format);\n        format = null;\n      }\n    }\n\n    forEach(parts, function(value){\n      fn = DATE_FORMATS[value];\n      text += fn ? fn(date, $locale.DATETIME_FORMATS)\n                 : value.replace(/(^'|'$)/g, '').replace(/''/g, \"'\");\n    });\n\n    return text;\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name json\n * @kind function\n *\n * @description\n *   Allows you to convert a JavaScript object into JSON string.\n *\n *   This filter is mostly useful for debugging. When using the double curly {{value}} notation\n *   the binding is automatically converted to JSON.\n *\n * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.\n * @returns {string} JSON string.\n *\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <pre>{{ {'name':'value'} | json }}</pre>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should jsonify filtered objects', function() {\n         expect(element(by.binding(\"{'name':'value'}\")).getText()).toMatch(/\\{\\n  \"name\": ?\"value\"\\n}/);\n       });\n     </file>\n   </example>\n *\n */\nfunction jsonFilter() {\n  return function(object) {\n    return toJson(object, true);\n  };\n}\n\n\n/**\n * @ngdoc filter\n * @name lowercase\n * @kind function\n * @description\n * Converts string to lowercase.\n * @see angular.lowercase\n */\nvar lowercaseFilter = valueFn(lowercase);\n\n\n/**\n * @ngdoc filter\n * @name uppercase\n * @kind function\n * @description\n * Converts string to uppercase.\n * @see angular.uppercase\n */\nvar uppercaseFilter = valueFn(uppercase);\n\n/**\n * @ngdoc filter\n * @name limitTo\n * @kind function\n *\n * @description\n * Creates a new array or string containing only a specified number of elements. The elements\n * are taken from either the beginning or the end of the source array or string, as specified by\n * the value and sign (positive or negative) of `limit`.\n *\n * @param {Array|string} input Source array or string to be limited.\n * @param {string|number} limit The length of the returned array or string. If the `limit` number\n *     is positive, `limit` number of items from the beginning of the source array/string are copied.\n *     If the number is negative, `limit` number  of items from the end of the source array/string\n *     are copied. The `limit` will be trimmed if it exceeds `array.length`\n * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array\n *     had less than `limit` elements.\n *\n * @example\n   <example module=\"limitToExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('limitToExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.numbers = [1,2,3,4,5,6,7,8,9];\n             $scope.letters = \"abcdefghi\";\n             $scope.numLimit = 3;\n             $scope.letterLimit = 3;\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Limit {{numbers}} to: <input type=\"number\" step=\"1\" ng-model=\"numLimit\">\n         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>\n         Limit {{letters}} to: <input type=\"number\" step=\"1\" ng-model=\"letterLimit\">\n         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var numLimitInput = element(by.model('numLimit'));\n       var letterLimitInput = element(by.model('letterLimit'));\n       var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));\n       var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));\n\n       it('should limit the number array to first three items', function() {\n         expect(numLimitInput.getAttribute('value')).toBe('3');\n         expect(letterLimitInput.getAttribute('value')).toBe('3');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abc');\n       });\n\n       // There is a bug in safari and protractor that doesn't like the minus key\n       // it('should update the output when -3 is entered', function() {\n       //   numLimitInput.clear();\n       //   numLimitInput.sendKeys('-3');\n       //   letterLimitInput.clear();\n       //   letterLimitInput.sendKeys('-3');\n       //   expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');\n       //   expect(limitedLetters.getText()).toEqual('Output letters: ghi');\n       // });\n\n       it('should not exceed the maximum size of input array', function() {\n         numLimitInput.clear();\n         numLimitInput.sendKeys('100');\n         letterLimitInput.clear();\n         letterLimitInput.sendKeys('100');\n         expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');\n         expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');\n       });\n     </file>\n   </example>\n */\nfunction limitToFilter(){\n  return function(input, limit) {\n    if (!isArray(input) && !isString(input)) return input;\n\n    if (Math.abs(Number(limit)) === Infinity) {\n      limit = Number(limit);\n    } else {\n      limit = int(limit);\n    }\n\n    if (isString(input)) {\n      //NaN check on limit\n      if (limit) {\n        return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);\n      } else {\n        return \"\";\n      }\n    }\n\n    var out = [],\n      i, n;\n\n    // if abs(limit) exceeds maximum length, trim it\n    if (limit > input.length)\n      limit = input.length;\n    else if (limit < -input.length)\n      limit = -input.length;\n\n    if (limit > 0) {\n      i = 0;\n      n = limit;\n    } else {\n      i = input.length + limit;\n      n = input.length;\n    }\n\n    for (; i<n; i++) {\n      out.push(input[i]);\n    }\n\n    return out;\n  };\n}\n\n/**\n * @ngdoc filter\n * @name orderBy\n * @kind function\n *\n * @description\n * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically\n * for strings and numerically for numbers. Note: if you notice numbers are not being sorted\n * correctly, make sure they are actually being saved as numbers and not strings.\n *\n * @param {Array} array The array to sort.\n * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be\n *    used by the comparator to determine the order of elements.\n *\n *    Can be one of:\n *\n *    - `function`: Getter function. The result of this function will be sorted using the\n *      `<`, `=`, `>` operator.\n *    - `string`: An Angular expression. The result of this expression is used to compare elements\n *      (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by\n *      3 first characters of a property called `name`). The result of a constant expression\n *      is interpreted as a property name to be used in comparisons (for example `\"special name\"`\n *      to sort object by the value of their `special name` property). An expression can be\n *      optionally prefixed with `+` or `-` to control ascending or descending sort order\n *      (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array\n *      element itself is used to compare where sorting.\n *    - `Array`: An array of function or string predicates. The first predicate in the array\n *      is used for sorting, but when two items are equivalent, the next predicate is used.\n *\n *    If the predicate is missing or empty then it defaults to `'+'`.\n *\n * @param {boolean=} reverse Reverse the order of the array.\n * @returns {Array} Sorted copy of the source array.\n *\n * @example\n   <example module=\"orderByExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('orderByExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.friends =\n                 [{name:'John', phone:'555-1212', age:10},\n                  {name:'Mary', phone:'555-9876', age:19},\n                  {name:'Mike', phone:'555-4321', age:21},\n                  {name:'Adam', phone:'555-5678', age:35},\n                  {name:'Julie', phone:'555-8765', age:29}];\n             $scope.predicate = '-age';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>\n         <hr/>\n         [ <a href=\"\" ng-click=\"predicate=''\">unsorted</a> ]\n         <table class=\"friend\">\n           <tr>\n             <th><a href=\"\" ng-click=\"predicate = 'name'; reverse=false\">Name</a>\n                 (<a href=\"\" ng-click=\"predicate = '-name'; reverse=false\">^</a>)</th>\n             <th><a href=\"\" ng-click=\"predicate = 'phone'; reverse=!reverse\">Phone Number</a></th>\n             <th><a href=\"\" ng-click=\"predicate = 'age'; reverse=!reverse\">Age</a></th>\n           </tr>\n           <tr ng-repeat=\"friend in friends | orderBy:predicate:reverse\">\n             <td>{{friend.name}}</td>\n             <td>{{friend.phone}}</td>\n             <td>{{friend.age}}</td>\n           </tr>\n         </table>\n       </div>\n     </file>\n   </example>\n *\n * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the\n * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the\n * desired parameters.\n *\n * Example:\n *\n * @example\n  <example module=\"orderByExample\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <table class=\"friend\">\n          <tr>\n            <th><a href=\"\" ng-click=\"reverse=false;order('name', false)\">Name</a>\n              (<a href=\"\" ng-click=\"order('-name',false)\">^</a>)</th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('phone', reverse)\">Phone Number</a></th>\n            <th><a href=\"\" ng-click=\"reverse=!reverse;order('age',reverse)\">Age</a></th>\n          </tr>\n          <tr ng-repeat=\"friend in friends\">\n            <td>{{friend.name}}</td>\n            <td>{{friend.phone}}</td>\n            <td>{{friend.age}}</td>\n          </tr>\n        </table>\n      </div>\n    </file>\n\n    <file name=\"script.js\">\n      angular.module('orderByExample', [])\n        .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {\n          var orderBy = $filter('orderBy');\n          $scope.friends = [\n            { name: 'John',    phone: '555-1212',    age: 10 },\n            { name: 'Mary',    phone: '555-9876',    age: 19 },\n            { name: 'Mike',    phone: '555-4321',    age: 21 },\n            { name: 'Adam',    phone: '555-5678',    age: 35 },\n            { name: 'Julie',   phone: '555-8765',    age: 29 }\n          ];\n          $scope.order = function(predicate, reverse) {\n            $scope.friends = orderBy($scope.friends, predicate, reverse);\n          };\n          $scope.order('-age',false);\n        }]);\n    </file>\n</example>\n */\norderByFilter.$inject = ['$parse'];\nfunction orderByFilter($parse){\n  return function(array, sortPredicate, reverseOrder) {\n    if (!(isArrayLike(array))) return array;\n    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];\n    if (sortPredicate.length === 0) { sortPredicate = ['+']; }\n    sortPredicate = map(sortPredicate, function(predicate){\n      var descending = false, get = predicate || identity;\n      if (isString(predicate)) {\n        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {\n          descending = predicate.charAt(0) == '-';\n          predicate = predicate.substring(1);\n        }\n        if ( predicate === '' ) {\n          // Effectively no predicate was passed so we compare identity\n          return reverseComparator(function(a,b) {\n            return compare(a, b);\n          }, descending);\n        }\n        get = $parse(predicate);\n        if (get.constant) {\n          var key = get();\n          return reverseComparator(function(a,b) {\n            return compare(a[key], b[key]);\n          }, descending);\n        }\n      }\n      return reverseComparator(function(a,b){\n        return compare(get(a),get(b));\n      }, descending);\n    });\n    return slice.call(array).sort(reverseComparator(comparator, reverseOrder));\n\n    function comparator(o1, o2){\n      for ( var i = 0; i < sortPredicate.length; i++) {\n        var comp = sortPredicate[i](o1, o2);\n        if (comp !== 0) return comp;\n      }\n      return 0;\n    }\n    function reverseComparator(comp, descending) {\n      return toBoolean(descending)\n          ? function(a,b){return comp(b,a);}\n          : comp;\n    }\n    function compare(v1, v2){\n      var t1 = typeof v1;\n      var t2 = typeof v2;\n      if (t1 == t2) {\n        if (isDate(v1) && isDate(v2)) {\n          v1 = v1.valueOf();\n          v2 = v2.valueOf();\n        }\n        if (t1 == \"string\") {\n           v1 = v1.toLowerCase();\n           v2 = v2.toLowerCase();\n        }\n        if (v1 === v2) return 0;\n        return v1 < v2 ? -1 : 1;\n      } else {\n        return t1 < t2 ? -1 : 1;\n      }\n    }\n  };\n}\n\nfunction ngDirective(directive) {\n  if (isFunction(directive)) {\n    directive = {\n      link: directive\n    };\n  }\n  directive.restrict = directive.restrict || 'AC';\n  return valueFn(directive);\n}\n\n/**\n * @ngdoc directive\n * @name a\n * @restrict E\n *\n * @description\n * Modifies the default behavior of the html A tag so that the default action is prevented when\n * the href attribute is empty.\n *\n * This change permits the easy creation of action links with the `ngClick` directive\n * without changing the location or causing page reloads, e.g.:\n * `<a href=\"\" ng-click=\"list.addItem()\">Add Item</a>`\n */\nvar htmlAnchorDirective = valueFn({\n  restrict: 'E',\n  compile: function(element, attr) {\n\n    if (msie <= 8) {\n\n      // turn <a href ng-click=\"..\">link</a> into a stylable link in IE\n      // but only if it doesn't have name attribute, in which case it's an anchor\n      if (!attr.href && !attr.name) {\n        attr.$set('href', '');\n      }\n\n      // add a comment node to anchors to workaround IE bug that causes element content to be reset\n      // to new attribute content if attribute is updated with value containing @ and element also\n      // contains value with @\n      // see issue #1949\n      element.append(document.createComment('IE fix'));\n    }\n\n    if (!attr.href && !attr.xlinkHref && !attr.name) {\n      return function(scope, element) {\n        // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.\n        var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?\n                   'xlink:href' : 'href';\n        element.on('click', function(event){\n          // if we have no href url, then don't navigate anywhere.\n          if (!element.attr(href)) {\n            event.preventDefault();\n          }\n        });\n      };\n    }\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngHref\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in an href attribute will\n * make the link go to the wrong URL if the user clicks it before\n * Angular has a chance to replace the `{{hash}}` markup with its\n * value. Until Angular replaces the markup the link will be broken\n * and will most likely return a 404 error. The `ngHref` directive\n * solves this problem.\n *\n * The wrong way to write it:\n * ```html\n * <a href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <a ng-href=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * @element A\n * @param {template} ngHref any string which can contain `{{}}` markup.\n *\n * @example\n * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes\n * in links and their different behaviors:\n    <example>\n      <file name=\"index.html\">\n        <input ng-model=\"value\" /><br />\n        <a id=\"link-1\" href ng-click=\"value = 1\">link 1</a> (link, don't reload)<br />\n        <a id=\"link-2\" href=\"\" ng-click=\"value = 2\">link 2</a> (link, don't reload)<br />\n        <a id=\"link-3\" ng-href=\"/{{'123'}}\">link 3</a> (link, reload!)<br />\n        <a id=\"link-4\" href=\"\" name=\"xx\" ng-click=\"value = 4\">anchor</a> (link, don't reload)<br />\n        <a id=\"link-5\" name=\"xxx\" ng-click=\"value = 5\">anchor</a> (no link)<br />\n        <a id=\"link-6\" ng-href=\"{{value}}\">link</a> (link, change location)\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should execute ng-click but not reload when href without value', function() {\n          element(by.id('link-1')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('1');\n          expect(element(by.id('link-1')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when href empty string', function() {\n          element(by.id('link-2')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('2');\n          expect(element(by.id('link-2')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click and change url when ng-href specified', function() {\n          expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\\/123$/);\n\n          element(by.id('link-3')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/123$/);\n            });\n          }, 5000, 'page should navigate to /123');\n        });\n\n        xit('should execute ng-click but not reload when href empty string and name specified', function() {\n          element(by.id('link-4')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('4');\n          expect(element(by.id('link-4')).getAttribute('href')).toBe('');\n        });\n\n        it('should execute ng-click but not reload when no href but name specified', function() {\n          element(by.id('link-5')).click();\n          expect(element(by.model('value')).getAttribute('value')).toEqual('5');\n          expect(element(by.id('link-5')).getAttribute('href')).toBe(null);\n        });\n\n        it('should only change url when only ng-href', function() {\n          element(by.model('value')).clear();\n          element(by.model('value')).sendKeys('6');\n          expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\\/6$/);\n\n          element(by.id('link-6')).click();\n\n          // At this point, we navigate away from an Angular page, so we need\n          // to use browser.driver to get the base webdriver.\n          browser.wait(function() {\n            return browser.driver.getCurrentUrl().then(function(url) {\n              return url.match(/\\/6$/);\n            });\n          }, 5000, 'page should navigate to /6');\n        });\n      </file>\n    </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngSrc\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `src` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrc` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-src=\"http://www.gravatar.com/avatar/{{hash}}\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrc any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngSrcset\n * @restrict A\n * @priority 99\n *\n * @description\n * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't\n * work right: The browser will fetch from the URL with the literal\n * text `{{hash}}` until Angular replaces the expression inside\n * `{{hash}}`. The `ngSrcset` directive solves this problem.\n *\n * The buggy way to write it:\n * ```html\n * <img srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * The correct way to write it:\n * ```html\n * <img ng-srcset=\"http://www.gravatar.com/avatar/{{hash}} 2x\"/>\n * ```\n *\n * @element IMG\n * @param {template} ngSrcset any string which can contain `{{}}` markup.\n */\n\n/**\n * @ngdoc directive\n * @name ngDisabled\n * @restrict A\n * @priority 100\n *\n * @description\n *\n * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:\n * ```html\n * <div ng-init=\"scope = { isDisabled: false }\">\n *  <button disabled=\"{{scope.isDisabled}}\">Disabled</button>\n * </div>\n * ```\n *\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as disabled. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngDisabled` directive solves this problem for the `disabled` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Click me to toggle: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <button ng-model=\"button\" ng-disabled=\"checked\">Button</button>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle button', function() {\n          expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,\n *     then special attribute \"disabled\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngChecked\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as checked. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngChecked` directive solves this problem for the `checked` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to check both: <input type=\"checkbox\" ng-model=\"master\"><br/>\n        <input id=\"checkSlave\" type=\"checkbox\" ng-checked=\"master\">\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should check both checkBoxes', function() {\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();\n          element(by.model('master')).click();\n          expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,\n *     then special attribute \"checked\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngReadonly\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as readonly. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngReadonly` directive solves this problem for the `readonly` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to make text readonly: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n        <input type=\"text\" ng-readonly=\"checked\" value=\"I'm Angular\"/>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should toggle readonly attr', function() {\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeFalsy();\n          element(by.model('checked')).click();\n          expect(element(by.css('[type=\"text\"]')).getAttribute('readonly')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element INPUT\n * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,\n *     then special attribute \"readonly\" will be set on the element\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSelected\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as selected. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngSelected` directive solves this problem for the `selected` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        Check me to select: <input type=\"checkbox\" ng-model=\"selected\"><br/>\n        <select>\n          <option>Hello!</option>\n          <option id=\"greet\" ng-selected=\"selected\">Greetings!</option>\n        </select>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should select Greetings!', function() {\n          expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();\n          element(by.model('selected')).click();\n          expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();\n        });\n      </file>\n    </example>\n *\n * @element OPTION\n * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,\n *     then special attribute \"selected\" will be set on the element\n */\n\n/**\n * @ngdoc directive\n * @name ngOpen\n * @restrict A\n * @priority 100\n *\n * @description\n * The HTML specification does not require browsers to preserve the values of boolean attributes\n * such as open. (Their presence means true and their absence means false.)\n * If we put an Angular interpolation expression into such an attribute then the\n * binding information would be lost when the browser removes the attribute.\n * The `ngOpen` directive solves this problem for the `open` attribute.\n * This complementary directive is not removed by the browser and so provides\n * a permanent reliable place to store the binding information.\n * @example\n     <example>\n       <file name=\"index.html\">\n         Check me check multiple: <input type=\"checkbox\" ng-model=\"open\"><br/>\n         <details id=\"details\" ng-open=\"open\">\n            <summary>Show/Hide me</summary>\n         </details>\n       </file>\n       <file name=\"protractor.js\" type=\"protractor\">\n         it('should toggle open', function() {\n           expect(element(by.id('details')).getAttribute('open')).toBeFalsy();\n           element(by.model('open')).click();\n           expect(element(by.id('details')).getAttribute('open')).toBeTruthy();\n         });\n       </file>\n     </example>\n *\n * @element DETAILS\n * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,\n *     then special attribute \"open\" will be set on the element\n */\n\nvar ngAttributeAliasDirectives = {};\n\n\n// boolean attrs are evaluated\nforEach(BOOLEAN_ATTR, function(propName, attrName) {\n  // binding to multiple is not supported\n  if (propName == \"multiple\") return;\n\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 100,\n      link: function(scope, element, attr) {\n        scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {\n          attr.$set(attrName, !!value);\n        });\n      }\n    };\n  };\n});\n\n\n// ng-src, ng-srcset, ng-href are interpolated\nforEach(['src', 'srcset', 'href'], function(attrName) {\n  var normalized = directiveNormalize('ng-' + attrName);\n  ngAttributeAliasDirectives[normalized] = function() {\n    return {\n      priority: 99, // it needs to run after the attributes are interpolated\n      link: function(scope, element, attr) {\n        var propName = attrName,\n            name = attrName;\n\n        if (attrName === 'href' &&\n            toString.call(element.prop('href')) === '[object SVGAnimatedString]') {\n          name = 'xlinkHref';\n          attr.$attr[name] = 'xlink:href';\n          propName = null;\n        }\n\n        attr.$observe(normalized, function(value) {\n          if (!value) {\n            if (attrName === 'href') {\n              attr.$set(name, null);\n            }\n            return;\n          }\n\n          attr.$set(name, value);\n\n          // on IE, if \"ng:src\" directive declaration is used and \"src\" attribute doesn't exist\n          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need\n          // to set the property as well to achieve the desired effect.\n          // we use attr[attrName] value since $set can sanitize the url.\n          if (msie && propName) element.prop(propName, attr[name]);\n        });\n      }\n    };\n  };\n});\n\n/* global -nullFormCtrl */\nvar nullFormCtrl = {\n  $addControl: noop,\n  $removeControl: noop,\n  $setValidity: noop,\n  $setDirty: noop,\n  $setPristine: noop\n};\n\n/**\n * @ngdoc type\n * @name form.FormController\n *\n * @property {boolean} $pristine True if user has not interacted with the form yet.\n * @property {boolean} $dirty True if user has already interacted with the form.\n * @property {boolean} $valid True if all of the containing forms and controls are valid.\n * @property {boolean} $invalid True if at least one containing control or form is invalid.\n *\n * @property {Object} $error Is an object hash, containing references to all invalid controls or\n *  forms, where:\n *\n *  - keys are validation tokens (error names),\n *  - values are arrays of controls or forms that are invalid for given error name.\n *\n *\n *  Built-in validation tokens:\n *\n *  - `email`\n *  - `max`\n *  - `maxlength`\n *  - `min`\n *  - `minlength`\n *  - `number`\n *  - `pattern`\n *  - `required`\n *  - `url`\n *\n * @description\n * `FormController` keeps track of all its controls and nested forms as well as the state of them,\n * such as being valid/invalid or dirty/pristine.\n *\n * Each {@link ng.directive:form form} directive creates an instance\n * of `FormController`.\n *\n */\n//asks for $scope to fool the BC controller module\nFormController.$inject = ['$element', '$attrs', '$scope', '$animate'];\nfunction FormController(element, attrs, $scope, $animate) {\n  var form = this,\n      parentForm = element.parent().controller('form') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      errors = form.$error = {},\n      controls = [];\n\n  // init state\n  form.$name = attrs.name || attrs.ngForm;\n  form.$dirty = false;\n  form.$pristine = true;\n  form.$valid = true;\n  form.$invalid = false;\n\n  parentForm.$addControl(form);\n\n  // Setup initial state of the control\n  element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $animate.setClass(element,\n      (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey,\n      (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$addControl\n   *\n   * @description\n   * Register a control with the form.\n   *\n   * Input elements using ngModelController do this automatically when they are linked.\n   */\n  form.$addControl = function(control) {\n    // Breaking change - before, inputs whose name was \"hasOwnProperty\" were quietly ignored\n    // and not added to the scope.  Now we throw an error.\n    assertNotHasOwnProperty(control.$name, 'input');\n    controls.push(control);\n\n    if (control.$name) {\n      form[control.$name] = control;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$removeControl\n   *\n   * @description\n   * Deregister a control from the form.\n   *\n   * Input elements using ngModelController do this automatically when they are destroyed.\n   */\n  form.$removeControl = function(control) {\n    if (control.$name && form[control.$name] === control) {\n      delete form[control.$name];\n    }\n    forEach(errors, function(queue, validationToken) {\n      form.$setValidity(validationToken, true, control);\n    });\n\n    arrayRemove(controls, control);\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setValidity\n   *\n   * @description\n   * Sets the validity of a form control.\n   *\n   * This method will also propagate to parent forms.\n   */\n  form.$setValidity = function(validationToken, isValid, control) {\n    var queue = errors[validationToken];\n\n    if (isValid) {\n      if (queue) {\n        arrayRemove(queue, control);\n        if (!queue.length) {\n          invalidCount--;\n          if (!invalidCount) {\n            toggleValidCss(isValid);\n            form.$valid = true;\n            form.$invalid = false;\n          }\n          errors[validationToken] = false;\n          toggleValidCss(true, validationToken);\n          parentForm.$setValidity(validationToken, true, form);\n        }\n      }\n\n    } else {\n      if (!invalidCount) {\n        toggleValidCss(isValid);\n      }\n      if (queue) {\n        if (includes(queue, control)) return;\n      } else {\n        errors[validationToken] = queue = [];\n        invalidCount++;\n        toggleValidCss(false, validationToken);\n        parentForm.$setValidity(validationToken, false, form);\n      }\n      queue.push(control);\n\n      form.$valid = false;\n      form.$invalid = true;\n    }\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setDirty\n   *\n   * @description\n   * Sets the form to a dirty state.\n   *\n   * This method can be called to add the 'ng-dirty' class and set the form to a dirty\n   * state (ng-dirty class). This method will also propagate to parent forms.\n   */\n  form.$setDirty = function() {\n    $animate.removeClass(element, PRISTINE_CLASS);\n    $animate.addClass(element, DIRTY_CLASS);\n    form.$dirty = true;\n    form.$pristine = false;\n    parentForm.$setDirty();\n  };\n\n  /**\n   * @ngdoc method\n   * @name form.FormController#$setPristine\n   *\n   * @description\n   * Sets the form to its pristine state.\n   *\n   * This method can be called to remove the 'ng-dirty' class and set the form to its pristine\n   * state (ng-pristine class). This method will also propagate to all the controls contained\n   * in this form.\n   *\n   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after\n   * saving or resetting it.\n   */\n  form.$setPristine = function () {\n    $animate.removeClass(element, DIRTY_CLASS);\n    $animate.addClass(element, PRISTINE_CLASS);\n    form.$dirty = false;\n    form.$pristine = true;\n    forEach(controls, function(control) {\n      control.$setPristine();\n    });\n  };\n}\n\n\n/**\n * @ngdoc directive\n * @name ngForm\n * @restrict EAC\n *\n * @description\n * Nestable alias of {@link ng.directive:form `form`} directive. HTML\n * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a\n * sub-group of controls needs to be determined.\n *\n * Note: the purpose of `ngForm` is to group controls,\n * but not to be a replacement for the `<form>` tag with all of its capabilities\n * (e.g. posting to the server, ...).\n *\n * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n *\n */\n\n /**\n * @ngdoc directive\n * @name form\n * @restrict E\n *\n * @description\n * Directive that instantiates\n * {@link form.FormController FormController}.\n *\n * If the `name` attribute is specified, the form controller is published onto the current scope under\n * this name.\n *\n * # Alias: {@link ng.directive:ngForm `ngForm`}\n *\n * In Angular forms can be nested. This means that the outer form is valid when all of the child\n * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so\n * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to\n * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when\n * using Angular validation directives in forms that are dynamically generated using the\n * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`\n * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an\n * `ngForm` directive and nest these in an outer `form` element.\n *\n *\n * # CSS classes\n *  - `ng-valid` is set if the form is valid.\n *  - `ng-invalid` is set if the form is invalid.\n *  - `ng-pristine` is set if the form is pristine.\n *  - `ng-dirty` is set if the form is dirty.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n *\n * # Submitting a form and preventing the default action\n *\n * Since the role of forms in client-side Angular applications is different than in classical\n * roundtrip apps, it is desirable for the browser not to translate the form submission into a full\n * page reload that sends the data to the server. Instead some javascript logic should be triggered\n * to handle the form submission in an application-specific way.\n *\n * For this reason, Angular prevents the default action (form submission to the server) unless the\n * `<form>` element has an `action` attribute specified.\n *\n * You can use one of the following two ways to specify what javascript method should be called when\n * a form is submitted:\n *\n * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element\n * - {@link ng.directive:ngClick ngClick} directive on the first\n  *  button or input field of type submit (input[type=submit])\n *\n * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}\n * or {@link ng.directive:ngClick ngClick} directives.\n * This is because of the following form submission rules in the HTML specification:\n *\n * - If a form has only one input field then hitting enter in this field triggers form submit\n * (`ngSubmit`)\n * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter\n * doesn't trigger submit\n * - if a form has one or more input fields and one or more buttons or input[type=submit] then\n * hitting enter in any of the input fields will trigger the click handler on the *first* button or\n * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)\n *\n *\n * ## Animation Hooks\n *\n * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.\n * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any\n * other validations that are performed within the form. Animations in ngForm are similar to how\n * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well\n * as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style a form element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-form {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-form.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n    <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"formExample\">\n      <file name=\"index.html\">\n       <script>\n         angular.module('formExample', [])\n           .controller('FormController', ['$scope', function($scope) {\n             $scope.userType = 'guest';\n           }]);\n       </script>\n       <style>\n        .my-form {\n          -webkit-transition:all linear 0.5s;\n          transition:all linear 0.5s;\n          background: transparent;\n        }\n        .my-form.ng-invalid {\n          background: red;\n        }\n       </style>\n       <form name=\"myForm\" ng-controller=\"FormController\" class=\"my-form\">\n         userType: <input name=\"input\" ng-model=\"userType\" required>\n         <span class=\"error\" ng-show=\"myForm.input.$error.required\">Required!</span><br>\n         <tt>userType = {{userType}}</tt><br>\n         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>\n         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should initialize to model', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n\n          expect(userType.getText()).toContain('guest');\n          expect(valid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty', function() {\n          var userType = element(by.binding('userType'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var userInput = element(by.model('userType'));\n\n          userInput.clear();\n          userInput.sendKeys('');\n\n          expect(userType.getText()).toEqual('userType =');\n          expect(valid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n *\n * @param {string=} name Name of the form. If specified, the form controller will be published into\n *                       related scope, under this name.\n */\nvar formDirectiveFactory = function(isNgForm) {\n  return ['$timeout', function($timeout) {\n    var formDirective = {\n      name: 'form',\n      restrict: isNgForm ? 'EAC' : 'E',\n      controller: FormController,\n      compile: function() {\n        return {\n          pre: function(scope, formElement, attr, controller) {\n            if (!attr.action) {\n              // we can't use jq events because if a form is destroyed during submission the default\n              // action is not prevented. see #1238\n              //\n              // IE 9 is not affected because it doesn't fire a submit event and try to do a full\n              // page reload if the form was destroyed by submission of the form via a click handler\n              // on a button in the form. Looks like an IE9 specific bug.\n              var preventDefaultListener = function(event) {\n                event.preventDefault\n                  ? event.preventDefault()\n                  : event.returnValue = false; // IE\n              };\n\n              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n\n              // unregister the preventDefault listener so that we don't not leak memory but in a\n              // way that will achieve the prevention of the default action.\n              formElement.on('$destroy', function() {\n                $timeout(function() {\n                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);\n                }, 0, false);\n              });\n            }\n\n            var parentFormCtrl = formElement.parent().controller('form'),\n                alias = attr.name || attr.ngForm;\n\n            if (alias) {\n              setter(scope, alias, controller, alias);\n            }\n            if (parentFormCtrl) {\n              formElement.on('$destroy', function() {\n                parentFormCtrl.$removeControl(controller);\n                if (alias) {\n                  setter(scope, alias, undefined, alias);\n                }\n                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards\n              });\n            }\n          }\n        };\n      }\n    };\n\n    return formDirective;\n  }];\n};\n\nvar formDirective = formDirectiveFactory();\nvar ngFormDirective = formDirectiveFactory(true);\n\n/* global VALID_CLASS: true,\n    INVALID_CLASS: true,\n    PRISTINE_CLASS: true,\n    DIRTY_CLASS: true\n*/\n\nvar URL_REGEXP = /^(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?$/;\nvar EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;\nvar NUMBER_REGEXP = /^\\s*(\\-|\\+)?(\\d+|(\\d*(\\.\\d*)))\\s*$/;\n\nvar inputType = {\n\n  /**\n   * @ngdoc input\n   * @name input[text]\n   *\n   * @description\n   * Standard HTML text input with angular data binding, inherited by most of the `input` elements.\n   *\n   * *NOTE* Not every feature offered is available for all input types.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Adds `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n   *    This parameter is ignored for input[type=password] controls, which will never trim the\n   *    input.\n   *\n   * @example\n      <example name=\"text-input-directive\" module=\"textInputExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('textInputExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.text = 'guest';\n               $scope.word = /^\\s*\\w*\\s*$/;\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Single word: <input type=\"text\" name=\"input\" ng-model=\"text\"\n                               ng-pattern=\"word\" required ng-trim=\"false\">\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.pattern\">\n             Single word only!</span>\n\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('guest');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if multi word', function() {\n            input.clear();\n            input.sendKeys('hello world');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'text': textInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[number]\n   *\n   * @description\n   * Text input with number validation and transformation. Sets the `number` validation\n   * error if not a valid number.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.\n   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"number-input-directive\" module=\"numberExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('numberExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.value = 12;\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Number: <input type=\"number\" name=\"input\" ng-model=\"value\"\n                          min=\"0\" max=\"99\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.number\">\n             Not valid number!</span>\n           <tt>value = {{value}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var value = element(by.binding('value'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('value'));\n\n          it('should initialize to model', function() {\n            expect(value.getText()).toContain('12');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if over max', function() {\n            input.clear();\n            input.sendKeys('123');\n            expect(value.getText()).toEqual('value =');\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'number': numberInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[url]\n   *\n   * @description\n   * Text input with URL validation. Sets the `url` validation error key if the content is not a\n   * valid URL.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"url-input-directive\" module=\"urlExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('urlExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.text = 'http://google.com';\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           URL: <input type=\"url\" name=\"input\" ng-model=\"text\" required>\n           <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n             Required!</span>\n           <span class=\"error\" ng-show=\"myForm.input.$error.url\">\n             Not valid url!</span>\n           <tt>text = {{text}}</tt><br/>\n           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('http://google.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not url', function() {\n            input.clear();\n            input.sendKeys('box');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'url': urlInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[email]\n   *\n   * @description\n   * Text input with email validation. Sets the `email` validation error key if not a valid email\n   * address.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} required Sets `required` validation error key if the value is not entered.\n   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n   *    `required` when you want to data-bind to the `required` attribute.\n   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n   *    minlength.\n   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n   *    maxlength.\n   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n   *    patterns defined as scope expressions.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"email-input-directive\" module=\"emailExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('emailExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.text = 'me@example.com';\n             }]);\n         </script>\n           <form name=\"myForm\" ng-controller=\"ExampleController\">\n             Email: <input type=\"email\" name=\"input\" ng-model=\"text\" required>\n             <span class=\"error\" ng-show=\"myForm.input.$error.required\">\n               Required!</span>\n             <span class=\"error\" ng-show=\"myForm.input.$error.email\">\n               Not valid email!</span>\n             <tt>text = {{text}}</tt><br/>\n             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>\n             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>\n             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>\n           </form>\n         </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          var text = element(by.binding('text'));\n          var valid = element(by.binding('myForm.input.$valid'));\n          var input = element(by.model('text'));\n\n          it('should initialize to model', function() {\n            expect(text.getText()).toContain('me@example.com');\n            expect(valid.getText()).toContain('true');\n          });\n\n          it('should be invalid if empty', function() {\n            input.clear();\n            input.sendKeys('');\n            expect(text.getText()).toEqual('text =');\n            expect(valid.getText()).toContain('false');\n          });\n\n          it('should be invalid if not email', function() {\n            input.clear();\n            input.sendKeys('xxx');\n\n            expect(valid.getText()).toContain('false');\n          });\n        </file>\n      </example>\n   */\n  'email': emailInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[radio]\n   *\n   * @description\n   * HTML radio button.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string} value The value to which the expression should be set when selected.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   * @param {string} ngValue Angular expression which sets the value to which the expression should\n   *    be set when selected.\n   *\n   * @example\n      <example name=\"radio-input-directive\" module=\"radioExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('radioExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.color = 'blue';\n               $scope.specialValue = {\n                 \"id\": \"12345\",\n                 \"value\": \"green\"\n               };\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           <input type=\"radio\" ng-model=\"color\" value=\"red\">  Red <br/>\n           <input type=\"radio\" ng-model=\"color\" ng-value=\"specialValue\"> Green <br/>\n           <input type=\"radio\" ng-model=\"color\" value=\"blue\"> Blue <br/>\n           <tt>color = {{color | json}}</tt><br/>\n          </form>\n          Note that `ng-value=\"specialValue\"` sets radio item's value to be the value of `$scope.specialValue`.\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var color = element(by.binding('color'));\n\n            expect(color.getText()).toContain('blue');\n\n            element.all(by.model('color')).get(0).click();\n\n            expect(color.getText()).toContain('red');\n          });\n        </file>\n      </example>\n   */\n  'radio': radioInputType,\n\n\n  /**\n   * @ngdoc input\n   * @name input[checkbox]\n   *\n   * @description\n   * HTML checkbox.\n   *\n   * @param {string} ngModel Assignable angular expression to data-bind to.\n   * @param {string=} name Property name of the form under which the control is published.\n   * @param {string=} ngTrueValue The value to which the expression should be set when selected.\n   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.\n   * @param {string=} ngChange Angular expression to be executed when input changes due to user\n   *    interaction with the input element.\n   *\n   * @example\n      <example name=\"checkbox-input-directive\" module=\"checkboxExample\">\n        <file name=\"index.html\">\n         <script>\n           angular.module('checkboxExample', [])\n             .controller('ExampleController', ['$scope', function($scope) {\n               $scope.value1 = true;\n               $scope.value2 = 'YES'\n             }]);\n         </script>\n         <form name=\"myForm\" ng-controller=\"ExampleController\">\n           Value1: <input type=\"checkbox\" ng-model=\"value1\"> <br/>\n           Value2: <input type=\"checkbox\" ng-model=\"value2\"\n                          ng-true-value=\"YES\" ng-false-value=\"NO\"> <br/>\n           <tt>value1 = {{value1}}</tt><br/>\n           <tt>value2 = {{value2}}</tt><br/>\n          </form>\n        </file>\n        <file name=\"protractor.js\" type=\"protractor\">\n          it('should change state', function() {\n            var value1 = element(by.binding('value1'));\n            var value2 = element(by.binding('value2'));\n\n            expect(value1.getText()).toContain('true');\n            expect(value2.getText()).toContain('YES');\n\n            element(by.model('value1')).click();\n            element(by.model('value2')).click();\n\n            expect(value1.getText()).toContain('false');\n            expect(value2.getText()).toContain('NO');\n          });\n        </file>\n      </example>\n   */\n  'checkbox': checkboxInputType,\n\n  'hidden': noop,\n  'button': noop,\n  'submit': noop,\n  'reset': noop,\n  'file': noop\n};\n\n// A helper function to call $setValidity and return the value / undefined,\n// a pattern that is repeated a lot in the input validation logic.\nfunction validate(ctrl, validatorName, validity, value){\n  ctrl.$setValidity(validatorName, validity);\n  return validity ? value : undefined;\n}\n\nfunction testFlags(validity, flags) {\n  var i, flag;\n  if (flags) {\n    for (i=0; i<flags.length; ++i) {\n      flag = flags[i];\n      if (validity[flag]) {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n// Pass validity so that behaviour can be mocked easier.\nfunction addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreFlags, validity) {\n  if (isObject(validity)) {\n    ctrl.$$hasNativeValidators = true;\n    var validator = function(value) {\n      // Don't overwrite previous validation, don't consider valueMissing to apply (ng-required can\n      // perform the required validation)\n      if (!ctrl.$error[validatorName] &&\n          !testFlags(validity, ignoreFlags) &&\n          testFlags(validity, badFlags)) {\n        ctrl.$setValidity(validatorName, false);\n        return;\n      }\n      return value;\n    };\n    ctrl.$parsers.push(validator);\n  }\n}\n\nfunction textInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  var validity = element.prop(VALIDITY_STATE_PROPERTY);\n  var placeholder = element[0].placeholder, noevent = {};\n  var type = lowercase(element[0].type);\n  ctrl.$$validityState = validity;\n\n  // In composition mode, users are still inputing intermediate text buffer,\n  // hold the listener until composition is done.\n  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent\n  if (!$sniffer.android) {\n    var composing = false;\n\n    element.on('compositionstart', function(data) {\n      composing = true;\n    });\n\n    element.on('compositionend', function() {\n      composing = false;\n      listener();\n    });\n  }\n\n  var listener = function(ev) {\n    if (composing) return;\n    var value = element.val();\n\n    // IE (11 and under) seem to emit an 'input' event if the placeholder value changes.\n    // We don't want to dirty the value when this happens, so we abort here. Unfortunately,\n    // IE also sends input events for other non-input-related things, (such as focusing on a\n    // form control), so this change is not entirely enough to solve this.\n    if (msie && (ev || noevent).type === 'input' && element[0].placeholder !== placeholder) {\n      placeholder = element[0].placeholder;\n      return;\n    }\n\n    // By default we will trim the value\n    // If the attribute ng-trim exists we will avoid trimming\n    // If input type is 'password', the value is never trimmed\n    if (type !== 'password' && (toBoolean(attr.ngTrim || 'T'))) {\n      value = trim(value);\n    }\n\n    // If a control is suffering from bad input, browsers discard its value, so it may be\n    // necessary to revalidate even if the control's value is the same empty value twice in\n    // a row.\n    var revalidate = validity && ctrl.$$hasNativeValidators;\n    if (ctrl.$viewValue !== value || (value === '' && revalidate)) {\n      if (scope.$root.$$phase) {\n        ctrl.$setViewValue(value);\n      } else {\n        scope.$apply(function() {\n          ctrl.$setViewValue(value);\n        });\n      }\n    }\n  };\n\n  // if the browser does support \"input\" event, we are fine - except on IE9 which doesn't fire the\n  // input event on backspace, delete or cut\n  if ($sniffer.hasEvent('input')) {\n    element.on('input', listener);\n  } else {\n    var timeout;\n\n    var deferListener = function() {\n      if (!timeout) {\n        timeout = $browser.defer(function() {\n          listener();\n          timeout = null;\n        });\n      }\n    };\n\n    element.on('keydown', function(event) {\n      var key = event.keyCode;\n\n      // ignore\n      //    command            modifiers                   arrows\n      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;\n\n      deferListener();\n    });\n\n    // if user modifies input value using context menu in IE, we need \"paste\" and \"cut\" events to catch it\n    if ($sniffer.hasEvent('paste')) {\n      element.on('paste cut', deferListener);\n    }\n  }\n\n  // if user paste into input using mouse on older browser\n  // or form autocomplete on newer browser, we need \"change\" event to catch it\n  element.on('change', listener);\n\n  ctrl.$render = function() {\n    element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);\n  };\n\n  // pattern validator\n  var pattern = attr.ngPattern,\n      patternValidator,\n      match;\n\n  if (pattern) {\n    var validateRegex = function(regexp, value) {\n      return validate(ctrl, 'pattern', ctrl.$isEmpty(value) || regexp.test(value), value);\n    };\n    match = pattern.match(/^\\/(.*)\\/([gim]*)$/);\n    if (match) {\n      pattern = new RegExp(match[1], match[2]);\n      patternValidator = function(value) {\n        return validateRegex(pattern, value);\n      };\n    } else {\n      patternValidator = function(value) {\n        var patternObj = scope.$eval(pattern);\n\n        if (!patternObj || !patternObj.test) {\n          throw minErr('ngPattern')('noregexp',\n            'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern,\n            patternObj, startingTag(element));\n        }\n        return validateRegex(patternObj, value);\n      };\n    }\n\n    ctrl.$formatters.push(patternValidator);\n    ctrl.$parsers.push(patternValidator);\n  }\n\n  // min length validator\n  if (attr.ngMinlength) {\n    var minlength = int(attr.ngMinlength);\n    var minLengthValidator = function(value) {\n      return validate(ctrl, 'minlength', ctrl.$isEmpty(value) || value.length >= minlength, value);\n    };\n\n    ctrl.$parsers.push(minLengthValidator);\n    ctrl.$formatters.push(minLengthValidator);\n  }\n\n  // max length validator\n  if (attr.ngMaxlength) {\n    var maxlength = int(attr.ngMaxlength);\n    var maxLengthValidator = function(value) {\n      return validate(ctrl, 'maxlength', ctrl.$isEmpty(value) || value.length <= maxlength, value);\n    };\n\n    ctrl.$parsers.push(maxLengthValidator);\n    ctrl.$formatters.push(maxLengthValidator);\n  }\n}\n\nvar numberBadFlags = ['badInput'];\n\nfunction numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  ctrl.$parsers.push(function(value) {\n    var empty = ctrl.$isEmpty(value);\n    if (empty || NUMBER_REGEXP.test(value)) {\n      ctrl.$setValidity('number', true);\n      return value === '' ? null : (empty ? value : parseFloat(value));\n    } else {\n      ctrl.$setValidity('number', false);\n      return undefined;\n    }\n  });\n\n  addNativeHtml5Validators(ctrl, 'number', numberBadFlags, null, ctrl.$$validityState);\n\n  ctrl.$formatters.push(function(value) {\n    return ctrl.$isEmpty(value) ? '' : '' + value;\n  });\n\n  if (attr.min) {\n    var minValidator = function(value) {\n      var min = parseFloat(attr.min);\n      return validate(ctrl, 'min', ctrl.$isEmpty(value) || value >= min, value);\n    };\n\n    ctrl.$parsers.push(minValidator);\n    ctrl.$formatters.push(minValidator);\n  }\n\n  if (attr.max) {\n    var maxValidator = function(value) {\n      var max = parseFloat(attr.max);\n      return validate(ctrl, 'max', ctrl.$isEmpty(value) || value <= max, value);\n    };\n\n    ctrl.$parsers.push(maxValidator);\n    ctrl.$formatters.push(maxValidator);\n  }\n\n  ctrl.$formatters.push(function(value) {\n    return validate(ctrl, 'number', ctrl.$isEmpty(value) || isNumber(value), value);\n  });\n}\n\nfunction urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var urlValidator = function(value) {\n    return validate(ctrl, 'url', ctrl.$isEmpty(value) || URL_REGEXP.test(value), value);\n  };\n\n  ctrl.$formatters.push(urlValidator);\n  ctrl.$parsers.push(urlValidator);\n}\n\nfunction emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {\n  textInputType(scope, element, attr, ctrl, $sniffer, $browser);\n\n  var emailValidator = function(value) {\n    return validate(ctrl, 'email', ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value), value);\n  };\n\n  ctrl.$formatters.push(emailValidator);\n  ctrl.$parsers.push(emailValidator);\n}\n\nfunction radioInputType(scope, element, attr, ctrl) {\n  // make the name unique, if not defined\n  if (isUndefined(attr.name)) {\n    element.attr('name', nextUid());\n  }\n\n  element.on('click', function() {\n    if (element[0].checked) {\n      scope.$apply(function() {\n        ctrl.$setViewValue(attr.value);\n      });\n    }\n  });\n\n  ctrl.$render = function() {\n    var value = attr.value;\n    element[0].checked = (value == ctrl.$viewValue);\n  };\n\n  attr.$observe('value', ctrl.$render);\n}\n\nfunction checkboxInputType(scope, element, attr, ctrl) {\n  var trueValue = attr.ngTrueValue,\n      falseValue = attr.ngFalseValue;\n\n  if (!isString(trueValue)) trueValue = true;\n  if (!isString(falseValue)) falseValue = false;\n\n  element.on('click', function() {\n    scope.$apply(function() {\n      ctrl.$setViewValue(element[0].checked);\n    });\n  });\n\n  ctrl.$render = function() {\n    element[0].checked = ctrl.$viewValue;\n  };\n\n  // Override the standard `$isEmpty` because a value of `false` means empty in a checkbox.\n  ctrl.$isEmpty = function(value) {\n    return value !== trueValue;\n  };\n\n  ctrl.$formatters.push(function(value) {\n    return value === trueValue;\n  });\n\n  ctrl.$parsers.push(function(value) {\n    return value ? trueValue : falseValue;\n  });\n}\n\n\n/**\n * @ngdoc directive\n * @name textarea\n * @restrict E\n *\n * @description\n * HTML textarea element control with angular data-binding. The data-binding and validation\n * properties of this element are exactly the same as those of the\n * {@link ng.directive:input input element}.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n */\n\n\n/**\n * @ngdoc directive\n * @name input\n * @restrict E\n *\n * @description\n * HTML input element control with angular data-binding. Input control follows HTML5 input types\n * and polyfills the HTML5 validation behavior for older browsers.\n *\n * *NOTE* Not every feature offered is available for all input types.\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required Sets `required` validation error key if the value is not entered.\n * @param {boolean=} ngRequired Sets `required` attribute if set to true\n * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than\n *    minlength.\n * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than\n *    maxlength.\n * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the\n *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for\n *    patterns defined as scope expressions.\n * @param {string=} ngChange Angular expression to be executed when input changes due to user\n *    interaction with the input element.\n * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.\n *    This parameter is ignored for input[type=password] controls, which will never trim the\n *    input.\n *\n * @example\n    <example name=\"input-directive\" module=\"inputExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('inputExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.user = {name: 'guest', last: 'visitor'};\n            }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <form name=\"myForm\">\n           User name: <input type=\"text\" name=\"userName\" ng-model=\"user.name\" required>\n           <span class=\"error\" ng-show=\"myForm.userName.$error.required\">\n             Required!</span><br>\n           Last name: <input type=\"text\" name=\"lastName\" ng-model=\"user.last\"\n             ng-minlength=\"3\" ng-maxlength=\"10\">\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.minlength\">\n             Too short!</span>\n           <span class=\"error\" ng-show=\"myForm.lastName.$error.maxlength\">\n             Too long!</span><br>\n         </form>\n         <hr>\n         <tt>user = {{user}}</tt><br/>\n         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>\n         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>\n         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>\n         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>\n         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>\n         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>\n       </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var user = element(by.binding('{{user}}'));\n        var userNameValid = element(by.binding('myForm.userName.$valid'));\n        var lastNameValid = element(by.binding('myForm.lastName.$valid'));\n        var lastNameError = element(by.binding('myForm.lastName.$error'));\n        var formValid = element(by.binding('myForm.$valid'));\n        var userNameInput = element(by.model('user.name'));\n        var userLastInput = element(by.model('user.last'));\n\n        it('should initialize to model', function() {\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if empty when required', function() {\n          userNameInput.clear();\n          userNameInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"last\":\"visitor\"}');\n          expect(userNameValid.getText()).toContain('false');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be valid if empty when min length is set', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\",\"last\":\"\"}');\n          expect(lastNameValid.getText()).toContain('true');\n          expect(formValid.getText()).toContain('true');\n        });\n\n        it('should be invalid if less than required min length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('xx');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('minlength');\n          expect(formValid.getText()).toContain('false');\n        });\n\n        it('should be invalid if longer than max length', function() {\n          userLastInput.clear();\n          userLastInput.sendKeys('some ridiculously long name');\n\n          expect(user.getText()).toContain('{\"name\":\"guest\"}');\n          expect(lastNameValid.getText()).toContain('false');\n          expect(lastNameError.getText()).toContain('maxlength');\n          expect(formValid.getText()).toContain('false');\n        });\n      </file>\n    </example>\n */\nvar inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {\n  return {\n    restrict: 'E',\n    require: '?ngModel',\n    link: function(scope, element, attr, ctrl) {\n      if (ctrl) {\n        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,\n                                                            $browser);\n      }\n    }\n  };\n}];\n\nvar VALID_CLASS = 'ng-valid',\n    INVALID_CLASS = 'ng-invalid',\n    PRISTINE_CLASS = 'ng-pristine',\n    DIRTY_CLASS = 'ng-dirty';\n\n/**\n * @ngdoc type\n * @name ngModel.NgModelController\n *\n * @property {string} $viewValue Actual string value in the view.\n * @property {*} $modelValue The value in the model, that the control is bound to.\n * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever\n       the control reads value from the DOM.  Each function is called, in turn, passing the value\n       through to the next. The last return value is used to populate the model.\n       Used to sanitize / convert the value as well as validation. For validation,\n       the parsers should update the validity state using\n       {@link ngModel.NgModelController#$setValidity $setValidity()},\n       and return `undefined` for invalid values.\n\n *\n * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever\n       the model value changes. Each function is called, in turn, passing the value through to the\n       next. Used to format / convert values for display in the control and validation.\n * ```js\n * function formatter(value) {\n *   if (value) {\n *     return value.toUpperCase();\n *   }\n * }\n * ngModel.$formatters.push(formatter);\n * ```\n *\n * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the\n *     view value has changed. It is called with no arguments, and its return value is ignored.\n *     This can be used in place of additional $watches against the model value.\n *\n * @property {Object} $error An object hash with all errors as keys.\n *\n * @property {boolean} $pristine True if user has not interacted with the control yet.\n * @property {boolean} $dirty True if user has already interacted with the control.\n * @property {boolean} $valid True if there is no error.\n * @property {boolean} $invalid True if at least one error on the control.\n *\n * @description\n *\n * `NgModelController` provides API for the `ng-model` directive. The controller contains\n * services for data-binding, validation, CSS updates, and value formatting and parsing. It\n * purposefully does not contain any logic which deals with DOM rendering or listening to\n * DOM events. Such DOM related logic should be provided by other directives which make use of\n * `NgModelController` for data-binding.\n *\n * ## Custom Control Example\n * This example shows how to use `NgModelController` with a custom control to achieve\n * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)\n * collaborate together to achieve the desired result.\n *\n * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element\n * contents be edited in place by the user.  This will not work on older browsers.\n *\n * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}\n * module to automatically remove \"bad\" content like inline event listener (e.g. `<span onclick=\"...\">`).\n * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks\n * that content using the `$sce` service.\n *\n * <example name=\"NgModelController\" module=\"customControl\" deps=\"angular-sanitize.js\">\n    <file name=\"style.css\">\n      [contenteditable] {\n        border: 1px solid black;\n        background-color: white;\n        min-height: 20px;\n      }\n\n      .ng-invalid {\n        border: 1px solid red;\n      }\n\n    </file>\n    <file name=\"script.js\">\n      angular.module('customControl', ['ngSanitize']).\n        directive('contenteditable', ['$sce', function($sce) {\n          return {\n            restrict: 'A', // only activate on element attribute\n            require: '?ngModel', // get a hold of NgModelController\n            link: function(scope, element, attrs, ngModel) {\n              if(!ngModel) return; // do nothing if no ng-model\n\n              // Specify how UI should be updated\n              ngModel.$render = function() {\n                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));\n              };\n\n              // Listen for change events to enable binding\n              element.on('blur keyup change', function() {\n                scope.$evalAsync(read);\n              });\n              read(); // initialize\n\n              // Write data to the model\n              function read() {\n                var html = element.html();\n                // When we clear the content editable the browser leaves a <br> behind\n                // If strip-br attribute is provided then we strip this out\n                if( attrs.stripBr && html == '<br>' ) {\n                  html = '';\n                }\n                ngModel.$setViewValue(html);\n              }\n            }\n          };\n        }]);\n    </file>\n    <file name=\"index.html\">\n      <form name=\"myForm\">\n       <div contenteditable\n            name=\"myWidget\" ng-model=\"userContent\"\n            strip-br=\"true\"\n            required>Change me!</div>\n        <span ng-show=\"myForm.myWidget.$error.required\">Required!</span>\n       <hr>\n       <textarea ng-model=\"userContent\"></textarea>\n      </form>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n    it('should data-bind and become invalid', function() {\n      if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {\n        // SafariDriver can't handle contenteditable\n        // and Firefox driver can't clear contenteditables very well\n        return;\n      }\n      var contentEditable = element(by.css('[contenteditable]'));\n      var content = 'Change me!';\n\n      expect(contentEditable.getText()).toEqual(content);\n\n      contentEditable.clear();\n      contentEditable.sendKeys(protractor.Key.BACK_SPACE);\n      expect(contentEditable.getText()).toEqual('');\n      expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);\n    });\n    </file>\n * </example>\n *\n *\n */\nvar NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate',\n    function($scope, $exceptionHandler, $attr, $element, $parse, $animate) {\n  this.$viewValue = Number.NaN;\n  this.$modelValue = Number.NaN;\n  this.$parsers = [];\n  this.$formatters = [];\n  this.$viewChangeListeners = [];\n  this.$pristine = true;\n  this.$dirty = false;\n  this.$valid = true;\n  this.$invalid = false;\n  this.$name = $attr.name;\n\n  var ngModelGet = $parse($attr.ngModel),\n      ngModelSet = ngModelGet.assign;\n\n  if (!ngModelSet) {\n    throw minErr('ngModel')('nonassign', \"Expression '{0}' is non-assignable. Element: {1}\",\n        $attr.ngModel, startingTag($element));\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$render\n   *\n   * @description\n   * Called when the view needs to be updated. It is expected that the user of the ng-model\n   * directive will implement this method.\n   */\n  this.$render = noop;\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$isEmpty\n   *\n   * @description\n   * This is called when we need to determine if the value of the input is empty.\n   *\n   * For instance, the required directive does this to work out if the input has data or not.\n   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.\n   *\n   * You can override this for input directives whose concept of being empty is different to the\n   * default. The `checkboxInputType` directive does this because in its case a value of `false`\n   * implies empty.\n   *\n   * @param {*} value Reference to check.\n   * @returns {boolean} True if `value` is empty.\n   */\n  this.$isEmpty = function(value) {\n    return isUndefined(value) || value === '' || value === null || value !== value;\n  };\n\n  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,\n      invalidCount = 0, // used to easily determine if we are valid\n      $error = this.$error = {}; // keep invalid keys here\n\n\n  // Setup initial state of the control\n  $element.addClass(PRISTINE_CLASS);\n  toggleValidCss(true);\n\n  // convenience method for easy toggling of classes\n  function toggleValidCss(isValid, validationErrorKey) {\n    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';\n    $animate.removeClass($element, (isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey);\n    $animate.addClass($element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);\n  }\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setValidity\n   *\n   * @description\n   * Change the validity state, and notifies the form when the control changes validity. (i.e. it\n   * does not notify form if given validator is already marked as invalid).\n   *\n   * This method should be called by validators - i.e. the parser or formatter functions.\n   *\n   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign\n   *        to `$error[validationErrorKey]=!isValid` so that it is available for data-binding.\n   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case\n   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`\n   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .\n   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).\n   */\n  this.$setValidity = function(validationErrorKey, isValid) {\n    // Purposeful use of ! here to cast isValid to boolean in case it is undefined\n    // jshint -W018\n    if ($error[validationErrorKey] === !isValid) return;\n    // jshint +W018\n\n    if (isValid) {\n      if ($error[validationErrorKey]) invalidCount--;\n      if (!invalidCount) {\n        toggleValidCss(true);\n        this.$valid = true;\n        this.$invalid = false;\n      }\n    } else {\n      toggleValidCss(false);\n      this.$invalid = true;\n      this.$valid = false;\n      invalidCount++;\n    }\n\n    $error[validationErrorKey] = !isValid;\n    toggleValidCss(isValid, validationErrorKey);\n\n    parentForm.$setValidity(validationErrorKey, isValid, this);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setPristine\n   *\n   * @description\n   * Sets the control to its pristine state.\n   *\n   * This method can be called to remove the 'ng-dirty' class and set the control to its pristine\n   * state (ng-pristine class).\n   */\n  this.$setPristine = function () {\n    this.$dirty = false;\n    this.$pristine = true;\n    $animate.removeClass($element, DIRTY_CLASS);\n    $animate.addClass($element, PRISTINE_CLASS);\n  };\n\n  /**\n   * @ngdoc method\n   * @name ngModel.NgModelController#$setViewValue\n   *\n   * @description\n   * Update the view value.\n   *\n   * This method should be called when the view value changes, typically from within a DOM event handler.\n   * For example {@link ng.directive:input input} and\n   * {@link ng.directive:select select} directives call it.\n   *\n   * It will update the $viewValue, then pass this value through each of the functions in `$parsers`,\n   * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to\n   * `$modelValue` and the **expression** specified in the `ng-model` attribute.\n   *\n   * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.\n   *\n   * Note that calling this function does not trigger a `$digest`.\n   *\n   * @param {string} value Value from the view.\n   */\n  this.$setViewValue = function(value) {\n    this.$viewValue = value;\n\n    // change to dirty\n    if (this.$pristine) {\n      this.$dirty = true;\n      this.$pristine = false;\n      $animate.removeClass($element, PRISTINE_CLASS);\n      $animate.addClass($element, DIRTY_CLASS);\n      parentForm.$setDirty();\n    }\n\n    forEach(this.$parsers, function(fn) {\n      value = fn(value);\n    });\n\n    if (this.$modelValue !== value) {\n      this.$modelValue = value;\n      ngModelSet($scope, value);\n      forEach(this.$viewChangeListeners, function(listener) {\n        try {\n          listener();\n        } catch(e) {\n          $exceptionHandler(e);\n        }\n      });\n    }\n  };\n\n  // model -> value\n  var ctrl = this;\n\n  $scope.$watch(function ngModelWatch() {\n    var value = ngModelGet($scope);\n\n    // if scope model value and ngModel value are out of sync\n    if (ctrl.$modelValue !== value) {\n\n      var formatters = ctrl.$formatters,\n          idx = formatters.length;\n\n      ctrl.$modelValue = value;\n      while(idx--) {\n        value = formatters[idx](value);\n      }\n\n      if (ctrl.$viewValue !== value) {\n        ctrl.$viewValue = value;\n        ctrl.$render();\n      }\n    }\n\n    return value;\n  });\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngModel\n *\n * @element input\n *\n * @description\n * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a\n * property on the scope using {@link ngModel.NgModelController NgModelController},\n * which is created and exposed by this directive.\n *\n * `ngModel` is responsible for:\n *\n * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`\n *   require.\n * - Providing validation behavior (i.e. required, number, email, url).\n * - Keeping the state of the control (valid/invalid, dirty/pristine, validation errors).\n * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`) including animations.\n * - Registering the control with its parent {@link ng.directive:form form}.\n *\n * Note: `ngModel` will try to bind to the property given by evaluating the expression on the\n * current scope. If the property doesn't already exist on this scope, it will be created\n * implicitly and added to the scope.\n *\n * For best practices on using `ngModel`, see:\n *\n *  - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)\n *\n * For basic examples, how to use `ngModel`, see:\n *\n *  - {@link ng.directive:input input}\n *    - {@link input[text] text}\n *    - {@link input[checkbox] checkbox}\n *    - {@link input[radio] radio}\n *    - {@link input[number] number}\n *    - {@link input[email] email}\n *    - {@link input[url] url}\n *  - {@link ng.directive:select select}\n *  - {@link ng.directive:textarea textarea}\n *\n * # CSS classes\n * The following CSS classes are added and removed on the associated input/select/textarea element\n * depending on the validity of the model.\n *\n *  - `ng-valid` is set if the model is valid.\n *  - `ng-invalid` is set if the model is invalid.\n *  - `ng-pristine` is set if the model is pristine.\n *  - `ng-dirty` is set if the model is dirty.\n *\n * Keep in mind that ngAnimate can detect each of these classes when added and removed.\n *\n * ## Animation Hooks\n *\n * Animations within models are triggered when any of the associated CSS classes are added and removed\n * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,\n * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.\n * The animations that are triggered within ngModel are similar to how they work in ngClass and\n * animations can be hooked into using CSS transitions, keyframes as well as JS animations.\n *\n * The following example shows a simple way to utilize CSS transitions to style an input element\n * that has been rendered as invalid after it has been validated:\n *\n * <pre>\n * //be sure to include ngAnimate as a module to hook into more\n * //advanced animations\n * .my-input {\n *   transition:0.5s linear all;\n *   background: white;\n * }\n * .my-input.ng-invalid {\n *   background: red;\n *   color:white;\n * }\n * </pre>\n *\n * @example\n * <example deps=\"angular-animate.js\" animations=\"true\" fixBase=\"true\" module=\"inputExample\">\n     <file name=\"index.html\">\n       <script>\n        angular.module('inputExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.val = '1';\n          }]);\n       </script>\n       <style>\n         .my-input {\n           -webkit-transition:all linear 0.5s;\n           transition:all linear 0.5s;\n           background: transparent;\n         }\n         .my-input.ng-invalid {\n           color:white;\n           background: red;\n         }\n       </style>\n       Update input to see transitions when valid/invalid.\n       Integer is a valid value.\n       <form name=\"testForm\" ng-controller=\"ExampleController\">\n         <input ng-model=\"val\" ng-pattern=\"/^\\d+$/\" name=\"anim\" class=\"my-input\" />\n       </form>\n     </file>\n * </example>\n */\nvar ngModelDirective = function() {\n  return {\n    require: ['ngModel', '^?form'],\n    controller: NgModelController,\n    link: function(scope, element, attr, ctrls) {\n      // notify others, especially parent forms\n\n      var modelCtrl = ctrls[0],\n          formCtrl = ctrls[1] || nullFormCtrl;\n\n      formCtrl.$addControl(modelCtrl);\n\n      scope.$on('$destroy', function() {\n        formCtrl.$removeControl(modelCtrl);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ngChange\n *\n * @description\n * Evaluate the given expression when the user changes the input.\n * The expression is evaluated immediately, unlike the JavaScript onchange event\n * which only triggers at the end of a change (usually, when the user leaves the\n * form element or presses the return key).\n * The expression is not evaluated when the value change is coming from the model.\n *\n * Note, this directive requires `ngModel` to be present.\n *\n * @element input\n * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change\n * in input value.\n *\n * @example\n * <example name=\"ngChange-directive\" module=\"changeExample\">\n *   <file name=\"index.html\">\n *     <script>\n *       angular.module('changeExample', [])\n *         .controller('ExampleController', ['$scope', function($scope) {\n *           $scope.counter = 0;\n *           $scope.change = function() {\n *             $scope.counter++;\n *           };\n *         }]);\n *     </script>\n *     <div ng-controller=\"ExampleController\">\n *       <input type=\"checkbox\" ng-model=\"confirmed\" ng-change=\"change()\" id=\"ng-change-example1\" />\n *       <input type=\"checkbox\" ng-model=\"confirmed\" id=\"ng-change-example2\" />\n *       <label for=\"ng-change-example2\">Confirmed</label><br />\n *       <tt>debug = {{confirmed}}</tt><br/>\n *       <tt>counter = {{counter}}</tt><br/>\n *     </div>\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     var counter = element(by.binding('counter'));\n *     var debug = element(by.binding('confirmed'));\n *\n *     it('should evaluate the expression if changing from view', function() {\n *       expect(counter.getText()).toContain('0');\n *\n *       element(by.id('ng-change-example1')).click();\n *\n *       expect(counter.getText()).toContain('1');\n *       expect(debug.getText()).toContain('true');\n *     });\n *\n *     it('should not evaluate the expression if changing from model', function() {\n *       element(by.id('ng-change-example2')).click();\n\n *       expect(counter.getText()).toContain('0');\n *       expect(debug.getText()).toContain('true');\n *     });\n *   </file>\n * </example>\n */\nvar ngChangeDirective = valueFn({\n  require: 'ngModel',\n  link: function(scope, element, attr, ctrl) {\n    ctrl.$viewChangeListeners.push(function() {\n      scope.$eval(attr.ngChange);\n    });\n  }\n});\n\n\nvar requiredDirective = function() {\n  return {\n    require: '?ngModel',\n    link: function(scope, elm, attr, ctrl) {\n      if (!ctrl) return;\n      attr.required = true; // force truthy in case we are on non input element\n\n      var validator = function(value) {\n        if (attr.required && ctrl.$isEmpty(value)) {\n          ctrl.$setValidity('required', false);\n          return;\n        } else {\n          ctrl.$setValidity('required', true);\n          return value;\n        }\n      };\n\n      ctrl.$formatters.push(validator);\n      ctrl.$parsers.unshift(validator);\n\n      attr.$observe('required', function() {\n        validator(ctrl.$viewValue);\n      });\n    }\n  };\n};\n\n\n/**\n * @ngdoc directive\n * @name ngList\n *\n * @description\n * Text input that converts between a delimited string and an array of strings. The delimiter\n * can be a fixed string (by default a comma) or a regular expression.\n *\n * @element input\n * @param {string=} ngList optional delimiter that should be used to split the value. If\n *   specified in form `/something/` then the value will be converted into a regular expression.\n *\n * @example\n    <example name=\"ngList-directive\" module=\"listExample\">\n      <file name=\"index.html\">\n       <script>\n         angular.module('listExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.names = ['igor', 'misko', 'vojta'];\n           }]);\n       </script>\n       <form name=\"myForm\" ng-controller=\"ExampleController\">\n         List: <input name=\"namesInput\" ng-model=\"names\" ng-list required>\n         <span class=\"error\" ng-show=\"myForm.namesInput.$error.required\">\n           Required!</span>\n         <br>\n         <tt>names = {{names}}</tt><br/>\n         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>\n         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>\n         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>\n         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var listInput = element(by.model('names'));\n        var names = element(by.binding('{{names}}'));\n        var valid = element(by.binding('myForm.namesInput.$valid'));\n        var error = element(by.css('span.error'));\n\n        it('should initialize to model', function() {\n          expect(names.getText()).toContain('[\"igor\",\"misko\",\"vojta\"]');\n          expect(valid.getText()).toContain('true');\n          expect(error.getCssValue('display')).toBe('none');\n        });\n\n        it('should be invalid if empty', function() {\n          listInput.clear();\n          listInput.sendKeys('');\n\n          expect(names.getText()).toContain('');\n          expect(valid.getText()).toContain('false');\n          expect(error.getCssValue('display')).not.toBe('none');        });\n      </file>\n    </example>\n */\nvar ngListDirective = function() {\n  return {\n    require: 'ngModel',\n    link: function(scope, element, attr, ctrl) {\n      var match = /\\/(.*)\\//.exec(attr.ngList),\n          separator = match && new RegExp(match[1]) || attr.ngList || ',';\n\n      var parse = function(viewValue) {\n        // If the viewValue is invalid (say required but empty) it will be `undefined`\n        if (isUndefined(viewValue)) return;\n\n        var list = [];\n\n        if (viewValue) {\n          forEach(viewValue.split(separator), function(value) {\n            if (value) list.push(trim(value));\n          });\n        }\n\n        return list;\n      };\n\n      ctrl.$parsers.push(parse);\n      ctrl.$formatters.push(function(value) {\n        if (isArray(value)) {\n          return value.join(', ');\n        }\n\n        return undefined;\n      });\n\n      // Override the standard $isEmpty because an empty array means the input is empty.\n      ctrl.$isEmpty = function(value) {\n        return !value || !value.length;\n      };\n    }\n  };\n};\n\n\nvar CONSTANT_VALUE_REGEXP = /^(true|false|\\d+)$/;\n/**\n * @ngdoc directive\n * @name ngValue\n *\n * @description\n * Binds the given expression to the value of `input[select]` or `input[radio]`, so\n * that when the element is selected, the `ngModel` of that element is set to the\n * bound value.\n *\n * `ngValue` is useful when dynamically generating lists of radio buttons using `ng-repeat`, as\n * shown below.\n *\n * @element input\n * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute\n *   of the `input` element\n *\n * @example\n    <example name=\"ngValue-directive\" module=\"valueExample\">\n      <file name=\"index.html\">\n       <script>\n          angular.module('valueExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.names = ['pizza', 'unicorns', 'robots'];\n              $scope.my = { favorite: 'unicorns' };\n            }]);\n       </script>\n        <form ng-controller=\"ExampleController\">\n          <h2>Which is your favorite?</h2>\n            <label ng-repeat=\"name in names\" for=\"{{name}}\">\n              {{name}}\n              <input type=\"radio\"\n                     ng-model=\"my.favorite\"\n                     ng-value=\"name\"\n                     id=\"{{name}}\"\n                     name=\"favorite\">\n            </label>\n          <div>You chose {{my.favorite}}</div>\n        </form>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        var favorite = element(by.binding('my.favorite'));\n\n        it('should initialize to model', function() {\n          expect(favorite.getText()).toContain('unicorns');\n        });\n        it('should bind the values to the inputs', function() {\n          element.all(by.model('my.favorite')).get(0).click();\n          expect(favorite.getText()).toContain('pizza');\n        });\n      </file>\n    </example>\n */\nvar ngValueDirective = function() {\n  return {\n    priority: 100,\n    compile: function(tpl, tplAttr) {\n      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {\n        return function ngValueConstantLink(scope, elm, attr) {\n          attr.$set('value', scope.$eval(attr.ngValue));\n        };\n      } else {\n        return function ngValueLink(scope, elm, attr) {\n          scope.$watch(attr.ngValue, function valueWatchAction(value) {\n            attr.$set('value', value);\n          });\n        };\n      }\n    }\n  };\n};\n\n/**\n * @ngdoc directive\n * @name ngBind\n * @restrict AC\n *\n * @description\n * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element\n * with the value of a given expression, and to update the text content when the value of that\n * expression changes.\n *\n * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like\n * `{{ expression }}` which is similar but less verbose.\n *\n * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily\n * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an\n * element attribute, it makes the bindings invisible to the user while the page is loading.\n *\n * An alternative solution to this problem would be using the\n * {@link ng.directive:ngCloak ngCloak} directive.\n *\n *\n * @element ANY\n * @param {expression} ngBind {@link guide/expression Expression} to evaluate.\n *\n * @example\n * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function($scope) {\n             $scope.name = 'Whirled';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         Enter name: <input type=\"text\" ng-model=\"name\"><br>\n         Hello <span ng-bind=\"name\"></span>!\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var nameInput = element(by.model('name'));\n\n         expect(element(by.binding('name')).getText()).toBe('Whirled');\n         nameInput.clear();\n         nameInput.sendKeys('world');\n         expect(element(by.binding('name')).getText()).toBe('world');\n       });\n     </file>\n   </example>\n */\nvar ngBindDirective = ngDirective({\n  compile: function(templateElement) {\n    templateElement.addClass('ng-binding');\n    return function (scope, element, attr) {\n      element.data('$binding', attr.ngBind);\n      scope.$watch(attr.ngBind, function ngBindWatchAction(value) {\n        // We are purposefully using == here rather than === because we want to\n        // catch when value is \"null or undefined\"\n        // jshint -W041\n        element.text(value == undefined ? '' : value);\n      });\n    };\n  }\n});\n\n\n/**\n * @ngdoc directive\n * @name ngBindTemplate\n *\n * @description\n * The `ngBindTemplate` directive specifies that the element\n * text content should be replaced with the interpolation of the template\n * in the `ngBindTemplate` attribute.\n * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`\n * expressions. This directive is needed since some HTML elements\n * (such as TITLE and OPTION) cannot contain SPAN elements.\n *\n * @element ANY\n * @param {string} ngBindTemplate template of form\n *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.\n *\n * @example\n * Try it here: enter text in text box and watch the greeting change.\n   <example module=\"bindExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('bindExample', [])\n           .controller('ExampleController', ['$scope', function ($scope) {\n             $scope.salutation = 'Hello';\n             $scope.name = 'World';\n           }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n        Salutation: <input type=\"text\" ng-model=\"salutation\"><br>\n        Name: <input type=\"text\" ng-model=\"name\"><br>\n        <pre ng-bind-template=\"{{salutation}} {{name}}!\"></pre>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind', function() {\n         var salutationElem = element(by.binding('salutation'));\n         var salutationInput = element(by.model('salutation'));\n         var nameInput = element(by.model('name'));\n\n         expect(salutationElem.getText()).toBe('Hello World!');\n\n         salutationInput.clear();\n         salutationInput.sendKeys('Greetings');\n         nameInput.clear();\n         nameInput.sendKeys('user');\n\n         expect(salutationElem.getText()).toBe('Greetings user!');\n       });\n     </file>\n   </example>\n */\nvar ngBindTemplateDirective = ['$interpolate', function($interpolate) {\n  return function(scope, element, attr) {\n    // TODO: move this to scenario runner\n    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));\n    element.addClass('ng-binding').data('$binding', interpolateFn);\n    attr.$observe('ngBindTemplate', function(value) {\n      element.text(value);\n    });\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngBindHtml\n *\n * @description\n * Creates a binding that will innerHTML the result of evaluating the `expression` into the current\n * element in a secure way.  By default, the innerHTML-ed content will be sanitized using the {@link\n * ngSanitize.$sanitize $sanitize} service.  To utilize this functionality, ensure that `$sanitize`\n * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in\n * core Angular). In order to use {@link ngSanitize} in your module's dependencies, you need to\n * include \"angular-sanitize.js\" in your application.\n *\n * You may also bypass sanitization for values you know are safe. To do so, bind to\n * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example\n * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}.\n *\n * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you\n * will have an exception (instead of an exploit.)\n *\n * @element ANY\n * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.\n *\n * @example\n\n   <example module=\"bindHtmlExample\" deps=\"angular-sanitize.js\">\n     <file name=\"index.html\">\n       <div ng-controller=\"ExampleController\">\n        <p ng-bind-html=\"myHTML\"></p>\n       </div>\n     </file>\n\n     <file name=\"script.js\">\n       angular.module('bindHtmlExample', ['ngSanitize'])\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.myHTML =\n              'I am an <code>HTML</code>string with ' +\n              '<a href=\"#\">links!</a> and other <em>stuff</em>';\n         }]);\n     </file>\n\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-bind-html', function() {\n         expect(element(by.binding('myHTML')).getText()).toBe(\n             'I am an HTMLstring with links! and other stuff');\n       });\n     </file>\n   </example>\n */\nvar ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {\n  return {\n    compile: function (tElement) {\n      tElement.addClass('ng-binding');\n\n      return function (scope, element, attr) {\n        element.data('$binding', attr.ngBindHtml);\n\n        var parsed = $parse(attr.ngBindHtml);\n\n        function getStringValue() {\n          return (parsed(scope) || '').toString();\n        }\n\n        scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {\n          element.html($sce.getTrustedHtml(parsed(scope)) || '');\n        });\n      };\n    }\n  };\n}];\n\nfunction classDirective(name, selector) {\n  name = 'ngClass' + name;\n  return ['$animate', function($animate) {\n    return {\n      restrict: 'AC',\n      link: function(scope, element, attr) {\n        var oldVal;\n\n        scope.$watch(attr[name], ngClassWatchAction, true);\n\n        attr.$observe('class', function(value) {\n          ngClassWatchAction(scope.$eval(attr[name]));\n        });\n\n\n        if (name !== 'ngClass') {\n          scope.$watch('$index', function($index, old$index) {\n            // jshint bitwise: false\n            var mod = $index & 1;\n            if (mod !== (old$index & 1)) {\n              var classes = arrayClasses(scope.$eval(attr[name]));\n              mod === selector ?\n                addClasses(classes) :\n                removeClasses(classes);\n            }\n          });\n        }\n\n        function addClasses(classes) {\n          var newClasses = digestClassCounts(classes, 1);\n          attr.$addClass(newClasses);\n        }\n\n        function removeClasses(classes) {\n          var newClasses = digestClassCounts(classes, -1);\n          attr.$removeClass(newClasses);\n        }\n\n        function digestClassCounts (classes, count) {\n          var classCounts = element.data('$classCounts') || {};\n          var classesToUpdate = [];\n          forEach(classes, function (className) {\n            if (count > 0 || classCounts[className]) {\n              classCounts[className] = (classCounts[className] || 0) + count;\n              if (classCounts[className] === +(count > 0)) {\n                classesToUpdate.push(className);\n              }\n            }\n          });\n          element.data('$classCounts', classCounts);\n          return classesToUpdate.join(' ');\n        }\n\n        function updateClasses (oldClasses, newClasses) {\n          var toAdd = arrayDifference(newClasses, oldClasses);\n          var toRemove = arrayDifference(oldClasses, newClasses);\n          toRemove = digestClassCounts(toRemove, -1);\n          toAdd = digestClassCounts(toAdd, 1);\n\n          if (toAdd.length === 0) {\n            $animate.removeClass(element, toRemove);\n          } else if (toRemove.length === 0) {\n            $animate.addClass(element, toAdd);\n          } else {\n            $animate.setClass(element, toAdd, toRemove);\n          }\n        }\n\n        function ngClassWatchAction(newVal) {\n          if (selector === true || scope.$index % 2 === selector) {\n            var newClasses = arrayClasses(newVal || []);\n            if (!oldVal) {\n              addClasses(newClasses);\n            } else if (!equals(newVal,oldVal)) {\n              var oldClasses = arrayClasses(oldVal);\n              updateClasses(oldClasses, newClasses);\n            }\n          }\n          oldVal = shallowCopy(newVal);\n        }\n      }\n    };\n\n    function arrayDifference(tokens1, tokens2) {\n      var values = [];\n\n      outer:\n      for(var i = 0; i < tokens1.length; i++) {\n        var token = tokens1[i];\n        for(var j = 0; j < tokens2.length; j++) {\n          if(token == tokens2[j]) continue outer;\n        }\n        values.push(token);\n      }\n      return values;\n    }\n\n    function arrayClasses (classVal) {\n      if (isArray(classVal)) {\n        return classVal;\n      } else if (isString(classVal)) {\n        return classVal.split(' ');\n      } else if (isObject(classVal)) {\n        var classes = [], i = 0;\n        forEach(classVal, function(v, k) {\n          if (v) {\n            classes = classes.concat(k.split(' '));\n          }\n        });\n        return classes;\n      }\n      return classVal;\n    }\n  }];\n}\n\n/**\n * @ngdoc directive\n * @name ngClass\n * @restrict AC\n *\n * @description\n * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding\n * an expression that represents all classes to be added.\n *\n * The directive operates in three different ways, depending on which of three types the expression\n * evaluates to:\n *\n * 1. If the expression evaluates to a string, the string should be one or more space-delimited class\n * names.\n *\n * 2. If the expression evaluates to an array, each element of the array should be a string that is\n * one or more space-delimited class names.\n *\n * 3. If the expression evaluates to an object, then for each key-value pair of the\n * object with a truthy value the corresponding key is used as a class name.\n *\n * The directive won't add duplicate classes if a particular class was already set.\n *\n * When the expression changes, the previously added classes are removed and only then the\n * new classes are added.\n *\n * @animations\n * add - happens just before the class is applied to the element\n * remove - happens just before the class is removed from the element\n *\n * @element ANY\n * @param {expression} ngClass {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class\n *   names, an array, or a map of class names to boolean values. In the case of a map, the\n *   names of the properties whose values are truthy will be added as css classes to the\n *   element.\n *\n * @example Example that demonstrates basic bindings via ngClass directive.\n   <example>\n     <file name=\"index.html\">\n       <p ng-class=\"{strike: deleted, bold: important, red: error}\">Map Syntax Example</p>\n       <input type=\"checkbox\" ng-model=\"deleted\"> deleted (apply \"strike\" class)<br>\n       <input type=\"checkbox\" ng-model=\"important\"> important (apply \"bold\" class)<br>\n       <input type=\"checkbox\" ng-model=\"error\"> error (apply \"red\" class)\n       <hr>\n       <p ng-class=\"style\">Using String Syntax</p>\n       <input type=\"text\" ng-model=\"style\" placeholder=\"Type: bold strike red\">\n       <hr>\n       <p ng-class=\"[style1, style2, style3]\">Using Array Syntax</p>\n       <input ng-model=\"style1\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style2\" placeholder=\"Type: bold, strike or red\"><br>\n       <input ng-model=\"style3\" placeholder=\"Type: bold, strike or red\"><br>\n     </file>\n     <file name=\"style.css\">\n       .strike {\n         text-decoration: line-through;\n       }\n       .bold {\n           font-weight: bold;\n       }\n       .red {\n           color: red;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var ps = element.all(by.css('p'));\n\n       it('should let you toggle the class', function() {\n\n         expect(ps.first().getAttribute('class')).not.toMatch(/bold/);\n         expect(ps.first().getAttribute('class')).not.toMatch(/red/);\n\n         element(by.model('important')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/bold/);\n\n         element(by.model('error')).click();\n         expect(ps.first().getAttribute('class')).toMatch(/red/);\n       });\n\n       it('should let you toggle string example', function() {\n         expect(ps.get(1).getAttribute('class')).toBe('');\n         element(by.model('style')).clear();\n         element(by.model('style')).sendKeys('red');\n         expect(ps.get(1).getAttribute('class')).toBe('red');\n       });\n\n       it('array example should have 3 classes', function() {\n         expect(ps.last().getAttribute('class')).toBe('');\n         element(by.model('style1')).sendKeys('bold');\n         element(by.model('style2')).sendKeys('strike');\n         element(by.model('style3')).sendKeys('red');\n         expect(ps.last().getAttribute('class')).toBe('bold strike red');\n       });\n     </file>\n   </example>\n\n   ## Animations\n\n   The example below demonstrates how to perform animations using ngClass.\n\n   <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n     <file name=\"index.html\">\n      <input id=\"setbtn\" type=\"button\" value=\"set\" ng-click=\"myVar='my-class'\">\n      <input id=\"clearbtn\" type=\"button\" value=\"clear\" ng-click=\"myVar=''\">\n      <br>\n      <span class=\"base-class\" ng-class=\"myVar\">Sample Text</span>\n     </file>\n     <file name=\"style.css\">\n       .base-class {\n         -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n       }\n\n       .base-class.my-class {\n         color: red;\n         font-size:3em;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class', function() {\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n\n         element(by.id('setbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).\n           toMatch(/my-class/);\n\n         element(by.id('clearbtn')).click();\n\n         expect(element(by.css('.base-class')).getAttribute('class')).not.\n           toMatch(/my-class/);\n       });\n     </file>\n   </example>\n\n\n   ## ngClass and pre-existing CSS3 Transitions/Animations\n   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.\n   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder\n   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure\n   to view the step by step details of {@link ngAnimate.$animate#addclass $animate.addClass} and\n   {@link ngAnimate.$animate#removeclass $animate.removeClass}.\n */\nvar ngClassDirective = classDirective('', true);\n\n/**\n * @ngdoc directive\n * @name ngClassOdd\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result\n *   of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}}\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassOddDirective = classDirective('Odd', 0);\n\n/**\n * @ngdoc directive\n * @name ngClassEven\n * @restrict AC\n *\n * @description\n * The `ngClassOdd` and `ngClassEven` directives work exactly as\n * {@link ng.directive:ngClass ngClass}, except they work in\n * conjunction with `ngRepeat` and take effect only on odd (even) rows.\n *\n * This directive can be applied only within the scope of an\n * {@link ng.directive:ngRepeat ngRepeat}.\n *\n * @element ANY\n * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The\n *   result of the evaluation can be a string representing space delimited class names or an array.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <ol ng-init=\"names=['John', 'Mary', 'Cate', 'Suz']\">\n          <li ng-repeat=\"name in names\">\n           <span ng-class-odd=\"'odd'\" ng-class-even=\"'even'\">\n             {{name}} &nbsp; &nbsp; &nbsp;\n           </span>\n          </li>\n        </ol>\n     </file>\n     <file name=\"style.css\">\n       .odd {\n         color: red;\n       }\n       .even {\n         color: blue;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-class-odd and ng-class-even', function() {\n         expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).\n           toMatch(/odd/);\n         expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).\n           toMatch(/even/);\n       });\n     </file>\n   </example>\n */\nvar ngClassEvenDirective = classDirective('Even', 1);\n\n/**\n * @ngdoc directive\n * @name ngCloak\n * @restrict AC\n *\n * @description\n * The `ngCloak` directive is used to prevent the Angular html template from being briefly\n * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this\n * directive to avoid the undesirable flicker effect caused by the html template display.\n *\n * The directive can be applied to the `<body>` element, but the preferred usage is to apply\n * multiple `ngCloak` directives to small portions of the page to permit progressive rendering\n * of the browser view.\n *\n * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and\n * `angular.min.js`.\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```css\n * [ng\\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {\n *   display: none !important;\n * }\n * ```\n *\n * When this css rule is loaded by the browser, all html elements (including their children) that\n * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive\n * during the compilation of the template it deletes the `ngCloak` element attribute, making\n * the compiled element visible.\n *\n * For the best result, the `angular.js` script must be loaded in the head section of the html\n * document; alternatively, the css rule above must be included in the external stylesheet of the\n * application.\n *\n * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they\n * cannot match the `[ng\\:cloak]` selector. To work around this limitation, you must add the css\n * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.\n *\n * @element ANY\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <div id=\"template1\" ng-cloak>{{ 'hello' }}</div>\n        <div id=\"template2\" ng-cloak class=\"ng-cloak\">{{ 'hello IE7' }}</div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should remove the template directive and css class', function() {\n         expect($('#template1').getAttribute('ng-cloak')).\n           toBeNull();\n         expect($('#template2').getAttribute('ng-cloak')).\n           toBeNull();\n       });\n     </file>\n   </example>\n *\n */\nvar ngCloakDirective = ngDirective({\n  compile: function(element, attr) {\n    attr.$set('ngCloak', undefined);\n    element.removeClass('ng-cloak');\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngController\n *\n * @description\n * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular\n * supports the principles behind the Model-View-Controller design pattern.\n *\n * MVC components in angular:\n *\n * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties\n *   are accessed through bindings.\n * * View — The template (HTML with data bindings) that is rendered into the View.\n * * Controller — The `ngController` directive specifies a Controller class; the class contains business\n *   logic behind the application to decorate the scope with functions and values\n *\n * Note that you can also attach controllers to the DOM by declaring it in a route definition\n * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller\n * again using `ng-controller` in the template itself.  This will cause the controller to be attached\n * and executed twice.\n *\n * @element ANY\n * @scope\n * @priority 500\n * @param {expression} ngController Name of a globally accessible constructor function or an\n *     {@link guide/expression expression} that on the current scope evaluates to a\n *     constructor function. The controller instance can be published into a scope property\n *     by specifying `as propertyName`.\n *\n * @example\n * Here is a simple form for editing user contact information. Adding, removing, clearing, and\n * greeting are methods declared on the controller (see source tab). These methods can\n * easily be called from the angular markup. Any changes to the data are automatically reflected\n * in the View without the need for a manual update.\n *\n * Two different declaration styles are included below:\n *\n * * one binds methods and properties directly onto the controller using `this`:\n * `ng-controller=\"SettingsController1 as settings\"`\n * * one injects `$scope` into the controller:\n * `ng-controller=\"SettingsController2\"`\n *\n * The second option is more common in the Angular community, and is generally used in boilerplates\n * and in this guide. However, there are advantages to binding properties directly to the controller\n * and avoiding scope.\n *\n * * Using `controller as` makes it obvious which controller you are accessing in the template when\n * multiple controllers apply to an element.\n * * If you are writing your controllers as classes you have easier access to the properties and\n * methods, which will appear on the scope, from inside the controller code.\n * * Since there is always a `.` in the bindings, you don't have to worry about prototypal\n * inheritance masking primitives.\n *\n * This example demonstrates the `controller as` syntax.\n *\n * <example name=\"ngControllerAs\" module=\"controllerAsExample\">\n *   <file name=\"index.html\">\n *    <div id=\"ctrl-as-exmpl\" ng-controller=\"SettingsController1 as settings\">\n *      Name: <input type=\"text\" ng-model=\"settings.name\"/>\n *      [ <a href=\"\" ng-click=\"settings.greet()\">greet</a> ]<br/>\n *      Contact:\n *      <ul>\n *        <li ng-repeat=\"contact in settings.contacts\">\n *          <select ng-model=\"contact.type\">\n *             <option>phone</option>\n *             <option>email</option>\n *          </select>\n *          <input type=\"text\" ng-model=\"contact.value\"/>\n *          [ <a href=\"\" ng-click=\"settings.clearContact(contact)\">clear</a>\n *          | <a href=\"\" ng-click=\"settings.removeContact(contact)\">X</a> ]\n *        </li>\n *        <li>[ <a href=\"\" ng-click=\"settings.addContact()\">add</a> ]</li>\n *     </ul>\n *    </div>\n *   </file>\n *   <file name=\"app.js\">\n *    angular.module('controllerAsExample', [])\n *      .controller('SettingsController1', SettingsController1);\n *\n *    function SettingsController1() {\n *      this.name = \"John Smith\";\n *      this.contacts = [\n *        {type: 'phone', value: '408 555 1212'},\n *        {type: 'email', value: 'john.smith@example.org'} ];\n *    }\n *\n *    SettingsController1.prototype.greet = function() {\n *      alert(this.name);\n *    };\n *\n *    SettingsController1.prototype.addContact = function() {\n *      this.contacts.push({type: 'email', value: 'yourname@example.org'});\n *    };\n *\n *    SettingsController1.prototype.removeContact = function(contactToRemove) {\n *     var index = this.contacts.indexOf(contactToRemove);\n *      this.contacts.splice(index, 1);\n *    };\n *\n *    SettingsController1.prototype.clearContact = function(contact) {\n *      contact.type = 'phone';\n *      contact.value = '';\n *    };\n *   </file>\n *   <file name=\"protractor.js\" type=\"protractor\">\n *     it('should check controller as', function() {\n *       var container = element(by.id('ctrl-as-exmpl'));\n *         expect(container.element(by.model('settings.name'))\n *           .getAttribute('value')).toBe('John Smith');\n *\n *       var firstRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(0));\n *       var secondRepeat =\n *           container.element(by.repeater('contact in settings.contacts').row(1));\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('408 555 1212');\n *\n *       expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('john.smith@example.org');\n *\n *       firstRepeat.element(by.linkText('clear')).click();\n *\n *       expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *           .toBe('');\n *\n *       container.element(by.linkText('add')).click();\n *\n *       expect(container.element(by.repeater('contact in settings.contacts').row(2))\n *           .element(by.model('contact.value'))\n *           .getAttribute('value'))\n *           .toBe('yourname@example.org');\n *     });\n *   </file>\n * </example>\n *\n * This example demonstrates the \"attach to `$scope`\" style of controller.\n *\n * <example name=\"ngController\" module=\"controllerExample\">\n *  <file name=\"index.html\">\n *   <div id=\"ctrl-exmpl\" ng-controller=\"SettingsController2\">\n *     Name: <input type=\"text\" ng-model=\"name\"/>\n *     [ <a href=\"\" ng-click=\"greet()\">greet</a> ]<br/>\n *     Contact:\n *     <ul>\n *       <li ng-repeat=\"contact in contacts\">\n *         <select ng-model=\"contact.type\">\n *            <option>phone</option>\n *            <option>email</option>\n *         </select>\n *         <input type=\"text\" ng-model=\"contact.value\"/>\n *         [ <a href=\"\" ng-click=\"clearContact(contact)\">clear</a>\n *         | <a href=\"\" ng-click=\"removeContact(contact)\">X</a> ]\n *       </li>\n *       <li>[ <a href=\"\" ng-click=\"addContact()\">add</a> ]</li>\n *    </ul>\n *   </div>\n *  </file>\n *  <file name=\"app.js\">\n *   angular.module('controllerExample', [])\n *     .controller('SettingsController2', ['$scope', SettingsController2]);\n *\n *   function SettingsController2($scope) {\n *     $scope.name = \"John Smith\";\n *     $scope.contacts = [\n *       {type:'phone', value:'408 555 1212'},\n *       {type:'email', value:'john.smith@example.org'} ];\n *\n *     $scope.greet = function() {\n *       alert($scope.name);\n *     };\n *\n *     $scope.addContact = function() {\n *       $scope.contacts.push({type:'email', value:'yourname@example.org'});\n *     };\n *\n *     $scope.removeContact = function(contactToRemove) {\n *       var index = $scope.contacts.indexOf(contactToRemove);\n *       $scope.contacts.splice(index, 1);\n *     };\n *\n *     $scope.clearContact = function(contact) {\n *       contact.type = 'phone';\n *       contact.value = '';\n *     };\n *   }\n *  </file>\n *  <file name=\"protractor.js\" type=\"protractor\">\n *    it('should check controller', function() {\n *      var container = element(by.id('ctrl-exmpl'));\n *\n *      expect(container.element(by.model('name'))\n *          .getAttribute('value')).toBe('John Smith');\n *\n *      var firstRepeat =\n *          container.element(by.repeater('contact in contacts').row(0));\n *      var secondRepeat =\n *          container.element(by.repeater('contact in contacts').row(1));\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('408 555 1212');\n *      expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('john.smith@example.org');\n *\n *      firstRepeat.element(by.linkText('clear')).click();\n *\n *      expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))\n *          .toBe('');\n *\n *      container.element(by.linkText('add')).click();\n *\n *      expect(container.element(by.repeater('contact in contacts').row(2))\n *          .element(by.model('contact.value'))\n *          .getAttribute('value'))\n *          .toBe('yourname@example.org');\n *    });\n *  </file>\n *</example>\n\n */\nvar ngControllerDirective = [function() {\n  return {\n    scope: true,\n    controller: '@',\n    priority: 500\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngCsp\n *\n * @element html\n * @description\n * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.\n *\n * This is necessary when developing things like Google Chrome Extensions.\n *\n * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).\n * For Angular to be CSP compatible there are only two things that we need to do differently:\n *\n * - don't use `Function` constructor to generate optimized value getters\n * - don't inject custom stylesheet into the document\n *\n * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`\n * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will\n * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will\n * be raised.\n *\n * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically\n * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).\n * To make those directives work in CSP mode, include the `angular-csp.css` manually.\n *\n * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This\n * autodetection however triggers a CSP error to be logged in the console:\n *\n * ```\n * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of\n * script in the following Content Security Policy directive: \"default-src 'self'\". Note that\n * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.\n * ```\n *\n * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`\n * directive on the root element of the application or on the `angular.js` script tag, whichever\n * appears first in the html document.\n *\n * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*\n *\n * @example\n * This example shows how to apply the `ngCsp` directive to the `html` tag.\n   ```html\n     <!doctype html>\n     <html ng-app ng-csp>\n     ...\n     ...\n     </html>\n   ```\n */\n\n// ngCsp is not implemented as a proper directive any more, because we need it be processed while we\n// bootstrap the system (before $parse is instantiated), for this reason we just have\n// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc\n\n/**\n * @ngdoc directive\n * @name ngClick\n *\n * @description\n * The ngClick directive allows you to specify custom behavior when\n * an element is clicked.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon\n * click. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-click=\"count = count + 1\" ng-init=\"count=0\">\n        Increment\n      </button>\n      <span>\n        count: {{count}}\n      <span>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-click', function() {\n         expect(element(by.binding('count')).getText()).toMatch('0');\n         element(by.css('button')).click();\n         expect(element(by.binding('count')).getText()).toMatch('1');\n       });\n     </file>\n   </example>\n */\n/*\n * A collection of directives that allows creation of custom event handlers that are defined as\n * angular expressions and are compiled and executed within the current scope.\n */\nvar ngEventDirectives = {};\n\n// For events that might fire synchronously during DOM manipulation\n// we need to execute their event handlers asynchronously using $evalAsync,\n// so that they are not executed in an inconsistent state.\nvar forceAsyncEvents = {\n  'blur': true,\n  'focus': true\n};\nforEach(\n  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),\n  function(eventName) {\n    var directiveName = directiveNormalize('ng-' + eventName);\n    ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {\n      return {\n        compile: function($element, attr) {\n          // We expose the powerful $event object on the scope that provides access to the Window,\n          // etc. that isn't protected by the fast paths in $parse.  We explicitly request better\n          // checks at the cost of speed since event handler expressions are not executed as\n          // frequently as regular change detection.\n          var fn = $parse(attr[directiveName], /* expensiveChecks */ true);\n          return function ngEventHandler(scope, element) {\n            element.on(eventName, function(event) {\n              var callback = function() {\n                fn(scope, {$event:event});\n              };\n              if (forceAsyncEvents[eventName] && $rootScope.$$phase) {\n                scope.$evalAsync(callback);\n              } else {\n                scope.$apply(callback);\n              }\n            });\n          };\n        }\n      };\n    }];\n  }\n);\n\n/**\n * @ngdoc directive\n * @name ngDblclick\n *\n * @description\n * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon\n * a dblclick. (The Event object is available as `$event`)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-dblclick=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on double click)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousedown\n *\n * @description\n * The ngMousedown directive allows you to specify custom behavior on mousedown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon\n * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousedown=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse down)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseup\n *\n * @description\n * Specify custom behavior on mouseup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon\n * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseup=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (on mouse up)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngMouseover\n *\n * @description\n * Specify custom behavior on mouseover event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon\n * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseover=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse is over)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseenter\n *\n * @description\n * Specify custom behavior on mouseenter event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon\n * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseenter=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse enters)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMouseleave\n *\n * @description\n * Specify custom behavior on mouseleave event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon\n * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mouseleave=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse leaves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngMousemove\n *\n * @description\n * Specify custom behavior on mousemove event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon\n * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <button ng-mousemove=\"count = count + 1\" ng-init=\"count=0\">\n        Increment (when mouse moves)\n      </button>\n      count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeydown\n *\n * @description\n * Specify custom behavior on keydown event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon\n * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keydown=\"count = count + 1\" ng-init=\"count=0\">\n      key down count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeyup\n *\n * @description\n * Specify custom behavior on keyup event.\n *\n * @element ANY\n * @priority 0\n * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon\n * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n       <p>Typing in the input box below updates the key count</p>\n       <input ng-keyup=\"count = count + 1\" ng-init=\"count=0\"> key up count: {{count}}\n\n       <p>Typing in the input box below updates the keycode</p>\n       <input ng-keyup=\"event=$event\">\n       <p>event keyCode: {{ event.keyCode }}</p>\n       <p>event altKey: {{ event.altKey }}</p>\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngKeypress\n *\n * @description\n * Specify custom behavior on keypress event.\n *\n * @element ANY\n * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon\n * keypress. ({@link guide/expression#-event- Event object is available as `$event`}\n * and can be interrogated for keyCode, altKey, etc.)\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-keypress=\"count = count + 1\" ng-init=\"count=0\">\n      key press count: {{count}}\n     </file>\n   </example>\n */\n\n\n/**\n * @ngdoc directive\n * @name ngSubmit\n *\n * @description\n * Enables binding angular expressions to onsubmit events.\n *\n * Additionally it prevents the default action (which for form means sending the request to the\n * server and reloading the current page), but only if the form does not contain `action`,\n * `data-action`, or `x-action` attributes.\n *\n * <div class=\"alert alert-warning\">\n * **Warning:** Be careful not to cause \"double-submission\" by using both the `ngClick` and\n * `ngSubmit` handlers together. See the\n * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}\n * for a detailed discussion of when `ngSubmit` may be triggered.\n * </div>\n *\n * @element form\n * @priority 0\n * @param {expression} ngSubmit {@link guide/expression Expression} to eval.\n * ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example module=\"submitExample\">\n     <file name=\"index.html\">\n      <script>\n        angular.module('submitExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.list = [];\n            $scope.text = 'hello';\n            $scope.submit = function() {\n              if ($scope.text) {\n                $scope.list.push(this.text);\n                $scope.text = '';\n              }\n            };\n          }]);\n      </script>\n      <form ng-submit=\"submit()\" ng-controller=\"ExampleController\">\n        Enter text and hit enter:\n        <input type=\"text\" ng-model=\"text\" name=\"text\" />\n        <input type=\"submit\" id=\"submit\" value=\"Submit\" />\n        <pre>list={{list}}</pre>\n      </form>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-submit', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n         expect(element(by.model('text')).getAttribute('value')).toBe('');\n       });\n       it('should ignore empty strings', function() {\n         expect(element(by.binding('list')).getText()).toBe('list=[]');\n         element(by.css('#submit')).click();\n         element(by.css('#submit')).click();\n         expect(element(by.binding('list')).getText()).toContain('hello');\n        });\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngFocus\n *\n * @description\n * Specify custom behavior on focus event.\n *\n * Note: As the `focus` event is executed synchronously when calling `input.focus()`\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon\n * focus. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngBlur\n *\n * @description\n * Specify custom behavior on blur event.\n *\n * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when\n * an element has lost focus.\n *\n * Note: As the `blur` event is executed synchronously also during DOM manipulations\n * (e.g. removing a focussed input),\n * AngularJS executes the expression using `scope.$evalAsync` if the event is fired\n * during an `$apply` to ensure a consistent state.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon\n * blur. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n * See {@link ng.directive:ngClick ngClick}\n */\n\n/**\n * @ngdoc directive\n * @name ngCopy\n *\n * @description\n * Specify custom behavior on copy event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon\n * copy. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-copy=\"copied=true\" ng-init=\"copied=false; value='copy me'\" ng-model=\"value\">\n      copied: {{copied}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngCut\n *\n * @description\n * Specify custom behavior on cut event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon\n * cut. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-cut=\"cut=true\" ng-init=\"cut=false; value='cut me'\" ng-model=\"value\">\n      cut: {{cut}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngPaste\n *\n * @description\n * Specify custom behavior on paste event.\n *\n * @element window, input, select, textarea, a\n * @priority 0\n * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon\n * paste. ({@link guide/expression#-event- Event object is available as `$event`})\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n      <input ng-paste=\"paste=true\" ng-init=\"paste=false\" placeholder='paste here'>\n      pasted: {{paste}}\n     </file>\n   </example>\n */\n\n/**\n * @ngdoc directive\n * @name ngIf\n * @restrict A\n *\n * @description\n * The `ngIf` directive removes or recreates a portion of the DOM tree based on an\n * {expression}. If the expression assigned to `ngIf` evaluates to a false\n * value then the element is removed from the DOM, otherwise a clone of the\n * element is reinserted into the DOM.\n *\n * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the\n * element in the DOM rather than changing its visibility via the `display` css property.  A common\n * case when this difference is significant is when using css selectors that rely on an element's\n * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.\n *\n * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope\n * is created when the element is restored.  The scope created within `ngIf` inherits from\n * its parent scope using\n * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).\n * An important implication of this is if `ngModel` is used within `ngIf` to bind to\n * a javascript primitive defined in the parent scope. In this case any modifications made to the\n * variable within the child scope will override (hide) the value in the parent scope.\n *\n * Also, `ngIf` recreates elements using their compiled state. An example of this behavior\n * is if an element's class attribute is directly modified after it's compiled, using something like\n * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element\n * the added class will be lost because the original compiled state is used to regenerate the element.\n *\n * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`\n * and `leave` effects.\n *\n * @animations\n * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container\n * leave - happens just before the `ngIf` contents are removed from the DOM\n *\n * @element ANY\n * @scope\n * @priority 600\n * @param {expression} ngIf If the {@link guide/expression expression} is falsy then\n *     the element is removed from the DOM tree. If it is truthy a copy of the compiled\n *     element is added to the DOM tree.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\" ng-init=\"checked=true\" /><br/>\n      Show when checked:\n      <span ng-if=\"checked\" class=\"animate-if\">\n        I'm removed when the checkbox is unchecked.\n      </span>\n    </file>\n    <file name=\"animations.css\">\n      .animate-if {\n        background:white;\n        border:1px solid black;\n        padding:10px;\n      }\n\n      .animate-if.ng-enter, .animate-if.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n      }\n\n      .animate-if.ng-enter,\n      .animate-if.ng-leave.ng-leave-active {\n        opacity:0;\n      }\n\n      .animate-if.ng-leave,\n      .animate-if.ng-enter.ng-enter-active {\n        opacity:1;\n      }\n    </file>\n  </example>\n */\nvar ngIfDirective = ['$animate', function($animate) {\n  return {\n    transclude: 'element',\n    priority: 600,\n    terminal: true,\n    restrict: 'A',\n    $$tlb: true,\n    link: function ($scope, $element, $attr, ctrl, $transclude) {\n        var block, childScope, previousElements;\n        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {\n\n          if (toBoolean(value)) {\n            if (!childScope) {\n              childScope = $scope.$new();\n              $transclude(childScope, function (clone) {\n                clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block = {\n                  clone: clone\n                };\n                $animate.enter(clone, $element.parent(), $element);\n              });\n            }\n          } else {\n            if(previousElements) {\n              previousElements.remove();\n              previousElements = null;\n            }\n            if(childScope) {\n              childScope.$destroy();\n              childScope = null;\n            }\n            if(block) {\n              previousElements = getBlockElements(block.clone);\n              $animate.leave(previousElements, function() {\n                previousElements = null;\n              });\n              block = null;\n            }\n          }\n        });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngInclude\n * @restrict ECA\n *\n * @description\n * Fetches, compiles and includes an external HTML fragment.\n *\n * By default, the template URL is restricted to the same domain and protocol as the\n * application document. This is done by calling {@link ng.$sce#getTrustedResourceUrl\n * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols\n * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or\n * [wrap them](ng.$sce#trustAsResourceUrl) as trusted values. Refer to Angular's {@link\n * ng.$sce Strict Contextual Escaping}.\n *\n * In addition, the browser's\n * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)\n * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)\n * policy may further restrict whether the template is successfully loaded.\n * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`\n * access on some browsers.\n *\n * @animations\n * enter - animation is used to bring new content into the browser.\n * leave - animation is used to animate existing content away.\n *\n * The enter and leave animation occur concurrently.\n *\n * @scope\n * @priority 400\n *\n * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,\n *                 make sure you wrap it in **single** quotes, e.g. `src=\"'myPartialTemplate.html'\"`.\n * @param {string=} onload Expression to evaluate when a new partial is loaded.\n *\n * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll\n *                  $anchorScroll} to scroll the viewport after the content is loaded.\n *\n *                  - If the attribute is not set, disable scrolling.\n *                  - If the attribute is set without value, enable scrolling.\n *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.\n *\n * @example\n  <example module=\"includeExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n     <div ng-controller=\"ExampleController\">\n       <select ng-model=\"template\" ng-options=\"t.name for t in templates\">\n        <option value=\"\">(blank)</option>\n       </select>\n       url of the template: <tt>{{template.url}}</tt>\n       <hr/>\n       <div class=\"slide-animate-container\">\n         <div class=\"slide-animate\" ng-include=\"template.url\"></div>\n       </div>\n     </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('includeExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.templates =\n            [ { name: 'template1.html', url: 'template1.html'},\n              { name: 'template2.html', url: 'template2.html'} ];\n          $scope.template = $scope.templates[0];\n        }]);\n     </file>\n    <file name=\"template1.html\">\n      Content of template1.html\n    </file>\n    <file name=\"template2.html\">\n      Content of template2.html\n    </file>\n    <file name=\"animations.css\">\n      .slide-animate-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .slide-animate {\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter, .slide-animate.ng-leave {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n        display:block;\n        padding:10px;\n      }\n\n      .slide-animate.ng-enter {\n        top:-50px;\n      }\n      .slide-animate.ng-enter.ng-enter-active {\n        top:0;\n      }\n\n      .slide-animate.ng-leave {\n        top:0;\n      }\n      .slide-animate.ng-leave.ng-leave-active {\n        top:50px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var templateSelect = element(by.model('template'));\n      var includeElem = element(by.css('[ng-include]'));\n\n      it('should load template1.html', function() {\n        expect(includeElem.getText()).toMatch(/Content of template1.html/);\n      });\n\n      it('should load template2.html', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          // See https://github.com/angular/protractor/issues/480\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(2).click();\n        expect(includeElem.getText()).toMatch(/Content of template2.html/);\n      });\n\n      it('should change to blank', function() {\n        if (browser.params.browser == 'firefox') {\n          // Firefox can't handle using selects\n          return;\n        }\n        templateSelect.click();\n        templateSelect.all(by.css('option')).get(0).click();\n        expect(includeElem.isPresent()).toBe(false);\n      });\n    </file>\n  </example>\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentRequested\n * @eventType emit on the scope ngInclude was declared in\n * @description\n * Emitted every time the ngInclude content is requested.\n */\n\n\n/**\n * @ngdoc event\n * @name ngInclude#$includeContentLoaded\n * @eventType emit on the current ngInclude scope\n * @description\n * Emitted every time the ngInclude content is reloaded.\n */\nvar ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',\n                  function($http,   $templateCache,   $anchorScroll,   $animate,   $sce) {\n  return {\n    restrict: 'ECA',\n    priority: 400,\n    terminal: true,\n    transclude: 'element',\n    controller: angular.noop,\n    compile: function(element, attr) {\n      var srcExp = attr.ngInclude || attr.src,\n          onloadExp = attr.onload || '',\n          autoScrollExp = attr.autoscroll;\n\n      return function(scope, $element, $attr, ctrl, $transclude) {\n        var changeCounter = 0,\n            currentScope,\n            previousElement,\n            currentElement;\n\n        var cleanupLastIncludeContent = function() {\n          if(previousElement) {\n            previousElement.remove();\n            previousElement = null;\n          }\n          if(currentScope) {\n            currentScope.$destroy();\n            currentScope = null;\n          }\n          if(currentElement) {\n            $animate.leave(currentElement, function() {\n              previousElement = null;\n            });\n            previousElement = currentElement;\n            currentElement = null;\n          }\n        };\n\n        scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {\n          var afterAnimation = function() {\n            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {\n              $anchorScroll();\n            }\n          };\n          var thisChangeId = ++changeCounter;\n\n          if (src) {\n            $http.get(src, {cache: $templateCache}).success(function(response) {\n              if (thisChangeId !== changeCounter) return;\n              var newScope = scope.$new();\n              ctrl.template = response;\n\n              // Note: This will also link all children of ng-include that were contained in the original\n              // html. If that content contains controllers, ... they could pollute/change the scope.\n              // However, using ng-include on an element with additional content does not make sense...\n              // Note: We can't remove them in the cloneAttchFn of $transclude as that\n              // function is called before linking the content, which would apply child\n              // directives to non existing elements.\n              var clone = $transclude(newScope, function(clone) {\n                cleanupLastIncludeContent();\n                $animate.enter(clone, null, $element, afterAnimation);\n              });\n\n              currentScope = newScope;\n              currentElement = clone;\n\n              currentScope.$emit('$includeContentLoaded');\n              scope.$eval(onloadExp);\n            }).error(function() {\n              if (thisChangeId === changeCounter) cleanupLastIncludeContent();\n            });\n            scope.$emit('$includeContentRequested');\n          } else {\n            cleanupLastIncludeContent();\n            ctrl.template = null;\n          }\n        });\n      };\n    }\n  };\n}];\n\n// This directive is called during the $transclude call of the first `ngInclude` directive.\n// It will replace and compile the content of the element with the loaded template.\n// We need this directive so that the element content is already filled when\n// the link function of another directive on the same element as ngInclude\n// is called.\nvar ngIncludeFillContentDirective = ['$compile',\n  function($compile) {\n    return {\n      restrict: 'ECA',\n      priority: -400,\n      require: 'ngInclude',\n      link: function(scope, $element, $attr, ctrl) {\n        $element.html(ctrl.template);\n        $compile($element.contents())(scope);\n      }\n    };\n  }];\n\n/**\n * @ngdoc directive\n * @name ngInit\n * @restrict AC\n *\n * @description\n * The `ngInit` directive allows you to evaluate an expression in the\n * current scope.\n *\n * <div class=\"alert alert-error\">\n * The only appropriate use of `ngInit` is for aliasing special properties of\n * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you\n * should use {@link guide/controller controllers} rather than `ngInit`\n * to initialize values on a scope.\n * </div>\n * <div class=\"alert alert-warning\">\n * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make\n * sure you have parenthesis for correct precedence:\n * <pre class=\"prettyprint\">\n *   <div ng-init=\"test1 = (data | orderBy:'name')\"></div>\n * </pre>\n * </div>\n *\n * @priority 450\n *\n * @element ANY\n * @param {expression} ngInit {@link guide/expression Expression} to eval.\n *\n * @example\n   <example module=\"initExample\">\n     <file name=\"index.html\">\n   <script>\n     angular.module('initExample', [])\n       .controller('ExampleController', ['$scope', function($scope) {\n         $scope.list = [['a', 'b'], ['c', 'd']];\n       }]);\n   </script>\n   <div ng-controller=\"ExampleController\">\n     <div ng-repeat=\"innerList in list\" ng-init=\"outerIndex = $index\">\n       <div ng-repeat=\"value in innerList\" ng-init=\"innerIndex = $index\">\n          <span class=\"example-init\">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>\n       </div>\n     </div>\n   </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       it('should alias index positions', function() {\n         var elements = element.all(by.css('.example-init'));\n         expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');\n         expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');\n         expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');\n         expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');\n       });\n     </file>\n   </example>\n */\nvar ngInitDirective = ngDirective({\n  priority: 450,\n  compile: function() {\n    return {\n      pre: function(scope, element, attrs) {\n        scope.$eval(attrs.ngInit);\n      }\n    };\n  }\n});\n\n/**\n * @ngdoc directive\n * @name ngNonBindable\n * @restrict AC\n * @priority 1000\n *\n * @description\n * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current\n * DOM element. This is useful if the element contains what appears to be Angular directives and\n * bindings but which should be ignored by Angular. This could be the case if you have a site that\n * displays snippets of code, for instance.\n *\n * @element ANY\n *\n * @example\n * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,\n * but the one wrapped in `ngNonBindable` is left alone.\n *\n * @example\n    <example>\n      <file name=\"index.html\">\n        <div>Normal: {{1 + 2}}</div>\n        <div ng-non-bindable>Ignored: {{1 + 2}}</div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n       it('should check ng-non-bindable', function() {\n         expect(element(by.binding('1 + 2')).getText()).toContain('3');\n         expect(element.all(by.css('div')).last().getText()).toMatch(/1 \\+ 2/);\n       });\n      </file>\n    </example>\n */\nvar ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });\n\n/**\n * @ngdoc directive\n * @name ngPluralize\n * @restrict EA\n *\n * @description\n * `ngPluralize` is a directive that displays messages according to en-US localization rules.\n * These rules are bundled with angular.js, but can be overridden\n * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive\n * by specifying the mappings between\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * and the strings to be displayed.\n *\n * # Plural categories and explicit number rules\n * There are two\n * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)\n * in Angular's default en-US locale: \"one\" and \"other\".\n *\n * While a plural category may match many numbers (for example, in en-US locale, \"other\" can match\n * any number that is not 1), an explicit number rule can only match one number. For example, the\n * explicit number rule for \"3\" matches the number 3. There are examples of plural categories\n * and explicit number rules throughout the rest of this documentation.\n *\n * # Configuring ngPluralize\n * You configure ngPluralize by providing 2 attributes: `count` and `when`.\n * You can also provide an optional attribute, `offset`.\n *\n * The value of the `count` attribute can be either a string or an {@link guide/expression\n * Angular expression}; these are evaluated on the current scope for its bound value.\n *\n * The `when` attribute specifies the mappings between plural categories and the actual\n * string to be displayed. The value of the attribute should be a JSON object.\n *\n * The following example shows how to configure ngPluralize:\n *\n * ```html\n * <ng-pluralize count=\"personCount\"\n                 when=\"{'0': 'Nobody is viewing.',\n *                      'one': '1 person is viewing.',\n *                      'other': '{} people are viewing.'}\">\n * </ng-pluralize>\n *```\n *\n * In the example, `\"0: Nobody is viewing.\"` is an explicit number rule. If you did not\n * specify this rule, 0 would be matched to the \"other\" category and \"0 people are viewing\"\n * would be shown instead of \"Nobody is viewing\". You can specify an explicit number rule for\n * other numbers, for example 12, so that instead of showing \"12 people are viewing\", you can\n * show \"a dozen people are viewing\".\n *\n * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted\n * into pluralized strings. In the previous example, Angular will replace `{}` with\n * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder\n * for <span ng-non-bindable>{{numberExpression}}</span>.\n *\n * # Configuring ngPluralize with offset\n * The `offset` attribute allows further customization of pluralized text, which can result in\n * a better user experience. For example, instead of the message \"4 people are viewing this document\",\n * you might display \"John, Kate and 2 others are viewing this document\".\n * The offset attribute allows you to offset a number by any desired value.\n * Let's take a look at an example:\n *\n * ```html\n * <ng-pluralize count=\"personCount\" offset=2\n *               when=\"{'0': 'Nobody is viewing.',\n *                      '1': '{{person1}} is viewing.',\n *                      '2': '{{person1}} and {{person2}} are viewing.',\n *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',\n *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n * </ng-pluralize>\n * ```\n *\n * Notice that we are still using two plural categories(one, other), but we added\n * three explicit number rules 0, 1 and 2.\n * When one person, perhaps John, views the document, \"John is viewing\" will be shown.\n * When three people view the document, no explicit number rule is found, so\n * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.\n * In this case, plural category 'one' is matched and \"John, Mary and one other person are viewing\"\n * is shown.\n *\n * Note that when you specify offsets, you must provide explicit number rules for\n * numbers from 0 up to and including the offset. If you use an offset of 3, for example,\n * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for\n * plural categories \"one\" and \"other\".\n *\n * @param {string|expression} count The variable to be bound to.\n * @param {string} when The mapping between plural category to its corresponding strings.\n * @param {number=} offset Offset to deduct from the total number.\n *\n * @example\n    <example module=\"pluralizeExample\">\n      <file name=\"index.html\">\n        <script>\n          angular.module('pluralizeExample', [])\n            .controller('ExampleController', ['$scope', function($scope) {\n              $scope.person1 = 'Igor';\n              $scope.person2 = 'Misko';\n              $scope.personCount = 1;\n            }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          Person 1:<input type=\"text\" ng-model=\"person1\" value=\"Igor\" /><br/>\n          Person 2:<input type=\"text\" ng-model=\"person2\" value=\"Misko\" /><br/>\n          Number of People:<input type=\"text\" ng-model=\"personCount\" value=\"1\" /><br/>\n\n          <!--- Example with simple pluralization rules for en locale --->\n          Without Offset:\n          <ng-pluralize count=\"personCount\"\n                        when=\"{'0': 'Nobody is viewing.',\n                               'one': '1 person is viewing.',\n                               'other': '{} people are viewing.'}\">\n          </ng-pluralize><br>\n\n          <!--- Example with offset --->\n          With Offset(2):\n          <ng-pluralize count=\"personCount\" offset=2\n                        when=\"{'0': 'Nobody is viewing.',\n                               '1': '{{person1}} is viewing.',\n                               '2': '{{person1}} and {{person2}} are viewing.',\n                               'one': '{{person1}}, {{person2}} and one other person are viewing.',\n                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}\">\n          </ng-pluralize>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n        it('should show correct pluralized string', function() {\n          var withoutOffset = element.all(by.css('ng-pluralize')).get(0);\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var countInput = element(by.model('personCount'));\n\n          expect(withoutOffset.getText()).toEqual('1 person is viewing.');\n          expect(withOffset.getText()).toEqual('Igor is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('0');\n\n          expect(withoutOffset.getText()).toEqual('Nobody is viewing.');\n          expect(withOffset.getText()).toEqual('Nobody is viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('2');\n\n          expect(withoutOffset.getText()).toEqual('2 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('3');\n\n          expect(withoutOffset.getText()).toEqual('3 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');\n\n          countInput.clear();\n          countInput.sendKeys('4');\n\n          expect(withoutOffset.getText()).toEqual('4 people are viewing.');\n          expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');\n        });\n        it('should show data-bound names', function() {\n          var withOffset = element.all(by.css('ng-pluralize')).get(1);\n          var personCount = element(by.model('personCount'));\n          var person1 = element(by.model('person1'));\n          var person2 = element(by.model('person2'));\n          personCount.clear();\n          personCount.sendKeys('4');\n          person1.clear();\n          person1.sendKeys('Di');\n          person2.clear();\n          person2.sendKeys('Vojta');\n          expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');\n        });\n      </file>\n    </example>\n */\nvar ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {\n  var BRACE = /{}/g;\n  return {\n    restrict: 'EA',\n    link: function(scope, element, attr) {\n      var numberExp = attr.count,\n          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs\n          offset = attr.offset || 0,\n          whens = scope.$eval(whenExp) || {},\n          whensExpFns = {},\n          startSymbol = $interpolate.startSymbol(),\n          endSymbol = $interpolate.endSymbol(),\n          isWhen = /^when(Minus)?(.+)$/;\n\n      forEach(attr, function(expression, attributeName) {\n        if (isWhen.test(attributeName)) {\n          whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =\n            element.attr(attr.$attr[attributeName]);\n        }\n      });\n      forEach(whens, function(expression, key) {\n        whensExpFns[key] =\n          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +\n            offset + endSymbol));\n      });\n\n      scope.$watch(function ngPluralizeWatch() {\n        var value = parseFloat(scope.$eval(numberExp));\n\n        if (!isNaN(value)) {\n          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,\n          //check it against pluralization rules in $locale service\n          if (!(value in whens)) value = $locale.pluralCat(value - offset);\n           return whensExpFns[value](scope, element, true);\n        } else {\n          return '';\n        }\n      }, function ngPluralizeWatchAction(newVal) {\n        element.text(newVal);\n      });\n    }\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngRepeat\n *\n * @description\n * The `ngRepeat` directive instantiates a template once per item from a collection. Each template\n * instance gets its own scope, where the given loop variable is set to the current collection item,\n * and `$index` is set to the item index or key.\n *\n * Special properties are exposed on the local scope of each template instance, including:\n *\n * | Variable  | Type            | Details                                                                     |\n * |-----------|-----------------|-----------------------------------------------------------------------------|\n * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |\n * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |\n * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |\n * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |\n * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |\n * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |\n *\n * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.\n * This may be useful when, for instance, nesting ngRepeats.\n *\n * # Special repeat start and end points\n * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending\n * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.\n * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)\n * up to and including the ending HTML tag where **ng-repeat-end** is placed.\n *\n * The example below makes use of this feature:\n * ```html\n *   <header ng-repeat-start=\"item in items\">\n *     Header {{ item }}\n *   </header>\n *   <div class=\"body\">\n *     Body {{ item }}\n *   </div>\n *   <footer ng-repeat-end>\n *     Footer {{ item }}\n *   </footer>\n * ```\n *\n * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:\n * ```html\n *   <header>\n *     Header A\n *   </header>\n *   <div class=\"body\">\n *     Body A\n *   </div>\n *   <footer>\n *     Footer A\n *   </footer>\n *   <header>\n *     Header B\n *   </header>\n *   <div class=\"body\">\n *     Body B\n *   </div>\n *   <footer>\n *     Footer B\n *   </footer>\n * ```\n *\n * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such\n * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).\n *\n * @animations\n * **.enter** - when a new item is added to the list or when an item is revealed after a filter\n *\n * **.leave** - when an item is removed from the list or when an item is filtered out\n *\n * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered\n *\n * @element ANY\n * @scope\n * @priority 1000\n * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These\n *   formats are currently supported:\n *\n *   * `variable in expression` – where variable is the user defined loop variable and `expression`\n *     is a scope expression giving the collection to enumerate.\n *\n *     For example: `album in artist.albums`.\n *\n *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,\n *     and `expression` is the scope expression giving the collection to enumerate.\n *\n *     For example: `(name, age) in {'adam':10, 'amalie':12}`.\n *\n *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking function\n *     which can be used to associate the objects in the collection with the DOM elements. If no tracking function\n *     is specified the ng-repeat associates elements by identity in the collection. It is an error to have\n *     more than one tracking function to resolve to the same key. (This would mean that two distinct objects are\n *     mapped to the same DOM element, which is not possible.)  Filters should be applied to the expression,\n *     before specifying a tracking expression.\n *\n *     For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements\n *     will be associated by item identity in the array.\n *\n *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique\n *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements\n *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM\n *     element in the same way in the DOM.\n *\n *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this\n *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`\n *     property is same.\n *\n *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter\n *     to items in conjunction with a tracking expression.\n *\n * @example\n * This example initializes the scope to a list of names and\n * then uses `ngRepeat` to display every person:\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-init=\"friends = [\n        {name:'John', age:25, gender:'boy'},\n        {name:'Jessie', age:30, gender:'girl'},\n        {name:'Johanna', age:28, gender:'girl'},\n        {name:'Joy', age:15, gender:'girl'},\n        {name:'Mary', age:28, gender:'girl'},\n        {name:'Peter', age:95, gender:'boy'},\n        {name:'Sebastian', age:50, gender:'boy'},\n        {name:'Erika', age:27, gender:'girl'},\n        {name:'Patrick', age:40, gender:'boy'},\n        {name:'Samantha', age:60, gender:'girl'}\n      ]\">\n        I have {{friends.length}} friends. They are:\n        <input type=\"search\" ng-model=\"q\" placeholder=\"filter friends...\" />\n        <ul class=\"example-animate-container\">\n          <li class=\"animate-repeat\" ng-repeat=\"friend in friends | filter:q\">\n            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.\n          </li>\n        </ul>\n      </div>\n    </file>\n    <file name=\"animations.css\">\n      .example-animate-container {\n        background:white;\n        border:1px solid black;\n        list-style:none;\n        margin:0;\n        padding:0 10px;\n      }\n\n      .animate-repeat {\n        line-height:40px;\n        list-style:none;\n        box-sizing:border-box;\n      }\n\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter,\n      .animate-repeat.ng-leave {\n        -webkit-transition:all linear 0.5s;\n        transition:all linear 0.5s;\n      }\n\n      .animate-repeat.ng-leave.ng-leave-active,\n      .animate-repeat.ng-move,\n      .animate-repeat.ng-enter {\n        opacity:0;\n        max-height:0;\n      }\n\n      .animate-repeat.ng-leave,\n      .animate-repeat.ng-move.ng-move-active,\n      .animate-repeat.ng-enter.ng-enter-active {\n        opacity:1;\n        max-height:40px;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var friends = element.all(by.repeater('friend in friends'));\n\n      it('should render initial data set', function() {\n        expect(friends.count()).toBe(10);\n        expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');\n        expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');\n        expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');\n        expect(element(by.binding('friends.length')).getText())\n            .toMatch(\"I have 10 friends. They are:\");\n      });\n\n       it('should update repeater when filter predicate changes', function() {\n         expect(friends.count()).toBe(10);\n\n         element(by.model('q')).sendKeys('ma');\n\n         expect(friends.count()).toBe(2);\n         expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');\n         expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');\n       });\n      </file>\n    </example>\n */\nvar ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {\n  var NG_REMOVED = '$$NG_REMOVED';\n  var ngRepeatMinErr = minErr('ngRepeat');\n  return {\n    transclude: 'element',\n    priority: 1000,\n    terminal: true,\n    $$tlb: true,\n    link: function($scope, $element, $attr, ctrl, $transclude){\n        var expression = $attr.ngRepeat;\n        var match = expression.match(/^\\s*([\\s\\S]+?)\\s+in\\s+([\\s\\S]+?)(?:\\s+track\\s+by\\s+([\\s\\S]+?))?\\s*$/),\n          trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,\n          lhs, rhs, valueIdentifier, keyIdentifier,\n          hashFnLocals = {$id: hashKey};\n\n        if (!match) {\n          throw ngRepeatMinErr('iexp', \"Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.\",\n            expression);\n        }\n\n        lhs = match[1];\n        rhs = match[2];\n        trackByExp = match[3];\n\n        if (trackByExp) {\n          trackByExpGetter = $parse(trackByExp);\n          trackByIdExpFn = function(key, value, index) {\n            // assign key, value, and $index to the locals so that they can be used in hash functions\n            if (keyIdentifier) hashFnLocals[keyIdentifier] = key;\n            hashFnLocals[valueIdentifier] = value;\n            hashFnLocals.$index = index;\n            return trackByExpGetter($scope, hashFnLocals);\n          };\n        } else {\n          trackByIdArrayFn = function(key, value) {\n            return hashKey(value);\n          };\n          trackByIdObjFn = function(key) {\n            return key;\n          };\n        }\n\n        match = lhs.match(/^(?:([\\$\\w]+)|\\(([\\$\\w]+)\\s*,\\s*([\\$\\w]+)\\))$/);\n        if (!match) {\n          throw ngRepeatMinErr('iidexp', \"'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.\",\n                                                                    lhs);\n        }\n        valueIdentifier = match[3] || match[1];\n        keyIdentifier = match[2];\n\n        // Store a list of elements from previous run. This is a hash where key is the item from the\n        // iterator, and the value is objects with following properties.\n        //   - scope: bound scope\n        //   - element: previous element.\n        //   - index: position\n        var lastBlockMap = {};\n\n        //watch props\n        $scope.$watchCollection(rhs, function ngRepeatAction(collection){\n          var index, length,\n              previousNode = $element[0],     // current position of the node\n              nextNode,\n              // Same as lastBlockMap but it has the current state. It will become the\n              // lastBlockMap on the next iteration.\n              nextBlockMap = {},\n              arrayLength,\n              childScope,\n              key, value, // key/value of iteration\n              trackById,\n              trackByIdFn,\n              collectionKeys,\n              block,       // last object information {scope, element, id}\n              nextBlockOrder = [],\n              elementsToRemove;\n\n\n          if (isArrayLike(collection)) {\n            collectionKeys = collection;\n            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;\n          } else {\n            trackByIdFn = trackByIdExpFn || trackByIdObjFn;\n            // if object, extract keys, sort them and use to determine order of iteration over obj props\n            collectionKeys = [];\n            for (key in collection) {\n              if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {\n                collectionKeys.push(key);\n              }\n            }\n            collectionKeys.sort();\n          }\n\n          arrayLength = collectionKeys.length;\n\n          // locate existing items\n          length = nextBlockOrder.length = collectionKeys.length;\n          for(index = 0; index < length; index++) {\n           key = (collection === collectionKeys) ? index : collectionKeys[index];\n           value = collection[key];\n           trackById = trackByIdFn(key, value, index);\n           assertNotHasOwnProperty(trackById, '`track by` id');\n           if(lastBlockMap.hasOwnProperty(trackById)) {\n             block = lastBlockMap[trackById];\n             delete lastBlockMap[trackById];\n             nextBlockMap[trackById] = block;\n             nextBlockOrder[index] = block;\n           } else if (nextBlockMap.hasOwnProperty(trackById)) {\n             // restore lastBlockMap\n             forEach(nextBlockOrder, function(block) {\n               if (block && block.scope) lastBlockMap[block.id] = block;\n             });\n             // This is a duplicate and we need to throw an error\n             throw ngRepeatMinErr('dupes',\n                  \"Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}\",\n                  expression, trackById, toJson(value));\n           } else {\n             // new never before seen block\n             nextBlockOrder[index] = { id: trackById };\n             nextBlockMap[trackById] = false;\n           }\n         }\n\n          // remove existing items\n          for (key in lastBlockMap) {\n            // lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn\n            if (lastBlockMap.hasOwnProperty(key)) {\n              block = lastBlockMap[key];\n              elementsToRemove = getBlockElements(block.clone);\n              $animate.leave(elementsToRemove);\n              forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });\n              block.scope.$destroy();\n            }\n          }\n\n          // we are not using forEach for perf reasons (trying to avoid #call)\n          for (index = 0, length = collectionKeys.length; index < length; index++) {\n            key = (collection === collectionKeys) ? index : collectionKeys[index];\n            value = collection[key];\n            block = nextBlockOrder[index];\n            if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);\n\n            if (block.scope) {\n              // if we have already seen this object, then we need to reuse the\n              // associated scope/element\n              childScope = block.scope;\n\n              nextNode = previousNode;\n              do {\n                nextNode = nextNode.nextSibling;\n              } while(nextNode && nextNode[NG_REMOVED]);\n\n              if (getBlockStart(block) != nextNode) {\n                // existing item which got moved\n                $animate.move(getBlockElements(block.clone), null, jqLite(previousNode));\n              }\n              previousNode = getBlockEnd(block);\n            } else {\n              // new item which we don't know about\n              childScope = $scope.$new();\n            }\n\n            childScope[valueIdentifier] = value;\n            if (keyIdentifier) childScope[keyIdentifier] = key;\n            childScope.$index = index;\n            childScope.$first = (index === 0);\n            childScope.$last = (index === (arrayLength - 1));\n            childScope.$middle = !(childScope.$first || childScope.$last);\n            // jshint bitwise: false\n            childScope.$odd = !(childScope.$even = (index&1) === 0);\n            // jshint bitwise: true\n\n            if (!block.scope) {\n              $transclude(childScope, function(clone) {\n                clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');\n                $animate.enter(clone, null, jqLite(previousNode));\n                previousNode = clone;\n                block.scope = childScope;\n                // Note: We only need the first/last node of the cloned nodes.\n                // However, we need to keep the reference to the jqlite wrapper as it might be changed later\n                // by a directive with templateUrl when its template arrives.\n                block.clone = clone;\n                nextBlockMap[block.id] = block;\n              });\n            }\n          }\n          lastBlockMap = nextBlockMap;\n        });\n    }\n  };\n\n  function getBlockStart(block) {\n    return block.clone[0];\n  }\n\n  function getBlockEnd(block) {\n    return block.clone[block.clone.length - 1];\n  }\n}];\n\n/**\n * @ngdoc directive\n * @name ngShow\n *\n * @description\n * The `ngShow` directive shows or hides the given HTML element based on the expression\n * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding\n * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is visible) -->\n * <div ng-show=\"myValue\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is hidden) -->\n * <div ng-show=\"myValue\" class=\"ng-hide\"></div>\n * ```\n *\n * When the `ngShow` expression evaluates to false then the `.ng-hide` CSS class is added to the class attribute\n * on the element causing it to become hidden. When true, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />\n * \"f\" / \"0\" / \"false\" / \"no\" / \"n\" / \"[]\"\n * </div>\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class in CSS:\n *\n * ```css\n * .ng-hide {\n *   //this is just another form of hiding an element\n *   display:block!important;\n *   position:absolute;\n *   top:-9999px;\n *   left:-9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngShow`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass except that\n * you must also include the !important flag to override the display property\n * so that you can perform an animation when the element is hidden during the time of the animation.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition:0.5s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible\n * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden\n *\n * @element ANY\n * @param {expression} ngShow If the {@link guide/expression expression} is truthy\n *     then the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-show\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-show\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-show {\n        -webkit-transition:all linear 0.5s;\n        transition:all linear 0.5s;\n        line-height:20px;\n        opacity:1;\n        padding:10px;\n        border:1px solid black;\n        background:white;\n      }\n\n      .animate-show.ng-hide {\n        line-height:0;\n        opacity:0;\n        padding:0 10px;\n      }\n\n      .check-element {\n        padding:10px;\n        border:1px solid black;\n        background:white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngShowDirective = ['$animate', function($animate) {\n  return function(scope, element, attr) {\n    scope.$watch(attr.ngShow, function ngShowWatchAction(value){\n      $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');\n    });\n  };\n}];\n\n\n/**\n * @ngdoc directive\n * @name ngHide\n *\n * @description\n * The `ngHide` directive shows or hides the given HTML element based on the expression\n * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding\n * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined\n * in AngularJS and sets the display style to none (using an !important flag).\n * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).\n *\n * ```html\n * <!-- when $scope.myValue is truthy (element is hidden) -->\n * <div ng-hide=\"myValue\" class=\"ng-hide\"></div>\n *\n * <!-- when $scope.myValue is falsy (element is visible) -->\n * <div ng-hide=\"myValue\"></div>\n * ```\n *\n * When the `.ngHide` expression evaluates to true then the `.ng-hide` CSS class is added to the class attribute\n * on the element causing it to become hidden. When false, the `.ng-hide` CSS class is removed\n * from the element causing the element not to appear hidden.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />\n * \"f\" / \"0\" / \"false\" / \"no\" / \"n\" / \"[]\"\n * </div>\n *\n * ## Why is !important used?\n *\n * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector\n * can be easily overridden by heavier selectors. For example, something as simple\n * as changing the display style on a HTML list item would make hidden elements appear visible.\n * This also becomes a bigger issue when dealing with CSS frameworks.\n *\n * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector\n * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the\n * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.\n *\n * ### Overriding `.ng-hide`\n *\n * By default, the `.ng-hide` class will style the element with `display:none!important`. If you wish to change\n * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`\n * class in CSS:\n *\n * ```css\n * .ng-hide {\n *   //this is just another form of hiding an element\n *   display:block!important;\n *   position:absolute;\n *   top:-9999px;\n *   left:-9999px;\n * }\n * ```\n *\n * By default you don't need to override in CSS anything and the animations will work around the display style.\n *\n * ## A note about animations with `ngHide`\n *\n * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression\n * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`\n * CSS class is added and removed for you instead of your own CSS class.\n *\n * ```css\n * //\n * //a working example can be found at the bottom of this page\n * //\n * .my-element.ng-hide-add, .my-element.ng-hide-remove {\n *   transition:0.5s linear all;\n * }\n *\n * .my-element.ng-hide-add { ... }\n * .my-element.ng-hide-add.ng-hide-add-active { ... }\n * .my-element.ng-hide-remove { ... }\n * .my-element.ng-hide-remove.ng-hide-remove-active { ... }\n * ```\n *\n * Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display\n * property to block during animation states--ngAnimate will handle the style toggling automatically for you.\n *\n * @animations\n * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden\n * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible\n *\n * @element ANY\n * @param {expression} ngHide If the {@link guide/expression expression} is truthy then\n *     the element is shown or hidden respectively.\n *\n * @example\n  <example module=\"ngAnimate\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      Click me: <input type=\"checkbox\" ng-model=\"checked\"><br/>\n      <div>\n        Show:\n        <div class=\"check-element animate-hide\" ng-show=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-up\"></span> I show up when your checkbox is checked.\n        </div>\n      </div>\n      <div>\n        Hide:\n        <div class=\"check-element animate-hide\" ng-hide=\"checked\">\n          <span class=\"glyphicon glyphicon-thumbs-down\"></span> I hide when your checkbox is checked.\n        </div>\n      </div>\n    </file>\n    <file name=\"glyphicons.css\">\n      @import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css);\n    </file>\n    <file name=\"animations.css\">\n      .animate-hide {\n        -webkit-transition:all linear 0.5s;\n        transition:all linear 0.5s;\n        line-height:20px;\n        opacity:1;\n        padding:10px;\n        border:1px solid black;\n        background:white;\n      }\n\n      .animate-hide.ng-hide {\n        line-height:0;\n        opacity:0;\n        padding:0 10px;\n      }\n\n      .check-element {\n        padding:10px;\n        border:1px solid black;\n        background:white;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));\n      var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));\n\n      it('should check ng-show / ng-hide', function() {\n        expect(thumbsUp.isDisplayed()).toBeFalsy();\n        expect(thumbsDown.isDisplayed()).toBeTruthy();\n\n        element(by.model('checked')).click();\n\n        expect(thumbsUp.isDisplayed()).toBeTruthy();\n        expect(thumbsDown.isDisplayed()).toBeFalsy();\n      });\n    </file>\n  </example>\n */\nvar ngHideDirective = ['$animate', function($animate) {\n  return function(scope, element, attr) {\n    scope.$watch(attr.ngHide, function ngHideWatchAction(value){\n      $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');\n    });\n  };\n}];\n\n/**\n * @ngdoc directive\n * @name ngStyle\n * @restrict AC\n *\n * @description\n * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.\n *\n * @element ANY\n * @param {expression} ngStyle\n *\n * {@link guide/expression Expression} which evals to an\n * object whose keys are CSS style names and values are corresponding values for those CSS\n * keys.\n *\n * Since some CSS style names are not valid keys for an object, they must be quoted.\n * See the 'background-color' style in the example below.\n *\n * @example\n   <example>\n     <file name=\"index.html\">\n        <input type=\"button\" value=\"set color\" ng-click=\"myStyle={color:'red'}\">\n        <input type=\"button\" value=\"set background\" ng-click=\"myStyle={'background-color':'blue'}\">\n        <input type=\"button\" value=\"clear\" ng-click=\"myStyle={}\">\n        <br/>\n        <span ng-style=\"myStyle\">Sample Text</span>\n        <pre>myStyle={{myStyle}}</pre>\n     </file>\n     <file name=\"style.css\">\n       span {\n         color: black;\n       }\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n       var colorSpan = element(by.css('span'));\n\n       it('should check ng-style', function() {\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n         element(by.css('input[value=\\'set color\\']')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');\n         element(by.css('input[value=clear]')).click();\n         expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');\n       });\n     </file>\n   </example>\n */\nvar ngStyleDirective = ngDirective(function(scope, element, attr) {\n  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {\n    if (oldStyles && (newStyles !== oldStyles)) {\n      forEach(oldStyles, function(val, style) { element.css(style, '');});\n    }\n    if (newStyles) element.css(newStyles);\n  }, true);\n});\n\n/**\n * @ngdoc directive\n * @name ngSwitch\n * @restrict EA\n *\n * @description\n * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.\n * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location\n * as specified in the template.\n *\n * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it\n * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element\n * matches the value obtained from the evaluated expression. In other words, you define a container element\n * (where you place the directive), place an expression on the **`on=\"...\"` attribute**\n * (or the **`ng-switch=\"...\"` attribute**), define any inner elements inside of the directive and place\n * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on\n * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default\n * attribute is displayed.\n *\n * <div class=\"alert alert-info\">\n * Be aware that the attribute values to match against cannot be expressions. They are interpreted\n * as literal string values to match against.\n * For example, **`ng-switch-when=\"someVal\"`** will match against the string `\"someVal\"` not against the\n * value of the expression `$scope.someVal`.\n * </div>\n\n * @animations\n * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container\n * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM\n *\n * @usage\n *\n * ```\n * <ANY ng-switch=\"expression\">\n *   <ANY ng-switch-when=\"matchValue1\">...</ANY>\n *   <ANY ng-switch-when=\"matchValue2\">...</ANY>\n *   <ANY ng-switch-default>...</ANY>\n * </ANY>\n * ```\n *\n *\n * @scope\n * @priority 800\n * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.\n * On child elements add:\n *\n * * `ngSwitchWhen`: the case statement to match against. If match then this\n *   case will be displayed. If the same match appears multiple times, all the\n *   elements will be displayed.\n * * `ngSwitchDefault`: the default case when no other case match. If there\n *   are multiple default cases, all of them will be displayed when no other\n *   case match.\n *\n *\n * @example\n  <example module=\"switchExample\" deps=\"angular-animate.js\" animations=\"true\">\n    <file name=\"index.html\">\n      <div ng-controller=\"ExampleController\">\n        <select ng-model=\"selection\" ng-options=\"item for item in items\">\n        </select>\n        <tt>selection={{selection}}</tt>\n        <hr/>\n        <div class=\"animate-switch-container\"\n          ng-switch on=\"selection\">\n            <div class=\"animate-switch\" ng-switch-when=\"settings\">Settings Div</div>\n            <div class=\"animate-switch\" ng-switch-when=\"home\">Home Span</div>\n            <div class=\"animate-switch\" ng-switch-default>default</div>\n        </div>\n      </div>\n    </file>\n    <file name=\"script.js\">\n      angular.module('switchExample', ['ngAnimate'])\n        .controller('ExampleController', ['$scope', function($scope) {\n          $scope.items = ['settings', 'home', 'other'];\n          $scope.selection = $scope.items[0];\n        }]);\n    </file>\n    <file name=\"animations.css\">\n      .animate-switch-container {\n        position:relative;\n        background:white;\n        border:1px solid black;\n        height:40px;\n        overflow:hidden;\n      }\n\n      .animate-switch {\n        padding:10px;\n      }\n\n      .animate-switch.ng-animate {\n        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;\n\n        position:absolute;\n        top:0;\n        left:0;\n        right:0;\n        bottom:0;\n      }\n\n      .animate-switch.ng-leave.ng-leave-active,\n      .animate-switch.ng-enter {\n        top:-50px;\n      }\n      .animate-switch.ng-leave,\n      .animate-switch.ng-enter.ng-enter-active {\n        top:0;\n      }\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      var switchElem = element(by.css('[ng-switch]'));\n      var select = element(by.model('selection'));\n\n      it('should start in settings', function() {\n        expect(switchElem.getText()).toMatch(/Settings Div/);\n      });\n      it('should change to home', function() {\n        select.all(by.css('option')).get(1).click();\n        expect(switchElem.getText()).toMatch(/Home Span/);\n      });\n      it('should select default', function() {\n        select.all(by.css('option')).get(2).click();\n        expect(switchElem.getText()).toMatch(/default/);\n      });\n    </file>\n  </example>\n */\nvar ngSwitchDirective = ['$animate', function($animate) {\n  return {\n    restrict: 'EA',\n    require: 'ngSwitch',\n\n    // asks for $scope to fool the BC controller module\n    controller: ['$scope', function ngSwitchController() {\n     this.cases = {};\n    }],\n    link: function(scope, element, attr, ngSwitchController) {\n      var watchExpr = attr.ngSwitch || attr.on,\n          selectedTranscludes = [],\n          selectedElements = [],\n          previousElements = [],\n          selectedScopes = [];\n\n      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {\n        var i, ii;\n        for (i = 0, ii = previousElements.length; i < ii; ++i) {\n          previousElements[i].remove();\n        }\n        previousElements.length = 0;\n\n        for (i = 0, ii = selectedScopes.length; i < ii; ++i) {\n          var selected = selectedElements[i];\n          selectedScopes[i].$destroy();\n          previousElements[i] = selected;\n          $animate.leave(selected, function() {\n            previousElements.splice(i, 1);\n          });\n        }\n\n        selectedElements.length = 0;\n        selectedScopes.length = 0;\n\n        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {\n          scope.$eval(attr.change);\n          forEach(selectedTranscludes, function(selectedTransclude) {\n            var selectedScope = scope.$new();\n            selectedScopes.push(selectedScope);\n            selectedTransclude.transclude(selectedScope, function(caseElement) {\n              var anchor = selectedTransclude.element;\n\n              selectedElements.push(caseElement);\n              $animate.enter(caseElement, anchor.parent(), anchor);\n            });\n          });\n        }\n      });\n    }\n  };\n}];\n\nvar ngSwitchWhenDirective = ngDirective({\n  transclude: 'element',\n  priority: 800,\n  require: '^ngSwitch',\n  link: function(scope, element, attrs, ctrl, $transclude) {\n    ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);\n    ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });\n  }\n});\n\nvar ngSwitchDefaultDirective = ngDirective({\n  transclude: 'element',\n  priority: 800,\n  require: '^ngSwitch',\n  link: function(scope, element, attr, ctrl, $transclude) {\n    ctrl.cases['?'] = (ctrl.cases['?'] || []);\n    ctrl.cases['?'].push({ transclude: $transclude, element: element });\n   }\n});\n\n/**\n * @ngdoc directive\n * @name ngTransclude\n * @restrict AC\n *\n * @description\n * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.\n *\n * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.\n *\n * @element ANY\n *\n * @example\n   <example module=\"transcludeExample\">\n     <file name=\"index.html\">\n       <script>\n         angular.module('transcludeExample', [])\n          .directive('pane', function(){\n             return {\n               restrict: 'E',\n               transclude: true,\n               scope: { title:'@' },\n               template: '<div style=\"border: 1px solid black;\">' +\n                           '<div style=\"background-color: gray\">{{title}}</div>' +\n                           '<div ng-transclude></div>' +\n                         '</div>'\n             };\n         })\n         .controller('ExampleController', ['$scope', function($scope) {\n           $scope.title = 'Lorem Ipsum';\n           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';\n         }]);\n       </script>\n       <div ng-controller=\"ExampleController\">\n         <input ng-model=\"title\"><br>\n         <textarea ng-model=\"text\"></textarea> <br/>\n         <pane title=\"{{title}}\">{{text}}</pane>\n       </div>\n     </file>\n     <file name=\"protractor.js\" type=\"protractor\">\n        it('should have transcluded', function() {\n          var titleElement = element(by.model('title'));\n          titleElement.clear();\n          titleElement.sendKeys('TITLE');\n          var textElement = element(by.model('text'));\n          textElement.clear();\n          textElement.sendKeys('TEXT');\n          expect(element(by.binding('title')).getText()).toEqual('TITLE');\n          expect(element(by.binding('text')).getText()).toEqual('TEXT');\n        });\n     </file>\n   </example>\n *\n */\nvar ngTranscludeDirective = ngDirective({\n  link: function($scope, $element, $attrs, controller, $transclude) {\n    if (!$transclude) {\n      throw minErr('ngTransclude')('orphan',\n       'Illegal use of ngTransclude directive in the template! ' +\n       'No parent directive that requires a transclusion found. ' +\n       'Element: {0}',\n       startingTag($element));\n    }\n\n    $transclude(function(clone) {\n      $element.empty();\n      $element.append(clone);\n    });\n  }\n});\n\n/**\n * @ngdoc directive\n * @name script\n * @restrict E\n *\n * @description\n * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the\n * template can be used by {@link ng.directive:ngInclude `ngInclude`},\n * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the\n * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be\n * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.\n *\n * @param {string} type Must be set to `'text/ng-template'`.\n * @param {string} id Cache name of the template.\n *\n * @example\n  <example>\n    <file name=\"index.html\">\n      <script type=\"text/ng-template\" id=\"/tpl.html\">\n        Content of the template.\n      </script>\n\n      <a ng-click=\"currentTpl='/tpl.html'\" id=\"tpl-link\">Load inlined template</a>\n      <div id=\"tpl-content\" ng-include src=\"currentTpl\"></div>\n    </file>\n    <file name=\"protractor.js\" type=\"protractor\">\n      it('should load template defined inside script tag', function() {\n        element(by.css('#tpl-link')).click();\n        expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);\n      });\n    </file>\n  </example>\n */\nvar scriptDirective = ['$templateCache', function($templateCache) {\n  return {\n    restrict: 'E',\n    terminal: true,\n    compile: function(element, attr) {\n      if (attr.type == 'text/ng-template') {\n        var templateUrl = attr.id,\n            text = element[0].text;\n\n        $templateCache.put(templateUrl, text);\n      }\n    }\n  };\n}];\n\nvar ngOptionsMinErr = minErr('ngOptions');\n/**\n * @ngdoc directive\n * @name select\n * @restrict E\n *\n * @description\n * HTML `SELECT` element with angular data-binding.\n *\n * # `ngOptions`\n *\n * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`\n * elements for the `<select>` element using the array or object obtained by evaluating the\n * `ngOptions` comprehension_expression.\n *\n * When an item in the `<select>` menu is selected, the array element or object property\n * represented by the selected option will be bound to the model identified by the `ngModel`\n * directive.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** `ngModel` compares by reference, not value. This is important when binding to an\n * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/).\n * </div>\n *\n * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can\n * be nested into the `<select>` element. This element will then represent the `null` or \"not selected\"\n * option. See example below for demonstration.\n *\n * <div class=\"alert alert-warning\">\n * **Note:** `ngOptions` provides an iterator facility for the `<option>` element which should be used instead\n * of {@link ng.directive:ngRepeat ngRepeat} when you want the\n * `select` model to be bound to a non-string value. This is because an option element can only\n * be bound to string values at present.\n * </div>\n *\n * @param {string} ngModel Assignable angular expression to data-bind to.\n * @param {string=} name Property name of the form under which the control is published.\n * @param {string=} required The control is considered valid only if value is entered.\n * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to\n *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of\n *    `required` when you want to data-bind to the `required` attribute.\n * @param {comprehension_expression=} ngOptions in one of the following forms:\n *\n *   * for array data sources:\n *     * `label` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`\n *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`\n *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`\n *   * for object data sources:\n *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`\n *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`\n *     * `select` **`as`** `label` **`group by`** `group`\n *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`\n *\n * Where:\n *\n *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.\n *   * `value`: local variable which will refer to each item in the `array` or each property value\n *      of `object` during iteration.\n *   * `key`: local variable which will refer to a property name in `object` during iteration.\n *   * `label`: The result of this expression will be the label for `<option>` element. The\n *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).\n *   * `select`: The result of this expression will be bound to the model of the parent `<select>`\n *      element. If not specified, `select` expression will default to `value`.\n *   * `group`: The result of this expression will be used to group options using the `<optgroup>`\n *      DOM element.\n *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be\n *      used to identify the objects in the array. The `trackexpr` will most likely refer to the\n *     `value` variable (e.g. `value.propertyName`).\n *\n * @example\n    <example module=\"selectExample\">\n      <file name=\"index.html\">\n        <script>\n        angular.module('selectExample', [])\n          .controller('ExampleController', ['$scope', function($scope) {\n            $scope.colors = [\n              {name:'black', shade:'dark'},\n              {name:'white', shade:'light'},\n              {name:'red', shade:'dark'},\n              {name:'blue', shade:'dark'},\n              {name:'yellow', shade:'light'}\n            ];\n            $scope.myColor = $scope.colors[2]; // red\n          }]);\n        </script>\n        <div ng-controller=\"ExampleController\">\n          <ul>\n            <li ng-repeat=\"color in colors\">\n              Name: <input ng-model=\"color.name\">\n              [<a href ng-click=\"colors.splice($index, 1)\">X</a>]\n            </li>\n            <li>\n              [<a href ng-click=\"colors.push({})\">add</a>]\n            </li>\n          </ul>\n          <hr/>\n          Color (null not allowed):\n          <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\"></select><br>\n\n          Color (null allowed):\n          <span  class=\"nullable\">\n            <select ng-model=\"myColor\" ng-options=\"color.name for color in colors\">\n              <option value=\"\">-- choose color --</option>\n            </select>\n          </span><br/>\n\n          Color grouped by shade:\n          <select ng-model=\"myColor\" ng-options=\"color.name group by color.shade for color in colors\">\n          </select><br/>\n\n\n          Select <a href ng-click=\"myColor = { name:'not in list', shade: 'other' }\">bogus</a>.<br>\n          <hr/>\n          Currently selected: {{ {selected_color:myColor}  }}\n          <div style=\"border:solid 1px black; height:20px\"\n               ng-style=\"{'background-color':myColor.name}\">\n          </div>\n        </div>\n      </file>\n      <file name=\"protractor.js\" type=\"protractor\">\n         it('should check ng-options', function() {\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');\n           element.all(by.model('myColor')).first().click();\n           element.all(by.css('select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');\n           element(by.css('.nullable select[ng-model=\"myColor\"]')).click();\n           element.all(by.css('.nullable select[ng-model=\"myColor\"] option')).first().click();\n           expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');\n         });\n      </file>\n    </example>\n */\n\nvar ngOptionsDirective = valueFn({ terminal: true });\n// jshint maxlen: false\nvar selectDirective = ['$compile', '$parse', function($compile,   $parse) {\n                         //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888\n  var NG_OPTIONS_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?(?:\\s+group\\s+by\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+([\\s\\S]+?)(?:\\s+track\\s+by\\s+([\\s\\S]+?))?$/,\n      nullModelCtrl = {$setViewValue: noop};\n// jshint maxlen: 100\n\n  return {\n    restrict: 'E',\n    require: ['select', '?ngModel'],\n    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {\n      var self = this,\n          optionsMap = {},\n          ngModelCtrl = nullModelCtrl,\n          nullOption,\n          unknownOption;\n\n\n      self.databound = $attrs.ngModel;\n\n\n      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {\n        ngModelCtrl = ngModelCtrl_;\n        nullOption = nullOption_;\n        unknownOption = unknownOption_;\n      };\n\n\n      self.addOption = function(value) {\n        assertNotHasOwnProperty(value, '\"option value\"');\n        optionsMap[value] = true;\n\n        if (ngModelCtrl.$viewValue == value) {\n          $element.val(value);\n          if (unknownOption.parent()) unknownOption.remove();\n        }\n      };\n\n\n      self.removeOption = function(value) {\n        if (this.hasOption(value)) {\n          delete optionsMap[value];\n          if (ngModelCtrl.$viewValue == value) {\n            this.renderUnknownOption(value);\n          }\n        }\n      };\n\n\n      self.renderUnknownOption = function(val) {\n        var unknownVal = '? ' + hashKey(val) + ' ?';\n        unknownOption.val(unknownVal);\n        $element.prepend(unknownOption);\n        $element.val(unknownVal);\n        unknownOption.prop('selected', true); // needed for IE\n      };\n\n\n      self.hasOption = function(value) {\n        return optionsMap.hasOwnProperty(value);\n      };\n\n      $scope.$on('$destroy', function() {\n        // disable unknown option so that we don't do work when the whole select is being destroyed\n        self.renderUnknownOption = noop;\n      });\n    }],\n\n    link: function(scope, element, attr, ctrls) {\n      // if ngModel is not defined, we don't need to do anything\n      if (!ctrls[1]) return;\n\n      var selectCtrl = ctrls[0],\n          ngModelCtrl = ctrls[1],\n          multiple = attr.multiple,\n          optionsExp = attr.ngOptions,\n          nullOption = false, // if false, user will not be able to select it (used by ngOptions)\n          emptyOption,\n          // we can't just jqLite('<option>') since jqLite is not smart enough\n          // to create it in <select> and IE barfs otherwise.\n          optionTemplate = jqLite(document.createElement('option')),\n          optGroupTemplate =jqLite(document.createElement('optgroup')),\n          unknownOption = optionTemplate.clone();\n\n      // find \"null\" option\n      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {\n        if (children[i].value === '') {\n          emptyOption = nullOption = children.eq(i);\n          break;\n        }\n      }\n\n      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);\n\n      // required validator\n      if (multiple) {\n        ngModelCtrl.$isEmpty = function(value) {\n          return !value || value.length === 0;\n        };\n      }\n\n      if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);\n      else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);\n      else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);\n\n\n      ////////////////////////////\n\n\n\n      function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {\n        ngModelCtrl.$render = function() {\n          var viewValue = ngModelCtrl.$viewValue;\n\n          if (selectCtrl.hasOption(viewValue)) {\n            if (unknownOption.parent()) unknownOption.remove();\n            selectElement.val(viewValue);\n            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy\n          } else {\n            if (isUndefined(viewValue) && emptyOption) {\n              selectElement.val('');\n            } else {\n              selectCtrl.renderUnknownOption(viewValue);\n            }\n          }\n        };\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            if (unknownOption.parent()) unknownOption.remove();\n            ngModelCtrl.$setViewValue(selectElement.val());\n          });\n        });\n      }\n\n      function setupAsMultiple(scope, selectElement, ctrl) {\n        var lastView;\n        ctrl.$render = function() {\n          var items = new HashMap(ctrl.$viewValue);\n          forEach(selectElement.find('option'), function(option) {\n            option.selected = isDefined(items.get(option.value));\n          });\n        };\n\n        // we have to do it on each watch since ngModel watches reference, but\n        // we need to work of an array, so we need to see if anything was inserted/removed\n        scope.$watch(function selectMultipleWatch() {\n          if (!equals(lastView, ctrl.$viewValue)) {\n            lastView = shallowCopy(ctrl.$viewValue);\n            ctrl.$render();\n          }\n        });\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            var array = [];\n            forEach(selectElement.find('option'), function(option) {\n              if (option.selected) {\n                array.push(option.value);\n              }\n            });\n            ctrl.$setViewValue(array);\n          });\n        });\n      }\n\n      function setupAsOptions(scope, selectElement, ctrl) {\n        var match;\n\n        if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) {\n          throw ngOptionsMinErr('iexp',\n            \"Expected expression in form of \" +\n            \"'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'\" +\n            \" but got '{0}'. Element: {1}\",\n            optionsExp, startingTag(selectElement));\n        }\n\n        var displayFn = $parse(match[2] || match[1]),\n            valueName = match[4] || match[6],\n            keyName = match[5],\n            groupByFn = $parse(match[3] || ''),\n            valueFn = $parse(match[2] ? match[1] : valueName),\n            valuesFn = $parse(match[7]),\n            track = match[8],\n            trackFn = track ? $parse(match[8]) : null,\n            // This is an array of array of existing option groups in DOM.\n            // We try to reuse these if possible\n            // - optionGroupsCache[0] is the options with no option group\n            // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element\n            optionGroupsCache = [[{element: selectElement, label:''}]];\n\n        if (nullOption) {\n          // compile the element since there might be bindings in it\n          $compile(nullOption)(scope);\n\n          // remove the class, which is added automatically because we recompile the element and it\n          // becomes the compilation root\n          nullOption.removeClass('ng-scope');\n\n          // we need to remove it before calling selectElement.empty() because otherwise IE will\n          // remove the label from the element. wtf?\n          nullOption.remove();\n        }\n\n        // clear contents, we'll add what's needed based on the model\n        selectElement.empty();\n\n        selectElement.on('change', function() {\n          scope.$apply(function() {\n            var optionGroup,\n                collection = valuesFn(scope) || [],\n                locals = {},\n                key, value, optionElement, index, groupIndex, length, groupLength, trackIndex;\n\n            if (multiple) {\n              value = [];\n              for (groupIndex = 0, groupLength = optionGroupsCache.length;\n                   groupIndex < groupLength;\n                   groupIndex++) {\n                // list of options for that group. (first item has the parent)\n                optionGroup = optionGroupsCache[groupIndex];\n\n                for(index = 1, length = optionGroup.length; index < length; index++) {\n                  if ((optionElement = optionGroup[index].element)[0].selected) {\n                    key = optionElement.val();\n                    if (keyName) locals[keyName] = key;\n                    if (trackFn) {\n                      for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {\n                        locals[valueName] = collection[trackIndex];\n                        if (trackFn(scope, locals) == key) break;\n                      }\n                    } else {\n                      locals[valueName] = collection[key];\n                    }\n                    value.push(valueFn(scope, locals));\n                  }\n                }\n              }\n            } else {\n              key = selectElement.val();\n              if (key == '?') {\n                value = undefined;\n              } else if (key === ''){\n                value = null;\n              } else {\n                if (trackFn) {\n                  for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {\n                    locals[valueName] = collection[trackIndex];\n                    if (trackFn(scope, locals) == key) {\n                      value = valueFn(scope, locals);\n                      break;\n                    }\n                  }\n                } else {\n                  locals[valueName] = collection[key];\n                  if (keyName) locals[keyName] = key;\n                  value = valueFn(scope, locals);\n                }\n              }\n            }\n            ctrl.$setViewValue(value);\n            render();\n          });\n        });\n\n        ctrl.$render = render;\n\n        scope.$watchCollection(valuesFn, render);\n        scope.$watchCollection(function () {\n          var locals = {},\n              values = valuesFn(scope);\n          if (values) {\n            var toDisplay = new Array(values.length);\n            for (var i = 0, ii = values.length; i < ii; i++) {\n              locals[valueName] = values[i];\n              toDisplay[i] = displayFn(scope, locals);\n            }\n            return toDisplay;\n          }\n        }, render);\n\n        if ( multiple ) {\n          scope.$watchCollection(function() { return ctrl.$modelValue; }, render);\n        }\n\n        function getSelectedSet() {\n          var selectedSet = false;\n          if (multiple) {\n            var modelValue = ctrl.$modelValue;\n            if (trackFn && isArray(modelValue)) {\n              selectedSet = new HashMap([]);\n              var locals = {};\n              for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {\n                locals[valueName] = modelValue[trackIndex];\n                selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);\n              }\n            } else {\n              selectedSet = new HashMap(modelValue);\n            }\n          }\n          return selectedSet;\n        }\n\n\n        function render() {\n              // Temporary location for the option groups before we render them\n          var optionGroups = {'':[]},\n              optionGroupNames = [''],\n              optionGroupName,\n              optionGroup,\n              option,\n              existingParent, existingOptions, existingOption,\n              modelValue = ctrl.$modelValue,\n              values = valuesFn(scope) || [],\n              keys = keyName ? sortedKeys(values) : values,\n              key,\n              groupLength, length,\n              groupIndex, index,\n              locals = {},\n              selected,\n              selectedSet = getSelectedSet(),\n              lastElement,\n              element,\n              label;\n\n\n          // We now build up the list of options we need (we merge later)\n          for (index = 0; length = keys.length, index < length; index++) {\n\n            key = index;\n            if (keyName) {\n              key = keys[index];\n              if ( key.charAt(0) === '$' ) continue;\n              locals[keyName] = key;\n            }\n\n            locals[valueName] = values[key];\n\n            optionGroupName = groupByFn(scope, locals) || '';\n            if (!(optionGroup = optionGroups[optionGroupName])) {\n              optionGroup = optionGroups[optionGroupName] = [];\n              optionGroupNames.push(optionGroupName);\n            }\n            if (multiple) {\n              selected = isDefined(\n                selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals))\n              );\n            } else {\n              if (trackFn) {\n                var modelCast = {};\n                modelCast[valueName] = modelValue;\n                selected = trackFn(scope, modelCast) === trackFn(scope, locals);\n              } else {\n                selected = modelValue === valueFn(scope, locals);\n              }\n              selectedSet = selectedSet || selected; // see if at least one item is selected\n            }\n            label = displayFn(scope, locals); // what will be seen by the user\n\n            // doing displayFn(scope, locals) || '' overwrites zero values\n            label = isDefined(label) ? label : '';\n            optionGroup.push({\n              // either the index into array or key from object\n              id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index),\n              label: label,\n              selected: selected                   // determine if we should be selected\n            });\n          }\n          if (!multiple) {\n            if (nullOption || modelValue === null) {\n              // insert null option if we have a placeholder, or the model is null\n              optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});\n            } else if (!selectedSet) {\n              // option could not be found, we have to insert the undefined item\n              optionGroups[''].unshift({id:'?', label:'', selected:true});\n            }\n          }\n\n          // Now we need to update the list of DOM nodes to match the optionGroups we computed above\n          for (groupIndex = 0, groupLength = optionGroupNames.length;\n               groupIndex < groupLength;\n               groupIndex++) {\n            // current option group name or '' if no group\n            optionGroupName = optionGroupNames[groupIndex];\n\n            // list of options for that group. (first item has the parent)\n            optionGroup = optionGroups[optionGroupName];\n\n            if (optionGroupsCache.length <= groupIndex) {\n              // we need to grow the optionGroups\n              existingParent = {\n                element: optGroupTemplate.clone().attr('label', optionGroupName),\n                label: optionGroup.label\n              };\n              existingOptions = [existingParent];\n              optionGroupsCache.push(existingOptions);\n              selectElement.append(existingParent.element);\n            } else {\n              existingOptions = optionGroupsCache[groupIndex];\n              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element\n\n              // update the OPTGROUP label if not the same.\n              if (existingParent.label != optionGroupName) {\n                existingParent.element.attr('label', existingParent.label = optionGroupName);\n              }\n            }\n\n            lastElement = null;  // start at the beginning\n            for(index = 0, length = optionGroup.length; index < length; index++) {\n              option = optionGroup[index];\n              if ((existingOption = existingOptions[index+1])) {\n                // reuse elements\n                lastElement = existingOption.element;\n                if (existingOption.label !== option.label) {\n                  lastElement.text(existingOption.label = option.label);\n                  lastElement.prop('label', existingOption.label);\n                }\n                if (existingOption.id !== option.id) {\n                  lastElement.val(existingOption.id = option.id);\n                }\n                // lastElement.prop('selected') provided by jQuery has side-effects\n                if (lastElement[0].selected !== option.selected) {\n                  lastElement.prop('selected', (existingOption.selected = option.selected));\n                  if (msie) {\n                    // See #7692\n                    // The selected item wouldn't visually update on IE without this.\n                    // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well\n                    lastElement.prop('selected', existingOption.selected);\n                  }\n                }\n              } else {\n                // grow elements\n\n                // if it's a null option\n                if (option.id === '' && nullOption) {\n                  // put back the pre-compiled element\n                  element = nullOption;\n                } else {\n                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but\n                  // in this version of jQuery on some browser the .text() returns a string\n                  // rather then the element.\n                  (element = optionTemplate.clone())\n                      .val(option.id)\n                      .prop('selected', option.selected)\n                      .attr('selected', option.selected)\n                      .prop('label', option.label)\n                      .text(option.label);\n                }\n\n                existingOptions.push(existingOption = {\n                    element: element,\n                    label: option.label,\n                    id: option.id,\n                    selected: option.selected\n                });\n                selectCtrl.addOption(option.label, element);\n                if (lastElement) {\n                  lastElement.after(element);\n                } else {\n                  existingParent.element.append(element);\n                }\n                lastElement = element;\n              }\n            }\n            // remove any excessive OPTIONs in a group\n            index++; // increment since the existingOptions[0] is parent element not OPTION\n            while(existingOptions.length > index) {\n              option = existingOptions.pop();\n              selectCtrl.removeOption(option.label);\n              option.element.remove();\n            }\n          }\n          // remove any excessive OPTGROUPs from select\n          while(optionGroupsCache.length > groupIndex) {\n            optionGroupsCache.pop()[0].element.remove();\n          }\n        }\n      }\n    }\n  };\n}];\n\nvar optionDirective = ['$interpolate', function($interpolate) {\n  var nullSelectCtrl = {\n    addOption: noop,\n    removeOption: noop\n  };\n\n  return {\n    restrict: 'E',\n    priority: 100,\n    compile: function(element, attr) {\n      if (isUndefined(attr.value)) {\n        var interpolateFn = $interpolate(element.text(), true);\n        if (!interpolateFn) {\n          attr.$set('value', element.text());\n        }\n      }\n\n      return function (scope, element, attr) {\n        var selectCtrlName = '$selectController',\n            parent = element.parent(),\n            selectCtrl = parent.data(selectCtrlName) ||\n              parent.parent().data(selectCtrlName); // in case we are in optgroup\n\n        if (selectCtrl && selectCtrl.databound) {\n          // For some reason Opera defaults to true and if not overridden this messes up the repeater.\n          // We don't want the view to drive the initialization of the model anyway.\n          element.prop('selected', false);\n        } else {\n          selectCtrl = nullSelectCtrl;\n        }\n\n        if (interpolateFn) {\n          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {\n            attr.$set('value', newVal);\n            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);\n            selectCtrl.addOption(newVal);\n          });\n        } else {\n          selectCtrl.addOption(attr.value);\n        }\n\n        element.on('$destroy', function() {\n          selectCtrl.removeOption(attr.value);\n        });\n      };\n    }\n  };\n}];\n\nvar styleDirective = valueFn({\n  restrict: 'E',\n  terminal: true\n});\n\n  if (window.angular.bootstrap) {\n    //AngularJS is already loaded, so we can return here...\n    console.log('WARNING: Tried to load angular more than once.');\n    return;\n  }\n\n  //try to bind to jquery now so that one can write angular.element().read()\n  //but we will rebind on bootstrap again.\n  bindJQuery();\n\n  publishExternalAPI(angular);\n\n  jqLite(document).ready(function() {\n    angularInit(document, bootstrap);\n  });\n\n})(window, document);\n\n!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type=\"text/css\">@charset \"UTF-8\";[ng\\\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\\\:form{display:block;}.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}.ng-hide-add-active,.ng-hide-remove{display:block!important;}</style>');"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular/bower.json",
    "content": "{\n  \"name\": \"angular\",\n  \"version\": \"1.2.28\",\n  \"main\": \"./angular.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n  }\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular/package.json",
    "content": "{\n  \"name\": \"angular\",\n  \"version\": \"1.2.28\",\n  \"description\": \"HTML enhanced for web apps\",\n  \"main\": \"angular.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/angular/angular.js.git\"\n  },\n  \"keywords\": [\n    \"angular\",\n    \"framework\",\n    \"browser\",\n    \"client-side\"\n  ],\n  \"author\": \"Angular Core Team <angular-core+npm@google.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/angular/angular.js/issues\"\n  },\n  \"homepage\": \"http://angularjs.org\"\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/.bower.json",
    "content": "{\n  \"name\": \"angular-marked\",\n  \"version\": \"0.0.12\",\n  \"authors\": [\n    \"J. Harshbarger\"\n  ],\n  \"description\": \"AngularJS Markdown using marked.\",\n  \"main\": \"angular-marked.js\",\n  \"keywords\": [\n    \"angularjs\",\n    \"markdown\",\n    \"marked\",\n    \"directive\",\n    \"filter\"\n  ],\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"node_modules\",\n    \"bower_components\",\n    \"test\",\n    \"tests\"\n  ],\n  \"dependencies\": {\n    \"angular\": \">= 1.2.5\",\n    \"marked\": \"~0.3.1\"\n  },\n  \"devDependencies\": {\n    \"angular-mocks\": \">= 1.2.5\"\n  },\n  \"homepage\": \"https://github.com/Hypercubed/angular-marked\",\n  \"_release\": \"0.0.12\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v0.0.12\",\n    \"commit\": \"acb0738d108ee5cd35f3812492d7590495cf9ecd\"\n  },\n  \"_source\": \"git://github.com/Hypercubed/angular-marked.git\",\n  \"_target\": \"~0.0.12\",\n  \"_originalSource\": \"angular-marked\"\n}"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/README.md",
    "content": "# angular-marked\nAngularJS Markdown using [marked](https://github.com/chjj/marked).\n\n## Usage\n1. `bower install angular-marked` or `bower install Hypercubed/angular-marked`\n2. Include the `marked.js` script into your app.  By default should be at `bower_components/marked/lib/marked.js`.\n3. Include the `angular-marked.js` into your app.  By default should be at `bower_components/angular-marked/angular-marked.js`.\n4. Add `hc.marked` as a module dependency to your app.\n\n### Set default options (optional)\n\n```js\n\n\tapp.config(['markedProvider', function(markedProvider) {\n\t  markedProvider.setOptions({gfm: true});\n\t}]);\n```\n\nExample using [highlight.js Javascript syntax highlighter](http://highlightjs.org/) (must include highlight.js script).\n\n```js\n\tmarkedProvider.setOptions({\n      gfm: true,\n      tables: true,\n      highlight: function (code) {\n        return hljs.highlightAuto(code).value;\n      }\n    });\n```\n\n### As a directive\n\n```html\n\n\t<marked>   \n\t     #Markdown directive   \n\t     *It works!*  \n\t</marked>\n```\n\nBind the markdown input to a scope variable:\n\n```html\n\n\t<div marked=\"my_markdown\"> \n\t</div>\n\t<!-- Uses $scope.my_markdown -->\n```\n\nInclude a markdown file:\n\n```html\n\n\t<div marked ng-include=\"'README.md'\"> \n\t</div>\n\t<!-- Uses markdown content from README.md -->\n```\n\n### As a service\n\n```js\n\n\tapp.controller('myCtrl', ['marked', function(marked) {\n\t  $scope.html = marked('#TEST');\n\t}]);\n```\n\n## Testing\n\nInstall npm and bower dependencies: \n\n```\n\tnpm install\n\tbower install\n\tnpm test\n```\n\n## Why?\n\nI wanted to use `marked` instead of `showdown` as used in `angular-markdown-directive` as well as expose the option to globally set defaults.  Yes, it is probably best to avoid creating a bunch of angular wrapper modules... but I use this enough across multiple projects to make it worth while for me.  Use it if you like.  Pull requests are welcome.\n\n## Acknowledgments\nBased on [angular-markdown-directive](https://github.com/btford/angular-markdown-directive) by [briantford](http://briantford.com/) which, in turn, is based on [this excellent tutorial](http://blog.angularjs.org/2012/05/custom-components-part-1.html) by [@johnlinquist](https://twitter.com/johnlindquist).\n\n## License\nMIT\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/angular-marked.js",
    "content": "/*\n * angular-marked\n * (c) 2014 J. Harshbarger\n * Licensed MIT\n */\n\n/* jshint undef: true, unused: true */\n/* global angular:true */\n\n(function () {\n\t'use strict';\n\n  var app = angular.module('hc.marked', []);\n\n  //app.constant('marked', window.marked);\n\n  app.provider('marked', function () {\n\n    var self = this;\n\n    self.setOptions = function(opts) {  // Store options for later\n      this.defaults = opts;\n    };\n\n    self.$get = ['$window',function ($window) { \n      var m = $window.marked;\n\n      self.setOptions = m.setOptions;\n      m.setOptions(self.defaults);\n\n      return m;\n    }];\n\n  });\n\n  // TODO: filter tests */\n  //app.filter('marked', ['marked', function(marked) {\n\t//  return marked;\n\t//}]);\n\n  app.directive('marked', ['marked', function (marked) {\n    return {\n      restrict: 'AE',\n      replace: true,\n      scope: {\n        opts: '=',\n        marked: '='\n      },\n      link: function (scope, element, attrs) {\n        set(scope.marked || element.text() || '');\n\n        function set(val) {\n        \telement.html(marked(val || '', scope.opts || null));\n        }\n        \n        if (attrs.marked) {\n          scope.$watch('marked', set);        \t\n        }\n\n      }\n    };\n  }]);\n\n}());"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/bower.json",
    "content": "{\n  \"name\": \"angular-marked\",\n  \"version\": \"0.0.12\",\n  \"authors\": [\n    \"J. Harshbarger\"\n  ],\n  \"description\": \"AngularJS Markdown using marked.\",\n  \"main\": \"angular-marked.js\",\n  \"keywords\": [\n    \"angularjs\",\n    \"markdown\",\n    \"marked\",\n    \"directive\",\n    \"filter\"\n  ],\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"node_modules\",\n    \"bower_components\",\n    \"test\",\n    \"tests\"\n  ],\n  \"dependencies\": {\n    \"angular\": \">= 1.2.5\",\n    \"marked\": \"~0.3.1\"\n  },\n  \"devDependencies\": {\n    \"angular-mocks\": \">= 1.2.5\"\n  }\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/example/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\" ng-app=\"example-app\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>angular-marked example</title>\n    <style>\n    body {\n      margin: 0;\n      padding: 20px;\n      font-family: Helvetica, sans-serif;\n      font-size: 14px;\n    }\n\n    </style>\n    <script src=\"../bower_components/angular/angular.js\"></script>\n    <script src=\"../bower_components/marked/lib/marked.js\"></script>\n    <script src=\"../angular-marked.js\"></script>\n  </head>\n  <body>\n\n    <h1>angular-marked</h1>\n\n    <div ng-controller=\"MainController\">\n\n<marked>\n### What?\nConvert markdown to html at run time.\n</marked>\n\nFor example, this:\n<p>\n<form>\n  <p><textarea placeholder=\"Enter markdown here\" ng-model=\"my_markdown\" cols=\"60\" rows=\"5\"></textarea></p>\n</form>\n</p>\n\nBecomes this:\n<div marked=\"my_markdown\">\n</div>\n\n<marked>\n### Why?\nI wanted to use `marked` instead of `showdown` as used in `angular-markdown-directive` as well as expose the option to globally set defaults.\n\n### How?\n</marked>\n\n<p>A block of text:</p>\n<div class=\"highlight highlight-html\"><pre>    <span class=\"nt\">&lt;marked&gt;</span>\n#Markdown directive   \n*It works!*\n    <span class=\"nt\">&lt;/marked&gt;</span>\n</pre></div>\n<p>Bind the markdown input to a scope variable:</p>\n<div class=\"highlight highlight-html\"><pre>    <span class=\"nt\">&lt;div</span> <span class=\"na\">marked=</span><span class=\"s\">\"my_markdown\"</span><span class=\"nt\">&gt;</span> \n    <span class=\"nt\">&lt;/div&gt;</span>\n    <span class=\"c\">&lt;!-- Uses $scope.my_markdown --&gt;</span>\n</pre></div>\n<p>Include a markdown file:</p>\n<div class=\"highlight highlight-html\"><pre>    <span class=\"nt\">&lt;div</span> <span class=\"na\">marked</span> <span class=\"na\">ng-include=</span><span class=\"s\">\"'README.md'\"</span><span class=\"nt\">&gt;</span> \n    <span class=\"nt\">&lt;/div&gt;</span>\n    <span class=\"c\">&lt;!-- Uses markdown content from README.md --&gt;</span>\n</pre></div>\n\n<marked>\nSet default options\n\n```js\napp.config(['markedProvider', function(markedProvider) {\n  markedProvider.setOptions({gfm: true});\n}]);\n\n```\n\n</marked>\n\n    </div>\n  </body>\n\n  <script>\n    var app = angular.module('example-app', ['hc.marked']);\n\n    app.config(['markedProvider', function(markedProvider) {\n      markedProvider.setOptions({gfm: true});\n    }]);\n\n    app.controller('MainController', ['$scope', function($scope) {\n      $scope.my_markdown = \"*This* **is** [markdown](https://daringfireball.net/projects/markdown/)\";\n    }]);\n  </script>\n</html>"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/gruntfile.js",
    "content": "module.exports = function(grunt){\n  'use strict';\n\n  grunt.initConfig({\n    pkg: grunt.file.readJSON('bower.json'),\n    jshint: {\n      options: { jshintrc: true },\n      all: ['gruntfile.js', '<%= pkg.name %>.js']\n    },\n    bump: {\n      options: {\n        files: ['bower.json','package.json'],\n        commit: true,\n        commitMessage: 'release %VERSION%',\n        commitFiles: ['package.json','bower.json','<%= pkg.name %>.min.js'], // '-a' for all files\n        pushTo: 'origin',\n      }\n    },\n    uglify: {\n      options: {\n        banner: '/*\\n * <%= pkg.title || pkg.name %> <%= pkg.version %>\\n' +\n          ' * (c) <%= grunt.template.today(\"yyyy\") %> <%= pkg.authors.join(\" \") %>\\n' +\n          ' * Licensed <%= pkg.license %>\\n */\\n'\n      },\n      src: {\n        files: {\n          '<%= pkg.name %>.min.js': '<%= pkg.name %>.js'\n        }\n      }\n    },\n    karma: {\n      unit: {\n        configFile: 'karma.conf.js'\n      },\n      once: {\n        configFile: 'karma.conf.js',\n        singleRun: true,\n        browsers: ['PhantomJS']\n      }\n    }\n  });\n\n  require('load-grunt-tasks')(grunt);\n\n  grunt.registerTask('default', ['build','test']);\n  grunt.registerTask('build', ['jshint', 'uglify']);\n  grunt.registerTask('test', ['karma:once']);\n  grunt.registerTask('publish', ['test','bump-only','uglify','bump-commit']);\n\n};"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/karma.conf.js",
    "content": "// Karma configuration\n// http://karma-runner.github.io/0.10/config/configuration-file.html\n\nmodule.exports = function(config) {\n  config.set({\n    // base path, that will be used to resolve files and exclude\n    basePath: '',\n\n    // testing framework to use (jasmine/mocha/qunit/...)\n    frameworks: ['jasmine'],\n\n    preprocessors: {'*/.html': [] },\n\n    // list of files / patterns to load in the browser\n    files: [\n      'bower_components/angular/angular.js',\n      'bower_components/angular-mocks/angular-mocks.js',\n      'angular-marked.js',\n      'bower_components/marked/lib/marked.js',\n      'test/spec/**/*.js'\n    ],\n\n    // list of files / patterns to exclude\n    exclude: [],\n\n    progress: ['dots'],\n\n    // web server port\n    port: 8080,\n\n    // level of logging\n    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG\n    logLevel: config.LOG_INFO,\n\n\n    // enable / disable watching file and executing tests whenever any file changes\n    autoWatch: false,\n\n\n    // Start these browsers, currently available:\n    // - Chrome\n    // - ChromeCanary\n    // - Firefox\n    // - Opera\n    // - Safari (only Mac)\n    // - PhantomJS\n    // - IE (only Windows)\n    browsers: ['Chrome'],\n\n\n    // Continuous Integration mode\n    // if true, it capture browsers, run tests and exit\n    singleRun: false\n  });\n};"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/package.json",
    "content": "{\n  \"name\": \"angular-marked\",\n  \"version\": \"0.0.12\",\n  \"description\": \"AngularJS Markdown using marked.\",\n  \"main\": \"angular-marked.js\",\n  \"directories\": {\n    \"test\": \"test\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"load-grunt-tasks\": \"^0.4.0\",\n    \"grunt-contrib-jshint\": \"^0.10.0\",\n    \"grunt\": \"^0.4.4\",\n    \"karma\": \"^0.12.9\",\n    \"karma-chrome-launcher\": \"^0.1.3\",\n    \"karma-jasmine\": \"^0.1.5\",\n    \"grunt-contrib-uglify\": \"^0.4.0\",\n    \"grunt-karma\": \"^0.8.2\",\n    \"karma-phantomjs-launcher\": \"^0.1.4\",\n    \"grunt-bump\": \"0.0.13\"\n  },\n  \"scripts\": {\n    \"test\": \"grunt test\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/Hypercubed/angular-marked.git\"\n  },\n  \"keywords\": [\n    \"marked\",\n    \"markdown\"\n  ],\n  \"author\": \"J. Harshbarger\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/Hypercubed/angular-marked/issues\"\n  },\n  \"homepage\": \"https://github.com/Hypercubed/angular-marked\"\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/angular-marked/todo.md",
    "content": "# Todo list\n\n_\\( managed using [todo-md](https://github.com/Hypercubed/todo-md) \\)_\n\n- [ ] Compatibility with RequireJS #3\n- [ ] Add testing to gruntfile\n- [x] Minify?\n- [ ] ngmin?"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/.bower.json",
    "content": "{\n  \"name\": \"d3\",\n  \"version\": \"3.4.13\",\n  \"main\": \"d3.js\",\n  \"scripts\": [\n    \"d3.js\"\n  ],\n  \"ignore\": [\n    \".DS_Store\",\n    \".git\",\n    \".gitignore\",\n    \".npmignore\",\n    \".travis.yml\",\n    \"Makefile\",\n    \"bin\",\n    \"component.json\",\n    \"index.js\",\n    \"lib\",\n    \"node_modules\",\n    \"package.json\",\n    \"src\",\n    \"test\"\n  ],\n  \"homepage\": \"https://github.com/mbostock/d3\",\n  \"_release\": \"3.4.13\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v3.4.13\",\n    \"commit\": \"e2dc80f5385c153066150075a4208131e0b78c68\"\n  },\n  \"_source\": \"git://github.com/mbostock/d3.git\",\n  \"_target\": \"~3.4.9\",\n  \"_originalSource\": \"d3\"\n}"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/.spmignore",
    "content": "bin\nlib\nsrc\ntest\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/CONTRIBUTING.md",
    "content": "# Contributing\n\nIf you’re looking for ways to contribute, please [peruse open issues](https://github.com/mbostock/d3/issues?milestone=&page=1&state=open). The icebox is a good place to find ideas that are not currently in development. If you already have an idea, please check past issues to see whether your idea or a similar one was previously discussed.\n\nBefore submitting a pull request, consider implementing a live example first, say using [bl.ocks.org](http://bl.ocks.org). Real-world use cases go a long way to demonstrating the usefulness of a proposed feature. The more complex a feature’s implementation, the more usefulness it should provide. Share your demo using the #d3js tag on Twitter or by sending it to the d3-js Google group.\n\nIf your proposed feature does not involve changing core functionality, consider submitting it instead as a [D3 plugin](https://github.com/d3/d3-plugins). New core features should be for general use, whereas plugins are suitable for more specialized use cases. When in doubt, it’s easier to start with a plugin before “graduating” to core.\n\nTo contribute new documentation or add examples to the gallery, just [edit the Wiki](https://github.com/mbostock/d3/wiki)!\n\n## How to Submit a Pull Request\n\n1. Click the “Fork” button to create your personal fork of the D3 repository.\n\n2. After cloning your fork of the D3 repository in the terminal, run `npm install` to install D3’s dependencies.\n\n3. Create a new branch for your new feature. For example: `git checkout -b my-awesome-feature`. A dedicated branch for your pull request means you can develop multiple features at the same time, and ensures that your pull request is stable even if you later decide to develop an unrelated feature.\n\n4. The `d3.js` and `d3.min.js` files are built from source files in the `src` directory. _Do not edit `d3.js` directly._ Instead, edit the source files, and then run `make` to build the generated files.\n\n5. Use `make test` to run tests and verify your changes. If you are adding a new feature, you should add new tests! If you are changing existing functionality, make sure the existing tests run, or update them as appropriate.\n\n6. Sign D3’s [Individual Contributor License Agreement](https://docs.google.com/forms/d/1CzjdBKtDuA8WeuFJinadx956xLQ4Xriv7-oDvXnZMaI/viewform). Unless you are submitting a trivial patch (such as fixing a typo), this form is needed to verify that you are able to contribute.\n\n7. Submit your pull request, and good luck!\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/LICENSE",
    "content": "Copyright (c) 2010-2014, Michael Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* The name Michael Bostock may not be used to endorse or promote products\n  derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\nOF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/README.md",
    "content": "# Data-Driven Documents\n\n<a href=\"http://d3js.org\"><img src=\"http://d3js.org/logo.svg\" align=\"left\" hspace=\"10\" vspace=\"6\"></a>\n\n**D3.js** is a JavaScript library for manipulating documents based on data. **D3** helps you bring data to life using HTML, SVG and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.\n\nWant to learn more? [See the wiki.](https://github.com/mbostock/d3/wiki)\n\nFor examples, [see the gallery](https://github.com/mbostock/d3/wiki/Gallery) and [mbostock’s bl.ocks](http://bl.ocks.org/mbostock).\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/bower.json",
    "content": "{\n  \"name\": \"d3\",\n  \"version\": \"3.4.13\",\n  \"main\": \"d3.js\",\n  \"scripts\": [\n    \"d3.js\"\n  ],\n  \"ignore\": [\n    \".DS_Store\",\n    \".git\",\n    \".gitignore\",\n    \".npmignore\",\n    \".travis.yml\",\n    \"Makefile\",\n    \"bin\",\n    \"component.json\",\n    \"index.js\",\n    \"lib\",\n    \"node_modules\",\n    \"package.json\",\n    \"src\",\n    \"test\"\n  ]\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/composer.json",
    "content": "{\n\t\"name\": \"mbostock/d3\",\n\t\"description\": \"A small, free JavaScript library for manipulating documents based on data.\",\n\t\"keywords\": [\"dom\", \"svg\", \"visualization\", \"js\", \"canvas\"],\n\t\"homepage\": \"http://d3js.org/\",\n\t\"license\": \"BSD-3-Clause\",\n\t\"authors\": [\n\t\t{\n\t\t\t\"name\": \"Mike Bostock\",\n\t\t\t\"homepage\": \"http://bost.ocks.org/mike\"\n\t\t}\n\t],\n\t\"support\": {\n\t\t\"issues\": \"https://github.com/mbostock/d3/issues\",\n\t\t\"wiki\": \"https://github.com/mbostock/d3/wiki\",\n\t\t\"API\": \"https://github.com/mbostock/d3/wiki/API-Reference\",\n\t\t\"source\": \"https://github.com/mbostock/d3\"\n\t}\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/d3/d3.js",
    "content": "!function() {\n  var d3 = {\n    version: \"3.4.13\"\n  };\n  if (!Date.now) Date.now = function() {\n    return +new Date();\n  };\n  var d3_arraySlice = [].slice, d3_array = function(list) {\n    return d3_arraySlice.call(list);\n  };\n  var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window;\n  try {\n    d3_array(d3_documentElement.childNodes)[0].nodeType;\n  } catch (e) {\n    d3_array = function(list) {\n      var i = list.length, array = new Array(i);\n      while (i--) array[i] = list[i];\n      return array;\n    };\n  }\n  try {\n    d3_document.createElement(\"div\").style.setProperty(\"opacity\", 0, \"\");\n  } catch (error) {\n    var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;\n    d3_element_prototype.setAttribute = function(name, value) {\n      d3_element_setAttribute.call(this, name, value + \"\");\n    };\n    d3_element_prototype.setAttributeNS = function(space, local, value) {\n      d3_element_setAttributeNS.call(this, space, local, value + \"\");\n    };\n    d3_style_prototype.setProperty = function(name, value, priority) {\n      d3_style_setProperty.call(this, name, value + \"\", priority);\n    };\n  }\n  d3.ascending = d3_ascending;\n  function d3_ascending(a, b) {\n    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;\n  }\n  d3.descending = function(a, b) {\n    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;\n  };\n  d3.min = function(array, f) {\n    var i = -1, n = array.length, a, b;\n    if (arguments.length === 1) {\n      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;\n      while (++i < n) if ((b = array[i]) != null && a > b) a = b;\n    } else {\n      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;\n    }\n    return a;\n  };\n  d3.max = function(array, f) {\n    var i = -1, n = array.length, a, b;\n    if (arguments.length === 1) {\n      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;\n      while (++i < n) if ((b = array[i]) != null && b > a) a = b;\n    } else {\n      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;\n    }\n    return a;\n  };\n  d3.extent = function(array, f) {\n    var i = -1, n = array.length, a, b, c;\n    if (arguments.length === 1) {\n      while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined;\n      while (++i < n) if ((b = array[i]) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    } else {\n      while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined;\n      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    }\n    return [ a, c ];\n  };\n  function d3_number(x) {\n    return x === null ? NaN : +x;\n  }\n  function d3_numeric(x) {\n    return !isNaN(x);\n  }\n  d3.sum = function(array, f) {\n    var s = 0, n = array.length, a, i = -1;\n    if (arguments.length === 1) {\n      while (++i < n) if (d3_numeric(a = +array[i])) s += a;\n    } else {\n      while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;\n    }\n    return s;\n  };\n  d3.mean = function(array, f) {\n    var s = 0, n = array.length, a, i = -1, j = n;\n    if (arguments.length === 1) {\n      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;\n    } else {\n      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;\n    }\n    return j ? s / j : undefined;\n  };\n  d3.quantile = function(values, p) {\n    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;\n    return e ? v + e * (values[h] - v) : v;\n  };\n  d3.median = function(array, f) {\n    var numbers = [], n = array.length, a, i = -1;\n    if (arguments.length === 1) {\n      while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);\n    } else {\n      while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);\n    }\n    return numbers.length ? d3.quantile(numbers.sort(d3_ascending), .5) : undefined;\n  };\n  function d3_bisector(compare) {\n    return {\n      left: function(a, x, lo, hi) {\n        if (arguments.length < 3) lo = 0;\n        if (arguments.length < 4) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;\n        }\n        return lo;\n      },\n      right: function(a, x, lo, hi) {\n        if (arguments.length < 3) lo = 0;\n        if (arguments.length < 4) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;\n        }\n        return lo;\n      }\n    };\n  }\n  var d3_bisect = d3_bisector(d3_ascending);\n  d3.bisectLeft = d3_bisect.left;\n  d3.bisect = d3.bisectRight = d3_bisect.right;\n  d3.bisector = function(f) {\n    return d3_bisector(f.length === 1 ? function(d, x) {\n      return d3_ascending(f(d), x);\n    } : f);\n  };\n  d3.shuffle = function(array) {\n    var m = array.length, t, i;\n    while (m) {\n      i = Math.random() * m-- | 0;\n      t = array[m], array[m] = array[i], array[i] = t;\n    }\n    return array;\n  };\n  d3.permute = function(array, indexes) {\n    var i = indexes.length, permutes = new Array(i);\n    while (i--) permutes[i] = array[indexes[i]];\n    return permutes;\n  };\n  d3.pairs = function(array) {\n    var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);\n    while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];\n    return pairs;\n  };\n  d3.zip = function() {\n    if (!(n = arguments.length)) return [];\n    for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {\n      for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {\n        zip[j] = arguments[j][i];\n      }\n    }\n    return zips;\n  };\n  function d3_zipLength(d) {\n    return d.length;\n  }\n  d3.transpose = function(matrix) {\n    return d3.zip.apply(d3, matrix);\n  };\n  d3.keys = function(map) {\n    var keys = [];\n    for (var key in map) keys.push(key);\n    return keys;\n  };\n  d3.values = function(map) {\n    var values = [];\n    for (var key in map) values.push(map[key]);\n    return values;\n  };\n  d3.entries = function(map) {\n    var entries = [];\n    for (var key in map) entries.push({\n      key: key,\n      value: map[key]\n    });\n    return entries;\n  };\n  d3.merge = function(arrays) {\n    var n = arrays.length, m, i = -1, j = 0, merged, array;\n    while (++i < n) j += arrays[i].length;\n    merged = new Array(j);\n    while (--n >= 0) {\n      array = arrays[n];\n      m = array.length;\n      while (--m >= 0) {\n        merged[--j] = array[m];\n      }\n    }\n    return merged;\n  };\n  var abs = Math.abs;\n  d3.range = function(start, stop, step) {\n    if (arguments.length < 3) {\n      step = 1;\n      if (arguments.length < 2) {\n        stop = start;\n        start = 0;\n      }\n    }\n    if ((stop - start) / step === Infinity) throw new Error(\"infinite range\");\n    var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;\n    start *= k, stop *= k, step *= k;\n    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);\n    return range;\n  };\n  function d3_range_integerScale(x) {\n    var k = 1;\n    while (x * k % 1) k *= 10;\n    return k;\n  }\n  function d3_class(ctor, properties) {\n    for (var key in properties) {\n      Object.defineProperty(ctor.prototype, key, {\n        value: properties[key],\n        enumerable: false\n      });\n    }\n  }\n  d3.map = function(object) {\n    var map = new d3_Map();\n    if (object instanceof d3_Map) object.forEach(function(key, value) {\n      map.set(key, value);\n    }); else for (var key in object) map.set(key, object[key]);\n    return map;\n  };\n  function d3_Map() {\n    this._ = Object.create(null);\n  }\n  var d3_map_proto = \"__proto__\", d3_map_zero = \"\\x00\";\n  d3_class(d3_Map, {\n    has: d3_map_has,\n    get: function(key) {\n      return this._[d3_map_escape(key)];\n    },\n    set: function(key, value) {\n      return this._[d3_map_escape(key)] = value;\n    },\n    remove: d3_map_remove,\n    keys: d3_map_keys,\n    values: function() {\n      var values = [];\n      for (var key in this._) values.push(this._[key]);\n      return values;\n    },\n    entries: function() {\n      var entries = [];\n      for (var key in this._) entries.push({\n        key: d3_map_unescape(key),\n        value: this._[key]\n      });\n      return entries;\n    },\n    size: d3_map_size,\n    empty: d3_map_empty,\n    forEach: function(f) {\n      for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);\n    }\n  });\n  function d3_map_escape(key) {\n    return (key += \"\") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;\n  }\n  function d3_map_unescape(key) {\n    return (key += \"\")[0] === d3_map_zero ? key.slice(1) : key;\n  }\n  function d3_map_has(key) {\n    return d3_map_escape(key) in this._;\n  }\n  function d3_map_remove(key) {\n    return (key = d3_map_escape(key)) in this._ && delete this._[key];\n  }\n  function d3_map_keys() {\n    var keys = [];\n    for (var key in this._) keys.push(d3_map_unescape(key));\n    return keys;\n  }\n  function d3_map_size() {\n    var size = 0;\n    for (var key in this._) ++size;\n    return size;\n  }\n  function d3_map_empty() {\n    for (var key in this._) return false;\n    return true;\n  }\n  d3.nest = function() {\n    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;\n    function map(mapType, array, depth) {\n      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;\n      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;\n      while (++i < n) {\n        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {\n          values.push(object);\n        } else {\n          valuesByKey.set(keyValue, [ object ]);\n        }\n      }\n      if (mapType) {\n        object = mapType();\n        setter = function(keyValue, values) {\n          object.set(keyValue, map(mapType, values, depth));\n        };\n      } else {\n        object = {};\n        setter = function(keyValue, values) {\n          object[keyValue] = map(mapType, values, depth);\n        };\n      }\n      valuesByKey.forEach(setter);\n      return object;\n    }\n    function entries(map, depth) {\n      if (depth >= keys.length) return map;\n      var array = [], sortKey = sortKeys[depth++];\n      map.forEach(function(key, keyMap) {\n        array.push({\n          key: key,\n          values: entries(keyMap, depth)\n        });\n      });\n      return sortKey ? array.sort(function(a, b) {\n        return sortKey(a.key, b.key);\n      }) : array;\n    }\n    nest.map = function(array, mapType) {\n      return map(mapType, array, 0);\n    };\n    nest.entries = function(array) {\n      return entries(map(d3.map, array, 0), 0);\n    };\n    nest.key = function(d) {\n      keys.push(d);\n      return nest;\n    };\n    nest.sortKeys = function(order) {\n      sortKeys[keys.length - 1] = order;\n      return nest;\n    };\n    nest.sortValues = function(order) {\n      sortValues = order;\n      return nest;\n    };\n    nest.rollup = function(f) {\n      rollup = f;\n      return nest;\n    };\n    return nest;\n  };\n  d3.set = function(array) {\n    var set = new d3_Set();\n    if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);\n    return set;\n  };\n  function d3_Set() {\n    this._ = Object.create(null);\n  }\n  d3_class(d3_Set, {\n    has: d3_map_has,\n    add: function(key) {\n      this._[d3_map_escape(key += \"\")] = true;\n      return key;\n    },\n    remove: d3_map_remove,\n    values: d3_map_keys,\n    size: d3_map_size,\n    empty: d3_map_empty,\n    forEach: function(f) {\n      for (var key in this._) f.call(this, d3_map_unescape(key));\n    }\n  });\n  d3.behavior = {};\n  d3.rebind = function(target, source) {\n    var i = 1, n = arguments.length, method;\n    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);\n    return target;\n  };\n  function d3_rebind(target, source, method) {\n    return function() {\n      var value = method.apply(source, arguments);\n      return value === source ? target : value;\n    };\n  }\n  function d3_vendorSymbol(object, name) {\n    if (name in object) return name;\n    name = name.charAt(0).toUpperCase() + name.slice(1);\n    for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {\n      var prefixName = d3_vendorPrefixes[i] + name;\n      if (prefixName in object) return prefixName;\n    }\n  }\n  var d3_vendorPrefixes = [ \"webkit\", \"ms\", \"moz\", \"Moz\", \"o\", \"O\" ];\n  function d3_noop() {}\n  d3.dispatch = function() {\n    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;\n    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);\n    return dispatch;\n  };\n  function d3_dispatch() {}\n  d3_dispatch.prototype.on = function(type, listener) {\n    var i = type.indexOf(\".\"), name = \"\";\n    if (i >= 0) {\n      name = type.slice(i + 1);\n      type = type.slice(0, i);\n    }\n    if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);\n    if (arguments.length === 2) {\n      if (listener == null) for (type in this) {\n        if (this.hasOwnProperty(type)) this[type].on(name, null);\n      }\n      return this;\n    }\n  };\n  function d3_dispatch_event(dispatch) {\n    var listeners = [], listenerByName = new d3_Map();\n    function event() {\n      var z = listeners, i = -1, n = z.length, l;\n      while (++i < n) if (l = z[i].on) l.apply(this, arguments);\n      return dispatch;\n    }\n    event.on = function(name, listener) {\n      var l = listenerByName.get(name), i;\n      if (arguments.length < 2) return l && l.on;\n      if (l) {\n        l.on = null;\n        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));\n        listenerByName.remove(name);\n      }\n      if (listener) listeners.push(listenerByName.set(name, {\n        on: listener\n      }));\n      return dispatch;\n    };\n    return event;\n  }\n  d3.event = null;\n  function d3_eventPreventDefault() {\n    d3.event.preventDefault();\n  }\n  function d3_eventSource() {\n    var e = d3.event, s;\n    while (s = e.sourceEvent) e = s;\n    return e;\n  }\n  function d3_eventDispatch(target) {\n    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;\n    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);\n    dispatch.of = function(thiz, argumentz) {\n      return function(e1) {\n        try {\n          var e0 = e1.sourceEvent = d3.event;\n          e1.target = target;\n          d3.event = e1;\n          dispatch[e1.type].apply(thiz, argumentz);\n        } finally {\n          d3.event = e0;\n        }\n      };\n    };\n    return dispatch;\n  }\n  d3.requote = function(s) {\n    return s.replace(d3_requote_re, \"\\\\$&\");\n  };\n  var d3_requote_re = /[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g;\n  var d3_subclass = {}.__proto__ ? function(object, prototype) {\n    object.__proto__ = prototype;\n  } : function(object, prototype) {\n    for (var property in prototype) object[property] = prototype[property];\n  };\n  function d3_selection(groups) {\n    d3_subclass(groups, d3_selectionPrototype);\n    return groups;\n  }\n  var d3_select = function(s, n) {\n    return n.querySelector(s);\n  }, d3_selectAll = function(s, n) {\n    return n.querySelectorAll(s);\n  }, d3_selectMatcher = d3_documentElement.matches || d3_documentElement[d3_vendorSymbol(d3_documentElement, \"matchesSelector\")], d3_selectMatches = function(n, s) {\n    return d3_selectMatcher.call(n, s);\n  };\n  if (typeof Sizzle === \"function\") {\n    d3_select = function(s, n) {\n      return Sizzle(s, n)[0] || null;\n    };\n    d3_selectAll = Sizzle;\n    d3_selectMatches = Sizzle.matchesSelector;\n  }\n  d3.selection = function() {\n    return d3_selectionRoot;\n  };\n  var d3_selectionPrototype = d3.selection.prototype = [];\n  d3_selectionPrototype.select = function(selector) {\n    var subgroups = [], subgroup, subnode, group, node;\n    selector = d3_selection_selector(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = (group = this[j]).parentNode;\n      for (var i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroup.push(subnode = selector.call(node, node.__data__, i, j));\n          if (subnode && \"__data__\" in node) subnode.__data__ = node.__data__;\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_selector(selector) {\n    return typeof selector === \"function\" ? selector : function() {\n      return d3_select(selector, this);\n    };\n  }\n  d3_selectionPrototype.selectAll = function(selector) {\n    var subgroups = [], subgroup, node;\n    selector = d3_selection_selectorAll(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));\n          subgroup.parentNode = node;\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_selectorAll(selector) {\n    return typeof selector === \"function\" ? selector : function() {\n      return d3_selectAll(selector, this);\n    };\n  }\n  var d3_nsPrefix = {\n    svg: \"http://www.w3.org/2000/svg\",\n    xhtml: \"http://www.w3.org/1999/xhtml\",\n    xlink: \"http://www.w3.org/1999/xlink\",\n    xml: \"http://www.w3.org/XML/1998/namespace\",\n    xmlns: \"http://www.w3.org/2000/xmlns/\"\n  };\n  d3.ns = {\n    prefix: d3_nsPrefix,\n    qualify: function(name) {\n      var i = name.indexOf(\":\"), prefix = name;\n      if (i >= 0) {\n        prefix = name.slice(0, i);\n        name = name.slice(i + 1);\n      }\n      return d3_nsPrefix.hasOwnProperty(prefix) ? {\n        space: d3_nsPrefix[prefix],\n        local: name\n      } : name;\n    }\n  };\n  d3_selectionPrototype.attr = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") {\n        var node = this.node();\n        name = d3.ns.qualify(name);\n        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);\n      }\n      for (value in name) this.each(d3_selection_attr(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_attr(name, value));\n  };\n  function d3_selection_attr(name, value) {\n    name = d3.ns.qualify(name);\n    function attrNull() {\n      this.removeAttribute(name);\n    }\n    function attrNullNS() {\n      this.removeAttributeNS(name.space, name.local);\n    }\n    function attrConstant() {\n      this.setAttribute(name, value);\n    }\n    function attrConstantNS() {\n      this.setAttributeNS(name.space, name.local, value);\n    }\n    function attrFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);\n    }\n    function attrFunctionNS() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);\n    }\n    return value == null ? name.local ? attrNullNS : attrNull : typeof value === \"function\" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;\n  }\n  function d3_collapse(s) {\n    return s.trim().replace(/\\s+/g, \" \");\n  }\n  d3_selectionPrototype.classed = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") {\n        var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;\n        if (value = node.classList) {\n          while (++i < n) if (!value.contains(name[i])) return false;\n        } else {\n          value = node.getAttribute(\"class\");\n          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;\n        }\n        return true;\n      }\n      for (value in name) this.each(d3_selection_classed(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_classed(name, value));\n  };\n  function d3_selection_classedRe(name) {\n    return new RegExp(\"(?:^|\\\\s+)\" + d3.requote(name) + \"(?:\\\\s+|$)\", \"g\");\n  }\n  function d3_selection_classes(name) {\n    return (name + \"\").trim().split(/^|\\s+/);\n  }\n  function d3_selection_classed(name, value) {\n    name = d3_selection_classes(name).map(d3_selection_classedName);\n    var n = name.length;\n    function classedConstant() {\n      var i = -1;\n      while (++i < n) name[i](this, value);\n    }\n    function classedFunction() {\n      var i = -1, x = value.apply(this, arguments);\n      while (++i < n) name[i](this, x);\n    }\n    return typeof value === \"function\" ? classedFunction : classedConstant;\n  }\n  function d3_selection_classedName(name) {\n    var re = d3_selection_classedRe(name);\n    return function(node, value) {\n      if (c = node.classList) return value ? c.add(name) : c.remove(name);\n      var c = node.getAttribute(\"class\") || \"\";\n      if (value) {\n        re.lastIndex = 0;\n        if (!re.test(c)) node.setAttribute(\"class\", d3_collapse(c + \" \" + name));\n      } else {\n        node.setAttribute(\"class\", d3_collapse(c.replace(re, \" \")));\n      }\n    };\n  }\n  d3_selectionPrototype.style = function(name, value, priority) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof name !== \"string\") {\n        if (n < 2) value = \"\";\n        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));\n        return this;\n      }\n      if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);\n      priority = \"\";\n    }\n    return this.each(d3_selection_style(name, value, priority));\n  };\n  function d3_selection_style(name, value, priority) {\n    function styleNull() {\n      this.style.removeProperty(name);\n    }\n    function styleConstant() {\n      this.style.setProperty(name, value, priority);\n    }\n    function styleFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);\n    }\n    return value == null ? styleNull : typeof value === \"function\" ? styleFunction : styleConstant;\n  }\n  d3_selectionPrototype.property = function(name, value) {\n    if (arguments.length < 2) {\n      if (typeof name === \"string\") return this.node()[name];\n      for (value in name) this.each(d3_selection_property(value, name[value]));\n      return this;\n    }\n    return this.each(d3_selection_property(name, value));\n  };\n  function d3_selection_property(name, value) {\n    function propertyNull() {\n      delete this[name];\n    }\n    function propertyConstant() {\n      this[name] = value;\n    }\n    function propertyFunction() {\n      var x = value.apply(this, arguments);\n      if (x == null) delete this[name]; else this[name] = x;\n    }\n    return value == null ? propertyNull : typeof value === \"function\" ? propertyFunction : propertyConstant;\n  }\n  d3_selectionPrototype.text = function(value) {\n    return arguments.length ? this.each(typeof value === \"function\" ? function() {\n      var v = value.apply(this, arguments);\n      this.textContent = v == null ? \"\" : v;\n    } : value == null ? function() {\n      this.textContent = \"\";\n    } : function() {\n      this.textContent = value;\n    }) : this.node().textContent;\n  };\n  d3_selectionPrototype.html = function(value) {\n    return arguments.length ? this.each(typeof value === \"function\" ? function() {\n      var v = value.apply(this, arguments);\n      this.innerHTML = v == null ? \"\" : v;\n    } : value == null ? function() {\n      this.innerHTML = \"\";\n    } : function() {\n      this.innerHTML = value;\n    }) : this.node().innerHTML;\n  };\n  d3_selectionPrototype.append = function(name) {\n    name = d3_selection_creator(name);\n    return this.select(function() {\n      return this.appendChild(name.apply(this, arguments));\n    });\n  };\n  function d3_selection_creator(name) {\n    return typeof name === \"function\" ? name : (name = d3.ns.qualify(name)).local ? function() {\n      return this.ownerDocument.createElementNS(name.space, name.local);\n    } : function() {\n      return this.ownerDocument.createElementNS(this.namespaceURI, name);\n    };\n  }\n  d3_selectionPrototype.insert = function(name, before) {\n    name = d3_selection_creator(name);\n    before = d3_selection_selector(before);\n    return this.select(function() {\n      return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);\n    });\n  };\n  d3_selectionPrototype.remove = function() {\n    return this.each(function() {\n      var parent = this.parentNode;\n      if (parent) parent.removeChild(this);\n    });\n  };\n  d3_selectionPrototype.data = function(value, key) {\n    var i = -1, n = this.length, group, node;\n    if (!arguments.length) {\n      value = new Array(n = (group = this[0]).length);\n      while (++i < n) {\n        if (node = group[i]) {\n          value[i] = node.__data__;\n        }\n      }\n      return value;\n    }\n    function bind(group, groupData) {\n      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;\n      if (key) {\n        var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;\n        for (i = -1; ++i < n; ) {\n          if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) {\n            exitNodes[i] = node;\n          } else {\n            nodeByKeyValue.set(keyValue, node);\n          }\n          keyValues[i] = keyValue;\n        }\n        for (i = -1; ++i < m; ) {\n          if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {\n            enterNodes[i] = d3_selection_dataNode(nodeData);\n          } else if (node !== true) {\n            updateNodes[i] = node;\n            node.__data__ = nodeData;\n          }\n          nodeByKeyValue.set(keyValue, true);\n        }\n        for (i = -1; ++i < n; ) {\n          if (nodeByKeyValue.get(keyValues[i]) !== true) {\n            exitNodes[i] = group[i];\n          }\n        }\n      } else {\n        for (i = -1; ++i < n0; ) {\n          node = group[i];\n          nodeData = groupData[i];\n          if (node) {\n            node.__data__ = nodeData;\n            updateNodes[i] = node;\n          } else {\n            enterNodes[i] = d3_selection_dataNode(nodeData);\n          }\n        }\n        for (;i < m; ++i) {\n          enterNodes[i] = d3_selection_dataNode(groupData[i]);\n        }\n        for (;i < n; ++i) {\n          exitNodes[i] = group[i];\n        }\n      }\n      enterNodes.update = updateNodes;\n      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;\n      enter.push(enterNodes);\n      update.push(updateNodes);\n      exit.push(exitNodes);\n    }\n    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);\n    if (typeof value === \"function\") {\n      while (++i < n) {\n        bind(group = this[i], value.call(group, group.parentNode.__data__, i));\n      }\n    } else {\n      while (++i < n) {\n        bind(group = this[i], value);\n      }\n    }\n    update.enter = function() {\n      return enter;\n    };\n    update.exit = function() {\n      return exit;\n    };\n    return update;\n  };\n  function d3_selection_dataNode(data) {\n    return {\n      __data__: data\n    };\n  }\n  d3_selectionPrototype.datum = function(value) {\n    return arguments.length ? this.property(\"__data__\", value) : this.property(\"__data__\");\n  };\n  d3_selectionPrototype.filter = function(filter) {\n    var subgroups = [], subgroup, group, node;\n    if (typeof filter !== \"function\") filter = d3_selection_filter(filter);\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = (group = this[j]).parentNode;\n      for (var i = 0, n = group.length; i < n; i++) {\n        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {\n          subgroup.push(node);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  function d3_selection_filter(selector) {\n    return function() {\n      return d3_selectMatches(this, selector);\n    };\n  }\n  d3_selectionPrototype.order = function() {\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {\n        if (node = group[i]) {\n          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);\n          next = node;\n        }\n      }\n    }\n    return this;\n  };\n  d3_selectionPrototype.sort = function(comparator) {\n    comparator = d3_selection_sortComparator.apply(this, arguments);\n    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);\n    return this.order();\n  };\n  function d3_selection_sortComparator(comparator) {\n    if (!arguments.length) comparator = d3_ascending;\n    return function(a, b) {\n      return a && b ? comparator(a.__data__, b.__data__) : !a - !b;\n    };\n  }\n  d3_selectionPrototype.each = function(callback) {\n    return d3_selection_each(this, function(node, i, j) {\n      callback.call(node, node.__data__, i, j);\n    });\n  };\n  function d3_selection_each(groups, callback) {\n    for (var j = 0, m = groups.length; j < m; j++) {\n      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {\n        if (node = group[i]) callback(node, i, j);\n      }\n    }\n    return groups;\n  }\n  d3_selectionPrototype.call = function(callback) {\n    var args = d3_array(arguments);\n    callback.apply(args[0] = this, args);\n    return this;\n  };\n  d3_selectionPrototype.empty = function() {\n    return !this.node();\n  };\n  d3_selectionPrototype.node = function() {\n    for (var j = 0, m = this.length; j < m; j++) {\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        var node = group[i];\n        if (node) return node;\n      }\n    }\n    return null;\n  };\n  d3_selectionPrototype.size = function() {\n    var n = 0;\n    d3_selection_each(this, function() {\n      ++n;\n    });\n    return n;\n  };\n  function d3_selection_enter(selection) {\n    d3_subclass(selection, d3_selection_enterPrototype);\n    return selection;\n  }\n  var d3_selection_enterPrototype = [];\n  d3.selection.enter = d3_selection_enter;\n  d3.selection.enter.prototype = d3_selection_enterPrototype;\n  d3_selection_enterPrototype.append = d3_selectionPrototype.append;\n  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;\n  d3_selection_enterPrototype.node = d3_selectionPrototype.node;\n  d3_selection_enterPrototype.call = d3_selectionPrototype.call;\n  d3_selection_enterPrototype.size = d3_selectionPrototype.size;\n  d3_selection_enterPrototype.select = function(selector) {\n    var subgroups = [], subgroup, subnode, upgroup, group, node;\n    for (var j = -1, m = this.length; ++j < m; ) {\n      upgroup = (group = this[j]).update;\n      subgroups.push(subgroup = []);\n      subgroup.parentNode = group.parentNode;\n      for (var i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));\n          subnode.__data__ = node.__data__;\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_selection(subgroups);\n  };\n  d3_selection_enterPrototype.insert = function(name, before) {\n    if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);\n    return d3_selectionPrototype.insert.call(this, name, before);\n  };\n  function d3_selection_enterInsertBefore(enter) {\n    var i0, j0;\n    return function(d, i, j) {\n      var group = enter[j].update, n = group.length, node;\n      if (j != j0) j0 = j, i0 = 0;\n      if (i >= i0) i0 = i + 1;\n      while (!(node = group[i0]) && ++i0 < n) ;\n      return node;\n    };\n  }\n  d3_selectionPrototype.transition = function() {\n    var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || {\n      time: Date.now(),\n      ease: d3_ease_cubicInOut,\n      delay: 0,\n      duration: 250\n    };\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) d3_transitionNode(node, i, id, transition);\n        subgroup.push(node);\n      }\n    }\n    return d3_transition(subgroups, id);\n  };\n  d3_selectionPrototype.interrupt = function() {\n    return this.each(d3_selection_interrupt);\n  };\n  function d3_selection_interrupt() {\n    var lock = this.__transition__;\n    if (lock) ++lock.active;\n  }\n  d3.select = function(node) {\n    var group = [ typeof node === \"string\" ? d3_select(node, d3_document) : node ];\n    group.parentNode = d3_documentElement;\n    return d3_selection([ group ]);\n  };\n  d3.selectAll = function(nodes) {\n    var group = d3_array(typeof nodes === \"string\" ? d3_selectAll(nodes, d3_document) : nodes);\n    group.parentNode = d3_documentElement;\n    return d3_selection([ group ]);\n  };\n  var d3_selectionRoot = d3.select(d3_documentElement);\n  d3_selectionPrototype.on = function(type, listener, capture) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof type !== \"string\") {\n        if (n < 2) listener = false;\n        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));\n        return this;\n      }\n      if (n < 2) return (n = this.node()[\"__on\" + type]) && n._;\n      capture = false;\n    }\n    return this.each(d3_selection_on(type, listener, capture));\n  };\n  function d3_selection_on(type, listener, capture) {\n    var name = \"__on\" + type, i = type.indexOf(\".\"), wrap = d3_selection_onListener;\n    if (i > 0) type = type.slice(0, i);\n    var filter = d3_selection_onFilters.get(type);\n    if (filter) type = filter, wrap = d3_selection_onFilter;\n    function onRemove() {\n      var l = this[name];\n      if (l) {\n        this.removeEventListener(type, l, l.$);\n        delete this[name];\n      }\n    }\n    function onAdd() {\n      var l = wrap(listener, d3_array(arguments));\n      onRemove.call(this);\n      this.addEventListener(type, this[name] = l, l.$ = capture);\n      l._ = listener;\n    }\n    function removeAll() {\n      var re = new RegExp(\"^__on([^.]+)\" + d3.requote(type) + \"$\"), match;\n      for (var name in this) {\n        if (match = name.match(re)) {\n          var l = this[name];\n          this.removeEventListener(match[1], l, l.$);\n          delete this[name];\n        }\n      }\n    }\n    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;\n  }\n  var d3_selection_onFilters = d3.map({\n    mouseenter: \"mouseover\",\n    mouseleave: \"mouseout\"\n  });\n  d3_selection_onFilters.forEach(function(k) {\n    if (\"on\" + k in d3_document) d3_selection_onFilters.remove(k);\n  });\n  function d3_selection_onListener(listener, argumentz) {\n    return function(e) {\n      var o = d3.event;\n      d3.event = e;\n      argumentz[0] = this.__data__;\n      try {\n        listener.apply(this, argumentz);\n      } finally {\n        d3.event = o;\n      }\n    };\n  }\n  function d3_selection_onFilter(listener, argumentz) {\n    var l = d3_selection_onListener(listener, argumentz);\n    return function(e) {\n      var target = this, related = e.relatedTarget;\n      if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {\n        l.call(target, e);\n      }\n    };\n  }\n  var d3_event_dragSelect = \"onselectstart\" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, \"userSelect\"), d3_event_dragId = 0;\n  function d3_event_dragSuppress() {\n    var name = \".dragsuppress-\" + ++d3_event_dragId, click = \"click\" + name, w = d3.select(d3_window).on(\"touchmove\" + name, d3_eventPreventDefault).on(\"dragstart\" + name, d3_eventPreventDefault).on(\"selectstart\" + name, d3_eventPreventDefault);\n    if (d3_event_dragSelect) {\n      var style = d3_documentElement.style, select = style[d3_event_dragSelect];\n      style[d3_event_dragSelect] = \"none\";\n    }\n    return function(suppressClick) {\n      w.on(name, null);\n      if (d3_event_dragSelect) style[d3_event_dragSelect] = select;\n      if (suppressClick) {\n        function off() {\n          w.on(click, null);\n        }\n        w.on(click, function() {\n          d3_eventPreventDefault();\n          off();\n        }, true);\n        setTimeout(off, 0);\n      }\n    };\n  }\n  d3.mouse = function(container) {\n    return d3_mousePoint(container, d3_eventSource());\n  };\n  var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;\n  function d3_mousePoint(container, e) {\n    if (e.changedTouches) e = e.changedTouches[0];\n    var svg = container.ownerSVGElement || container;\n    if (svg.createSVGPoint) {\n      var point = svg.createSVGPoint();\n      if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) {\n        svg = d3.select(\"body\").append(\"svg\").style({\n          position: \"absolute\",\n          top: 0,\n          left: 0,\n          margin: 0,\n          padding: 0,\n          border: \"none\"\n        }, \"important\");\n        var ctm = svg[0][0].getScreenCTM();\n        d3_mouse_bug44083 = !(ctm.f || ctm.e);\n        svg.remove();\n      }\n      if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, \n      point.y = e.clientY;\n      point = point.matrixTransform(container.getScreenCTM().inverse());\n      return [ point.x, point.y ];\n    }\n    var rect = container.getBoundingClientRect();\n    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];\n  }\n  d3.touch = function(container, touches, identifier) {\n    if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;\n    if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {\n      if ((touch = touches[i]).identifier === identifier) {\n        return d3_mousePoint(container, touch);\n      }\n    }\n  };\n  d3.behavior.drag = function() {\n    var event = d3_eventDispatch(drag, \"drag\", \"dragstart\", \"dragend\"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, \"mousemove\", \"mouseup\"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, \"touchmove\", \"touchend\");\n    function drag() {\n      this.on(\"mousedown.drag\", mousedown).on(\"touchstart.drag\", touchstart);\n    }\n    function dragstart(id, position, subject, move, end) {\n      return function() {\n        var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = \".drag\" + (dragId == null ? \"\" : \"-\" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId);\n        if (origin) {\n          dragOffset = origin.apply(that, arguments);\n          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];\n        } else {\n          dragOffset = [ 0, 0 ];\n        }\n        dispatch({\n          type: \"dragstart\"\n        });\n        function moved() {\n          var position1 = position(parent, dragId), dx, dy;\n          if (!position1) return;\n          dx = position1[0] - position0[0];\n          dy = position1[1] - position0[1];\n          dragged |= dx | dy;\n          position0 = position1;\n          dispatch({\n            type: \"drag\",\n            x: position1[0] + dragOffset[0],\n            y: position1[1] + dragOffset[1],\n            dx: dx,\n            dy: dy\n          });\n        }\n        function ended() {\n          if (!position(parent, dragId)) return;\n          dragSubject.on(move + dragName, null).on(end + dragName, null);\n          dragRestore(dragged && d3.event.target === target);\n          dispatch({\n            type: \"dragend\"\n          });\n        }\n      };\n    }\n    drag.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = x;\n      return drag;\n    };\n    return d3.rebind(drag, event, \"on\");\n  };\n  function d3_behavior_dragTouchId() {\n    return d3.event.changedTouches[0].identifier;\n  }\n  function d3_behavior_dragTouchSubject() {\n    return d3.event.target;\n  }\n  function d3_behavior_dragMouseSubject() {\n    return d3_window;\n  }\n  d3.touches = function(container, touches) {\n    if (arguments.length < 2) touches = d3_eventSource().touches;\n    return touches ? d3_array(touches).map(function(touch) {\n      var point = d3_mousePoint(container, touch);\n      point.identifier = touch.identifier;\n      return point;\n    }) : [];\n  };\n  var π = Math.PI, τ = 2 * π, halfπ = π / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = π / 180, d3_degrees = 180 / π;\n  function d3_sgn(x) {\n    return x > 0 ? 1 : x < 0 ? -1 : 0;\n  }\n  function d3_cross2d(a, b, c) {\n    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);\n  }\n  function d3_acos(x) {\n    return x > 1 ? 0 : x < -1 ? π : Math.acos(x);\n  }\n  function d3_asin(x) {\n    return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);\n  }\n  function d3_sinh(x) {\n    return ((x = Math.exp(x)) - 1 / x) / 2;\n  }\n  function d3_cosh(x) {\n    return ((x = Math.exp(x)) + 1 / x) / 2;\n  }\n  function d3_tanh(x) {\n    return ((x = Math.exp(2 * x)) - 1) / (x + 1);\n  }\n  function d3_haversin(x) {\n    return (x = Math.sin(x / 2)) * x;\n  }\n  var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;\n  d3.interpolateZoom = function(p0, p1) {\n    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];\n    var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;\n    function interpolate(t) {\n      var s = t * S;\n      if (dr) {\n        var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));\n        return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];\n      }\n      return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];\n    }\n    interpolate.duration = S * 1e3;\n    return interpolate;\n  };\n  d3.behavior.zoom = function() {\n    var view = {\n      x: 0,\n      y: 0,\n      k: 1\n    }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = \"mousedown.zoom\", mousemove = \"mousemove.zoom\", mouseup = \"mouseup.zoom\", mousewheelTimer, touchstart = \"touchstart.zoom\", touchtime, event = d3_eventDispatch(zoom, \"zoomstart\", \"zoom\", \"zoomend\"), x0, x1, y0, y1;\n    function zoom(g) {\n      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + \".zoom\", mousewheeled).on(\"dblclick.zoom\", dblclicked).on(touchstart, touchstarted);\n    }\n    zoom.event = function(g) {\n      g.each(function() {\n        var dispatch = event.of(this, arguments), view1 = view;\n        if (d3_transitionInheritId) {\n          d3.select(this).transition().each(\"start.zoom\", function() {\n            view = this.__chart__ || {\n              x: 0,\n              y: 0,\n              k: 1\n            };\n            zoomstarted(dispatch);\n          }).tween(\"zoom:zoom\", function() {\n            var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);\n            return function(t) {\n              var l = i(t), k = dx / l[2];\n              this.__chart__ = view = {\n                x: cx - l[0] * k,\n                y: cy - l[1] * k,\n                k: k\n              };\n              zoomed(dispatch);\n            };\n          }).each(\"end.zoom\", function() {\n            zoomended(dispatch);\n          });\n        } else {\n          this.__chart__ = view;\n          zoomstarted(dispatch);\n          zoomed(dispatch);\n          zoomended(dispatch);\n        }\n      });\n    };\n    zoom.translate = function(_) {\n      if (!arguments.length) return [ view.x, view.y ];\n      view = {\n        x: +_[0],\n        y: +_[1],\n        k: view.k\n      };\n      rescale();\n      return zoom;\n    };\n    zoom.scale = function(_) {\n      if (!arguments.length) return view.k;\n      view = {\n        x: view.x,\n        y: view.y,\n        k: +_\n      };\n      rescale();\n      return zoom;\n    };\n    zoom.scaleExtent = function(_) {\n      if (!arguments.length) return scaleExtent;\n      scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];\n      return zoom;\n    };\n    zoom.center = function(_) {\n      if (!arguments.length) return center;\n      center = _ && [ +_[0], +_[1] ];\n      return zoom;\n    };\n    zoom.size = function(_) {\n      if (!arguments.length) return size;\n      size = _ && [ +_[0], +_[1] ];\n      return zoom;\n    };\n    zoom.x = function(z) {\n      if (!arguments.length) return x1;\n      x1 = z;\n      x0 = z.copy();\n      view = {\n        x: 0,\n        y: 0,\n        k: 1\n      };\n      return zoom;\n    };\n    zoom.y = function(z) {\n      if (!arguments.length) return y1;\n      y1 = z;\n      y0 = z.copy();\n      view = {\n        x: 0,\n        y: 0,\n        k: 1\n      };\n      return zoom;\n    };\n    function location(p) {\n      return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];\n    }\n    function point(l) {\n      return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];\n    }\n    function scaleTo(s) {\n      view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));\n    }\n    function translateTo(p, l) {\n      l = point(l);\n      view.x += p[0] - l[0];\n      view.y += p[1] - l[1];\n    }\n    function rescale() {\n      if (x1) x1.domain(x0.range().map(function(x) {\n        return (x - view.x) / view.k;\n      }).map(x0.invert));\n      if (y1) y1.domain(y0.range().map(function(y) {\n        return (y - view.y) / view.k;\n      }).map(y0.invert));\n    }\n    function zoomstarted(dispatch) {\n      dispatch({\n        type: \"zoomstart\"\n      });\n    }\n    function zoomed(dispatch) {\n      rescale();\n      dispatch({\n        type: \"zoom\",\n        scale: view.k,\n        translate: [ view.x, view.y ]\n      });\n    }\n    function zoomended(dispatch) {\n      dispatch({\n        type: \"zoomend\"\n      });\n    }\n    function mousedowned() {\n      var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress();\n      d3_selection_interrupt.call(that);\n      zoomstarted(dispatch);\n      function moved() {\n        dragged = 1;\n        translateTo(d3.mouse(that), location0);\n        zoomed(dispatch);\n      }\n      function ended() {\n        subject.on(mousemove, null).on(mouseup, null);\n        dragRestore(dragged && d3.event.target === target);\n        zoomended(dispatch);\n      }\n    }\n    function touchstarted() {\n      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = \".zoom-\" + d3.event.changedTouches[0].identifier, touchmove = \"touchmove\" + zoomName, touchend = \"touchend\" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress();\n      d3_selection_interrupt.call(that);\n      started();\n      zoomstarted(dispatch);\n      subject.on(mousedown, null).on(touchstart, started);\n      function relocate() {\n        var touches = d3.touches(that);\n        scale0 = view.k;\n        touches.forEach(function(t) {\n          if (t.identifier in locations0) locations0[t.identifier] = location(t);\n        });\n        return touches;\n      }\n      function started() {\n        var target = d3.event.target;\n        d3.select(target).on(touchmove, moved).on(touchend, ended);\n        targets.push(target);\n        var changed = d3.event.changedTouches;\n        for (var i = 0, n = changed.length; i < n; ++i) {\n          locations0[changed[i].identifier] = null;\n        }\n        var touches = relocate(), now = Date.now();\n        if (touches.length === 1) {\n          if (now - touchtime < 500) {\n            var p = touches[0], l = locations0[p.identifier];\n            scaleTo(view.k * 2);\n            translateTo(p, l);\n            d3_eventPreventDefault();\n            zoomed(dispatch);\n          }\n          touchtime = now;\n        } else if (touches.length > 1) {\n          var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];\n          distance0 = dx * dx + dy * dy;\n        }\n      }\n      function moved() {\n        var touches = d3.touches(that), p0, l0, p1, l1;\n        for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {\n          p1 = touches[i];\n          if (l1 = locations0[p1.identifier]) {\n            if (l0) break;\n            p0 = p1, l0 = l1;\n          }\n        }\n        if (l1) {\n          var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);\n          p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];\n          l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];\n          scaleTo(scale1 * scale0);\n        }\n        touchtime = null;\n        translateTo(p0, l0);\n        zoomed(dispatch);\n      }\n      function ended() {\n        if (d3.event.touches.length) {\n          var changed = d3.event.changedTouches;\n          for (var i = 0, n = changed.length; i < n; ++i) {\n            delete locations0[changed[i].identifier];\n          }\n          for (var identifier in locations0) {\n            return void relocate();\n          }\n        }\n        d3.selectAll(targets).on(zoomName, null);\n        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);\n        dragRestore();\n        zoomended(dispatch);\n      }\n    }\n    function mousewheeled() {\n      var dispatch = event.of(this, arguments);\n      if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), \n      d3_selection_interrupt.call(this), zoomstarted(dispatch);\n      mousewheelTimer = setTimeout(function() {\n        mousewheelTimer = null;\n        zoomended(dispatch);\n      }, 50);\n      d3_eventPreventDefault();\n      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);\n      translateTo(center0, translate0);\n      zoomed(dispatch);\n    }\n    function dblclicked() {\n      var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2;\n      zoomstarted(dispatch);\n      scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));\n      translateTo(p, l);\n      zoomed(dispatch);\n      zoomended(dispatch);\n    }\n    return d3.rebind(zoom, event, \"on\");\n  };\n  var d3_behavior_zoomInfinity = [ 0, Infinity ];\n  var d3_behavior_zoomDelta, d3_behavior_zoomWheel = \"onwheel\" in d3_document ? (d3_behavior_zoomDelta = function() {\n    return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);\n  }, \"wheel\") : \"onmousewheel\" in d3_document ? (d3_behavior_zoomDelta = function() {\n    return d3.event.wheelDelta;\n  }, \"mousewheel\") : (d3_behavior_zoomDelta = function() {\n    return -d3.event.detail;\n  }, \"MozMousePixelScroll\");\n  d3.color = d3_color;\n  function d3_color() {}\n  d3_color.prototype.toString = function() {\n    return this.rgb() + \"\";\n  };\n  d3.hsl = d3_hsl;\n  function d3_hsl(h, s, l) {\n    return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse(\"\" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);\n  }\n  var d3_hslPrototype = d3_hsl.prototype = new d3_color();\n  d3_hslPrototype.brighter = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return new d3_hsl(this.h, this.s, this.l / k);\n  };\n  d3_hslPrototype.darker = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return new d3_hsl(this.h, this.s, k * this.l);\n  };\n  d3_hslPrototype.rgb = function() {\n    return d3_hsl_rgb(this.h, this.s, this.l);\n  };\n  function d3_hsl_rgb(h, s, l) {\n    var m1, m2;\n    h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;\n    s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;\n    l = l < 0 ? 0 : l > 1 ? 1 : l;\n    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;\n    m1 = 2 * l - m2;\n    function v(h) {\n      if (h > 360) h -= 360; else if (h < 0) h += 360;\n      if (h < 60) return m1 + (m2 - m1) * h / 60;\n      if (h < 180) return m2;\n      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;\n      return m1;\n    }\n    function vv(h) {\n      return Math.round(v(h) * 255);\n    }\n    return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));\n  }\n  d3.hcl = d3_hcl;\n  function d3_hcl(h, c, l) {\n    return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);\n  }\n  var d3_hclPrototype = d3_hcl.prototype = new d3_color();\n  d3_hclPrototype.brighter = function(k) {\n    return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));\n  };\n  d3_hclPrototype.darker = function(k) {\n    return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));\n  };\n  d3_hclPrototype.rgb = function() {\n    return d3_hcl_lab(this.h, this.c, this.l).rgb();\n  };\n  function d3_hcl_lab(h, c, l) {\n    if (isNaN(h)) h = 0;\n    if (isNaN(c)) c = 0;\n    return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);\n  }\n  d3.lab = d3_lab;\n  function d3_lab(l, a, b) {\n    return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);\n  }\n  var d3_lab_K = 18;\n  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;\n  var d3_labPrototype = d3_lab.prototype = new d3_color();\n  d3_labPrototype.brighter = function(k) {\n    return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);\n  };\n  d3_labPrototype.darker = function(k) {\n    return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);\n  };\n  d3_labPrototype.rgb = function() {\n    return d3_lab_rgb(this.l, this.a, this.b);\n  };\n  function d3_lab_rgb(l, a, b) {\n    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;\n    x = d3_lab_xyz(x) * d3_lab_X;\n    y = d3_lab_xyz(y) * d3_lab_Y;\n    z = d3_lab_xyz(z) * d3_lab_Z;\n    return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));\n  }\n  function d3_lab_hcl(l, a, b) {\n    return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);\n  }\n  function d3_lab_xyz(x) {\n    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;\n  }\n  function d3_xyz_lab(x) {\n    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;\n  }\n  function d3_xyz_rgb(r) {\n    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));\n  }\n  d3.rgb = d3_rgb;\n  function d3_rgb(r, g, b) {\n    return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse(\"\" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);\n  }\n  function d3_rgbNumber(value) {\n    return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);\n  }\n  function d3_rgbString(value) {\n    return d3_rgbNumber(value) + \"\";\n  }\n  var d3_rgbPrototype = d3_rgb.prototype = new d3_color();\n  d3_rgbPrototype.brighter = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    var r = this.r, g = this.g, b = this.b, i = 30;\n    if (!r && !g && !b) return new d3_rgb(i, i, i);\n    if (r && r < i) r = i;\n    if (g && g < i) g = i;\n    if (b && b < i) b = i;\n    return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));\n  };\n  d3_rgbPrototype.darker = function(k) {\n    k = Math.pow(.7, arguments.length ? k : 1);\n    return new d3_rgb(k * this.r, k * this.g, k * this.b);\n  };\n  d3_rgbPrototype.hsl = function() {\n    return d3_rgb_hsl(this.r, this.g, this.b);\n  };\n  d3_rgbPrototype.toString = function() {\n    return \"#\" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);\n  };\n  function d3_rgb_hex(v) {\n    return v < 16 ? \"0\" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);\n  }\n  function d3_rgb_parse(format, rgb, hsl) {\n    var r = 0, g = 0, b = 0, m1, m2, color;\n    m1 = /([a-z]+)\\((.*)\\)/i.exec(format);\n    if (m1) {\n      m2 = m1[2].split(\",\");\n      switch (m1[1]) {\n       case \"hsl\":\n        {\n          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);\n        }\n\n       case \"rgb\":\n        {\n          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));\n        }\n      }\n    }\n    if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b);\n    if (format != null && format.charAt(0) === \"#\" && !isNaN(color = parseInt(format.slice(1), 16))) {\n      if (format.length === 4) {\n        r = (color & 3840) >> 4;\n        r = r >> 4 | r;\n        g = color & 240;\n        g = g >> 4 | g;\n        b = color & 15;\n        b = b << 4 | b;\n      } else if (format.length === 7) {\n        r = (color & 16711680) >> 16;\n        g = (color & 65280) >> 8;\n        b = color & 255;\n      }\n    }\n    return rgb(r, g, b);\n  }\n  function d3_rgb_hsl(r, g, b) {\n    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;\n    if (d) {\n      s = l < .5 ? d / (max + min) : d / (2 - max - min);\n      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;\n      h *= 60;\n    } else {\n      h = NaN;\n      s = l > 0 && l < 1 ? 0 : h;\n    }\n    return new d3_hsl(h, s, l);\n  }\n  function d3_rgb_lab(r, g, b) {\n    r = d3_rgb_xyz(r);\n    g = d3_rgb_xyz(g);\n    b = d3_rgb_xyz(b);\n    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);\n    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));\n  }\n  function d3_rgb_xyz(r) {\n    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);\n  }\n  function d3_rgb_parseNumber(c) {\n    var f = parseFloat(c);\n    return c.charAt(c.length - 1) === \"%\" ? Math.round(f * 2.55) : f;\n  }\n  var d3_rgb_names = d3.map({\n    aliceblue: 15792383,\n    antiquewhite: 16444375,\n    aqua: 65535,\n    aquamarine: 8388564,\n    azure: 15794175,\n    beige: 16119260,\n    bisque: 16770244,\n    black: 0,\n    blanchedalmond: 16772045,\n    blue: 255,\n    blueviolet: 9055202,\n    brown: 10824234,\n    burlywood: 14596231,\n    cadetblue: 6266528,\n    chartreuse: 8388352,\n    chocolate: 13789470,\n    coral: 16744272,\n    cornflowerblue: 6591981,\n    cornsilk: 16775388,\n    crimson: 14423100,\n    cyan: 65535,\n    darkblue: 139,\n    darkcyan: 35723,\n    darkgoldenrod: 12092939,\n    darkgray: 11119017,\n    darkgreen: 25600,\n    darkgrey: 11119017,\n    darkkhaki: 12433259,\n    darkmagenta: 9109643,\n    darkolivegreen: 5597999,\n    darkorange: 16747520,\n    darkorchid: 10040012,\n    darkred: 9109504,\n    darksalmon: 15308410,\n    darkseagreen: 9419919,\n    darkslateblue: 4734347,\n    darkslategray: 3100495,\n    darkslategrey: 3100495,\n    darkturquoise: 52945,\n    darkviolet: 9699539,\n    deeppink: 16716947,\n    deepskyblue: 49151,\n    dimgray: 6908265,\n    dimgrey: 6908265,\n    dodgerblue: 2003199,\n    firebrick: 11674146,\n    floralwhite: 16775920,\n    forestgreen: 2263842,\n    fuchsia: 16711935,\n    gainsboro: 14474460,\n    ghostwhite: 16316671,\n    gold: 16766720,\n    goldenrod: 14329120,\n    gray: 8421504,\n    green: 32768,\n    greenyellow: 11403055,\n    grey: 8421504,\n    honeydew: 15794160,\n    hotpink: 16738740,\n    indianred: 13458524,\n    indigo: 4915330,\n    ivory: 16777200,\n    khaki: 15787660,\n    lavender: 15132410,\n    lavenderblush: 16773365,\n    lawngreen: 8190976,\n    lemonchiffon: 16775885,\n    lightblue: 11393254,\n    lightcoral: 15761536,\n    lightcyan: 14745599,\n    lightgoldenrodyellow: 16448210,\n    lightgray: 13882323,\n    lightgreen: 9498256,\n    lightgrey: 13882323,\n    lightpink: 16758465,\n    lightsalmon: 16752762,\n    lightseagreen: 2142890,\n    lightskyblue: 8900346,\n    lightslategray: 7833753,\n    lightslategrey: 7833753,\n    lightsteelblue: 11584734,\n    lightyellow: 16777184,\n    lime: 65280,\n    limegreen: 3329330,\n    linen: 16445670,\n    magenta: 16711935,\n    maroon: 8388608,\n    mediumaquamarine: 6737322,\n    mediumblue: 205,\n    mediumorchid: 12211667,\n    mediumpurple: 9662683,\n    mediumseagreen: 3978097,\n    mediumslateblue: 8087790,\n    mediumspringgreen: 64154,\n    mediumturquoise: 4772300,\n    mediumvioletred: 13047173,\n    midnightblue: 1644912,\n    mintcream: 16121850,\n    mistyrose: 16770273,\n    moccasin: 16770229,\n    navajowhite: 16768685,\n    navy: 128,\n    oldlace: 16643558,\n    olive: 8421376,\n    olivedrab: 7048739,\n    orange: 16753920,\n    orangered: 16729344,\n    orchid: 14315734,\n    palegoldenrod: 15657130,\n    palegreen: 10025880,\n    paleturquoise: 11529966,\n    palevioletred: 14381203,\n    papayawhip: 16773077,\n    peachpuff: 16767673,\n    peru: 13468991,\n    pink: 16761035,\n    plum: 14524637,\n    powderblue: 11591910,\n    purple: 8388736,\n    red: 16711680,\n    rosybrown: 12357519,\n    royalblue: 4286945,\n    saddlebrown: 9127187,\n    salmon: 16416882,\n    sandybrown: 16032864,\n    seagreen: 3050327,\n    seashell: 16774638,\n    sienna: 10506797,\n    silver: 12632256,\n    skyblue: 8900331,\n    slateblue: 6970061,\n    slategray: 7372944,\n    slategrey: 7372944,\n    snow: 16775930,\n    springgreen: 65407,\n    steelblue: 4620980,\n    tan: 13808780,\n    teal: 32896,\n    thistle: 14204888,\n    tomato: 16737095,\n    turquoise: 4251856,\n    violet: 15631086,\n    wheat: 16113331,\n    white: 16777215,\n    whitesmoke: 16119285,\n    yellow: 16776960,\n    yellowgreen: 10145074\n  });\n  d3_rgb_names.forEach(function(key, value) {\n    d3_rgb_names.set(key, d3_rgbNumber(value));\n  });\n  function d3_functor(v) {\n    return typeof v === \"function\" ? v : function() {\n      return v;\n    };\n  }\n  d3.functor = d3_functor;\n  function d3_identity(d) {\n    return d;\n  }\n  d3.xhr = d3_xhrType(d3_identity);\n  function d3_xhrType(response) {\n    return function(url, mimeType, callback) {\n      if (arguments.length === 2 && typeof mimeType === \"function\") callback = mimeType, \n      mimeType = null;\n      return d3_xhr(url, mimeType, response, callback);\n    };\n  }\n  function d3_xhr(url, mimeType, response, callback) {\n    var xhr = {}, dispatch = d3.dispatch(\"beforesend\", \"progress\", \"load\", \"error\"), headers = {}, request = new XMLHttpRequest(), responseType = null;\n    if (d3_window.XDomainRequest && !(\"withCredentials\" in request) && /^(http(s)?:)?\\/\\//.test(url)) request = new XDomainRequest();\n    \"onload\" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {\n      request.readyState > 3 && respond();\n    };\n    function respond() {\n      var status = request.status, result;\n      if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {\n        try {\n          result = response.call(xhr, request);\n        } catch (e) {\n          dispatch.error.call(xhr, e);\n          return;\n        }\n        dispatch.load.call(xhr, result);\n      } else {\n        dispatch.error.call(xhr, request);\n      }\n    }\n    request.onprogress = function(event) {\n      var o = d3.event;\n      d3.event = event;\n      try {\n        dispatch.progress.call(xhr, request);\n      } finally {\n        d3.event = o;\n      }\n    };\n    xhr.header = function(name, value) {\n      name = (name + \"\").toLowerCase();\n      if (arguments.length < 2) return headers[name];\n      if (value == null) delete headers[name]; else headers[name] = value + \"\";\n      return xhr;\n    };\n    xhr.mimeType = function(value) {\n      if (!arguments.length) return mimeType;\n      mimeType = value == null ? null : value + \"\";\n      return xhr;\n    };\n    xhr.responseType = function(value) {\n      if (!arguments.length) return responseType;\n      responseType = value;\n      return xhr;\n    };\n    xhr.response = function(value) {\n      response = value;\n      return xhr;\n    };\n    [ \"get\", \"post\" ].forEach(function(method) {\n      xhr[method] = function() {\n        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));\n      };\n    });\n    xhr.send = function(method, data, callback) {\n      if (arguments.length === 2 && typeof data === \"function\") callback = data, data = null;\n      request.open(method, url, true);\n      if (mimeType != null && !(\"accept\" in headers)) headers[\"accept\"] = mimeType + \",*/*\";\n      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);\n      if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);\n      if (responseType != null) request.responseType = responseType;\n      if (callback != null) xhr.on(\"error\", callback).on(\"load\", function(request) {\n        callback(null, request);\n      });\n      dispatch.beforesend.call(xhr, request);\n      request.send(data == null ? null : data);\n      return xhr;\n    };\n    xhr.abort = function() {\n      request.abort();\n      return xhr;\n    };\n    d3.rebind(xhr, dispatch, \"on\");\n    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));\n  }\n  function d3_xhr_fixCallback(callback) {\n    return callback.length === 1 ? function(error, request) {\n      callback(error == null ? request : null);\n    } : callback;\n  }\n  function d3_xhrHasResponse(request) {\n    var type = request.responseType;\n    return type && type !== \"text\" ? request.response : request.responseText;\n  }\n  d3.dsv = function(delimiter, mimeType) {\n    var reFormat = new RegExp('[\"' + delimiter + \"\\n]\"), delimiterCode = delimiter.charCodeAt(0);\n    function dsv(url, row, callback) {\n      if (arguments.length < 3) callback = row, row = null;\n      var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);\n      xhr.row = function(_) {\n        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;\n      };\n      return xhr;\n    }\n    function response(request) {\n      return dsv.parse(request.responseText);\n    }\n    function typedResponse(f) {\n      return function(request) {\n        return dsv.parse(request.responseText, f);\n      };\n    }\n    dsv.parse = function(text, f) {\n      var o;\n      return dsv.parseRows(text, function(row, i) {\n        if (o) return o(row, i - 1);\n        var a = new Function(\"d\", \"return {\" + row.map(function(name, i) {\n          return JSON.stringify(name) + \": d[\" + i + \"]\";\n        }).join(\",\") + \"}\");\n        o = f ? function(row, i) {\n          return f(a(row), i);\n        } : a;\n      });\n    };\n    dsv.parseRows = function(text, f) {\n      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;\n      function token() {\n        if (I >= N) return EOF;\n        if (eol) return eol = false, EOL;\n        var j = I;\n        if (text.charCodeAt(j) === 34) {\n          var i = j;\n          while (i++ < N) {\n            if (text.charCodeAt(i) === 34) {\n              if (text.charCodeAt(i + 1) !== 34) break;\n              ++i;\n            }\n          }\n          I = i + 2;\n          var c = text.charCodeAt(i + 1);\n          if (c === 13) {\n            eol = true;\n            if (text.charCodeAt(i + 2) === 10) ++I;\n          } else if (c === 10) {\n            eol = true;\n          }\n          return text.slice(j + 1, i).replace(/\"\"/g, '\"');\n        }\n        while (I < N) {\n          var c = text.charCodeAt(I++), k = 1;\n          if (c === 10) eol = true; else if (c === 13) {\n            eol = true;\n            if (text.charCodeAt(I) === 10) ++I, ++k;\n          } else if (c !== delimiterCode) continue;\n          return text.slice(j, I - k);\n        }\n        return text.slice(j);\n      }\n      while ((t = token()) !== EOF) {\n        var a = [];\n        while (t !== EOL && t !== EOF) {\n          a.push(t);\n          t = token();\n        }\n        if (f && (a = f(a, n++)) == null) continue;\n        rows.push(a);\n      }\n      return rows;\n    };\n    dsv.format = function(rows) {\n      if (Array.isArray(rows[0])) return dsv.formatRows(rows);\n      var fieldSet = new d3_Set(), fields = [];\n      rows.forEach(function(row) {\n        for (var field in row) {\n          if (!fieldSet.has(field)) {\n            fields.push(fieldSet.add(field));\n          }\n        }\n      });\n      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {\n        return fields.map(function(field) {\n          return formatValue(row[field]);\n        }).join(delimiter);\n      })).join(\"\\n\");\n    };\n    dsv.formatRows = function(rows) {\n      return rows.map(formatRow).join(\"\\n\");\n    };\n    function formatRow(row) {\n      return row.map(formatValue).join(delimiter);\n    }\n    function formatValue(text) {\n      return reFormat.test(text) ? '\"' + text.replace(/\\\"/g, '\"\"') + '\"' : text;\n    }\n    return dsv;\n  };\n  d3.csv = d3.dsv(\",\", \"text/csv\");\n  d3.tsv = d3.dsv(\"\t\", \"text/tab-separated-values\");\n  var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, \"requestAnimationFrame\")] || function(callback) {\n    setTimeout(callback, 17);\n  };\n  d3.timer = function(callback, delay, then) {\n    var n = arguments.length;\n    if (n < 2) delay = 0;\n    if (n < 3) then = Date.now();\n    var time = then + delay, timer = {\n      c: callback,\n      t: time,\n      f: false,\n      n: null\n    };\n    if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;\n    d3_timer_queueTail = timer;\n    if (!d3_timer_interval) {\n      d3_timer_timeout = clearTimeout(d3_timer_timeout);\n      d3_timer_interval = 1;\n      d3_timer_frame(d3_timer_step);\n    }\n  };\n  function d3_timer_step() {\n    var now = d3_timer_mark(), delay = d3_timer_sweep() - now;\n    if (delay > 24) {\n      if (isFinite(delay)) {\n        clearTimeout(d3_timer_timeout);\n        d3_timer_timeout = setTimeout(d3_timer_step, delay);\n      }\n      d3_timer_interval = 0;\n    } else {\n      d3_timer_interval = 1;\n      d3_timer_frame(d3_timer_step);\n    }\n  }\n  d3.timer.flush = function() {\n    d3_timer_mark();\n    d3_timer_sweep();\n  };\n  function d3_timer_mark() {\n    var now = Date.now();\n    d3_timer_active = d3_timer_queueHead;\n    while (d3_timer_active) {\n      if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);\n      d3_timer_active = d3_timer_active.n;\n    }\n    return now;\n  }\n  function d3_timer_sweep() {\n    var t0, t1 = d3_timer_queueHead, time = Infinity;\n    while (t1) {\n      if (t1.f) {\n        t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;\n      } else {\n        if (t1.t < time) time = t1.t;\n        t1 = (t0 = t1).n;\n      }\n    }\n    d3_timer_queueTail = t0;\n    return time;\n  }\n  function d3_format_precision(x, p) {\n    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);\n  }\n  d3.round = function(x, n) {\n    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);\n  };\n  var d3_formatPrefixes = [ \"y\", \"z\", \"a\", \"f\", \"p\", \"n\", \"µ\", \"m\", \"\", \"k\", \"M\", \"G\", \"T\", \"P\", \"E\", \"Z\", \"Y\" ].map(d3_formatPrefix);\n  d3.formatPrefix = function(value, precision) {\n    var i = 0;\n    if (value) {\n      if (value < 0) value *= -1;\n      if (precision) value = d3.round(value, d3_format_precision(value, precision));\n      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);\n      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));\n    }\n    return d3_formatPrefixes[8 + i / 3];\n  };\n  function d3_formatPrefix(d, i) {\n    var k = Math.pow(10, abs(8 - i) * 3);\n    return {\n      scale: i > 8 ? function(d) {\n        return d / k;\n      } : function(d) {\n        return d * k;\n      },\n      symbol: d\n    };\n  }\n  function d3_locale_numberFormat(locale) {\n    var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {\n      var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0;\n      while (i > 0 && g > 0) {\n        if (length + g + 1 > width) g = Math.max(1, width - length);\n        t.push(value.substring(i -= g, i + g));\n        if ((length += g + 1) > width) break;\n        g = locale_grouping[j = (j + 1) % locale_grouping.length];\n      }\n      return t.reverse().join(locale_thousands);\n    } : d3_identity;\n    return function(specifier) {\n      var match = d3_format_re.exec(specifier), fill = match[1] || \" \", align = match[2] || \">\", sign = match[3] || \"-\", symbol = match[4] || \"\", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = \"\", suffix = \"\", integer = false, exponent = true;\n      if (precision) precision = +precision.substring(1);\n      if (zfill || fill === \"0\" && align === \"=\") {\n        zfill = fill = \"0\";\n        align = \"=\";\n      }\n      switch (type) {\n       case \"n\":\n        comma = true;\n        type = \"g\";\n        break;\n\n       case \"%\":\n        scale = 100;\n        suffix = \"%\";\n        type = \"f\";\n        break;\n\n       case \"p\":\n        scale = 100;\n        suffix = \"%\";\n        type = \"r\";\n        break;\n\n       case \"b\":\n       case \"o\":\n       case \"x\":\n       case \"X\":\n        if (symbol === \"#\") prefix = \"0\" + type.toLowerCase();\n\n       case \"c\":\n        exponent = false;\n\n       case \"d\":\n        integer = true;\n        precision = 0;\n        break;\n\n       case \"s\":\n        scale = -1;\n        type = \"r\";\n        break;\n      }\n      if (symbol === \"$\") prefix = locale_currency[0], suffix = locale_currency[1];\n      if (type == \"r\" && !precision) type = \"g\";\n      if (precision != null) {\n        if (type == \"g\") precision = Math.max(1, Math.min(21, precision)); else if (type == \"e\" || type == \"f\") precision = Math.max(0, Math.min(20, precision));\n      }\n      type = d3_format_types.get(type) || d3_format_typeDefault;\n      var zcomma = zfill && comma;\n      return function(value) {\n        var fullSuffix = suffix;\n        if (integer && value % 1) return \"\";\n        var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, \"-\") : sign === \"-\" ? \"\" : sign;\n        if (scale < 0) {\n          var unit = d3.formatPrefix(value, precision);\n          value = unit.scale(value);\n          fullSuffix = unit.symbol + suffix;\n        } else {\n          value *= scale;\n        }\n        value = type(value, precision);\n        var i = value.lastIndexOf(\".\"), before, after;\n        if (i < 0) {\n          var j = exponent ? value.lastIndexOf(\"e\") : -1;\n          if (j < 0) before = value, after = \"\"; else before = value.substring(0, j), after = value.substring(j);\n        } else {\n          before = value.substring(0, i);\n          after = locale_decimal + value.substring(i + 1);\n        }\n        if (!zfill && comma) before = formatGroup(before, Infinity);\n        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : \"\";\n        if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);\n        negative += prefix;\n        value = before + after;\n        return (align === \"<\" ? negative + value + padding : align === \">\" ? padding + negative + value : align === \"^\" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;\n      };\n    };\n  }\n  var d3_format_re = /(?:([^{])?([<>=^]))?([+\\- ])?([$#])?(0)?(\\d+)?(,)?(\\.-?\\d+)?([a-z%])?/i;\n  var d3_format_types = d3.map({\n    b: function(x) {\n      return x.toString(2);\n    },\n    c: function(x) {\n      return String.fromCharCode(x);\n    },\n    o: function(x) {\n      return x.toString(8);\n    },\n    x: function(x) {\n      return x.toString(16);\n    },\n    X: function(x) {\n      return x.toString(16).toUpperCase();\n    },\n    g: function(x, p) {\n      return x.toPrecision(p);\n    },\n    e: function(x, p) {\n      return x.toExponential(p);\n    },\n    f: function(x, p) {\n      return x.toFixed(p);\n    },\n    r: function(x, p) {\n      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));\n    }\n  });\n  function d3_format_typeDefault(x) {\n    return x + \"\";\n  }\n  var d3_time = d3.time = {}, d3_date = Date;\n  function d3_date_utc() {\n    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);\n  }\n  d3_date_utc.prototype = {\n    getDate: function() {\n      return this._.getUTCDate();\n    },\n    getDay: function() {\n      return this._.getUTCDay();\n    },\n    getFullYear: function() {\n      return this._.getUTCFullYear();\n    },\n    getHours: function() {\n      return this._.getUTCHours();\n    },\n    getMilliseconds: function() {\n      return this._.getUTCMilliseconds();\n    },\n    getMinutes: function() {\n      return this._.getUTCMinutes();\n    },\n    getMonth: function() {\n      return this._.getUTCMonth();\n    },\n    getSeconds: function() {\n      return this._.getUTCSeconds();\n    },\n    getTime: function() {\n      return this._.getTime();\n    },\n    getTimezoneOffset: function() {\n      return 0;\n    },\n    valueOf: function() {\n      return this._.valueOf();\n    },\n    setDate: function() {\n      d3_time_prototype.setUTCDate.apply(this._, arguments);\n    },\n    setDay: function() {\n      d3_time_prototype.setUTCDay.apply(this._, arguments);\n    },\n    setFullYear: function() {\n      d3_time_prototype.setUTCFullYear.apply(this._, arguments);\n    },\n    setHours: function() {\n      d3_time_prototype.setUTCHours.apply(this._, arguments);\n    },\n    setMilliseconds: function() {\n      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);\n    },\n    setMinutes: function() {\n      d3_time_prototype.setUTCMinutes.apply(this._, arguments);\n    },\n    setMonth: function() {\n      d3_time_prototype.setUTCMonth.apply(this._, arguments);\n    },\n    setSeconds: function() {\n      d3_time_prototype.setUTCSeconds.apply(this._, arguments);\n    },\n    setTime: function() {\n      d3_time_prototype.setTime.apply(this._, arguments);\n    }\n  };\n  var d3_time_prototype = Date.prototype;\n  function d3_time_interval(local, step, number) {\n    function round(date) {\n      var d0 = local(date), d1 = offset(d0, 1);\n      return date - d0 < d1 - date ? d0 : d1;\n    }\n    function ceil(date) {\n      step(date = local(new d3_date(date - 1)), 1);\n      return date;\n    }\n    function offset(date, k) {\n      step(date = new d3_date(+date), k);\n      return date;\n    }\n    function range(t0, t1, dt) {\n      var time = ceil(t0), times = [];\n      if (dt > 1) {\n        while (time < t1) {\n          if (!(number(time) % dt)) times.push(new Date(+time));\n          step(time, 1);\n        }\n      } else {\n        while (time < t1) times.push(new Date(+time)), step(time, 1);\n      }\n      return times;\n    }\n    function range_utc(t0, t1, dt) {\n      try {\n        d3_date = d3_date_utc;\n        var utc = new d3_date_utc();\n        utc._ = t0;\n        return range(utc, t1, dt);\n      } finally {\n        d3_date = Date;\n      }\n    }\n    local.floor = local;\n    local.round = round;\n    local.ceil = ceil;\n    local.offset = offset;\n    local.range = range;\n    var utc = local.utc = d3_time_interval_utc(local);\n    utc.floor = utc;\n    utc.round = d3_time_interval_utc(round);\n    utc.ceil = d3_time_interval_utc(ceil);\n    utc.offset = d3_time_interval_utc(offset);\n    utc.range = range_utc;\n    return local;\n  }\n  function d3_time_interval_utc(method) {\n    return function(date, k) {\n      try {\n        d3_date = d3_date_utc;\n        var utc = new d3_date_utc();\n        utc._ = date;\n        return method(utc, k)._;\n      } finally {\n        d3_date = Date;\n      }\n    };\n  }\n  d3_time.year = d3_time_interval(function(date) {\n    date = d3_time.day(date);\n    date.setMonth(0, 1);\n    return date;\n  }, function(date, offset) {\n    date.setFullYear(date.getFullYear() + offset);\n  }, function(date) {\n    return date.getFullYear();\n  });\n  d3_time.years = d3_time.year.range;\n  d3_time.years.utc = d3_time.year.utc.range;\n  d3_time.day = d3_time_interval(function(date) {\n    var day = new d3_date(2e3, 0);\n    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());\n    return day;\n  }, function(date, offset) {\n    date.setDate(date.getDate() + offset);\n  }, function(date) {\n    return date.getDate() - 1;\n  });\n  d3_time.days = d3_time.day.range;\n  d3_time.days.utc = d3_time.day.utc.range;\n  d3_time.dayOfYear = function(date) {\n    var year = d3_time.year(date);\n    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);\n  };\n  [ \"sunday\", \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\", \"saturday\" ].forEach(function(day, i) {\n    i = 7 - i;\n    var interval = d3_time[day] = d3_time_interval(function(date) {\n      (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);\n      return date;\n    }, function(date, offset) {\n      date.setDate(date.getDate() + Math.floor(offset) * 7);\n    }, function(date) {\n      var day = d3_time.year(date).getDay();\n      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);\n    });\n    d3_time[day + \"s\"] = interval.range;\n    d3_time[day + \"s\"].utc = interval.utc.range;\n    d3_time[day + \"OfYear\"] = function(date) {\n      var day = d3_time.year(date).getDay();\n      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);\n    };\n  });\n  d3_time.week = d3_time.sunday;\n  d3_time.weeks = d3_time.sunday.range;\n  d3_time.weeks.utc = d3_time.sunday.utc.range;\n  d3_time.weekOfYear = d3_time.sundayOfYear;\n  function d3_locale_timeFormat(locale) {\n    var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;\n    function d3_time_format(template) {\n      var n = template.length;\n      function format(date) {\n        var string = [], i = -1, j = 0, c, p, f;\n        while (++i < n) {\n          if (template.charCodeAt(i) === 37) {\n            string.push(template.slice(j, i));\n            if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);\n            if (f = d3_time_formats[c]) c = f(date, p == null ? c === \"e\" ? \" \" : \"0\" : p);\n            string.push(c);\n            j = i + 1;\n          }\n        }\n        string.push(template.slice(j, i));\n        return string.join(\"\");\n      }\n      format.parse = function(string) {\n        var d = {\n          y: 1900,\n          m: 0,\n          d: 1,\n          H: 0,\n          M: 0,\n          S: 0,\n          L: 0,\n          Z: null\n        }, i = d3_time_parse(d, template, string, 0);\n        if (i != string.length) return null;\n        if (\"p\" in d) d.H = d.H % 12 + d.p * 12;\n        var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();\n        if (\"j\" in d) date.setFullYear(d.y, 0, d.j); else if (\"w\" in d && (\"W\" in d || \"U\" in d)) {\n          date.setFullYear(d.y, 0, 1);\n          date.setFullYear(d.y, 0, \"W\" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);\n        } else date.setFullYear(d.y, d.m, d.d);\n        date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L);\n        return localZ ? date._ : date;\n      };\n      format.toString = function() {\n        return template;\n      };\n      return format;\n    }\n    function d3_time_parse(date, template, string, j) {\n      var c, p, t, i = 0, n = template.length, m = string.length;\n      while (i < n) {\n        if (j >= m) return -1;\n        c = template.charCodeAt(i++);\n        if (c === 37) {\n          t = template.charAt(i++);\n          p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];\n          if (!p || (j = p(date, string, j)) < 0) return -1;\n        } else if (c != string.charCodeAt(j++)) {\n          return -1;\n        }\n      }\n      return j;\n    }\n    d3_time_format.utc = function(template) {\n      var local = d3_time_format(template);\n      function format(date) {\n        try {\n          d3_date = d3_date_utc;\n          var utc = new d3_date();\n          utc._ = date;\n          return local(utc);\n        } finally {\n          d3_date = Date;\n        }\n      }\n      format.parse = function(string) {\n        try {\n          d3_date = d3_date_utc;\n          var date = local.parse(string);\n          return date && date._;\n        } finally {\n          d3_date = Date;\n        }\n      };\n      format.toString = local.toString;\n      return format;\n    };\n    d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;\n    var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);\n    locale_periods.forEach(function(p, i) {\n      d3_time_periodLookup.set(p.toLowerCase(), i);\n    });\n    var d3_time_formats = {\n      a: function(d) {\n        return locale_shortDays[d.getDay()];\n      },\n      A: function(d) {\n        return locale_days[d.getDay()];\n      },\n      b: function(d) {\n        return locale_shortMonths[d.getMonth()];\n      },\n      B: function(d) {\n        return locale_months[d.getMonth()];\n      },\n      c: d3_time_format(locale_dateTime),\n      d: function(d, p) {\n        return d3_time_formatPad(d.getDate(), p, 2);\n      },\n      e: function(d, p) {\n        return d3_time_formatPad(d.getDate(), p, 2);\n      },\n      H: function(d, p) {\n        return d3_time_formatPad(d.getHours(), p, 2);\n      },\n      I: function(d, p) {\n        return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);\n      },\n      j: function(d, p) {\n        return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);\n      },\n      L: function(d, p) {\n        return d3_time_formatPad(d.getMilliseconds(), p, 3);\n      },\n      m: function(d, p) {\n        return d3_time_formatPad(d.getMonth() + 1, p, 2);\n      },\n      M: function(d, p) {\n        return d3_time_formatPad(d.getMinutes(), p, 2);\n      },\n      p: function(d) {\n        return locale_periods[+(d.getHours() >= 12)];\n      },\n      S: function(d, p) {\n        return d3_time_formatPad(d.getSeconds(), p, 2);\n      },\n      U: function(d, p) {\n        return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);\n      },\n      w: function(d) {\n        return d.getDay();\n      },\n      W: function(d, p) {\n        return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);\n      },\n      x: d3_time_format(locale_date),\n      X: d3_time_format(locale_time),\n      y: function(d, p) {\n        return d3_time_formatPad(d.getFullYear() % 100, p, 2);\n      },\n      Y: function(d, p) {\n        return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);\n      },\n      Z: d3_time_zone,\n      \"%\": function() {\n        return \"%\";\n      }\n    };\n    var d3_time_parsers = {\n      a: d3_time_parseWeekdayAbbrev,\n      A: d3_time_parseWeekday,\n      b: d3_time_parseMonthAbbrev,\n      B: d3_time_parseMonth,\n      c: d3_time_parseLocaleFull,\n      d: d3_time_parseDay,\n      e: d3_time_parseDay,\n      H: d3_time_parseHour24,\n      I: d3_time_parseHour24,\n      j: d3_time_parseDayOfYear,\n      L: d3_time_parseMilliseconds,\n      m: d3_time_parseMonthNumber,\n      M: d3_time_parseMinutes,\n      p: d3_time_parseAmPm,\n      S: d3_time_parseSeconds,\n      U: d3_time_parseWeekNumberSunday,\n      w: d3_time_parseWeekdayNumber,\n      W: d3_time_parseWeekNumberMonday,\n      x: d3_time_parseLocaleDate,\n      X: d3_time_parseLocaleTime,\n      y: d3_time_parseYear,\n      Y: d3_time_parseFullYear,\n      Z: d3_time_parseZone,\n      \"%\": d3_time_parseLiteralPercent\n    };\n    function d3_time_parseWeekdayAbbrev(date, string, i) {\n      d3_time_dayAbbrevRe.lastIndex = 0;\n      var n = d3_time_dayAbbrevRe.exec(string.slice(i));\n      return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n    }\n    function d3_time_parseWeekday(date, string, i) {\n      d3_time_dayRe.lastIndex = 0;\n      var n = d3_time_dayRe.exec(string.slice(i));\n      return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n    }\n    function d3_time_parseMonthAbbrev(date, string, i) {\n      d3_time_monthAbbrevRe.lastIndex = 0;\n      var n = d3_time_monthAbbrevRe.exec(string.slice(i));\n      return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n    }\n    function d3_time_parseMonth(date, string, i) {\n      d3_time_monthRe.lastIndex = 0;\n      var n = d3_time_monthRe.exec(string.slice(i));\n      return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n    }\n    function d3_time_parseLocaleFull(date, string, i) {\n      return d3_time_parse(date, d3_time_formats.c.toString(), string, i);\n    }\n    function d3_time_parseLocaleDate(date, string, i) {\n      return d3_time_parse(date, d3_time_formats.x.toString(), string, i);\n    }\n    function d3_time_parseLocaleTime(date, string, i) {\n      return d3_time_parse(date, d3_time_formats.X.toString(), string, i);\n    }\n    function d3_time_parseAmPm(date, string, i) {\n      var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase());\n      return n == null ? -1 : (date.p = n, i);\n    }\n    return d3_time_format;\n  }\n  var d3_time_formatPads = {\n    \"-\": \"\",\n    _: \" \",\n    \"0\": \"0\"\n  }, d3_time_numberRe = /^\\s*\\d+/, d3_time_percentRe = /^%/;\n  function d3_time_formatPad(value, fill, width) {\n    var sign = value < 0 ? \"-\" : \"\", string = (sign ? -value : value) + \"\", length = string.length;\n    return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);\n  }\n  function d3_time_formatRe(names) {\n    return new RegExp(\"^(?:\" + names.map(d3.requote).join(\"|\") + \")\", \"i\");\n  }\n  function d3_time_formatLookup(names) {\n    var map = new d3_Map(), i = -1, n = names.length;\n    while (++i < n) map.set(names[i].toLowerCase(), i);\n    return map;\n  }\n  function d3_time_parseWeekdayNumber(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 1));\n    return n ? (date.w = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseWeekNumberSunday(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i));\n    return n ? (date.U = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseWeekNumberMonday(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i));\n    return n ? (date.W = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseFullYear(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 4));\n    return n ? (date.y = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseYear(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 2));\n    return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;\n  }\n  function d3_time_parseZone(date, string, i) {\n    return /^[+-]\\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, \n    i + 5) : -1;\n  }\n  function d3_time_expandYear(d) {\n    return d + (d > 68 ? 1900 : 2e3);\n  }\n  function d3_time_parseMonthNumber(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 2));\n    return n ? (date.m = n[0] - 1, i + n[0].length) : -1;\n  }\n  function d3_time_parseDay(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 2));\n    return n ? (date.d = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseDayOfYear(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 3));\n    return n ? (date.j = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseHour24(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 2));\n    return n ? (date.H = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseMinutes(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 2));\n    return n ? (date.M = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseSeconds(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 2));\n    return n ? (date.S = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_parseMilliseconds(date, string, i) {\n    d3_time_numberRe.lastIndex = 0;\n    var n = d3_time_numberRe.exec(string.slice(i, i + 3));\n    return n ? (date.L = +n[0], i + n[0].length) : -1;\n  }\n  function d3_time_zone(d) {\n    var z = d.getTimezoneOffset(), zs = z > 0 ? \"-\" : \"+\", zh = abs(z) / 60 | 0, zm = abs(z) % 60;\n    return zs + d3_time_formatPad(zh, \"0\", 2) + d3_time_formatPad(zm, \"0\", 2);\n  }\n  function d3_time_parseLiteralPercent(date, string, i) {\n    d3_time_percentRe.lastIndex = 0;\n    var n = d3_time_percentRe.exec(string.slice(i, i + 1));\n    return n ? i + n[0].length : -1;\n  }\n  function d3_time_formatMulti(formats) {\n    var n = formats.length, i = -1;\n    while (++i < n) formats[i][0] = this(formats[i][0]);\n    return function(date) {\n      var i = 0, f = formats[i];\n      while (!f[1](date)) f = formats[++i];\n      return f[0](date);\n    };\n  }\n  d3.locale = function(locale) {\n    return {\n      numberFormat: d3_locale_numberFormat(locale),\n      timeFormat: d3_locale_timeFormat(locale)\n    };\n  };\n  var d3_locale_enUS = d3.locale({\n    decimal: \".\",\n    thousands: \",\",\n    grouping: [ 3 ],\n    currency: [ \"$\", \"\" ],\n    dateTime: \"%a %b %e %X %Y\",\n    date: \"%m/%d/%Y\",\n    time: \"%H:%M:%S\",\n    periods: [ \"AM\", \"PM\" ],\n    days: [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ],\n    shortDays: [ \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\" ],\n    months: [ \"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\" ],\n    shortMonths: [ \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\" ]\n  });\n  d3.format = d3_locale_enUS.numberFormat;\n  d3.geo = {};\n  function d3_adder() {}\n  d3_adder.prototype = {\n    s: 0,\n    t: 0,\n    add: function(y) {\n      d3_adderSum(y, this.t, d3_adderTemp);\n      d3_adderSum(d3_adderTemp.s, this.s, this);\n      if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;\n    },\n    reset: function() {\n      this.s = this.t = 0;\n    },\n    valueOf: function() {\n      return this.s;\n    }\n  };\n  var d3_adderTemp = new d3_adder();\n  function d3_adderSum(a, b, o) {\n    var x = o.s = a + b, bv = x - a, av = x - bv;\n    o.t = a - av + (b - bv);\n  }\n  d3.geo.stream = function(object, listener) {\n    if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {\n      d3_geo_streamObjectType[object.type](object, listener);\n    } else {\n      d3_geo_streamGeometry(object, listener);\n    }\n  };\n  function d3_geo_streamGeometry(geometry, listener) {\n    if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {\n      d3_geo_streamGeometryType[geometry.type](geometry, listener);\n    }\n  }\n  var d3_geo_streamObjectType = {\n    Feature: function(feature, listener) {\n      d3_geo_streamGeometry(feature.geometry, listener);\n    },\n    FeatureCollection: function(object, listener) {\n      var features = object.features, i = -1, n = features.length;\n      while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);\n    }\n  };\n  var d3_geo_streamGeometryType = {\n    Sphere: function(object, listener) {\n      listener.sphere();\n    },\n    Point: function(object, listener) {\n      object = object.coordinates;\n      listener.point(object[0], object[1], object[2]);\n    },\n    MultiPoint: function(object, listener) {\n      var coordinates = object.coordinates, i = -1, n = coordinates.length;\n      while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);\n    },\n    LineString: function(object, listener) {\n      d3_geo_streamLine(object.coordinates, listener, 0);\n    },\n    MultiLineString: function(object, listener) {\n      var coordinates = object.coordinates, i = -1, n = coordinates.length;\n      while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);\n    },\n    Polygon: function(object, listener) {\n      d3_geo_streamPolygon(object.coordinates, listener);\n    },\n    MultiPolygon: function(object, listener) {\n      var coordinates = object.coordinates, i = -1, n = coordinates.length;\n      while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);\n    },\n    GeometryCollection: function(object, listener) {\n      var geometries = object.geometries, i = -1, n = geometries.length;\n      while (++i < n) d3_geo_streamGeometry(geometries[i], listener);\n    }\n  };\n  function d3_geo_streamLine(coordinates, listener, closed) {\n    var i = -1, n = coordinates.length - closed, coordinate;\n    listener.lineStart();\n    while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);\n    listener.lineEnd();\n  }\n  function d3_geo_streamPolygon(coordinates, listener) {\n    var i = -1, n = coordinates.length;\n    listener.polygonStart();\n    while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);\n    listener.polygonEnd();\n  }\n  d3.geo.area = function(object) {\n    d3_geo_areaSum = 0;\n    d3.geo.stream(object, d3_geo_area);\n    return d3_geo_areaSum;\n  };\n  var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();\n  var d3_geo_area = {\n    sphere: function() {\n      d3_geo_areaSum += 4 * π;\n    },\n    point: d3_noop,\n    lineStart: d3_noop,\n    lineEnd: d3_noop,\n    polygonStart: function() {\n      d3_geo_areaRingSum.reset();\n      d3_geo_area.lineStart = d3_geo_areaRingStart;\n    },\n    polygonEnd: function() {\n      var area = 2 * d3_geo_areaRingSum;\n      d3_geo_areaSum += area < 0 ? 4 * π + area : area;\n      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;\n    }\n  };\n  function d3_geo_areaRingStart() {\n    var λ00, φ00, λ0, cosφ0, sinφ0;\n    d3_geo_area.point = function(λ, φ) {\n      d3_geo_area.point = nextPoint;\n      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), \n      sinφ0 = Math.sin(φ);\n    };\n    function nextPoint(λ, φ) {\n      λ *= d3_radians;\n      φ = φ * d3_radians / 2 + π / 4;\n      var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);\n      d3_geo_areaRingSum.add(Math.atan2(v, u));\n      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;\n    }\n    d3_geo_area.lineEnd = function() {\n      nextPoint(λ00, φ00);\n    };\n  }\n  function d3_geo_cartesian(spherical) {\n    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);\n    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];\n  }\n  function d3_geo_cartesianDot(a, b) {\n    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n  }\n  function d3_geo_cartesianCross(a, b) {\n    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];\n  }\n  function d3_geo_cartesianAdd(a, b) {\n    a[0] += b[0];\n    a[1] += b[1];\n    a[2] += b[2];\n  }\n  function d3_geo_cartesianScale(vector, k) {\n    return [ vector[0] * k, vector[1] * k, vector[2] * k ];\n  }\n  function d3_geo_cartesianNormalize(d) {\n    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);\n    d[0] /= l;\n    d[1] /= l;\n    d[2] /= l;\n  }\n  function d3_geo_spherical(cartesian) {\n    return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];\n  }\n  function d3_geo_sphericalEqual(a, b) {\n    return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;\n  }\n  d3.geo.bounds = function() {\n    var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;\n    var bound = {\n      point: point,\n      lineStart: lineStart,\n      lineEnd: lineEnd,\n      polygonStart: function() {\n        bound.point = ringPoint;\n        bound.lineStart = ringStart;\n        bound.lineEnd = ringEnd;\n        dλSum = 0;\n        d3_geo_area.polygonStart();\n      },\n      polygonEnd: function() {\n        d3_geo_area.polygonEnd();\n        bound.point = point;\n        bound.lineStart = lineStart;\n        bound.lineEnd = lineEnd;\n        if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;\n        range[0] = λ0, range[1] = λ1;\n      }\n    };\n    function point(λ, φ) {\n      ranges.push(range = [ λ0 = λ, λ1 = λ ]);\n      if (φ < φ0) φ0 = φ;\n      if (φ > φ1) φ1 = φ;\n    }\n    function linePoint(λ, φ) {\n      var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);\n      if (p0) {\n        var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);\n        d3_geo_cartesianNormalize(inflection);\n        inflection = d3_geo_spherical(inflection);\n        var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;\n        if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {\n          var φi = inflection[1] * d3_degrees;\n          if (φi > φ1) φ1 = φi;\n        } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {\n          var φi = -inflection[1] * d3_degrees;\n          if (φi < φ0) φ0 = φi;\n        } else {\n          if (φ < φ0) φ0 = φ;\n          if (φ > φ1) φ1 = φ;\n        }\n        if (antimeridian) {\n          if (λ < λ_) {\n            if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;\n          } else {\n            if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;\n          }\n        } else {\n          if (λ1 >= λ0) {\n            if (λ < λ0) λ0 = λ;\n            if (λ > λ1) λ1 = λ;\n          } else {\n            if (λ > λ_) {\n              if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;\n            } else {\n              if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;\n            }\n          }\n        }\n      } else {\n        point(λ, φ);\n      }\n      p0 = p, λ_ = λ;\n    }\n    function lineStart() {\n      bound.point = linePoint;\n    }\n    function lineEnd() {\n      range[0] = λ0, range[1] = λ1;\n      bound.point = point;\n      p0 = null;\n    }\n    function ringPoint(λ, φ) {\n      if (p0) {\n        var dλ = λ - λ_;\n        dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;\n      } else λ__ = λ, φ__ = φ;\n      d3_geo_area.point(λ, φ);\n      linePoint(λ, φ);\n    }\n    function ringStart() {\n      d3_geo_area.lineStart();\n    }\n    function ringEnd() {\n      ringPoint(λ__, φ__);\n      d3_geo_area.lineEnd();\n      if (abs(dλSum) > ε) λ0 = -(λ1 = 180);\n      range[0] = λ0, range[1] = λ1;\n      p0 = null;\n    }\n    function angle(λ0, λ1) {\n      return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;\n    }\n    function compareRanges(a, b) {\n      return a[0] - b[0];\n    }\n    function withinRange(x, range) {\n      return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;\n    }\n    return function(feature) {\n      φ1 = λ1 = -(λ0 = φ0 = Infinity);\n      ranges = [];\n      d3.geo.stream(feature, bound);\n      var n = ranges.length;\n      if (n) {\n        ranges.sort(compareRanges);\n        for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {\n          b = ranges[i];\n          if (withinRange(b[0], a) || withinRange(b[1], a)) {\n            if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];\n            if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];\n          } else {\n            merged.push(a = b);\n          }\n        }\n        var best = -Infinity, dλ;\n        for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {\n          b = merged[i];\n          if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];\n        }\n      }\n      ranges = range = null;\n      return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];\n    };\n  }();\n  d3.geo.centroid = function(object) {\n    d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;\n    d3.geo.stream(object, d3_geo_centroid);\n    var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;\n    if (m < ε2) {\n      x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;\n      if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;\n      m = x * x + y * y + z * z;\n      if (m < ε2) return [ NaN, NaN ];\n    }\n    return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];\n  };\n  var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;\n  var d3_geo_centroid = {\n    sphere: d3_noop,\n    point: d3_geo_centroidPoint,\n    lineStart: d3_geo_centroidLineStart,\n    lineEnd: d3_geo_centroidLineEnd,\n    polygonStart: function() {\n      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;\n    },\n    polygonEnd: function() {\n      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;\n    }\n  };\n  function d3_geo_centroidPoint(λ, φ) {\n    λ *= d3_radians;\n    var cosφ = Math.cos(φ *= d3_radians);\n    d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));\n  }\n  function d3_geo_centroidPointXYZ(x, y, z) {\n    ++d3_geo_centroidW0;\n    d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;\n    d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;\n    d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;\n  }\n  function d3_geo_centroidLineStart() {\n    var x0, y0, z0;\n    d3_geo_centroid.point = function(λ, φ) {\n      λ *= d3_radians;\n      var cosφ = Math.cos(φ *= d3_radians);\n      x0 = cosφ * Math.cos(λ);\n      y0 = cosφ * Math.sin(λ);\n      z0 = Math.sin(φ);\n      d3_geo_centroid.point = nextPoint;\n      d3_geo_centroidPointXYZ(x0, y0, z0);\n    };\n    function nextPoint(λ, φ) {\n      λ *= d3_radians;\n      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);\n      d3_geo_centroidW1 += w;\n      d3_geo_centroidX1 += w * (x0 + (x0 = x));\n      d3_geo_centroidY1 += w * (y0 + (y0 = y));\n      d3_geo_centroidZ1 += w * (z0 + (z0 = z));\n      d3_geo_centroidPointXYZ(x0, y0, z0);\n    }\n  }\n  function d3_geo_centroidLineEnd() {\n    d3_geo_centroid.point = d3_geo_centroidPoint;\n  }\n  function d3_geo_centroidRingStart() {\n    var λ00, φ00, x0, y0, z0;\n    d3_geo_centroid.point = function(λ, φ) {\n      λ00 = λ, φ00 = φ;\n      d3_geo_centroid.point = nextPoint;\n      λ *= d3_radians;\n      var cosφ = Math.cos(φ *= d3_radians);\n      x0 = cosφ * Math.cos(λ);\n      y0 = cosφ * Math.sin(λ);\n      z0 = Math.sin(φ);\n      d3_geo_centroidPointXYZ(x0, y0, z0);\n    };\n    d3_geo_centroid.lineEnd = function() {\n      nextPoint(λ00, φ00);\n      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;\n      d3_geo_centroid.point = d3_geo_centroidPoint;\n    };\n    function nextPoint(λ, φ) {\n      λ *= d3_radians;\n      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);\n      d3_geo_centroidX2 += v * cx;\n      d3_geo_centroidY2 += v * cy;\n      d3_geo_centroidZ2 += v * cz;\n      d3_geo_centroidW1 += w;\n      d3_geo_centroidX1 += w * (x0 + (x0 = x));\n      d3_geo_centroidY1 += w * (y0 + (y0 = y));\n      d3_geo_centroidZ1 += w * (z0 + (z0 = z));\n      d3_geo_centroidPointXYZ(x0, y0, z0);\n    }\n  }\n  function d3_true() {\n    return true;\n  }\n  function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {\n    var subject = [], clip = [];\n    segments.forEach(function(segment) {\n      if ((n = segment.length - 1) <= 0) return;\n      var n, p0 = segment[0], p1 = segment[n];\n      if (d3_geo_sphericalEqual(p0, p1)) {\n        listener.lineStart();\n        for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);\n        listener.lineEnd();\n        return;\n      }\n      var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);\n      a.o = b;\n      subject.push(a);\n      clip.push(b);\n      a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);\n      b = new d3_geo_clipPolygonIntersection(p1, null, a, true);\n      a.o = b;\n      subject.push(a);\n      clip.push(b);\n    });\n    clip.sort(compare);\n    d3_geo_clipPolygonLinkCircular(subject);\n    d3_geo_clipPolygonLinkCircular(clip);\n    if (!subject.length) return;\n    for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {\n      clip[i].e = entry = !entry;\n    }\n    var start = subject[0], points, point;\n    while (1) {\n      var current = start, isSubject = true;\n      while (current.v) if ((current = current.n) === start) return;\n      points = current.z;\n      listener.lineStart();\n      do {\n        current.v = current.o.v = true;\n        if (current.e) {\n          if (isSubject) {\n            for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);\n          } else {\n            interpolate(current.x, current.n.x, 1, listener);\n          }\n          current = current.n;\n        } else {\n          if (isSubject) {\n            points = current.p.z;\n            for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);\n          } else {\n            interpolate(current.x, current.p.x, -1, listener);\n          }\n          current = current.p;\n        }\n        current = current.o;\n        points = current.z;\n        isSubject = !isSubject;\n      } while (!current.v);\n      listener.lineEnd();\n    }\n  }\n  function d3_geo_clipPolygonLinkCircular(array) {\n    if (!(n = array.length)) return;\n    var n, i = 0, a = array[0], b;\n    while (++i < n) {\n      a.n = b = array[i];\n      b.p = a;\n      a = b;\n    }\n    a.n = b = array[0];\n    b.p = a;\n  }\n  function d3_geo_clipPolygonIntersection(point, points, other, entry) {\n    this.x = point;\n    this.z = points;\n    this.o = other;\n    this.e = entry;\n    this.v = false;\n    this.n = this.p = null;\n  }\n  function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {\n    return function(rotate, listener) {\n      var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);\n      var clip = {\n        point: point,\n        lineStart: lineStart,\n        lineEnd: lineEnd,\n        polygonStart: function() {\n          clip.point = pointRing;\n          clip.lineStart = ringStart;\n          clip.lineEnd = ringEnd;\n          segments = [];\n          polygon = [];\n        },\n        polygonEnd: function() {\n          clip.point = point;\n          clip.lineStart = lineStart;\n          clip.lineEnd = lineEnd;\n          segments = d3.merge(segments);\n          var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);\n          if (segments.length) {\n            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;\n            d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);\n          } else if (clipStartInside) {\n            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;\n            listener.lineStart();\n            interpolate(null, null, 1, listener);\n            listener.lineEnd();\n          }\n          if (polygonStarted) listener.polygonEnd(), polygonStarted = false;\n          segments = polygon = null;\n        },\n        sphere: function() {\n          listener.polygonStart();\n          listener.lineStart();\n          interpolate(null, null, 1, listener);\n          listener.lineEnd();\n          listener.polygonEnd();\n        }\n      };\n      function point(λ, φ) {\n        var point = rotate(λ, φ);\n        if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);\n      }\n      function pointLine(λ, φ) {\n        var point = rotate(λ, φ);\n        line.point(point[0], point[1]);\n      }\n      function lineStart() {\n        clip.point = pointLine;\n        line.lineStart();\n      }\n      function lineEnd() {\n        clip.point = point;\n        line.lineEnd();\n      }\n      var segments;\n      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;\n      function pointRing(λ, φ) {\n        ring.push([ λ, φ ]);\n        var point = rotate(λ, φ);\n        ringListener.point(point[0], point[1]);\n      }\n      function ringStart() {\n        ringListener.lineStart();\n        ring = [];\n      }\n      function ringEnd() {\n        pointRing(ring[0][0], ring[0][1]);\n        ringListener.lineEnd();\n        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;\n        ring.pop();\n        polygon.push(ring);\n        ring = null;\n        if (!n) return;\n        if (clean & 1) {\n          segment = ringSegments[0];\n          var n = segment.length - 1, i = -1, point;\n          if (n > 0) {\n            if (!polygonStarted) listener.polygonStart(), polygonStarted = true;\n            listener.lineStart();\n            while (++i < n) listener.point((point = segment[i])[0], point[1]);\n            listener.lineEnd();\n          }\n          return;\n        }\n        if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));\n        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));\n      }\n      return clip;\n    };\n  }\n  function d3_geo_clipSegmentLength1(segment) {\n    return segment.length > 1;\n  }\n  function d3_geo_clipBufferListener() {\n    var lines = [], line;\n    return {\n      lineStart: function() {\n        lines.push(line = []);\n      },\n      point: function(λ, φ) {\n        line.push([ λ, φ ]);\n      },\n      lineEnd: d3_noop,\n      buffer: function() {\n        var buffer = lines;\n        lines = [];\n        line = null;\n        return buffer;\n      },\n      rejoin: function() {\n        if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));\n      }\n    };\n  }\n  function d3_geo_clipSort(a, b) {\n    return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);\n  }\n  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);\n  function d3_geo_clipAntimeridianLine(listener) {\n    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;\n    return {\n      lineStart: function() {\n        listener.lineStart();\n        clean = 1;\n      },\n      point: function(λ1, φ1) {\n        var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);\n        if (abs(dλ - π) < ε) {\n          listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);\n          listener.point(sλ0, φ0);\n          listener.lineEnd();\n          listener.lineStart();\n          listener.point(sλ1, φ0);\n          listener.point(λ1, φ0);\n          clean = 0;\n        } else if (sλ0 !== sλ1 && dλ >= π) {\n          if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;\n          if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;\n          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);\n          listener.point(sλ0, φ0);\n          listener.lineEnd();\n          listener.lineStart();\n          listener.point(sλ1, φ0);\n          clean = 0;\n        }\n        listener.point(λ0 = λ1, φ0 = φ1);\n        sλ0 = sλ1;\n      },\n      lineEnd: function() {\n        listener.lineEnd();\n        λ0 = φ0 = NaN;\n      },\n      clean: function() {\n        return 2 - clean;\n      }\n    };\n  }\n  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {\n    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);\n    return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;\n  }\n  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {\n    var φ;\n    if (from == null) {\n      φ = direction * halfπ;\n      listener.point(-π, φ);\n      listener.point(0, φ);\n      listener.point(π, φ);\n      listener.point(π, 0);\n      listener.point(π, -φ);\n      listener.point(0, -φ);\n      listener.point(-π, -φ);\n      listener.point(-π, 0);\n      listener.point(-π, φ);\n    } else if (abs(from[0] - to[0]) > ε) {\n      var s = from[0] < to[0] ? π : -π;\n      φ = direction * s / 2;\n      listener.point(-s, φ);\n      listener.point(0, φ);\n      listener.point(s, φ);\n    } else {\n      listener.point(to[0], to[1]);\n    }\n  }\n  function d3_geo_pointInPolygon(point, polygon) {\n    var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;\n    d3_geo_areaRingSum.reset();\n    for (var i = 0, n = polygon.length; i < n; ++i) {\n      var ring = polygon[i], m = ring.length;\n      if (!m) continue;\n      var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;\n      while (true) {\n        if (j === m) j = 0;\n        point = ring[j];\n        var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;\n        d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));\n        polarAngle += antimeridian ? dλ + sdλ * τ : dλ;\n        if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {\n          var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));\n          d3_geo_cartesianNormalize(arc);\n          var intersection = d3_geo_cartesianCross(meridianNormal, arc);\n          d3_geo_cartesianNormalize(intersection);\n          var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);\n          if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {\n            winding += antimeridian ^ dλ >= 0 ? 1 : -1;\n          }\n        }\n        if (!j++) break;\n        λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;\n      }\n    }\n    return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1;\n  }\n  function d3_geo_clipCircle(radius) {\n    var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);\n    return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);\n    function visible(λ, φ) {\n      return Math.cos(λ) * Math.cos(φ) > cr;\n    }\n    function clipLine(listener) {\n      var point0, c0, v0, v00, clean;\n      return {\n        lineStart: function() {\n          v00 = v0 = false;\n          clean = 1;\n        },\n        point: function(λ, φ) {\n          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;\n          if (!point0 && (v00 = v0 = v)) listener.lineStart();\n          if (v !== v0) {\n            point2 = intersect(point0, point1);\n            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {\n              point1[0] += ε;\n              point1[1] += ε;\n              v = visible(point1[0], point1[1]);\n            }\n          }\n          if (v !== v0) {\n            clean = 0;\n            if (v) {\n              listener.lineStart();\n              point2 = intersect(point1, point0);\n              listener.point(point2[0], point2[1]);\n            } else {\n              point2 = intersect(point0, point1);\n              listener.point(point2[0], point2[1]);\n              listener.lineEnd();\n            }\n            point0 = point2;\n          } else if (notHemisphere && point0 && smallRadius ^ v) {\n            var t;\n            if (!(c & c0) && (t = intersect(point1, point0, true))) {\n              clean = 0;\n              if (smallRadius) {\n                listener.lineStart();\n                listener.point(t[0][0], t[0][1]);\n                listener.point(t[1][0], t[1][1]);\n                listener.lineEnd();\n              } else {\n                listener.point(t[1][0], t[1][1]);\n                listener.lineEnd();\n                listener.lineStart();\n                listener.point(t[0][0], t[0][1]);\n              }\n            }\n          }\n          if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {\n            listener.point(point1[0], point1[1]);\n          }\n          point0 = point1, v0 = v, c0 = c;\n        },\n        lineEnd: function() {\n          if (v0) listener.lineEnd();\n          point0 = null;\n        },\n        clean: function() {\n          return clean | (v00 && v0) << 1;\n        }\n      };\n    }\n    function intersect(a, b, two) {\n      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);\n      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;\n      if (!determinant) return !two && a;\n      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);\n      d3_geo_cartesianAdd(A, B);\n      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);\n      if (t2 < 0) return;\n      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);\n      d3_geo_cartesianAdd(q, A);\n      q = d3_geo_spherical(q);\n      if (!two) return q;\n      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;\n      if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;\n      var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;\n      if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;\n      if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {\n        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);\n        d3_geo_cartesianAdd(q1, A);\n        return [ q, d3_geo_spherical(q1) ];\n      }\n    }\n    function code(λ, φ) {\n      var r = smallRadius ? radius : π - radius, code = 0;\n      if (λ < -r) code |= 1; else if (λ > r) code |= 2;\n      if (φ < -r) code |= 4; else if (φ > r) code |= 8;\n      return code;\n    }\n  }\n  function d3_geom_clipLine(x0, y0, x1, y1) {\n    return function(line) {\n      var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;\n      r = x0 - ax;\n      if (!dx && r > 0) return;\n      r /= dx;\n      if (dx < 0) {\n        if (r < t0) return;\n        if (r < t1) t1 = r;\n      } else if (dx > 0) {\n        if (r > t1) return;\n        if (r > t0) t0 = r;\n      }\n      r = x1 - ax;\n      if (!dx && r < 0) return;\n      r /= dx;\n      if (dx < 0) {\n        if (r > t1) return;\n        if (r > t0) t0 = r;\n      } else if (dx > 0) {\n        if (r < t0) return;\n        if (r < t1) t1 = r;\n      }\n      r = y0 - ay;\n      if (!dy && r > 0) return;\n      r /= dy;\n      if (dy < 0) {\n        if (r < t0) return;\n        if (r < t1) t1 = r;\n      } else if (dy > 0) {\n        if (r > t1) return;\n        if (r > t0) t0 = r;\n      }\n      r = y1 - ay;\n      if (!dy && r < 0) return;\n      r /= dy;\n      if (dy < 0) {\n        if (r > t1) return;\n        if (r > t0) t0 = r;\n      } else if (dy > 0) {\n        if (r < t0) return;\n        if (r < t1) t1 = r;\n      }\n      if (t0 > 0) line.a = {\n        x: ax + t0 * dx,\n        y: ay + t0 * dy\n      };\n      if (t1 < 1) line.b = {\n        x: ax + t1 * dx,\n        y: ay + t1 * dy\n      };\n      return line;\n    };\n  }\n  var d3_geo_clipExtentMAX = 1e9;\n  d3.geo.clipExtent = function() {\n    var x0, y0, x1, y1, stream, clip, clipExtent = {\n      stream: function(output) {\n        if (stream) stream.valid = false;\n        stream = clip(output);\n        stream.valid = true;\n        return stream;\n      },\n      extent: function(_) {\n        if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];\n        clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);\n        if (stream) stream.valid = false, stream = null;\n        return clipExtent;\n      }\n    };\n    return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);\n  };\n  function d3_geo_clipExtent(x0, y0, x1, y1) {\n    return function(listener) {\n      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;\n      var clip = {\n        point: point,\n        lineStart: lineStart,\n        lineEnd: lineEnd,\n        polygonStart: function() {\n          listener = bufferListener;\n          segments = [];\n          polygon = [];\n          clean = true;\n        },\n        polygonEnd: function() {\n          listener = listener_;\n          segments = d3.merge(segments);\n          var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;\n          if (inside || visible) {\n            listener.polygonStart();\n            if (inside) {\n              listener.lineStart();\n              interpolate(null, null, 1, listener);\n              listener.lineEnd();\n            }\n            if (visible) {\n              d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);\n            }\n            listener.polygonEnd();\n          }\n          segments = polygon = ring = null;\n        }\n      };\n      function insidePolygon(p) {\n        var wn = 0, n = polygon.length, y = p[1];\n        for (var i = 0; i < n; ++i) {\n          for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {\n            b = v[j];\n            if (a[1] <= y) {\n              if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;\n            } else {\n              if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;\n            }\n            a = b;\n          }\n        }\n        return wn !== 0;\n      }\n      function interpolate(from, to, direction, listener) {\n        var a = 0, a1 = 0;\n        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {\n          do {\n            listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);\n          } while ((a = (a + direction + 4) % 4) !== a1);\n        } else {\n          listener.point(to[0], to[1]);\n        }\n      }\n      function pointVisible(x, y) {\n        return x0 <= x && x <= x1 && y0 <= y && y <= y1;\n      }\n      function point(x, y) {\n        if (pointVisible(x, y)) listener.point(x, y);\n      }\n      var x__, y__, v__, x_, y_, v_, first, clean;\n      function lineStart() {\n        clip.point = linePoint;\n        if (polygon) polygon.push(ring = []);\n        first = true;\n        v_ = false;\n        x_ = y_ = NaN;\n      }\n      function lineEnd() {\n        if (segments) {\n          linePoint(x__, y__);\n          if (v__ && v_) bufferListener.rejoin();\n          segments.push(bufferListener.buffer());\n        }\n        clip.point = point;\n        if (v_) listener.lineEnd();\n      }\n      function linePoint(x, y) {\n        x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));\n        y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));\n        var v = pointVisible(x, y);\n        if (polygon) ring.push([ x, y ]);\n        if (first) {\n          x__ = x, y__ = y, v__ = v;\n          first = false;\n          if (v) {\n            listener.lineStart();\n            listener.point(x, y);\n          }\n        } else {\n          if (v && v_) listener.point(x, y); else {\n            var l = {\n              a: {\n                x: x_,\n                y: y_\n              },\n              b: {\n                x: x,\n                y: y\n              }\n            };\n            if (clipLine(l)) {\n              if (!v_) {\n                listener.lineStart();\n                listener.point(l.a.x, l.a.y);\n              }\n              listener.point(l.b.x, l.b.y);\n              if (!v) listener.lineEnd();\n              clean = false;\n            } else if (v) {\n              listener.lineStart();\n              listener.point(x, y);\n              clean = false;\n            }\n          }\n        }\n        x_ = x, y_ = y, v_ = v;\n      }\n      return clip;\n    };\n    function corner(p, direction) {\n      return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;\n    }\n    function compare(a, b) {\n      return comparePoints(a.x, b.x);\n    }\n    function comparePoints(a, b) {\n      var ca = corner(a, 1), cb = corner(b, 1);\n      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];\n    }\n  }\n  function d3_geo_compose(a, b) {\n    function compose(x, y) {\n      return x = a(x, y), b(x[0], x[1]);\n    }\n    if (a.invert && b.invert) compose.invert = function(x, y) {\n      return x = b.invert(x, y), x && a.invert(x[0], x[1]);\n    };\n    return compose;\n  }\n  function d3_geo_conic(projectAt) {\n    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);\n    p.parallels = function(_) {\n      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];\n      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);\n    };\n    return p;\n  }\n  function d3_geo_conicEqualArea(φ0, φ1) {\n    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;\n    function forward(λ, φ) {\n      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;\n      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];\n    }\n    forward.invert = function(x, y) {\n      var ρ0_y = ρ0 - y;\n      return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];\n    };\n    return forward;\n  }\n  (d3.geo.conicEqualArea = function() {\n    return d3_geo_conic(d3_geo_conicEqualArea);\n  }).raw = d3_geo_conicEqualArea;\n  d3.geo.albers = function() {\n    return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);\n  };\n  d3.geo.albersUsa = function() {\n    var lower48 = d3.geo.albers();\n    var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);\n    var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);\n    var point, pointStream = {\n      point: function(x, y) {\n        point = [ x, y ];\n      }\n    }, lower48Point, alaskaPoint, hawaiiPoint;\n    function albersUsa(coordinates) {\n      var x = coordinates[0], y = coordinates[1];\n      point = null;\n      (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);\n      return point;\n    }\n    albersUsa.invert = function(coordinates) {\n      var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;\n      return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);\n    };\n    albersUsa.stream = function(stream) {\n      var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);\n      return {\n        point: function(x, y) {\n          lower48Stream.point(x, y);\n          alaskaStream.point(x, y);\n          hawaiiStream.point(x, y);\n        },\n        sphere: function() {\n          lower48Stream.sphere();\n          alaskaStream.sphere();\n          hawaiiStream.sphere();\n        },\n        lineStart: function() {\n          lower48Stream.lineStart();\n          alaskaStream.lineStart();\n          hawaiiStream.lineStart();\n        },\n        lineEnd: function() {\n          lower48Stream.lineEnd();\n          alaskaStream.lineEnd();\n          hawaiiStream.lineEnd();\n        },\n        polygonStart: function() {\n          lower48Stream.polygonStart();\n          alaskaStream.polygonStart();\n          hawaiiStream.polygonStart();\n        },\n        polygonEnd: function() {\n          lower48Stream.polygonEnd();\n          alaskaStream.polygonEnd();\n          hawaiiStream.polygonEnd();\n        }\n      };\n    };\n    albersUsa.precision = function(_) {\n      if (!arguments.length) return lower48.precision();\n      lower48.precision(_);\n      alaska.precision(_);\n      hawaii.precision(_);\n      return albersUsa;\n    };\n    albersUsa.scale = function(_) {\n      if (!arguments.length) return lower48.scale();\n      lower48.scale(_);\n      alaska.scale(_ * .35);\n      hawaii.scale(_);\n      return albersUsa.translate(lower48.translate());\n    };\n    albersUsa.translate = function(_) {\n      if (!arguments.length) return lower48.translate();\n      var k = lower48.scale(), x = +_[0], y = +_[1];\n      lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;\n      alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;\n      hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;\n      return albersUsa;\n    };\n    return albersUsa.scale(1070);\n  };\n  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {\n    point: d3_noop,\n    lineStart: d3_noop,\n    lineEnd: d3_noop,\n    polygonStart: function() {\n      d3_geo_pathAreaPolygon = 0;\n      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;\n    },\n    polygonEnd: function() {\n      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;\n      d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);\n    }\n  };\n  function d3_geo_pathAreaRingStart() {\n    var x00, y00, x0, y0;\n    d3_geo_pathArea.point = function(x, y) {\n      d3_geo_pathArea.point = nextPoint;\n      x00 = x0 = x, y00 = y0 = y;\n    };\n    function nextPoint(x, y) {\n      d3_geo_pathAreaPolygon += y0 * x - x0 * y;\n      x0 = x, y0 = y;\n    }\n    d3_geo_pathArea.lineEnd = function() {\n      nextPoint(x00, y00);\n    };\n  }\n  var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;\n  var d3_geo_pathBounds = {\n    point: d3_geo_pathBoundsPoint,\n    lineStart: d3_noop,\n    lineEnd: d3_noop,\n    polygonStart: d3_noop,\n    polygonEnd: d3_noop\n  };\n  function d3_geo_pathBoundsPoint(x, y) {\n    if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;\n    if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;\n    if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;\n    if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;\n  }\n  function d3_geo_pathBuffer() {\n    var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];\n    var stream = {\n      point: point,\n      lineStart: function() {\n        stream.point = pointLineStart;\n      },\n      lineEnd: lineEnd,\n      polygonStart: function() {\n        stream.lineEnd = lineEndPolygon;\n      },\n      polygonEnd: function() {\n        stream.lineEnd = lineEnd;\n        stream.point = point;\n      },\n      pointRadius: function(_) {\n        pointCircle = d3_geo_pathBufferCircle(_);\n        return stream;\n      },\n      result: function() {\n        if (buffer.length) {\n          var result = buffer.join(\"\");\n          buffer = [];\n          return result;\n        }\n      }\n    };\n    function point(x, y) {\n      buffer.push(\"M\", x, \",\", y, pointCircle);\n    }\n    function pointLineStart(x, y) {\n      buffer.push(\"M\", x, \",\", y);\n      stream.point = pointLine;\n    }\n    function pointLine(x, y) {\n      buffer.push(\"L\", x, \",\", y);\n    }\n    function lineEnd() {\n      stream.point = point;\n    }\n    function lineEndPolygon() {\n      buffer.push(\"Z\");\n    }\n    return stream;\n  }\n  function d3_geo_pathBufferCircle(radius) {\n    return \"m0,\" + radius + \"a\" + radius + \",\" + radius + \" 0 1,1 0,\" + -2 * radius + \"a\" + radius + \",\" + radius + \" 0 1,1 0,\" + 2 * radius + \"z\";\n  }\n  var d3_geo_pathCentroid = {\n    point: d3_geo_pathCentroidPoint,\n    lineStart: d3_geo_pathCentroidLineStart,\n    lineEnd: d3_geo_pathCentroidLineEnd,\n    polygonStart: function() {\n      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;\n    },\n    polygonEnd: function() {\n      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;\n      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;\n      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;\n    }\n  };\n  function d3_geo_pathCentroidPoint(x, y) {\n    d3_geo_centroidX0 += x;\n    d3_geo_centroidY0 += y;\n    ++d3_geo_centroidZ0;\n  }\n  function d3_geo_pathCentroidLineStart() {\n    var x0, y0;\n    d3_geo_pathCentroid.point = function(x, y) {\n      d3_geo_pathCentroid.point = nextPoint;\n      d3_geo_pathCentroidPoint(x0 = x, y0 = y);\n    };\n    function nextPoint(x, y) {\n      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);\n      d3_geo_centroidX1 += z * (x0 + x) / 2;\n      d3_geo_centroidY1 += z * (y0 + y) / 2;\n      d3_geo_centroidZ1 += z;\n      d3_geo_pathCentroidPoint(x0 = x, y0 = y);\n    }\n  }\n  function d3_geo_pathCentroidLineEnd() {\n    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;\n  }\n  function d3_geo_pathCentroidRingStart() {\n    var x00, y00, x0, y0;\n    d3_geo_pathCentroid.point = function(x, y) {\n      d3_geo_pathCentroid.point = nextPoint;\n      d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);\n    };\n    function nextPoint(x, y) {\n      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);\n      d3_geo_centroidX1 += z * (x0 + x) / 2;\n      d3_geo_centroidY1 += z * (y0 + y) / 2;\n      d3_geo_centroidZ1 += z;\n      z = y0 * x - x0 * y;\n      d3_geo_centroidX2 += z * (x0 + x);\n      d3_geo_centroidY2 += z * (y0 + y);\n      d3_geo_centroidZ2 += z * 3;\n      d3_geo_pathCentroidPoint(x0 = x, y0 = y);\n    }\n    d3_geo_pathCentroid.lineEnd = function() {\n      nextPoint(x00, y00);\n    };\n  }\n  function d3_geo_pathContext(context) {\n    var pointRadius = 4.5;\n    var stream = {\n      point: point,\n      lineStart: function() {\n        stream.point = pointLineStart;\n      },\n      lineEnd: lineEnd,\n      polygonStart: function() {\n        stream.lineEnd = lineEndPolygon;\n      },\n      polygonEnd: function() {\n        stream.lineEnd = lineEnd;\n        stream.point = point;\n      },\n      pointRadius: function(_) {\n        pointRadius = _;\n        return stream;\n      },\n      result: d3_noop\n    };\n    function point(x, y) {\n      context.moveTo(x, y);\n      context.arc(x, y, pointRadius, 0, τ);\n    }\n    function pointLineStart(x, y) {\n      context.moveTo(x, y);\n      stream.point = pointLine;\n    }\n    function pointLine(x, y) {\n      context.lineTo(x, y);\n    }\n    function lineEnd() {\n      stream.point = point;\n    }\n    function lineEndPolygon() {\n      context.closePath();\n    }\n    return stream;\n  }\n  function d3_geo_resample(project) {\n    var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;\n    function resample(stream) {\n      return (maxDepth ? resampleRecursive : resampleNone)(stream);\n    }\n    function resampleNone(stream) {\n      return d3_geo_transformPoint(stream, function(x, y) {\n        x = project(x, y);\n        stream.point(x[0], x[1]);\n      });\n    }\n    function resampleRecursive(stream) {\n      var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;\n      var resample = {\n        point: point,\n        lineStart: lineStart,\n        lineEnd: lineEnd,\n        polygonStart: function() {\n          stream.polygonStart();\n          resample.lineStart = ringStart;\n        },\n        polygonEnd: function() {\n          stream.polygonEnd();\n          resample.lineStart = lineStart;\n        }\n      };\n      function point(x, y) {\n        x = project(x, y);\n        stream.point(x[0], x[1]);\n      }\n      function lineStart() {\n        x0 = NaN;\n        resample.point = linePoint;\n        stream.lineStart();\n      }\n      function linePoint(λ, φ) {\n        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);\n        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);\n        stream.point(x0, y0);\n      }\n      function lineEnd() {\n        resample.point = point;\n        stream.lineEnd();\n      }\n      function ringStart() {\n        lineStart();\n        resample.point = ringPoint;\n        resample.lineEnd = ringEnd;\n      }\n      function ringPoint(λ, φ) {\n        linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;\n        resample.point = linePoint;\n      }\n      function ringEnd() {\n        resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);\n        resample.lineEnd = lineEnd;\n        lineEnd();\n      }\n      return resample;\n    }\n    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {\n      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;\n      if (d2 > 4 * δ2 && depth--) {\n        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;\n        if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {\n          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);\n          stream.point(x2, y2);\n          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);\n        }\n      }\n    }\n    resample.precision = function(_) {\n      if (!arguments.length) return Math.sqrt(δ2);\n      maxDepth = (δ2 = _ * _) > 0 && 16;\n      return resample;\n    };\n    return resample;\n  }\n  d3.geo.path = function() {\n    var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;\n    function path(object) {\n      if (object) {\n        if (typeof pointRadius === \"function\") contextStream.pointRadius(+pointRadius.apply(this, arguments));\n        if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);\n        d3.geo.stream(object, cacheStream);\n      }\n      return contextStream.result();\n    }\n    path.area = function(object) {\n      d3_geo_pathAreaSum = 0;\n      d3.geo.stream(object, projectStream(d3_geo_pathArea));\n      return d3_geo_pathAreaSum;\n    };\n    path.centroid = function(object) {\n      d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;\n      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));\n      return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];\n    };\n    path.bounds = function(object) {\n      d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);\n      d3.geo.stream(object, projectStream(d3_geo_pathBounds));\n      return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];\n    };\n    path.projection = function(_) {\n      if (!arguments.length) return projection;\n      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;\n      return reset();\n    };\n    path.context = function(_) {\n      if (!arguments.length) return context;\n      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);\n      if (typeof pointRadius !== \"function\") contextStream.pointRadius(pointRadius);\n      return reset();\n    };\n    path.pointRadius = function(_) {\n      if (!arguments.length) return pointRadius;\n      pointRadius = typeof _ === \"function\" ? _ : (contextStream.pointRadius(+_), +_);\n      return path;\n    };\n    function reset() {\n      cacheStream = null;\n      return path;\n    }\n    return path.projection(d3.geo.albersUsa()).context(null);\n  };\n  function d3_geo_pathProjectStream(project) {\n    var resample = d3_geo_resample(function(x, y) {\n      return project([ x * d3_degrees, y * d3_degrees ]);\n    });\n    return function(stream) {\n      return d3_geo_projectionRadians(resample(stream));\n    };\n  }\n  d3.geo.transform = function(methods) {\n    return {\n      stream: function(stream) {\n        var transform = new d3_geo_transform(stream);\n        for (var k in methods) transform[k] = methods[k];\n        return transform;\n      }\n    };\n  };\n  function d3_geo_transform(stream) {\n    this.stream = stream;\n  }\n  d3_geo_transform.prototype = {\n    point: function(x, y) {\n      this.stream.point(x, y);\n    },\n    sphere: function() {\n      this.stream.sphere();\n    },\n    lineStart: function() {\n      this.stream.lineStart();\n    },\n    lineEnd: function() {\n      this.stream.lineEnd();\n    },\n    polygonStart: function() {\n      this.stream.polygonStart();\n    },\n    polygonEnd: function() {\n      this.stream.polygonEnd();\n    }\n  };\n  function d3_geo_transformPoint(stream, point) {\n    return {\n      point: point,\n      sphere: function() {\n        stream.sphere();\n      },\n      lineStart: function() {\n        stream.lineStart();\n      },\n      lineEnd: function() {\n        stream.lineEnd();\n      },\n      polygonStart: function() {\n        stream.polygonStart();\n      },\n      polygonEnd: function() {\n        stream.polygonEnd();\n      }\n    };\n  }\n  d3.geo.projection = d3_geo_projection;\n  d3.geo.projectionMutator = d3_geo_projectionMutator;\n  function d3_geo_projection(project) {\n    return d3_geo_projectionMutator(function() {\n      return project;\n    })();\n  }\n  function d3_geo_projectionMutator(projectAt) {\n    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {\n      x = project(x, y);\n      return [ x[0] * k + δx, δy - x[1] * k ];\n    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;\n    function projection(point) {\n      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);\n      return [ point[0] * k + δx, δy - point[1] * k ];\n    }\n    function invert(point) {\n      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);\n      return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];\n    }\n    projection.stream = function(output) {\n      if (stream) stream.valid = false;\n      stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));\n      stream.valid = true;\n      return stream;\n    };\n    projection.clipAngle = function(_) {\n      if (!arguments.length) return clipAngle;\n      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);\n      return invalidate();\n    };\n    projection.clipExtent = function(_) {\n      if (!arguments.length) return clipExtent;\n      clipExtent = _;\n      postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;\n      return invalidate();\n    };\n    projection.scale = function(_) {\n      if (!arguments.length) return k;\n      k = +_;\n      return reset();\n    };\n    projection.translate = function(_) {\n      if (!arguments.length) return [ x, y ];\n      x = +_[0];\n      y = +_[1];\n      return reset();\n    };\n    projection.center = function(_) {\n      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];\n      λ = _[0] % 360 * d3_radians;\n      φ = _[1] % 360 * d3_radians;\n      return reset();\n    };\n    projection.rotate = function(_) {\n      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];\n      δλ = _[0] % 360 * d3_radians;\n      δφ = _[1] % 360 * d3_radians;\n      δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;\n      return reset();\n    };\n    d3.rebind(projection, projectResample, \"precision\");\n    function reset() {\n      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);\n      var center = project(λ, φ);\n      δx = x - center[0] * k;\n      δy = y + center[1] * k;\n      return invalidate();\n    }\n    function invalidate() {\n      if (stream) stream.valid = false, stream = null;\n      return projection;\n    }\n    return function() {\n      project = projectAt.apply(this, arguments);\n      projection.invert = project.invert && invert;\n      return reset();\n    };\n  }\n  function d3_geo_projectionRadians(stream) {\n    return d3_geo_transformPoint(stream, function(x, y) {\n      stream.point(x * d3_radians, y * d3_radians);\n    });\n  }\n  function d3_geo_equirectangular(λ, φ) {\n    return [ λ, φ ];\n  }\n  (d3.geo.equirectangular = function() {\n    return d3_geo_projection(d3_geo_equirectangular);\n  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;\n  d3.geo.rotation = function(rotate) {\n    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);\n    function forward(coordinates) {\n      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);\n      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;\n    }\n    forward.invert = function(coordinates) {\n      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);\n      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;\n    };\n    return forward;\n  };\n  function d3_geo_identityRotation(λ, φ) {\n    return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];\n  }\n  d3_geo_identityRotation.invert = d3_geo_equirectangular;\n  function d3_geo_rotation(δλ, δφ, δγ) {\n    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;\n  }\n  function d3_geo_forwardRotationλ(δλ) {\n    return function(λ, φ) {\n      return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];\n    };\n  }\n  function d3_geo_rotationλ(δλ) {\n    var rotation = d3_geo_forwardRotationλ(δλ);\n    rotation.invert = d3_geo_forwardRotationλ(-δλ);\n    return rotation;\n  }\n  function d3_geo_rotationφγ(δφ, δγ) {\n    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);\n    function rotation(λ, φ) {\n      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;\n      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];\n    }\n    rotation.invert = function(λ, φ) {\n      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;\n      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];\n    };\n    return rotation;\n  }\n  d3.geo.circle = function() {\n    var origin = [ 0, 0 ], angle, precision = 6, interpolate;\n    function circle() {\n      var center = typeof origin === \"function\" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];\n      interpolate(null, null, 1, {\n        point: function(x, y) {\n          ring.push(x = rotate(x, y));\n          x[0] *= d3_degrees, x[1] *= d3_degrees;\n        }\n      });\n      return {\n        type: \"Polygon\",\n        coordinates: [ ring ]\n      };\n    }\n    circle.origin = function(x) {\n      if (!arguments.length) return origin;\n      origin = x;\n      return circle;\n    };\n    circle.angle = function(x) {\n      if (!arguments.length) return angle;\n      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);\n      return circle;\n    };\n    circle.precision = function(_) {\n      if (!arguments.length) return precision;\n      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);\n      return circle;\n    };\n    return circle.angle(90);\n  };\n  function d3_geo_circleInterpolate(radius, precision) {\n    var cr = Math.cos(radius), sr = Math.sin(radius);\n    return function(from, to, direction, listener) {\n      var step = direction * precision;\n      if (from != null) {\n        from = d3_geo_circleAngle(cr, from);\n        to = d3_geo_circleAngle(cr, to);\n        if (direction > 0 ? from < to : from > to) from += direction * τ;\n      } else {\n        from = radius + direction * τ;\n        to = radius - .5 * step;\n      }\n      for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {\n        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);\n      }\n    };\n  }\n  function d3_geo_circleAngle(cr, point) {\n    var a = d3_geo_cartesian(point);\n    a[0] -= cr;\n    d3_geo_cartesianNormalize(a);\n    var angle = d3_acos(-a[1]);\n    return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);\n  }\n  d3.geo.distance = function(a, b) {\n    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;\n    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);\n  };\n  d3.geo.graticule = function() {\n    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;\n    function graticule() {\n      return {\n        type: \"MultiLineString\",\n        coordinates: lines()\n      };\n    }\n    function lines() {\n      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {\n        return abs(x % DX) > ε;\n      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {\n        return abs(y % DY) > ε;\n      }).map(y));\n    }\n    graticule.lines = function() {\n      return lines().map(function(coordinates) {\n        return {\n          type: \"LineString\",\n          coordinates: coordinates\n        };\n      });\n    };\n    graticule.outline = function() {\n      return {\n        type: \"Polygon\",\n        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]\n      };\n    };\n    graticule.extent = function(_) {\n      if (!arguments.length) return graticule.minorExtent();\n      return graticule.majorExtent(_).minorExtent(_);\n    };\n    graticule.majorExtent = function(_) {\n      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];\n      X0 = +_[0][0], X1 = +_[1][0];\n      Y0 = +_[0][1], Y1 = +_[1][1];\n      if (X0 > X1) _ = X0, X0 = X1, X1 = _;\n      if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;\n      return graticule.precision(precision);\n    };\n    graticule.minorExtent = function(_) {\n      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];\n      x0 = +_[0][0], x1 = +_[1][0];\n      y0 = +_[0][1], y1 = +_[1][1];\n      if (x0 > x1) _ = x0, x0 = x1, x1 = _;\n      if (y0 > y1) _ = y0, y0 = y1, y1 = _;\n      return graticule.precision(precision);\n    };\n    graticule.step = function(_) {\n      if (!arguments.length) return graticule.minorStep();\n      return graticule.majorStep(_).minorStep(_);\n    };\n    graticule.majorStep = function(_) {\n      if (!arguments.length) return [ DX, DY ];\n      DX = +_[0], DY = +_[1];\n      return graticule;\n    };\n    graticule.minorStep = function(_) {\n      if (!arguments.length) return [ dx, dy ];\n      dx = +_[0], dy = +_[1];\n      return graticule;\n    };\n    graticule.precision = function(_) {\n      if (!arguments.length) return precision;\n      precision = +_;\n      x = d3_geo_graticuleX(y0, y1, 90);\n      y = d3_geo_graticuleY(x0, x1, precision);\n      X = d3_geo_graticuleX(Y0, Y1, 90);\n      Y = d3_geo_graticuleY(X0, X1, precision);\n      return graticule;\n    };\n    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);\n  };\n  function d3_geo_graticuleX(y0, y1, dy) {\n    var y = d3.range(y0, y1 - ε, dy).concat(y1);\n    return function(x) {\n      return y.map(function(y) {\n        return [ x, y ];\n      });\n    };\n  }\n  function d3_geo_graticuleY(x0, x1, dx) {\n    var x = d3.range(x0, x1 - ε, dx).concat(x1);\n    return function(y) {\n      return x.map(function(x) {\n        return [ x, y ];\n      });\n    };\n  }\n  function d3_source(d) {\n    return d.source;\n  }\n  function d3_target(d) {\n    return d.target;\n  }\n  d3.geo.greatArc = function() {\n    var source = d3_source, source_, target = d3_target, target_;\n    function greatArc() {\n      return {\n        type: \"LineString\",\n        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]\n      };\n    }\n    greatArc.distance = function() {\n      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));\n    };\n    greatArc.source = function(_) {\n      if (!arguments.length) return source;\n      source = _, source_ = typeof _ === \"function\" ? null : _;\n      return greatArc;\n    };\n    greatArc.target = function(_) {\n      if (!arguments.length) return target;\n      target = _, target_ = typeof _ === \"function\" ? null : _;\n      return greatArc;\n    };\n    greatArc.precision = function() {\n      return arguments.length ? greatArc : 0;\n    };\n    return greatArc;\n  };\n  d3.geo.interpolate = function(source, target) {\n    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);\n  };\n  function d3_geo_interpolate(x0, y0, x1, y1) {\n    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);\n    var interpolate = d ? function(t) {\n      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;\n      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];\n    } : function() {\n      return [ x0 * d3_degrees, y0 * d3_degrees ];\n    };\n    interpolate.distance = d;\n    return interpolate;\n  }\n  d3.geo.length = function(object) {\n    d3_geo_lengthSum = 0;\n    d3.geo.stream(object, d3_geo_length);\n    return d3_geo_lengthSum;\n  };\n  var d3_geo_lengthSum;\n  var d3_geo_length = {\n    sphere: d3_noop,\n    point: d3_noop,\n    lineStart: d3_geo_lengthLineStart,\n    lineEnd: d3_noop,\n    polygonStart: d3_noop,\n    polygonEnd: d3_noop\n  };\n  function d3_geo_lengthLineStart() {\n    var λ0, sinφ0, cosφ0;\n    d3_geo_length.point = function(λ, φ) {\n      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);\n      d3_geo_length.point = nextPoint;\n    };\n    d3_geo_length.lineEnd = function() {\n      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;\n    };\n    function nextPoint(λ, φ) {\n      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);\n      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);\n      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;\n    }\n  }\n  function d3_geo_azimuthal(scale, angle) {\n    function azimuthal(λ, φ) {\n      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);\n      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];\n    }\n    azimuthal.invert = function(x, y) {\n      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);\n      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];\n    };\n    return azimuthal;\n  }\n  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {\n    return Math.sqrt(2 / (1 + cosλcosφ));\n  }, function(ρ) {\n    return 2 * Math.asin(ρ / 2);\n  });\n  (d3.geo.azimuthalEqualArea = function() {\n    return d3_geo_projection(d3_geo_azimuthalEqualArea);\n  }).raw = d3_geo_azimuthalEqualArea;\n  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {\n    var c = Math.acos(cosλcosφ);\n    return c && c / Math.sin(c);\n  }, d3_identity);\n  (d3.geo.azimuthalEquidistant = function() {\n    return d3_geo_projection(d3_geo_azimuthalEquidistant);\n  }).raw = d3_geo_azimuthalEquidistant;\n  function d3_geo_conicConformal(φ0, φ1) {\n    var cosφ0 = Math.cos(φ0), t = function(φ) {\n      return Math.tan(π / 4 + φ / 2);\n    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;\n    if (!n) return d3_geo_mercator;\n    function forward(λ, φ) {\n      if (F > 0) {\n        if (φ < -halfπ + ε) φ = -halfπ + ε;\n      } else {\n        if (φ > halfπ - ε) φ = halfπ - ε;\n      }\n      var ρ = F / Math.pow(t(φ), n);\n      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];\n    }\n    forward.invert = function(x, y) {\n      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);\n      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];\n    };\n    return forward;\n  }\n  (d3.geo.conicConformal = function() {\n    return d3_geo_conic(d3_geo_conicConformal);\n  }).raw = d3_geo_conicConformal;\n  function d3_geo_conicEquidistant(φ0, φ1) {\n    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;\n    if (abs(n) < ε) return d3_geo_equirectangular;\n    function forward(λ, φ) {\n      var ρ = G - φ;\n      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];\n    }\n    forward.invert = function(x, y) {\n      var ρ0_y = G - y;\n      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];\n    };\n    return forward;\n  }\n  (d3.geo.conicEquidistant = function() {\n    return d3_geo_conic(d3_geo_conicEquidistant);\n  }).raw = d3_geo_conicEquidistant;\n  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {\n    return 1 / cosλcosφ;\n  }, Math.atan);\n  (d3.geo.gnomonic = function() {\n    return d3_geo_projection(d3_geo_gnomonic);\n  }).raw = d3_geo_gnomonic;\n  function d3_geo_mercator(λ, φ) {\n    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];\n  }\n  d3_geo_mercator.invert = function(x, y) {\n    return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];\n  };\n  function d3_geo_mercatorProjection(project) {\n    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;\n    m.scale = function() {\n      var v = scale.apply(m, arguments);\n      return v === m ? clipAuto ? m.clipExtent(null) : m : v;\n    };\n    m.translate = function() {\n      var v = translate.apply(m, arguments);\n      return v === m ? clipAuto ? m.clipExtent(null) : m : v;\n    };\n    m.clipExtent = function(_) {\n      var v = clipExtent.apply(m, arguments);\n      if (v === m) {\n        if (clipAuto = _ == null) {\n          var k = π * scale(), t = translate();\n          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);\n        }\n      } else if (clipAuto) {\n        v = null;\n      }\n      return v;\n    };\n    return m.clipExtent(null);\n  }\n  (d3.geo.mercator = function() {\n    return d3_geo_mercatorProjection(d3_geo_mercator);\n  }).raw = d3_geo_mercator;\n  var d3_geo_orthographic = d3_geo_azimuthal(function() {\n    return 1;\n  }, Math.asin);\n  (d3.geo.orthographic = function() {\n    return d3_geo_projection(d3_geo_orthographic);\n  }).raw = d3_geo_orthographic;\n  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {\n    return 1 / (1 + cosλcosφ);\n  }, function(ρ) {\n    return 2 * Math.atan(ρ);\n  });\n  (d3.geo.stereographic = function() {\n    return d3_geo_projection(d3_geo_stereographic);\n  }).raw = d3_geo_stereographic;\n  function d3_geo_transverseMercator(λ, φ) {\n    return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];\n  }\n  d3_geo_transverseMercator.invert = function(x, y) {\n    return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];\n  };\n  (d3.geo.transverseMercator = function() {\n    var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;\n    projection.center = function(_) {\n      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);\n    };\n    projection.rotate = function(_) {\n      return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), \n      [ _[0], _[1], _[2] - 90 ]);\n    };\n    return rotate([ 0, 0, 90 ]);\n  }).raw = d3_geo_transverseMercator;\n  d3.geom = {};\n  function d3_geom_pointX(d) {\n    return d[0];\n  }\n  function d3_geom_pointY(d) {\n    return d[1];\n  }\n  d3.geom.hull = function(vertices) {\n    var x = d3_geom_pointX, y = d3_geom_pointY;\n    if (arguments.length) return hull(vertices);\n    function hull(data) {\n      if (data.length < 3) return [];\n      var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];\n      for (i = 0; i < n; i++) {\n        points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);\n      }\n      points.sort(d3_geom_hullOrder);\n      for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);\n      var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);\n      var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];\n      for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);\n      for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);\n      return polygon;\n    }\n    hull.x = function(_) {\n      return arguments.length ? (x = _, hull) : x;\n    };\n    hull.y = function(_) {\n      return arguments.length ? (y = _, hull) : y;\n    };\n    return hull;\n  };\n  function d3_geom_hullUpper(points) {\n    var n = points.length, hull = [ 0, 1 ], hs = 2;\n    for (var i = 2; i < n; i++) {\n      while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;\n      hull[hs++] = i;\n    }\n    return hull.slice(0, hs);\n  }\n  function d3_geom_hullOrder(a, b) {\n    return a[0] - b[0] || a[1] - b[1];\n  }\n  d3.geom.polygon = function(coordinates) {\n    d3_subclass(coordinates, d3_geom_polygonPrototype);\n    return coordinates;\n  };\n  var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];\n  d3_geom_polygonPrototype.area = function() {\n    var i = -1, n = this.length, a, b = this[n - 1], area = 0;\n    while (++i < n) {\n      a = b;\n      b = this[i];\n      area += a[1] * b[0] - a[0] * b[1];\n    }\n    return area * .5;\n  };\n  d3_geom_polygonPrototype.centroid = function(k) {\n    var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;\n    if (!arguments.length) k = -1 / (6 * this.area());\n    while (++i < n) {\n      a = b;\n      b = this[i];\n      c = a[0] * b[1] - b[0] * a[1];\n      x += (a[0] + b[0]) * c;\n      y += (a[1] + b[1]) * c;\n    }\n    return [ x * k, y * k ];\n  };\n  d3_geom_polygonPrototype.clip = function(subject) {\n    var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;\n    while (++i < n) {\n      input = subject.slice();\n      subject.length = 0;\n      b = this[i];\n      c = input[(m = input.length - closed) - 1];\n      j = -1;\n      while (++j < m) {\n        d = input[j];\n        if (d3_geom_polygonInside(d, a, b)) {\n          if (!d3_geom_polygonInside(c, a, b)) {\n            subject.push(d3_geom_polygonIntersect(c, d, a, b));\n          }\n          subject.push(d);\n        } else if (d3_geom_polygonInside(c, a, b)) {\n          subject.push(d3_geom_polygonIntersect(c, d, a, b));\n        }\n        c = d;\n      }\n      if (closed) subject.push(subject[0]);\n      a = b;\n    }\n    return subject;\n  };\n  function d3_geom_polygonInside(p, a, b) {\n    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);\n  }\n  function d3_geom_polygonIntersect(c, d, a, b) {\n    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);\n    return [ x1 + ua * x21, y1 + ua * y21 ];\n  }\n  function d3_geom_polygonClosed(coordinates) {\n    var a = coordinates[0], b = coordinates[coordinates.length - 1];\n    return !(a[0] - b[0] || a[1] - b[1]);\n  }\n  var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];\n  function d3_geom_voronoiBeach() {\n    d3_geom_voronoiRedBlackNode(this);\n    this.edge = this.site = this.circle = null;\n  }\n  function d3_geom_voronoiCreateBeach(site) {\n    var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();\n    beach.site = site;\n    return beach;\n  }\n  function d3_geom_voronoiDetachBeach(beach) {\n    d3_geom_voronoiDetachCircle(beach);\n    d3_geom_voronoiBeaches.remove(beach);\n    d3_geom_voronoiBeachPool.push(beach);\n    d3_geom_voronoiRedBlackNode(beach);\n  }\n  function d3_geom_voronoiRemoveBeach(beach) {\n    var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {\n      x: x,\n      y: y\n    }, previous = beach.P, next = beach.N, disappearing = [ beach ];\n    d3_geom_voronoiDetachBeach(beach);\n    var lArc = previous;\n    while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {\n      previous = lArc.P;\n      disappearing.unshift(lArc);\n      d3_geom_voronoiDetachBeach(lArc);\n      lArc = previous;\n    }\n    disappearing.unshift(lArc);\n    d3_geom_voronoiDetachCircle(lArc);\n    var rArc = next;\n    while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {\n      next = rArc.N;\n      disappearing.push(rArc);\n      d3_geom_voronoiDetachBeach(rArc);\n      rArc = next;\n    }\n    disappearing.push(rArc);\n    d3_geom_voronoiDetachCircle(rArc);\n    var nArcs = disappearing.length, iArc;\n    for (iArc = 1; iArc < nArcs; ++iArc) {\n      rArc = disappearing[iArc];\n      lArc = disappearing[iArc - 1];\n      d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);\n    }\n    lArc = disappearing[0];\n    rArc = disappearing[nArcs - 1];\n    rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);\n    d3_geom_voronoiAttachCircle(lArc);\n    d3_geom_voronoiAttachCircle(rArc);\n  }\n  function d3_geom_voronoiAddBeach(site) {\n    var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;\n    while (node) {\n      dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;\n      if (dxl > ε) node = node.L; else {\n        dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);\n        if (dxr > ε) {\n          if (!node.R) {\n            lArc = node;\n            break;\n          }\n          node = node.R;\n        } else {\n          if (dxl > -ε) {\n            lArc = node.P;\n            rArc = node;\n          } else if (dxr > -ε) {\n            lArc = node;\n            rArc = node.N;\n          } else {\n            lArc = rArc = node;\n          }\n          break;\n        }\n      }\n    }\n    var newArc = d3_geom_voronoiCreateBeach(site);\n    d3_geom_voronoiBeaches.insert(lArc, newArc);\n    if (!lArc && !rArc) return;\n    if (lArc === rArc) {\n      d3_geom_voronoiDetachCircle(lArc);\n      rArc = d3_geom_voronoiCreateBeach(lArc.site);\n      d3_geom_voronoiBeaches.insert(newArc, rArc);\n      newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);\n      d3_geom_voronoiAttachCircle(lArc);\n      d3_geom_voronoiAttachCircle(rArc);\n      return;\n    }\n    if (!rArc) {\n      newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);\n      return;\n    }\n    d3_geom_voronoiDetachCircle(lArc);\n    d3_geom_voronoiDetachCircle(rArc);\n    var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {\n      x: (cy * hb - by * hc) / d + ax,\n      y: (bx * hc - cx * hb) / d + ay\n    };\n    d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);\n    newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);\n    rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);\n    d3_geom_voronoiAttachCircle(lArc);\n    d3_geom_voronoiAttachCircle(rArc);\n  }\n  function d3_geom_voronoiLeftBreakPoint(arc, directrix) {\n    var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;\n    if (!pby2) return rfocx;\n    var lArc = arc.P;\n    if (!lArc) return -Infinity;\n    site = lArc.site;\n    var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;\n    if (!plby2) return lfocx;\n    var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;\n    if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;\n    return (rfocx + lfocx) / 2;\n  }\n  function d3_geom_voronoiRightBreakPoint(arc, directrix) {\n    var rArc = arc.N;\n    if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);\n    var site = arc.site;\n    return site.y === directrix ? site.x : Infinity;\n  }\n  function d3_geom_voronoiCell(site) {\n    this.site = site;\n    this.edges = [];\n  }\n  d3_geom_voronoiCell.prototype.prepare = function() {\n    var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;\n    while (iHalfEdge--) {\n      edge = halfEdges[iHalfEdge].edge;\n      if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);\n    }\n    halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);\n    return halfEdges.length;\n  };\n  function d3_geom_voronoiCloseCells(extent) {\n    var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;\n    while (iCell--) {\n      cell = cells[iCell];\n      if (!cell || !cell.prepare()) continue;\n      halfEdges = cell.edges;\n      nHalfEdges = halfEdges.length;\n      iHalfEdge = 0;\n      while (iHalfEdge < nHalfEdges) {\n        end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;\n        start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;\n        if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {\n          halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {\n            x: x0,\n            y: abs(x2 - x0) < ε ? y2 : y1\n          } : abs(y3 - y1) < ε && x1 - x3 > ε ? {\n            x: abs(y2 - y1) < ε ? x2 : x1,\n            y: y1\n          } : abs(x3 - x1) < ε && y3 - y0 > ε ? {\n            x: x1,\n            y: abs(x2 - x1) < ε ? y2 : y0\n          } : abs(y3 - y0) < ε && x3 - x0 > ε ? {\n            x: abs(y2 - y0) < ε ? x2 : x0,\n            y: y0\n          } : null), cell.site, null));\n          ++nHalfEdges;\n        }\n      }\n    }\n  }\n  function d3_geom_voronoiHalfEdgeOrder(a, b) {\n    return b.angle - a.angle;\n  }\n  function d3_geom_voronoiCircle() {\n    d3_geom_voronoiRedBlackNode(this);\n    this.x = this.y = this.arc = this.site = this.cy = null;\n  }\n  function d3_geom_voronoiAttachCircle(arc) {\n    var lArc = arc.P, rArc = arc.N;\n    if (!lArc || !rArc) return;\n    var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;\n    if (lSite === rSite) return;\n    var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;\n    var d = 2 * (ax * cy - ay * cx);\n    if (d >= -ε2) return;\n    var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;\n    var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();\n    circle.arc = arc;\n    circle.site = cSite;\n    circle.x = x + bx;\n    circle.y = cy + Math.sqrt(x * x + y * y);\n    circle.cy = cy;\n    arc.circle = circle;\n    var before = null, node = d3_geom_voronoiCircles._;\n    while (node) {\n      if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {\n        if (node.L) node = node.L; else {\n          before = node.P;\n          break;\n        }\n      } else {\n        if (node.R) node = node.R; else {\n          before = node;\n          break;\n        }\n      }\n    }\n    d3_geom_voronoiCircles.insert(before, circle);\n    if (!before) d3_geom_voronoiFirstCircle = circle;\n  }\n  function d3_geom_voronoiDetachCircle(arc) {\n    var circle = arc.circle;\n    if (circle) {\n      if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;\n      d3_geom_voronoiCircles.remove(circle);\n      d3_geom_voronoiCirclePool.push(circle);\n      d3_geom_voronoiRedBlackNode(circle);\n      arc.circle = null;\n    }\n  }\n  function d3_geom_voronoiClipEdges(extent) {\n    var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;\n    while (i--) {\n      e = edges[i];\n      if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {\n        e.a = e.b = null;\n        edges.splice(i, 1);\n      }\n    }\n  }\n  function d3_geom_voronoiConnectEdge(edge, extent) {\n    var vb = edge.b;\n    if (vb) return true;\n    var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;\n    if (ry === ly) {\n      if (fx < x0 || fx >= x1) return;\n      if (lx > rx) {\n        if (!va) va = {\n          x: fx,\n          y: y0\n        }; else if (va.y >= y1) return;\n        vb = {\n          x: fx,\n          y: y1\n        };\n      } else {\n        if (!va) va = {\n          x: fx,\n          y: y1\n        }; else if (va.y < y0) return;\n        vb = {\n          x: fx,\n          y: y0\n        };\n      }\n    } else {\n      fm = (lx - rx) / (ry - ly);\n      fb = fy - fm * fx;\n      if (fm < -1 || fm > 1) {\n        if (lx > rx) {\n          if (!va) va = {\n            x: (y0 - fb) / fm,\n            y: y0\n          }; else if (va.y >= y1) return;\n          vb = {\n            x: (y1 - fb) / fm,\n            y: y1\n          };\n        } else {\n          if (!va) va = {\n            x: (y1 - fb) / fm,\n            y: y1\n          }; else if (va.y < y0) return;\n          vb = {\n            x: (y0 - fb) / fm,\n            y: y0\n          };\n        }\n      } else {\n        if (ly < ry) {\n          if (!va) va = {\n            x: x0,\n            y: fm * x0 + fb\n          }; else if (va.x >= x1) return;\n          vb = {\n            x: x1,\n            y: fm * x1 + fb\n          };\n        } else {\n          if (!va) va = {\n            x: x1,\n            y: fm * x1 + fb\n          }; else if (va.x < x0) return;\n          vb = {\n            x: x0,\n            y: fm * x0 + fb\n          };\n        }\n      }\n    }\n    edge.a = va;\n    edge.b = vb;\n    return true;\n  }\n  function d3_geom_voronoiEdge(lSite, rSite) {\n    this.l = lSite;\n    this.r = rSite;\n    this.a = this.b = null;\n  }\n  function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {\n    var edge = new d3_geom_voronoiEdge(lSite, rSite);\n    d3_geom_voronoiEdges.push(edge);\n    if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);\n    if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);\n    d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));\n    d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));\n    return edge;\n  }\n  function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {\n    var edge = new d3_geom_voronoiEdge(lSite, null);\n    edge.a = va;\n    edge.b = vb;\n    d3_geom_voronoiEdges.push(edge);\n    return edge;\n  }\n  function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {\n    if (!edge.a && !edge.b) {\n      edge.a = vertex;\n      edge.l = lSite;\n      edge.r = rSite;\n    } else if (edge.l === rSite) {\n      edge.b = vertex;\n    } else {\n      edge.a = vertex;\n    }\n  }\n  function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {\n    var va = edge.a, vb = edge.b;\n    this.edge = edge;\n    this.site = lSite;\n    this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);\n  }\n  d3_geom_voronoiHalfEdge.prototype = {\n    start: function() {\n      return this.edge.l === this.site ? this.edge.a : this.edge.b;\n    },\n    end: function() {\n      return this.edge.l === this.site ? this.edge.b : this.edge.a;\n    }\n  };\n  function d3_geom_voronoiRedBlackTree() {\n    this._ = null;\n  }\n  function d3_geom_voronoiRedBlackNode(node) {\n    node.U = node.C = node.L = node.R = node.P = node.N = null;\n  }\n  d3_geom_voronoiRedBlackTree.prototype = {\n    insert: function(after, node) {\n      var parent, grandpa, uncle;\n      if (after) {\n        node.P = after;\n        node.N = after.N;\n        if (after.N) after.N.P = node;\n        after.N = node;\n        if (after.R) {\n          after = after.R;\n          while (after.L) after = after.L;\n          after.L = node;\n        } else {\n          after.R = node;\n        }\n        parent = after;\n      } else if (this._) {\n        after = d3_geom_voronoiRedBlackFirst(this._);\n        node.P = null;\n        node.N = after;\n        after.P = after.L = node;\n        parent = after;\n      } else {\n        node.P = node.N = null;\n        this._ = node;\n        parent = null;\n      }\n      node.L = node.R = null;\n      node.U = parent;\n      node.C = true;\n      after = node;\n      while (parent && parent.C) {\n        grandpa = parent.U;\n        if (parent === grandpa.L) {\n          uncle = grandpa.R;\n          if (uncle && uncle.C) {\n            parent.C = uncle.C = false;\n            grandpa.C = true;\n            after = grandpa;\n          } else {\n            if (after === parent.R) {\n              d3_geom_voronoiRedBlackRotateLeft(this, parent);\n              after = parent;\n              parent = after.U;\n            }\n            parent.C = false;\n            grandpa.C = true;\n            d3_geom_voronoiRedBlackRotateRight(this, grandpa);\n          }\n        } else {\n          uncle = grandpa.L;\n          if (uncle && uncle.C) {\n            parent.C = uncle.C = false;\n            grandpa.C = true;\n            after = grandpa;\n          } else {\n            if (after === parent.L) {\n              d3_geom_voronoiRedBlackRotateRight(this, parent);\n              after = parent;\n              parent = after.U;\n            }\n            parent.C = false;\n            grandpa.C = true;\n            d3_geom_voronoiRedBlackRotateLeft(this, grandpa);\n          }\n        }\n        parent = after.U;\n      }\n      this._.C = false;\n    },\n    remove: function(node) {\n      if (node.N) node.N.P = node.P;\n      if (node.P) node.P.N = node.N;\n      node.N = node.P = null;\n      var parent = node.U, sibling, left = node.L, right = node.R, next, red;\n      if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);\n      if (parent) {\n        if (parent.L === node) parent.L = next; else parent.R = next;\n      } else {\n        this._ = next;\n      }\n      if (left && right) {\n        red = next.C;\n        next.C = node.C;\n        next.L = left;\n        left.U = next;\n        if (next !== right) {\n          parent = next.U;\n          next.U = node.U;\n          node = next.R;\n          parent.L = node;\n          next.R = right;\n          right.U = next;\n        } else {\n          next.U = parent;\n          parent = next;\n          node = next.R;\n        }\n      } else {\n        red = node.C;\n        node = next;\n      }\n      if (node) node.U = parent;\n      if (red) return;\n      if (node && node.C) {\n        node.C = false;\n        return;\n      }\n      do {\n        if (node === this._) break;\n        if (node === parent.L) {\n          sibling = parent.R;\n          if (sibling.C) {\n            sibling.C = false;\n            parent.C = true;\n            d3_geom_voronoiRedBlackRotateLeft(this, parent);\n            sibling = parent.R;\n          }\n          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {\n            if (!sibling.R || !sibling.R.C) {\n              sibling.L.C = false;\n              sibling.C = true;\n              d3_geom_voronoiRedBlackRotateRight(this, sibling);\n              sibling = parent.R;\n            }\n            sibling.C = parent.C;\n            parent.C = sibling.R.C = false;\n            d3_geom_voronoiRedBlackRotateLeft(this, parent);\n            node = this._;\n            break;\n          }\n        } else {\n          sibling = parent.L;\n          if (sibling.C) {\n            sibling.C = false;\n            parent.C = true;\n            d3_geom_voronoiRedBlackRotateRight(this, parent);\n            sibling = parent.L;\n          }\n          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {\n            if (!sibling.L || !sibling.L.C) {\n              sibling.R.C = false;\n              sibling.C = true;\n              d3_geom_voronoiRedBlackRotateLeft(this, sibling);\n              sibling = parent.L;\n            }\n            sibling.C = parent.C;\n            parent.C = sibling.L.C = false;\n            d3_geom_voronoiRedBlackRotateRight(this, parent);\n            node = this._;\n            break;\n          }\n        }\n        sibling.C = true;\n        node = parent;\n        parent = parent.U;\n      } while (!node.C);\n      if (node) node.C = false;\n    }\n  };\n  function d3_geom_voronoiRedBlackRotateLeft(tree, node) {\n    var p = node, q = node.R, parent = p.U;\n    if (parent) {\n      if (parent.L === p) parent.L = q; else parent.R = q;\n    } else {\n      tree._ = q;\n    }\n    q.U = parent;\n    p.U = q;\n    p.R = q.L;\n    if (p.R) p.R.U = p;\n    q.L = p;\n  }\n  function d3_geom_voronoiRedBlackRotateRight(tree, node) {\n    var p = node, q = node.L, parent = p.U;\n    if (parent) {\n      if (parent.L === p) parent.L = q; else parent.R = q;\n    } else {\n      tree._ = q;\n    }\n    q.U = parent;\n    p.U = q;\n    p.L = q.R;\n    if (p.L) p.L.U = p;\n    q.R = p;\n  }\n  function d3_geom_voronoiRedBlackFirst(node) {\n    while (node.L) node = node.L;\n    return node;\n  }\n  function d3_geom_voronoi(sites, bbox) {\n    var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;\n    d3_geom_voronoiEdges = [];\n    d3_geom_voronoiCells = new Array(sites.length);\n    d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();\n    d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();\n    while (true) {\n      circle = d3_geom_voronoiFirstCircle;\n      if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {\n        if (site.x !== x0 || site.y !== y0) {\n          d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);\n          d3_geom_voronoiAddBeach(site);\n          x0 = site.x, y0 = site.y;\n        }\n        site = sites.pop();\n      } else if (circle) {\n        d3_geom_voronoiRemoveBeach(circle.arc);\n      } else {\n        break;\n      }\n    }\n    if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);\n    var diagram = {\n      cells: d3_geom_voronoiCells,\n      edges: d3_geom_voronoiEdges\n    };\n    d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;\n    return diagram;\n  }\n  function d3_geom_voronoiVertexOrder(a, b) {\n    return b.y - a.y || b.x - a.x;\n  }\n  d3.geom.voronoi = function(points) {\n    var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;\n    if (points) return voronoi(points);\n    function voronoi(data) {\n      var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];\n      d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {\n        var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {\n          var s = e.start();\n          return [ s.x, s.y ];\n        }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];\n        polygon.point = data[i];\n      });\n      return polygons;\n    }\n    function sites(data) {\n      return data.map(function(d, i) {\n        return {\n          x: Math.round(fx(d, i) / ε) * ε,\n          y: Math.round(fy(d, i) / ε) * ε,\n          i: i\n        };\n      });\n    }\n    voronoi.links = function(data) {\n      return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {\n        return edge.l && edge.r;\n      }).map(function(edge) {\n        return {\n          source: data[edge.l.i],\n          target: data[edge.r.i]\n        };\n      });\n    };\n    voronoi.triangles = function(data) {\n      var triangles = [];\n      d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {\n        var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;\n        while (++j < m) {\n          e0 = e1;\n          s0 = s1;\n          e1 = edges[j].edge;\n          s1 = e1.l === site ? e1.r : e1.l;\n          if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {\n            triangles.push([ data[i], data[s0.i], data[s1.i] ]);\n          }\n        }\n      });\n      return triangles;\n    };\n    voronoi.x = function(_) {\n      return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;\n    };\n    voronoi.y = function(_) {\n      return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;\n    };\n    voronoi.clipExtent = function(_) {\n      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;\n      clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;\n      return voronoi;\n    };\n    voronoi.size = function(_) {\n      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];\n      return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);\n    };\n    return voronoi;\n  };\n  var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];\n  function d3_geom_voronoiTriangleArea(a, b, c) {\n    return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);\n  }\n  d3.geom.delaunay = function(vertices) {\n    return d3.geom.voronoi().triangles(vertices);\n  };\n  d3.geom.quadtree = function(points, x1, y1, x2, y2) {\n    var x = d3_geom_pointX, y = d3_geom_pointY, compat;\n    if (compat = arguments.length) {\n      x = d3_geom_quadtreeCompatX;\n      y = d3_geom_quadtreeCompatY;\n      if (compat === 3) {\n        y2 = y1;\n        x2 = x1;\n        y1 = x1 = 0;\n      }\n      return quadtree(points);\n    }\n    function quadtree(data) {\n      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;\n      if (x1 != null) {\n        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;\n      } else {\n        x2_ = y2_ = -(x1_ = y1_ = Infinity);\n        xs = [], ys = [];\n        n = data.length;\n        if (compat) for (i = 0; i < n; ++i) {\n          d = data[i];\n          if (d.x < x1_) x1_ = d.x;\n          if (d.y < y1_) y1_ = d.y;\n          if (d.x > x2_) x2_ = d.x;\n          if (d.y > y2_) y2_ = d.y;\n          xs.push(d.x);\n          ys.push(d.y);\n        } else for (i = 0; i < n; ++i) {\n          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);\n          if (x_ < x1_) x1_ = x_;\n          if (y_ < y1_) y1_ = y_;\n          if (x_ > x2_) x2_ = x_;\n          if (y_ > y2_) y2_ = y_;\n          xs.push(x_);\n          ys.push(y_);\n        }\n      }\n      var dx = x2_ - x1_, dy = y2_ - y1_;\n      if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;\n      function insert(n, d, x, y, x1, y1, x2, y2) {\n        if (isNaN(x) || isNaN(y)) return;\n        if (n.leaf) {\n          var nx = n.x, ny = n.y;\n          if (nx != null) {\n            if (abs(nx - x) + abs(ny - y) < .01) {\n              insertChild(n, d, x, y, x1, y1, x2, y2);\n            } else {\n              var nPoint = n.point;\n              n.x = n.y = n.point = null;\n              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);\n              insertChild(n, d, x, y, x1, y1, x2, y2);\n            }\n          } else {\n            n.x = x, n.y = y, n.point = d;\n          }\n        } else {\n          insertChild(n, d, x, y, x1, y1, x2, y2);\n        }\n      }\n      function insertChild(n, d, x, y, x1, y1, x2, y2) {\n        var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right;\n        n.leaf = false;\n        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());\n        if (right) x1 = sx; else x2 = sx;\n        if (bottom) y1 = sy; else y2 = sy;\n        insert(n, d, x, y, x1, y1, x2, y2);\n      }\n      var root = d3_geom_quadtreeNode();\n      root.add = function(d) {\n        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);\n      };\n      root.visit = function(f) {\n        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);\n      };\n      i = -1;\n      if (x1 == null) {\n        while (++i < n) {\n          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);\n        }\n        --i;\n      } else data.forEach(root.add);\n      xs = ys = data = d = null;\n      return root;\n    }\n    quadtree.x = function(_) {\n      return arguments.length ? (x = _, quadtree) : x;\n    };\n    quadtree.y = function(_) {\n      return arguments.length ? (y = _, quadtree) : y;\n    };\n    quadtree.extent = function(_) {\n      if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];\n      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], \n      y2 = +_[1][1];\n      return quadtree;\n    };\n    quadtree.size = function(_) {\n      if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];\n      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];\n      return quadtree;\n    };\n    return quadtree;\n  };\n  function d3_geom_quadtreeCompatX(d) {\n    return d.x;\n  }\n  function d3_geom_quadtreeCompatY(d) {\n    return d.y;\n  }\n  function d3_geom_quadtreeNode() {\n    return {\n      leaf: true,\n      nodes: [],\n      point: null,\n      x: null,\n      y: null\n    };\n  }\n  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {\n    if (!f(node, x1, y1, x2, y2)) {\n      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;\n      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);\n      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);\n      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);\n      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);\n    }\n  }\n  d3.interpolateRgb = d3_interpolateRgb;\n  function d3_interpolateRgb(a, b) {\n    a = d3.rgb(a);\n    b = d3.rgb(b);\n    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;\n    return function(t) {\n      return \"#\" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));\n    };\n  }\n  d3.interpolateObject = d3_interpolateObject;\n  function d3_interpolateObject(a, b) {\n    var i = {}, c = {}, k;\n    for (k in a) {\n      if (k in b) {\n        i[k] = d3_interpolate(a[k], b[k]);\n      } else {\n        c[k] = a[k];\n      }\n    }\n    for (k in b) {\n      if (!(k in a)) {\n        c[k] = b[k];\n      }\n    }\n    return function(t) {\n      for (k in i) c[k] = i[k](t);\n      return c;\n    };\n  }\n  d3.interpolateNumber = d3_interpolateNumber;\n  function d3_interpolateNumber(a, b) {\n    a = +a, b = +b;\n    return function(t) {\n      return a * (1 - t) + b * t;\n    };\n  }\n  d3.interpolateString = d3_interpolateString;\n  function d3_interpolateString(a, b) {\n    var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];\n    a = a + \"\", b = b + \"\";\n    while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {\n      if ((bs = bm.index) > bi) {\n        bs = b.slice(bi, bs);\n        if (s[i]) s[i] += bs; else s[++i] = bs;\n      }\n      if ((am = am[0]) === (bm = bm[0])) {\n        if (s[i]) s[i] += bm; else s[++i] = bm;\n      } else {\n        s[++i] = null;\n        q.push({\n          i: i,\n          x: d3_interpolateNumber(am, bm)\n        });\n      }\n      bi = d3_interpolate_numberB.lastIndex;\n    }\n    if (bi < b.length) {\n      bs = b.slice(bi);\n      if (s[i]) s[i] += bs; else s[++i] = bs;\n    }\n    return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {\n      return b(t) + \"\";\n    }) : function() {\n      return b;\n    } : (b = q.length, function(t) {\n      for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);\n      return s.join(\"\");\n    });\n  }\n  var d3_interpolate_numberA = /[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, \"g\");\n  d3.interpolate = d3_interpolate;\n  function d3_interpolate(a, b) {\n    var i = d3.interpolators.length, f;\n    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;\n    return f;\n  }\n  d3.interpolators = [ function(a, b) {\n    var t = typeof b;\n    return (t === \"string\" ? d3_rgb_names.has(b) || /^(#|rgb\\(|hsl\\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === \"object\" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);\n  } ];\n  d3.interpolateArray = d3_interpolateArray;\n  function d3_interpolateArray(a, b) {\n    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;\n    for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));\n    for (;i < na; ++i) c[i] = a[i];\n    for (;i < nb; ++i) c[i] = b[i];\n    return function(t) {\n      for (i = 0; i < n0; ++i) c[i] = x[i](t);\n      return c;\n    };\n  }\n  var d3_ease_default = function() {\n    return d3_identity;\n  };\n  var d3_ease = d3.map({\n    linear: d3_ease_default,\n    poly: d3_ease_poly,\n    quad: function() {\n      return d3_ease_quad;\n    },\n    cubic: function() {\n      return d3_ease_cubic;\n    },\n    sin: function() {\n      return d3_ease_sin;\n    },\n    exp: function() {\n      return d3_ease_exp;\n    },\n    circle: function() {\n      return d3_ease_circle;\n    },\n    elastic: d3_ease_elastic,\n    back: d3_ease_back,\n    bounce: function() {\n      return d3_ease_bounce;\n    }\n  });\n  var d3_ease_mode = d3.map({\n    \"in\": d3_identity,\n    out: d3_ease_reverse,\n    \"in-out\": d3_ease_reflect,\n    \"out-in\": function(f) {\n      return d3_ease_reflect(d3_ease_reverse(f));\n    }\n  });\n  d3.ease = function(name) {\n    var i = name.indexOf(\"-\"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : \"in\";\n    t = d3_ease.get(t) || d3_ease_default;\n    m = d3_ease_mode.get(m) || d3_identity;\n    return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));\n  };\n  function d3_ease_clamp(f) {\n    return function(t) {\n      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);\n    };\n  }\n  function d3_ease_reverse(f) {\n    return function(t) {\n      return 1 - f(1 - t);\n    };\n  }\n  function d3_ease_reflect(f) {\n    return function(t) {\n      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));\n    };\n  }\n  function d3_ease_quad(t) {\n    return t * t;\n  }\n  function d3_ease_cubic(t) {\n    return t * t * t;\n  }\n  function d3_ease_cubicInOut(t) {\n    if (t <= 0) return 0;\n    if (t >= 1) return 1;\n    var t2 = t * t, t3 = t2 * t;\n    return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);\n  }\n  function d3_ease_poly(e) {\n    return function(t) {\n      return Math.pow(t, e);\n    };\n  }\n  function d3_ease_sin(t) {\n    return 1 - Math.cos(t * halfπ);\n  }\n  function d3_ease_exp(t) {\n    return Math.pow(2, 10 * (t - 1));\n  }\n  function d3_ease_circle(t) {\n    return 1 - Math.sqrt(1 - t * t);\n  }\n  function d3_ease_elastic(a, p) {\n    var s;\n    if (arguments.length < 2) p = .45;\n    if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;\n    return function(t) {\n      return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);\n    };\n  }\n  function d3_ease_back(s) {\n    if (!s) s = 1.70158;\n    return function(t) {\n      return t * t * ((s + 1) * t - s);\n    };\n  }\n  function d3_ease_bounce(t) {\n    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;\n  }\n  d3.interpolateHcl = d3_interpolateHcl;\n  function d3_interpolateHcl(a, b) {\n    a = d3.hcl(a);\n    b = d3.hcl(b);\n    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;\n    if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;\n    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;\n    return function(t) {\n      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + \"\";\n    };\n  }\n  d3.interpolateHsl = d3_interpolateHsl;\n  function d3_interpolateHsl(a, b) {\n    a = d3.hsl(a);\n    b = d3.hsl(b);\n    var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;\n    if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;\n    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;\n    return function(t) {\n      return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + \"\";\n    };\n  }\n  d3.interpolateLab = d3_interpolateLab;\n  function d3_interpolateLab(a, b) {\n    a = d3.lab(a);\n    b = d3.lab(b);\n    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;\n    return function(t) {\n      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + \"\";\n    };\n  }\n  d3.interpolateRound = d3_interpolateRound;\n  function d3_interpolateRound(a, b) {\n    b -= a;\n    return function(t) {\n      return Math.round(a + b * t);\n    };\n  }\n  d3.transform = function(string) {\n    var g = d3_document.createElementNS(d3.ns.prefix.svg, \"g\");\n    return (d3.transform = function(string) {\n      if (string != null) {\n        g.setAttribute(\"transform\", string);\n        var t = g.transform.baseVal.consolidate();\n      }\n      return new d3_transform(t ? t.matrix : d3_transformIdentity);\n    })(string);\n  };\n  function d3_transform(m) {\n    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;\n    if (r0[0] * r1[1] < r1[0] * r0[1]) {\n      r0[0] *= -1;\n      r0[1] *= -1;\n      kx *= -1;\n      kz *= -1;\n    }\n    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;\n    this.translate = [ m.e, m.f ];\n    this.scale = [ kx, ky ];\n    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;\n  }\n  d3_transform.prototype.toString = function() {\n    return \"translate(\" + this.translate + \")rotate(\" + this.rotate + \")skewX(\" + this.skew + \")scale(\" + this.scale + \")\";\n  };\n  function d3_transformDot(a, b) {\n    return a[0] * b[0] + a[1] * b[1];\n  }\n  function d3_transformNormalize(a) {\n    var k = Math.sqrt(d3_transformDot(a, a));\n    if (k) {\n      a[0] /= k;\n      a[1] /= k;\n    }\n    return k;\n  }\n  function d3_transformCombine(a, b, k) {\n    a[0] += k * b[0];\n    a[1] += k * b[1];\n    return a;\n  }\n  var d3_transformIdentity = {\n    a: 1,\n    b: 0,\n    c: 0,\n    d: 1,\n    e: 0,\n    f: 0\n  };\n  d3.interpolateTransform = d3_interpolateTransform;\n  function d3_interpolateTransform(a, b) {\n    var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;\n    if (ta[0] != tb[0] || ta[1] != tb[1]) {\n      s.push(\"translate(\", null, \",\", null, \")\");\n      q.push({\n        i: 1,\n        x: d3_interpolateNumber(ta[0], tb[0])\n      }, {\n        i: 3,\n        x: d3_interpolateNumber(ta[1], tb[1])\n      });\n    } else if (tb[0] || tb[1]) {\n      s.push(\"translate(\" + tb + \")\");\n    } else {\n      s.push(\"\");\n    }\n    if (ra != rb) {\n      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;\n      q.push({\n        i: s.push(s.pop() + \"rotate(\", null, \")\") - 2,\n        x: d3_interpolateNumber(ra, rb)\n      });\n    } else if (rb) {\n      s.push(s.pop() + \"rotate(\" + rb + \")\");\n    }\n    if (wa != wb) {\n      q.push({\n        i: s.push(s.pop() + \"skewX(\", null, \")\") - 2,\n        x: d3_interpolateNumber(wa, wb)\n      });\n    } else if (wb) {\n      s.push(s.pop() + \"skewX(\" + wb + \")\");\n    }\n    if (ka[0] != kb[0] || ka[1] != kb[1]) {\n      n = s.push(s.pop() + \"scale(\", null, \",\", null, \")\");\n      q.push({\n        i: n - 4,\n        x: d3_interpolateNumber(ka[0], kb[0])\n      }, {\n        i: n - 2,\n        x: d3_interpolateNumber(ka[1], kb[1])\n      });\n    } else if (kb[0] != 1 || kb[1] != 1) {\n      s.push(s.pop() + \"scale(\" + kb + \")\");\n    }\n    n = q.length;\n    return function(t) {\n      var i = -1, o;\n      while (++i < n) s[(o = q[i]).i] = o.x(t);\n      return s.join(\"\");\n    };\n  }\n  function d3_uninterpolateNumber(a, b) {\n    b = (b -= a = +a) || 1 / b;\n    return function(x) {\n      return (x - a) / b;\n    };\n  }\n  function d3_uninterpolateClamp(a, b) {\n    b = (b -= a = +a) || 1 / b;\n    return function(x) {\n      return Math.max(0, Math.min(1, (x - a) / b));\n    };\n  }\n  d3.layout = {};\n  d3.layout.bundle = function() {\n    return function(links) {\n      var paths = [], i = -1, n = links.length;\n      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));\n      return paths;\n    };\n  };\n  function d3_layout_bundlePath(link) {\n    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];\n    while (start !== lca) {\n      start = start.parent;\n      points.push(start);\n    }\n    var k = points.length;\n    while (end !== lca) {\n      points.splice(k, 0, end);\n      end = end.parent;\n    }\n    return points;\n  }\n  function d3_layout_bundleAncestors(node) {\n    var ancestors = [], parent = node.parent;\n    while (parent != null) {\n      ancestors.push(node);\n      node = parent;\n      parent = parent.parent;\n    }\n    ancestors.push(node);\n    return ancestors;\n  }\n  function d3_layout_bundleLeastCommonAncestor(a, b) {\n    if (a === b) return a;\n    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;\n    while (aNode === bNode) {\n      sharedNode = aNode;\n      aNode = aNodes.pop();\n      bNode = bNodes.pop();\n    }\n    return sharedNode;\n  }\n  d3.layout.chord = function() {\n    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;\n    function relayout() {\n      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;\n      chords = [];\n      groups = [];\n      k = 0, i = -1;\n      while (++i < n) {\n        x = 0, j = -1;\n        while (++j < n) {\n          x += matrix[i][j];\n        }\n        groupSums.push(x);\n        subgroupIndex.push(d3.range(n));\n        k += x;\n      }\n      if (sortGroups) {\n        groupIndex.sort(function(a, b) {\n          return sortGroups(groupSums[a], groupSums[b]);\n        });\n      }\n      if (sortSubgroups) {\n        subgroupIndex.forEach(function(d, i) {\n          d.sort(function(a, b) {\n            return sortSubgroups(matrix[i][a], matrix[i][b]);\n          });\n        });\n      }\n      k = (τ - padding * n) / k;\n      x = 0, i = -1;\n      while (++i < n) {\n        x0 = x, j = -1;\n        while (++j < n) {\n          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;\n          subgroups[di + \"-\" + dj] = {\n            index: di,\n            subindex: dj,\n            startAngle: a0,\n            endAngle: a1,\n            value: v\n          };\n        }\n        groups[di] = {\n          index: di,\n          startAngle: x0,\n          endAngle: x,\n          value: (x - x0) / k\n        };\n        x += padding;\n      }\n      i = -1;\n      while (++i < n) {\n        j = i - 1;\n        while (++j < n) {\n          var source = subgroups[i + \"-\" + j], target = subgroups[j + \"-\" + i];\n          if (source.value || target.value) {\n            chords.push(source.value < target.value ? {\n              source: target,\n              target: source\n            } : {\n              source: source,\n              target: target\n            });\n          }\n        }\n      }\n      if (sortChords) resort();\n    }\n    function resort() {\n      chords.sort(function(a, b) {\n        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);\n      });\n    }\n    chord.matrix = function(x) {\n      if (!arguments.length) return matrix;\n      n = (matrix = x) && matrix.length;\n      chords = groups = null;\n      return chord;\n    };\n    chord.padding = function(x) {\n      if (!arguments.length) return padding;\n      padding = x;\n      chords = groups = null;\n      return chord;\n    };\n    chord.sortGroups = function(x) {\n      if (!arguments.length) return sortGroups;\n      sortGroups = x;\n      chords = groups = null;\n      return chord;\n    };\n    chord.sortSubgroups = function(x) {\n      if (!arguments.length) return sortSubgroups;\n      sortSubgroups = x;\n      chords = null;\n      return chord;\n    };\n    chord.sortChords = function(x) {\n      if (!arguments.length) return sortChords;\n      sortChords = x;\n      if (chords) resort();\n      return chord;\n    };\n    chord.chords = function() {\n      if (!chords) relayout();\n      return chords;\n    };\n    chord.groups = function() {\n      if (!groups) relayout();\n      return groups;\n    };\n    return chord;\n  };\n  d3.layout.force = function() {\n    var force = {}, event = d3.dispatch(\"start\", \"tick\", \"end\"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;\n    function repulse(node) {\n      return function(quad, x1, _, x2) {\n        if (quad.point !== node) {\n          var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;\n          if (dw * dw / theta2 < dn) {\n            if (dn < chargeDistance2) {\n              var k = quad.charge / dn;\n              node.px -= dx * k;\n              node.py -= dy * k;\n            }\n            return true;\n          }\n          if (quad.point && dn && dn < chargeDistance2) {\n            var k = quad.pointCharge / dn;\n            node.px -= dx * k;\n            node.py -= dy * k;\n          }\n        }\n        return !quad.charge;\n      };\n    }\n    force.tick = function() {\n      if ((alpha *= .99) < .005) {\n        event.end({\n          type: \"end\",\n          alpha: alpha = 0\n        });\n        return true;\n      }\n      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;\n      for (i = 0; i < m; ++i) {\n        o = links[i];\n        s = o.source;\n        t = o.target;\n        x = t.x - s.x;\n        y = t.y - s.y;\n        if (l = x * x + y * y) {\n          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;\n          x *= l;\n          y *= l;\n          t.x -= x * (k = s.weight / (t.weight + s.weight));\n          t.y -= y * k;\n          s.x += x * (k = 1 - k);\n          s.y += y * k;\n        }\n      }\n      if (k = alpha * gravity) {\n        x = size[0] / 2;\n        y = size[1] / 2;\n        i = -1;\n        if (k) while (++i < n) {\n          o = nodes[i];\n          o.x += (x - o.x) * k;\n          o.y += (y - o.y) * k;\n        }\n      }\n      if (charge) {\n        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);\n        i = -1;\n        while (++i < n) {\n          if (!(o = nodes[i]).fixed) {\n            q.visit(repulse(o));\n          }\n        }\n      }\n      i = -1;\n      while (++i < n) {\n        o = nodes[i];\n        if (o.fixed) {\n          o.x = o.px;\n          o.y = o.py;\n        } else {\n          o.x -= (o.px - (o.px = o.x)) * friction;\n          o.y -= (o.py - (o.py = o.y)) * friction;\n        }\n      }\n      event.tick({\n        type: \"tick\",\n        alpha: alpha\n      });\n    };\n    force.nodes = function(x) {\n      if (!arguments.length) return nodes;\n      nodes = x;\n      return force;\n    };\n    force.links = function(x) {\n      if (!arguments.length) return links;\n      links = x;\n      return force;\n    };\n    force.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return force;\n    };\n    force.linkDistance = function(x) {\n      if (!arguments.length) return linkDistance;\n      linkDistance = typeof x === \"function\" ? x : +x;\n      return force;\n    };\n    force.distance = force.linkDistance;\n    force.linkStrength = function(x) {\n      if (!arguments.length) return linkStrength;\n      linkStrength = typeof x === \"function\" ? x : +x;\n      return force;\n    };\n    force.friction = function(x) {\n      if (!arguments.length) return friction;\n      friction = +x;\n      return force;\n    };\n    force.charge = function(x) {\n      if (!arguments.length) return charge;\n      charge = typeof x === \"function\" ? x : +x;\n      return force;\n    };\n    force.chargeDistance = function(x) {\n      if (!arguments.length) return Math.sqrt(chargeDistance2);\n      chargeDistance2 = x * x;\n      return force;\n    };\n    force.gravity = function(x) {\n      if (!arguments.length) return gravity;\n      gravity = +x;\n      return force;\n    };\n    force.theta = function(x) {\n      if (!arguments.length) return Math.sqrt(theta2);\n      theta2 = x * x;\n      return force;\n    };\n    force.alpha = function(x) {\n      if (!arguments.length) return alpha;\n      x = +x;\n      if (alpha) {\n        if (x > 0) alpha = x; else alpha = 0;\n      } else if (x > 0) {\n        event.start({\n          type: \"start\",\n          alpha: alpha = x\n        });\n        d3.timer(force.tick);\n      }\n      return force;\n    };\n    force.start = function() {\n      var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;\n      for (i = 0; i < n; ++i) {\n        (o = nodes[i]).index = i;\n        o.weight = 0;\n      }\n      for (i = 0; i < m; ++i) {\n        o = links[i];\n        if (typeof o.source == \"number\") o.source = nodes[o.source];\n        if (typeof o.target == \"number\") o.target = nodes[o.target];\n        ++o.source.weight;\n        ++o.target.weight;\n      }\n      for (i = 0; i < n; ++i) {\n        o = nodes[i];\n        if (isNaN(o.x)) o.x = position(\"x\", w);\n        if (isNaN(o.y)) o.y = position(\"y\", h);\n        if (isNaN(o.px)) o.px = o.x;\n        if (isNaN(o.py)) o.py = o.y;\n      }\n      distances = [];\n      if (typeof linkDistance === \"function\") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;\n      strengths = [];\n      if (typeof linkStrength === \"function\") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;\n      charges = [];\n      if (typeof charge === \"function\") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;\n      function position(dimension, size) {\n        if (!neighbors) {\n          neighbors = new Array(n);\n          for (j = 0; j < n; ++j) {\n            neighbors[j] = [];\n          }\n          for (j = 0; j < m; ++j) {\n            var o = links[j];\n            neighbors[o.source.index].push(o.target);\n            neighbors[o.target.index].push(o.source);\n          }\n        }\n        var candidates = neighbors[i], j = -1, m = candidates.length, x;\n        while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x;\n        return Math.random() * size;\n      }\n      return force.resume();\n    };\n    force.resume = function() {\n      return force.alpha(.1);\n    };\n    force.stop = function() {\n      return force.alpha(0);\n    };\n    force.drag = function() {\n      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on(\"dragstart.force\", d3_layout_forceDragstart).on(\"drag.force\", dragmove).on(\"dragend.force\", d3_layout_forceDragend);\n      if (!arguments.length) return drag;\n      this.on(\"mouseover.force\", d3_layout_forceMouseover).on(\"mouseout.force\", d3_layout_forceMouseout).call(drag);\n    };\n    function dragmove(d) {\n      d.px = d3.event.x, d.py = d3.event.y;\n      force.resume();\n    }\n    return d3.rebind(force, event, \"on\");\n  };\n  function d3_layout_forceDragstart(d) {\n    d.fixed |= 2;\n  }\n  function d3_layout_forceDragend(d) {\n    d.fixed &= ~6;\n  }\n  function d3_layout_forceMouseover(d) {\n    d.fixed |= 4;\n    d.px = d.x, d.py = d.y;\n  }\n  function d3_layout_forceMouseout(d) {\n    d.fixed &= ~4;\n  }\n  function d3_layout_forceAccumulate(quad, alpha, charges) {\n    var cx = 0, cy = 0;\n    quad.charge = 0;\n    if (!quad.leaf) {\n      var nodes = quad.nodes, n = nodes.length, i = -1, c;\n      while (++i < n) {\n        c = nodes[i];\n        if (c == null) continue;\n        d3_layout_forceAccumulate(c, alpha, charges);\n        quad.charge += c.charge;\n        cx += c.charge * c.cx;\n        cy += c.charge * c.cy;\n      }\n    }\n    if (quad.point) {\n      if (!quad.leaf) {\n        quad.point.x += Math.random() - .5;\n        quad.point.y += Math.random() - .5;\n      }\n      var k = alpha * charges[quad.point.index];\n      quad.charge += quad.pointCharge = k;\n      cx += k * quad.point.x;\n      cy += k * quad.point.y;\n    }\n    quad.cx = cx / quad.charge;\n    quad.cy = cy / quad.charge;\n  }\n  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;\n  d3.layout.hierarchy = function() {\n    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;\n    function hierarchy(root) {\n      var stack = [ root ], nodes = [], node;\n      root.depth = 0;\n      while ((node = stack.pop()) != null) {\n        nodes.push(node);\n        if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {\n          var n, childs, child;\n          while (--n >= 0) {\n            stack.push(child = childs[n]);\n            child.parent = node;\n            child.depth = node.depth + 1;\n          }\n          if (value) node.value = 0;\n          node.children = childs;\n        } else {\n          if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;\n          delete node.children;\n        }\n      }\n      d3_layout_hierarchyVisitAfter(root, function(node) {\n        var childs, parent;\n        if (sort && (childs = node.children)) childs.sort(sort);\n        if (value && (parent = node.parent)) parent.value += node.value;\n      });\n      return nodes;\n    }\n    hierarchy.sort = function(x) {\n      if (!arguments.length) return sort;\n      sort = x;\n      return hierarchy;\n    };\n    hierarchy.children = function(x) {\n      if (!arguments.length) return children;\n      children = x;\n      return hierarchy;\n    };\n    hierarchy.value = function(x) {\n      if (!arguments.length) return value;\n      value = x;\n      return hierarchy;\n    };\n    hierarchy.revalue = function(root) {\n      if (value) {\n        d3_layout_hierarchyVisitBefore(root, function(node) {\n          if (node.children) node.value = 0;\n        });\n        d3_layout_hierarchyVisitAfter(root, function(node) {\n          var parent;\n          if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;\n          if (parent = node.parent) parent.value += node.value;\n        });\n      }\n      return root;\n    };\n    return hierarchy;\n  };\n  function d3_layout_hierarchyRebind(object, hierarchy) {\n    d3.rebind(object, hierarchy, \"sort\", \"children\", \"value\");\n    object.nodes = object;\n    object.links = d3_layout_hierarchyLinks;\n    return object;\n  }\n  function d3_layout_hierarchyVisitBefore(node, callback) {\n    var nodes = [ node ];\n    while ((node = nodes.pop()) != null) {\n      callback(node);\n      if ((children = node.children) && (n = children.length)) {\n        var n, children;\n        while (--n >= 0) nodes.push(children[n]);\n      }\n    }\n  }\n  function d3_layout_hierarchyVisitAfter(node, callback) {\n    var nodes = [ node ], nodes2 = [];\n    while ((node = nodes.pop()) != null) {\n      nodes2.push(node);\n      if ((children = node.children) && (n = children.length)) {\n        var i = -1, n, children;\n        while (++i < n) nodes.push(children[i]);\n      }\n    }\n    while ((node = nodes2.pop()) != null) {\n      callback(node);\n    }\n  }\n  function d3_layout_hierarchyChildren(d) {\n    return d.children;\n  }\n  function d3_layout_hierarchyValue(d) {\n    return d.value;\n  }\n  function d3_layout_hierarchySort(a, b) {\n    return b.value - a.value;\n  }\n  function d3_layout_hierarchyLinks(nodes) {\n    return d3.merge(nodes.map(function(parent) {\n      return (parent.children || []).map(function(child) {\n        return {\n          source: parent,\n          target: child\n        };\n      });\n    }));\n  }\n  d3.layout.partition = function() {\n    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];\n    function position(node, x, dx, dy) {\n      var children = node.children;\n      node.x = x;\n      node.y = node.depth * dy;\n      node.dx = dx;\n      node.dy = dy;\n      if (children && (n = children.length)) {\n        var i = -1, n, c, d;\n        dx = node.value ? dx / node.value : 0;\n        while (++i < n) {\n          position(c = children[i], x, d = c.value * dx, dy);\n          x += d;\n        }\n      }\n    }\n    function depth(node) {\n      var children = node.children, d = 0;\n      if (children && (n = children.length)) {\n        var i = -1, n;\n        while (++i < n) d = Math.max(d, depth(children[i]));\n      }\n      return 1 + d;\n    }\n    function partition(d, i) {\n      var nodes = hierarchy.call(this, d, i);\n      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));\n      return nodes;\n    }\n    partition.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return partition;\n    };\n    return d3_layout_hierarchyRebind(partition, hierarchy);\n  };\n  d3.layout.pie = function() {\n    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ;\n    function pie(data) {\n      var values = data.map(function(d, i) {\n        return +value.call(pie, d, i);\n      });\n      var a = +(typeof startAngle === \"function\" ? startAngle.apply(this, arguments) : startAngle);\n      var k = ((typeof endAngle === \"function\" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);\n      var index = d3.range(data.length);\n      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {\n        return values[j] - values[i];\n      } : function(i, j) {\n        return sort(data[i], data[j]);\n      });\n      var arcs = [];\n      index.forEach(function(i) {\n        var d;\n        arcs[i] = {\n          data: data[i],\n          value: d = values[i],\n          startAngle: a,\n          endAngle: a += d * k\n        };\n      });\n      return arcs;\n    }\n    pie.value = function(x) {\n      if (!arguments.length) return value;\n      value = x;\n      return pie;\n    };\n    pie.sort = function(x) {\n      if (!arguments.length) return sort;\n      sort = x;\n      return pie;\n    };\n    pie.startAngle = function(x) {\n      if (!arguments.length) return startAngle;\n      startAngle = x;\n      return pie;\n    };\n    pie.endAngle = function(x) {\n      if (!arguments.length) return endAngle;\n      endAngle = x;\n      return pie;\n    };\n    return pie;\n  };\n  var d3_layout_pieSortByValue = {};\n  d3.layout.stack = function() {\n    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;\n    function stack(data, index) {\n      if (!(n = data.length)) return data;\n      var series = data.map(function(d, i) {\n        return values.call(stack, d, i);\n      });\n      var points = series.map(function(d) {\n        return d.map(function(v, i) {\n          return [ x.call(stack, v, i), y.call(stack, v, i) ];\n        });\n      });\n      var orders = order.call(stack, points, index);\n      series = d3.permute(series, orders);\n      points = d3.permute(points, orders);\n      var offsets = offset.call(stack, points, index);\n      var m = series[0].length, n, i, j, o;\n      for (j = 0; j < m; ++j) {\n        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);\n        for (i = 1; i < n; ++i) {\n          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);\n        }\n      }\n      return data;\n    }\n    stack.values = function(x) {\n      if (!arguments.length) return values;\n      values = x;\n      return stack;\n    };\n    stack.order = function(x) {\n      if (!arguments.length) return order;\n      order = typeof x === \"function\" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;\n      return stack;\n    };\n    stack.offset = function(x) {\n      if (!arguments.length) return offset;\n      offset = typeof x === \"function\" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;\n      return stack;\n    };\n    stack.x = function(z) {\n      if (!arguments.length) return x;\n      x = z;\n      return stack;\n    };\n    stack.y = function(z) {\n      if (!arguments.length) return y;\n      y = z;\n      return stack;\n    };\n    stack.out = function(z) {\n      if (!arguments.length) return out;\n      out = z;\n      return stack;\n    };\n    return stack;\n  };\n  function d3_layout_stackX(d) {\n    return d.x;\n  }\n  function d3_layout_stackY(d) {\n    return d.y;\n  }\n  function d3_layout_stackOut(d, y0, y) {\n    d.y0 = y0;\n    d.y = y;\n  }\n  var d3_layout_stackOrders = d3.map({\n    \"inside-out\": function(data) {\n      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {\n        return max[a] - max[b];\n      }), top = 0, bottom = 0, tops = [], bottoms = [];\n      for (i = 0; i < n; ++i) {\n        j = index[i];\n        if (top < bottom) {\n          top += sums[j];\n          tops.push(j);\n        } else {\n          bottom += sums[j];\n          bottoms.push(j);\n        }\n      }\n      return bottoms.reverse().concat(tops);\n    },\n    reverse: function(data) {\n      return d3.range(data.length).reverse();\n    },\n    \"default\": d3_layout_stackOrderDefault\n  });\n  var d3_layout_stackOffsets = d3.map({\n    silhouette: function(data) {\n      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];\n      for (j = 0; j < m; ++j) {\n        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];\n        if (o > max) max = o;\n        sums.push(o);\n      }\n      for (j = 0; j < m; ++j) {\n        y0[j] = (max - sums[j]) / 2;\n      }\n      return y0;\n    },\n    wiggle: function(data) {\n      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];\n      y0[0] = o = o0 = 0;\n      for (j = 1; j < m; ++j) {\n        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];\n        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {\n          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {\n            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;\n          }\n          s2 += s3 * data[i][j][1];\n        }\n        y0[j] = o -= s1 ? s2 / s1 * dx : 0;\n        if (o < o0) o0 = o;\n      }\n      for (j = 0; j < m; ++j) y0[j] -= o0;\n      return y0;\n    },\n    expand: function(data) {\n      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];\n      for (j = 0; j < m; ++j) {\n        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];\n        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;\n      }\n      for (j = 0; j < m; ++j) y0[j] = 0;\n      return y0;\n    },\n    zero: d3_layout_stackOffsetZero\n  });\n  function d3_layout_stackOrderDefault(data) {\n    return d3.range(data.length);\n  }\n  function d3_layout_stackOffsetZero(data) {\n    var j = -1, m = data[0].length, y0 = [];\n    while (++j < m) y0[j] = 0;\n    return y0;\n  }\n  function d3_layout_stackMaxIndex(array) {\n    var i = 1, j = 0, v = array[0][1], k, n = array.length;\n    for (;i < n; ++i) {\n      if ((k = array[i][1]) > v) {\n        j = i;\n        v = k;\n      }\n    }\n    return j;\n  }\n  function d3_layout_stackReduceSum(d) {\n    return d.reduce(d3_layout_stackSum, 0);\n  }\n  function d3_layout_stackSum(p, d) {\n    return p + d[1];\n  }\n  d3.layout.histogram = function() {\n    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;\n    function histogram(data, i) {\n      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;\n      while (++i < m) {\n        bin = bins[i] = [];\n        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);\n        bin.y = 0;\n      }\n      if (m > 0) {\n        i = -1;\n        while (++i < n) {\n          x = values[i];\n          if (x >= range[0] && x <= range[1]) {\n            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];\n            bin.y += k;\n            bin.push(data[i]);\n          }\n        }\n      }\n      return bins;\n    }\n    histogram.value = function(x) {\n      if (!arguments.length) return valuer;\n      valuer = x;\n      return histogram;\n    };\n    histogram.range = function(x) {\n      if (!arguments.length) return ranger;\n      ranger = d3_functor(x);\n      return histogram;\n    };\n    histogram.bins = function(x) {\n      if (!arguments.length) return binner;\n      binner = typeof x === \"number\" ? function(range) {\n        return d3_layout_histogramBinFixed(range, x);\n      } : d3_functor(x);\n      return histogram;\n    };\n    histogram.frequency = function(x) {\n      if (!arguments.length) return frequency;\n      frequency = !!x;\n      return histogram;\n    };\n    return histogram;\n  };\n  function d3_layout_histogramBinSturges(range, values) {\n    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));\n  }\n  function d3_layout_histogramBinFixed(range, n) {\n    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];\n    while (++x <= n) f[x] = m * x + b;\n    return f;\n  }\n  function d3_layout_histogramRange(values) {\n    return [ d3.min(values), d3.max(values) ];\n  }\n  d3.layout.pack = function() {\n    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;\n    function pack(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === \"function\" ? radius : function() {\n        return radius;\n      };\n      root.x = root.y = 0;\n      d3_layout_hierarchyVisitAfter(root, function(d) {\n        d.r = +r(d.value);\n      });\n      d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);\n      if (padding) {\n        var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;\n        d3_layout_hierarchyVisitAfter(root, function(d) {\n          d.r += dr;\n        });\n        d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);\n        d3_layout_hierarchyVisitAfter(root, function(d) {\n          d.r -= dr;\n        });\n      }\n      d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));\n      return nodes;\n    }\n    pack.size = function(_) {\n      if (!arguments.length) return size;\n      size = _;\n      return pack;\n    };\n    pack.radius = function(_) {\n      if (!arguments.length) return radius;\n      radius = _ == null || typeof _ === \"function\" ? _ : +_;\n      return pack;\n    };\n    pack.padding = function(_) {\n      if (!arguments.length) return padding;\n      padding = +_;\n      return pack;\n    };\n    return d3_layout_hierarchyRebind(pack, hierarchy);\n  };\n  function d3_layout_packSort(a, b) {\n    return a.value - b.value;\n  }\n  function d3_layout_packInsert(a, b) {\n    var c = a._pack_next;\n    a._pack_next = b;\n    b._pack_prev = a;\n    b._pack_next = c;\n    c._pack_prev = b;\n  }\n  function d3_layout_packSplice(a, b) {\n    a._pack_next = b;\n    b._pack_prev = a;\n  }\n  function d3_layout_packIntersects(a, b) {\n    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;\n    return .999 * dr * dr > dx * dx + dy * dy;\n  }\n  function d3_layout_packSiblings(node) {\n    if (!(nodes = node.children) || !(n = nodes.length)) return;\n    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;\n    function bound(node) {\n      xMin = Math.min(node.x - node.r, xMin);\n      xMax = Math.max(node.x + node.r, xMax);\n      yMin = Math.min(node.y - node.r, yMin);\n      yMax = Math.max(node.y + node.r, yMax);\n    }\n    nodes.forEach(d3_layout_packLink);\n    a = nodes[0];\n    a.x = -a.r;\n    a.y = 0;\n    bound(a);\n    if (n > 1) {\n      b = nodes[1];\n      b.x = b.r;\n      b.y = 0;\n      bound(b);\n      if (n > 2) {\n        c = nodes[2];\n        d3_layout_packPlace(a, b, c);\n        bound(c);\n        d3_layout_packInsert(a, c);\n        a._pack_prev = c;\n        d3_layout_packInsert(c, b);\n        b = a._pack_next;\n        for (i = 3; i < n; i++) {\n          d3_layout_packPlace(a, b, c = nodes[i]);\n          var isect = 0, s1 = 1, s2 = 1;\n          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {\n            if (d3_layout_packIntersects(j, c)) {\n              isect = 1;\n              break;\n            }\n          }\n          if (isect == 1) {\n            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {\n              if (d3_layout_packIntersects(k, c)) {\n                break;\n              }\n            }\n          }\n          if (isect) {\n            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);\n            i--;\n          } else {\n            d3_layout_packInsert(a, c);\n            b = c;\n            bound(c);\n          }\n        }\n      }\n    }\n    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;\n    for (i = 0; i < n; i++) {\n      c = nodes[i];\n      c.x -= cx;\n      c.y -= cy;\n      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));\n    }\n    node.r = cr;\n    nodes.forEach(d3_layout_packUnlink);\n  }\n  function d3_layout_packLink(node) {\n    node._pack_next = node._pack_prev = node;\n  }\n  function d3_layout_packUnlink(node) {\n    delete node._pack_next;\n    delete node._pack_prev;\n  }\n  function d3_layout_packTransform(node, x, y, k) {\n    var children = node.children;\n    node.x = x += k * node.x;\n    node.y = y += k * node.y;\n    node.r *= k;\n    if (children) {\n      var i = -1, n = children.length;\n      while (++i < n) d3_layout_packTransform(children[i], x, y, k);\n    }\n  }\n  function d3_layout_packPlace(a, b, c) {\n    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;\n    if (db && (dx || dy)) {\n      var da = b.r + c.r, dc = dx * dx + dy * dy;\n      da *= da;\n      db *= db;\n      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);\n      c.x = a.x + x * dx + y * dy;\n      c.y = a.y + x * dy - y * dx;\n    } else {\n      c.x = a.x + db;\n      c.y = a.y;\n    }\n  }\n  d3.layout.tree = function() {\n    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;\n    function tree(d, i) {\n      var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);\n      d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;\n      d3_layout_hierarchyVisitBefore(root1, secondWalk);\n      if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {\n        var left = root0, right = root0, bottom = root0;\n        d3_layout_hierarchyVisitBefore(root0, function(node) {\n          if (node.x < left.x) left = node;\n          if (node.x > right.x) right = node;\n          if (node.depth > bottom.depth) bottom = node;\n        });\n        var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);\n        d3_layout_hierarchyVisitBefore(root0, function(node) {\n          node.x = (node.x + tx) * kx;\n          node.y = node.depth * ky;\n        });\n      }\n      return nodes;\n    }\n    function wrapTree(root0) {\n      var root1 = {\n        A: null,\n        children: [ root0 ]\n      }, queue = [ root1 ], node1;\n      while ((node1 = queue.pop()) != null) {\n        for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {\n          queue.push((children[i] = child = {\n            _: children[i],\n            parent: node1,\n            children: (child = children[i].children) && child.slice() || [],\n            A: null,\n            a: null,\n            z: 0,\n            m: 0,\n            c: 0,\n            s: 0,\n            t: null,\n            i: i\n          }).a = child);\n        }\n      }\n      return root1.children[0];\n    }\n    function firstWalk(v) {\n      var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;\n      if (children.length) {\n        d3_layout_treeShift(v);\n        var midpoint = (children[0].z + children[children.length - 1].z) / 2;\n        if (w) {\n          v.z = w.z + separation(v._, w._);\n          v.m = v.z - midpoint;\n        } else {\n          v.z = midpoint;\n        }\n      } else if (w) {\n        v.z = w.z + separation(v._, w._);\n      }\n      v.parent.A = apportion(v, w, v.parent.A || siblings[0]);\n    }\n    function secondWalk(v) {\n      v._.x = v.z + v.parent.m;\n      v.m += v.parent.m;\n    }\n    function apportion(v, w, ancestor) {\n      if (w) {\n        var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;\n        while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {\n          vom = d3_layout_treeLeft(vom);\n          vop = d3_layout_treeRight(vop);\n          vop.a = v;\n          shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);\n          if (shift > 0) {\n            d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);\n            sip += shift;\n            sop += shift;\n          }\n          sim += vim.m;\n          sip += vip.m;\n          som += vom.m;\n          sop += vop.m;\n        }\n        if (vim && !d3_layout_treeRight(vop)) {\n          vop.t = vim;\n          vop.m += sim - sop;\n        }\n        if (vip && !d3_layout_treeLeft(vom)) {\n          vom.t = vip;\n          vom.m += sip - som;\n          ancestor = v;\n        }\n      }\n      return ancestor;\n    }\n    function sizeNode(node) {\n      node.x *= size[0];\n      node.y = node.depth * size[1];\n    }\n    tree.separation = function(x) {\n      if (!arguments.length) return separation;\n      separation = x;\n      return tree;\n    };\n    tree.size = function(x) {\n      if (!arguments.length) return nodeSize ? null : size;\n      nodeSize = (size = x) == null ? sizeNode : null;\n      return tree;\n    };\n    tree.nodeSize = function(x) {\n      if (!arguments.length) return nodeSize ? size : null;\n      nodeSize = (size = x) == null ? null : sizeNode;\n      return tree;\n    };\n    return d3_layout_hierarchyRebind(tree, hierarchy);\n  };\n  function d3_layout_treeSeparation(a, b) {\n    return a.parent == b.parent ? 1 : 2;\n  }\n  function d3_layout_treeLeft(v) {\n    var children = v.children;\n    return children.length ? children[0] : v.t;\n  }\n  function d3_layout_treeRight(v) {\n    var children = v.children, n;\n    return (n = children.length) ? children[n - 1] : v.t;\n  }\n  function d3_layout_treeMove(wm, wp, shift) {\n    var change = shift / (wp.i - wm.i);\n    wp.c -= change;\n    wp.s += shift;\n    wm.c += change;\n    wp.z += shift;\n    wp.m += shift;\n  }\n  function d3_layout_treeShift(v) {\n    var shift = 0, change = 0, children = v.children, i = children.length, w;\n    while (--i >= 0) {\n      w = children[i];\n      w.z += shift;\n      w.m += shift;\n      shift += w.s + (change += w.c);\n    }\n  }\n  function d3_layout_treeAncestor(vim, v, ancestor) {\n    return vim.a.parent === v.parent ? vim.a : ancestor;\n  }\n  d3.layout.cluster = function() {\n    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;\n    function cluster(d, i) {\n      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;\n      d3_layout_hierarchyVisitAfter(root, function(node) {\n        var children = node.children;\n        if (children && children.length) {\n          node.x = d3_layout_clusterX(children);\n          node.y = d3_layout_clusterY(children);\n        } else {\n          node.x = previousNode ? x += separation(node, previousNode) : 0;\n          node.y = 0;\n          previousNode = node;\n        }\n      });\n      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;\n      d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {\n        node.x = (node.x - root.x) * size[0];\n        node.y = (root.y - node.y) * size[1];\n      } : function(node) {\n        node.x = (node.x - x0) / (x1 - x0) * size[0];\n        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];\n      });\n      return nodes;\n    }\n    cluster.separation = function(x) {\n      if (!arguments.length) return separation;\n      separation = x;\n      return cluster;\n    };\n    cluster.size = function(x) {\n      if (!arguments.length) return nodeSize ? null : size;\n      nodeSize = (size = x) == null;\n      return cluster;\n    };\n    cluster.nodeSize = function(x) {\n      if (!arguments.length) return nodeSize ? size : null;\n      nodeSize = (size = x) != null;\n      return cluster;\n    };\n    return d3_layout_hierarchyRebind(cluster, hierarchy);\n  };\n  function d3_layout_clusterY(children) {\n    return 1 + d3.max(children, function(child) {\n      return child.y;\n    });\n  }\n  function d3_layout_clusterX(children) {\n    return children.reduce(function(x, child) {\n      return x + child.x;\n    }, 0) / children.length;\n  }\n  function d3_layout_clusterLeft(node) {\n    var children = node.children;\n    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;\n  }\n  function d3_layout_clusterRight(node) {\n    var children = node.children, n;\n    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;\n  }\n  d3.layout.treemap = function() {\n    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = \"squarify\", ratio = .5 * (1 + Math.sqrt(5));\n    function scale(children, k) {\n      var i = -1, n = children.length, child, area;\n      while (++i < n) {\n        area = (child = children[i]).value * (k < 0 ? 0 : k);\n        child.area = isNaN(area) || area <= 0 ? 0 : area;\n      }\n    }\n    function squarify(node) {\n      var children = node.children;\n      if (children && children.length) {\n        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === \"slice\" ? rect.dx : mode === \"dice\" ? rect.dy : mode === \"slice-dice\" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;\n        scale(remaining, rect.dx * rect.dy / node.value);\n        row.area = 0;\n        while ((n = remaining.length) > 0) {\n          row.push(child = remaining[n - 1]);\n          row.area += child.area;\n          if (mode !== \"squarify\" || (score = worst(row, u)) <= best) {\n            remaining.pop();\n            best = score;\n          } else {\n            row.area -= row.pop().area;\n            position(row, u, rect, false);\n            u = Math.min(rect.dx, rect.dy);\n            row.length = row.area = 0;\n            best = Infinity;\n          }\n        }\n        if (row.length) {\n          position(row, u, rect, true);\n          row.length = row.area = 0;\n        }\n        children.forEach(squarify);\n      }\n    }\n    function stickify(node) {\n      var children = node.children;\n      if (children && children.length) {\n        var rect = pad(node), remaining = children.slice(), child, row = [];\n        scale(remaining, rect.dx * rect.dy / node.value);\n        row.area = 0;\n        while (child = remaining.pop()) {\n          row.push(child);\n          row.area += child.area;\n          if (child.z != null) {\n            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);\n            row.length = row.area = 0;\n          }\n        }\n        children.forEach(stickify);\n      }\n    }\n    function worst(row, u) {\n      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;\n      while (++i < n) {\n        if (!(r = row[i].area)) continue;\n        if (r < rmin) rmin = r;\n        if (r > rmax) rmax = r;\n      }\n      s *= s;\n      u *= u;\n      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;\n    }\n    function position(row, u, rect, flush) {\n      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;\n      if (u == rect.dx) {\n        if (flush || v > rect.dy) v = rect.dy;\n        while (++i < n) {\n          o = row[i];\n          o.x = x;\n          o.y = y;\n          o.dy = v;\n          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);\n        }\n        o.z = true;\n        o.dx += rect.x + rect.dx - x;\n        rect.y += v;\n        rect.dy -= v;\n      } else {\n        if (flush || v > rect.dx) v = rect.dx;\n        while (++i < n) {\n          o = row[i];\n          o.x = x;\n          o.y = y;\n          o.dx = v;\n          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);\n        }\n        o.z = false;\n        o.dy += rect.y + rect.dy - y;\n        rect.x += v;\n        rect.dx -= v;\n      }\n    }\n    function treemap(d) {\n      var nodes = stickies || hierarchy(d), root = nodes[0];\n      root.x = 0;\n      root.y = 0;\n      root.dx = size[0];\n      root.dy = size[1];\n      if (stickies) hierarchy.revalue(root);\n      scale([ root ], root.dx * root.dy / root.value);\n      (stickies ? stickify : squarify)(root);\n      if (sticky) stickies = nodes;\n      return nodes;\n    }\n    treemap.size = function(x) {\n      if (!arguments.length) return size;\n      size = x;\n      return treemap;\n    };\n    treemap.padding = function(x) {\n      if (!arguments.length) return padding;\n      function padFunction(node) {\n        var p = x.call(treemap, node, node.depth);\n        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === \"number\" ? [ p, p, p, p ] : p);\n      }\n      function padConstant(node) {\n        return d3_layout_treemapPad(node, x);\n      }\n      var type;\n      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === \"function\" ? padFunction : type === \"number\" ? (x = [ x, x, x, x ], \n      padConstant) : padConstant;\n      return treemap;\n    };\n    treemap.round = function(x) {\n      if (!arguments.length) return round != Number;\n      round = x ? Math.round : Number;\n      return treemap;\n    };\n    treemap.sticky = function(x) {\n      if (!arguments.length) return sticky;\n      sticky = x;\n      stickies = null;\n      return treemap;\n    };\n    treemap.ratio = function(x) {\n      if (!arguments.length) return ratio;\n      ratio = x;\n      return treemap;\n    };\n    treemap.mode = function(x) {\n      if (!arguments.length) return mode;\n      mode = x + \"\";\n      return treemap;\n    };\n    return d3_layout_hierarchyRebind(treemap, hierarchy);\n  };\n  function d3_layout_treemapPadNull(node) {\n    return {\n      x: node.x,\n      y: node.y,\n      dx: node.dx,\n      dy: node.dy\n    };\n  }\n  function d3_layout_treemapPad(node, padding) {\n    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];\n    if (dx < 0) {\n      x += dx / 2;\n      dx = 0;\n    }\n    if (dy < 0) {\n      y += dy / 2;\n      dy = 0;\n    }\n    return {\n      x: x,\n      y: y,\n      dx: dx,\n      dy: dy\n    };\n  }\n  d3.random = {\n    normal: function(µ, σ) {\n      var n = arguments.length;\n      if (n < 2) σ = 1;\n      if (n < 1) µ = 0;\n      return function() {\n        var x, y, r;\n        do {\n          x = Math.random() * 2 - 1;\n          y = Math.random() * 2 - 1;\n          r = x * x + y * y;\n        } while (!r || r > 1);\n        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);\n      };\n    },\n    logNormal: function() {\n      var random = d3.random.normal.apply(d3, arguments);\n      return function() {\n        return Math.exp(random());\n      };\n    },\n    bates: function(m) {\n      var random = d3.random.irwinHall(m);\n      return function() {\n        return random() / m;\n      };\n    },\n    irwinHall: function(m) {\n      return function() {\n        for (var s = 0, j = 0; j < m; j++) s += Math.random();\n        return s;\n      };\n    }\n  };\n  d3.scale = {};\n  function d3_scaleExtent(domain) {\n    var start = domain[0], stop = domain[domain.length - 1];\n    return start < stop ? [ start, stop ] : [ stop, start ];\n  }\n  function d3_scaleRange(scale) {\n    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());\n  }\n  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {\n    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);\n    return function(x) {\n      return i(u(x));\n    };\n  }\n  function d3_scale_nice(domain, nice) {\n    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;\n    if (x1 < x0) {\n      dx = i0, i0 = i1, i1 = dx;\n      dx = x0, x0 = x1, x1 = dx;\n    }\n    domain[i0] = nice.floor(x0);\n    domain[i1] = nice.ceil(x1);\n    return domain;\n  }\n  function d3_scale_niceStep(step) {\n    return step ? {\n      floor: function(x) {\n        return Math.floor(x / step) * step;\n      },\n      ceil: function(x) {\n        return Math.ceil(x / step) * step;\n      }\n    } : d3_scale_niceIdentity;\n  }\n  var d3_scale_niceIdentity = {\n    floor: d3_identity,\n    ceil: d3_identity\n  };\n  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {\n    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;\n    if (domain[k] < domain[0]) {\n      domain = domain.slice().reverse();\n      range = range.slice().reverse();\n    }\n    while (++j <= k) {\n      u.push(uninterpolate(domain[j - 1], domain[j]));\n      i.push(interpolate(range[j - 1], range[j]));\n    }\n    return function(x) {\n      var j = d3.bisect(domain, x, 1, k) - 1;\n      return i[j](u[j](x));\n    };\n  }\n  d3.scale.linear = function() {\n    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);\n  };\n  function d3_scale_linear(domain, range, interpolate, clamp) {\n    var output, input;\n    function rescale() {\n      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;\n      output = linear(domain, range, uninterpolate, interpolate);\n      input = linear(range, domain, uninterpolate, d3_interpolate);\n      return scale;\n    }\n    function scale(x) {\n      return output(x);\n    }\n    scale.invert = function(y) {\n      return input(y);\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.map(Number);\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.rangeRound = function(x) {\n      return scale.range(x).interpolate(d3_interpolateRound);\n    };\n    scale.clamp = function(x) {\n      if (!arguments.length) return clamp;\n      clamp = x;\n      return rescale();\n    };\n    scale.interpolate = function(x) {\n      if (!arguments.length) return interpolate;\n      interpolate = x;\n      return rescale();\n    };\n    scale.ticks = function(m) {\n      return d3_scale_linearTicks(domain, m);\n    };\n    scale.tickFormat = function(m, format) {\n      return d3_scale_linearTickFormat(domain, m, format);\n    };\n    scale.nice = function(m) {\n      d3_scale_linearNice(domain, m);\n      return rescale();\n    };\n    scale.copy = function() {\n      return d3_scale_linear(domain, range, interpolate, clamp);\n    };\n    return rescale();\n  }\n  function d3_scale_linearRebind(scale, linear) {\n    return d3.rebind(scale, linear, \"range\", \"rangeRound\", \"interpolate\", \"clamp\");\n  }\n  function d3_scale_linearNice(domain, m) {\n    return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));\n  }\n  function d3_scale_linearTickRange(domain, m) {\n    if (m == null) m = 10;\n    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;\n    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;\n    extent[0] = Math.ceil(extent[0] / step) * step;\n    extent[1] = Math.floor(extent[1] / step) * step + step * .5;\n    extent[2] = step;\n    return extent;\n  }\n  function d3_scale_linearTicks(domain, m) {\n    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));\n  }\n  function d3_scale_linearTickFormat(domain, m, format) {\n    var range = d3_scale_linearTickRange(domain, m);\n    if (format) {\n      var match = d3_format_re.exec(format);\n      match.shift();\n      if (match[8] === \"s\") {\n        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));\n        if (!match[7]) match[7] = \".\" + d3_scale_linearPrecision(prefix.scale(range[2]));\n        match[8] = \"f\";\n        format = d3.format(match.join(\"\"));\n        return function(d) {\n          return format(prefix.scale(d)) + prefix.symbol;\n        };\n      }\n      if (!match[7]) match[7] = \".\" + d3_scale_linearFormatPrecision(match[8], range);\n      format = match.join(\"\");\n    } else {\n      format = \",.\" + d3_scale_linearPrecision(range[2]) + \"f\";\n    }\n    return d3.format(format);\n  }\n  var d3_scale_linearFormatSignificant = {\n    s: 1,\n    g: 1,\n    p: 1,\n    r: 1,\n    e: 1\n  };\n  function d3_scale_linearPrecision(value) {\n    return -Math.floor(Math.log(value) / Math.LN10 + .01);\n  }\n  function d3_scale_linearFormatPrecision(type, range) {\n    var p = d3_scale_linearPrecision(range[2]);\n    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== \"e\") : p - (type === \"%\") * 2;\n  }\n  d3.scale.log = function() {\n    return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);\n  };\n  function d3_scale_log(linear, base, positive, domain) {\n    function log(x) {\n      return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);\n    }\n    function pow(x) {\n      return positive ? Math.pow(base, x) : -Math.pow(base, -x);\n    }\n    function scale(x) {\n      return linear(log(x));\n    }\n    scale.invert = function(x) {\n      return pow(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      positive = x[0] >= 0;\n      linear.domain((domain = x.map(Number)).map(log));\n      return scale;\n    };\n    scale.base = function(_) {\n      if (!arguments.length) return base;\n      base = +_;\n      linear.domain(domain.map(log));\n      return scale;\n    };\n    scale.nice = function() {\n      var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);\n      linear.domain(niced);\n      domain = niced.map(pow);\n      return scale;\n    };\n    scale.ticks = function() {\n      var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;\n      if (isFinite(j - i)) {\n        if (positive) {\n          for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);\n          ticks.push(pow(i));\n        } else {\n          ticks.push(pow(i));\n          for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);\n        }\n        for (i = 0; ticks[i] < u; i++) {}\n        for (j = ticks.length; ticks[j - 1] > v; j--) {}\n        ticks = ticks.slice(i, j);\n      }\n      return ticks;\n    };\n    scale.tickFormat = function(n, format) {\n      if (!arguments.length) return d3_scale_logFormat;\n      if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== \"function\") format = d3.format(format);\n      var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, \n      Math.floor), e;\n      return function(d) {\n        return d / pow(f(log(d) + e)) <= k ? format(d) : \"\";\n      };\n    };\n    scale.copy = function() {\n      return d3_scale_log(linear.copy(), base, positive, domain);\n    };\n    return d3_scale_linearRebind(scale, linear);\n  }\n  var d3_scale_logFormat = d3.format(\".0e\"), d3_scale_logNiceNegative = {\n    floor: function(x) {\n      return -Math.ceil(-x);\n    },\n    ceil: function(x) {\n      return -Math.floor(-x);\n    }\n  };\n  d3.scale.pow = function() {\n    return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);\n  };\n  function d3_scale_pow(linear, exponent, domain) {\n    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);\n    function scale(x) {\n      return linear(powp(x));\n    }\n    scale.invert = function(x) {\n      return powb(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      linear.domain((domain = x.map(Number)).map(powp));\n      return scale;\n    };\n    scale.ticks = function(m) {\n      return d3_scale_linearTicks(domain, m);\n    };\n    scale.tickFormat = function(m, format) {\n      return d3_scale_linearTickFormat(domain, m, format);\n    };\n    scale.nice = function(m) {\n      return scale.domain(d3_scale_linearNice(domain, m));\n    };\n    scale.exponent = function(x) {\n      if (!arguments.length) return exponent;\n      powp = d3_scale_powPow(exponent = x);\n      powb = d3_scale_powPow(1 / exponent);\n      linear.domain(domain.map(powp));\n      return scale;\n    };\n    scale.copy = function() {\n      return d3_scale_pow(linear.copy(), exponent, domain);\n    };\n    return d3_scale_linearRebind(scale, linear);\n  }\n  function d3_scale_powPow(e) {\n    return function(x) {\n      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);\n    };\n  }\n  d3.scale.sqrt = function() {\n    return d3.scale.pow().exponent(.5);\n  };\n  d3.scale.ordinal = function() {\n    return d3_scale_ordinal([], {\n      t: \"range\",\n      a: [ [] ]\n    });\n  };\n  function d3_scale_ordinal(domain, ranger) {\n    var index, range, rangeBand;\n    function scale(x) {\n      return range[((index.get(x) || (ranger.t === \"range\" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];\n    }\n    function steps(start, step) {\n      return d3.range(domain.length).map(function(i) {\n        return start + step * i;\n      });\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = [];\n      index = new d3_Map();\n      var i = -1, n = x.length, xi;\n      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));\n      return scale[ranger.t].apply(scale, ranger.a);\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      rangeBand = 0;\n      ranger = {\n        t: \"range\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangePoints = function(x, padding) {\n      if (arguments.length < 2) padding = 0;\n      var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);\n      range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);\n      rangeBand = 0;\n      ranger = {\n        t: \"rangePoints\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeBands = function(x, padding, outerPadding) {\n      if (arguments.length < 2) padding = 0;\n      if (arguments.length < 3) outerPadding = padding;\n      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);\n      range = steps(start + step * outerPadding, step);\n      if (reverse) range.reverse();\n      rangeBand = step * (1 - padding);\n      ranger = {\n        t: \"rangeBands\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeRoundBands = function(x, padding, outerPadding) {\n      if (arguments.length < 2) padding = 0;\n      if (arguments.length < 3) outerPadding = padding;\n      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;\n      range = steps(start + Math.round(error / 2), step);\n      if (reverse) range.reverse();\n      rangeBand = Math.round(step * (1 - padding));\n      ranger = {\n        t: \"rangeRoundBands\",\n        a: arguments\n      };\n      return scale;\n    };\n    scale.rangeBand = function() {\n      return rangeBand;\n    };\n    scale.rangeExtent = function() {\n      return d3_scaleExtent(ranger.a[0]);\n    };\n    scale.copy = function() {\n      return d3_scale_ordinal(domain, ranger);\n    };\n    return scale.domain(domain);\n  }\n  d3.scale.category10 = function() {\n    return d3.scale.ordinal().range(d3_category10);\n  };\n  d3.scale.category20 = function() {\n    return d3.scale.ordinal().range(d3_category20);\n  };\n  d3.scale.category20b = function() {\n    return d3.scale.ordinal().range(d3_category20b);\n  };\n  d3.scale.category20c = function() {\n    return d3.scale.ordinal().range(d3_category20c);\n  };\n  var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);\n  var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);\n  var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);\n  var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);\n  d3.scale.quantile = function() {\n    return d3_scale_quantile([], []);\n  };\n  function d3_scale_quantile(domain, range) {\n    var thresholds;\n    function rescale() {\n      var k = 0, q = range.length;\n      thresholds = [];\n      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);\n      return scale;\n    }\n    function scale(x) {\n      if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending);\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.quantiles = function() {\n      return thresholds;\n    };\n    scale.invertExtent = function(y) {\n      y = range.indexOf(y);\n      return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];\n    };\n    scale.copy = function() {\n      return d3_scale_quantile(domain, range);\n    };\n    return rescale();\n  }\n  d3.scale.quantize = function() {\n    return d3_scale_quantize(0, 1, [ 0, 1 ]);\n  };\n  function d3_scale_quantize(x0, x1, range) {\n    var kx, i;\n    function scale(x) {\n      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];\n    }\n    function rescale() {\n      kx = range.length / (x1 - x0);\n      i = range.length - 1;\n      return scale;\n    }\n    scale.domain = function(x) {\n      if (!arguments.length) return [ x0, x1 ];\n      x0 = +x[0];\n      x1 = +x[x.length - 1];\n      return rescale();\n    };\n    scale.range = function(x) {\n      if (!arguments.length) return range;\n      range = x;\n      return rescale();\n    };\n    scale.invertExtent = function(y) {\n      y = range.indexOf(y);\n      y = y < 0 ? NaN : y / kx + x0;\n      return [ y, y + 1 / kx ];\n    };\n    scale.copy = function() {\n      return d3_scale_quantize(x0, x1, range);\n    };\n    return rescale();\n  }\n  d3.scale.threshold = function() {\n    return d3_scale_threshold([ .5 ], [ 0, 1 ]);\n  };\n  function d3_scale_threshold(domain, range) {\n    function scale(x) {\n      if (x <= x) return range[d3.bisect(domain, x)];\n    }\n    scale.domain = function(_) {\n      if (!arguments.length) return domain;\n      domain = _;\n      return scale;\n    };\n    scale.range = function(_) {\n      if (!arguments.length) return range;\n      range = _;\n      return scale;\n    };\n    scale.invertExtent = function(y) {\n      y = range.indexOf(y);\n      return [ domain[y - 1], domain[y] ];\n    };\n    scale.copy = function() {\n      return d3_scale_threshold(domain, range);\n    };\n    return scale;\n  }\n  d3.scale.identity = function() {\n    return d3_scale_identity([ 0, 1 ]);\n  };\n  function d3_scale_identity(domain) {\n    function identity(x) {\n      return +x;\n    }\n    identity.invert = identity;\n    identity.domain = identity.range = function(x) {\n      if (!arguments.length) return domain;\n      domain = x.map(identity);\n      return identity;\n    };\n    identity.ticks = function(m) {\n      return d3_scale_linearTicks(domain, m);\n    };\n    identity.tickFormat = function(m, format) {\n      return d3_scale_linearTickFormat(domain, m, format);\n    };\n    identity.copy = function() {\n      return d3_scale_identity(domain);\n    };\n    return identity;\n  }\n  d3.svg = {};\n  d3.svg.arc = function() {\n    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;\n    function arc() {\n      var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, \n      a0 = a1, a1 = da), a1 - a0), df = da < π ? \"0\" : \"1\", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);\n      return da >= d3_svg_arcMax ? r0 ? \"M0,\" + r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + -r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + r1 + \"M0,\" + r0 + \"A\" + r0 + \",\" + r0 + \" 0 1,0 0,\" + -r0 + \"A\" + r0 + \",\" + r0 + \" 0 1,0 0,\" + r0 + \"Z\" : \"M0,\" + r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + -r1 + \"A\" + r1 + \",\" + r1 + \" 0 1,1 0,\" + r1 + \"Z\" : r0 ? \"M\" + r1 * c0 + \",\" + r1 * s0 + \"A\" + r1 + \",\" + r1 + \" 0 \" + df + \",1 \" + r1 * c1 + \",\" + r1 * s1 + \"L\" + r0 * c1 + \",\" + r0 * s1 + \"A\" + r0 + \",\" + r0 + \" 0 \" + df + \",0 \" + r0 * c0 + \",\" + r0 * s0 + \"Z\" : \"M\" + r1 * c0 + \",\" + r1 * s0 + \"A\" + r1 + \",\" + r1 + \" 0 \" + df + \",1 \" + r1 * c1 + \",\" + r1 * s1 + \"L0,0\" + \"Z\";\n    }\n    arc.innerRadius = function(v) {\n      if (!arguments.length) return innerRadius;\n      innerRadius = d3_functor(v);\n      return arc;\n    };\n    arc.outerRadius = function(v) {\n      if (!arguments.length) return outerRadius;\n      outerRadius = d3_functor(v);\n      return arc;\n    };\n    arc.startAngle = function(v) {\n      if (!arguments.length) return startAngle;\n      startAngle = d3_functor(v);\n      return arc;\n    };\n    arc.endAngle = function(v) {\n      if (!arguments.length) return endAngle;\n      endAngle = d3_functor(v);\n      return arc;\n    };\n    arc.centroid = function() {\n      var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;\n      return [ Math.cos(a) * r, Math.sin(a) * r ];\n    };\n    return arc;\n  };\n  var d3_svg_arcOffset = -halfπ, d3_svg_arcMax = τ - ε;\n  function d3_svg_arcInnerRadius(d) {\n    return d.innerRadius;\n  }\n  function d3_svg_arcOuterRadius(d) {\n    return d.outerRadius;\n  }\n  function d3_svg_arcStartAngle(d) {\n    return d.startAngle;\n  }\n  function d3_svg_arcEndAngle(d) {\n    return d.endAngle;\n  }\n  function d3_svg_line(projection) {\n    var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;\n    function line(data) {\n      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);\n      function segment() {\n        segments.push(\"M\", interpolate(projection(points), tension));\n      }\n      while (++i < n) {\n        if (defined.call(this, d = data[i], i)) {\n          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);\n        } else if (points.length) {\n          segment();\n          points = [];\n        }\n      }\n      if (points.length) segment();\n      return segments.length ? segments.join(\"\") : null;\n    }\n    line.x = function(_) {\n      if (!arguments.length) return x;\n      x = _;\n      return line;\n    };\n    line.y = function(_) {\n      if (!arguments.length) return y;\n      y = _;\n      return line;\n    };\n    line.defined = function(_) {\n      if (!arguments.length) return defined;\n      defined = _;\n      return line;\n    };\n    line.interpolate = function(_) {\n      if (!arguments.length) return interpolateKey;\n      if (typeof _ === \"function\") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;\n      return line;\n    };\n    line.tension = function(_) {\n      if (!arguments.length) return tension;\n      tension = _;\n      return line;\n    };\n    return line;\n  }\n  d3.svg.line = function() {\n    return d3_svg_line(d3_identity);\n  };\n  var d3_svg_lineInterpolators = d3.map({\n    linear: d3_svg_lineLinear,\n    \"linear-closed\": d3_svg_lineLinearClosed,\n    step: d3_svg_lineStep,\n    \"step-before\": d3_svg_lineStepBefore,\n    \"step-after\": d3_svg_lineStepAfter,\n    basis: d3_svg_lineBasis,\n    \"basis-open\": d3_svg_lineBasisOpen,\n    \"basis-closed\": d3_svg_lineBasisClosed,\n    bundle: d3_svg_lineBundle,\n    cardinal: d3_svg_lineCardinal,\n    \"cardinal-open\": d3_svg_lineCardinalOpen,\n    \"cardinal-closed\": d3_svg_lineCardinalClosed,\n    monotone: d3_svg_lineMonotone\n  });\n  d3_svg_lineInterpolators.forEach(function(key, value) {\n    value.key = key;\n    value.closed = /-closed$/.test(key);\n  });\n  function d3_svg_lineLinear(points) {\n    return points.join(\"L\");\n  }\n  function d3_svg_lineLinearClosed(points) {\n    return d3_svg_lineLinear(points) + \"Z\";\n  }\n  function d3_svg_lineStep(points) {\n    var i = 0, n = points.length, p = points[0], path = [ p[0], \",\", p[1] ];\n    while (++i < n) path.push(\"H\", (p[0] + (p = points[i])[0]) / 2, \"V\", p[1]);\n    if (n > 1) path.push(\"H\", p[0]);\n    return path.join(\"\");\n  }\n  function d3_svg_lineStepBefore(points) {\n    var i = 0, n = points.length, p = points[0], path = [ p[0], \",\", p[1] ];\n    while (++i < n) path.push(\"V\", (p = points[i])[1], \"H\", p[0]);\n    return path.join(\"\");\n  }\n  function d3_svg_lineStepAfter(points) {\n    var i = 0, n = points.length, p = points[0], path = [ p[0], \",\", p[1] ];\n    while (++i < n) path.push(\"H\", (p = points[i])[0], \"V\", p[1]);\n    return path.join(\"\");\n  }\n  function d3_svg_lineCardinalOpen(points, tension) {\n    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));\n  }\n  function d3_svg_lineCardinalClosed(points, tension) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), \n    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));\n  }\n  function d3_svg_lineCardinal(points, tension) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));\n  }\n  function d3_svg_lineHermite(points, tangents) {\n    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {\n      return d3_svg_lineLinear(points);\n    }\n    var quad = points.length != tangents.length, path = \"\", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;\n    if (quad) {\n      path += \"Q\" + (p[0] - t0[0] * 2 / 3) + \",\" + (p[1] - t0[1] * 2 / 3) + \",\" + p[0] + \",\" + p[1];\n      p0 = points[1];\n      pi = 2;\n    }\n    if (tangents.length > 1) {\n      t = tangents[1];\n      p = points[pi];\n      pi++;\n      path += \"C\" + (p0[0] + t0[0]) + \",\" + (p0[1] + t0[1]) + \",\" + (p[0] - t[0]) + \",\" + (p[1] - t[1]) + \",\" + p[0] + \",\" + p[1];\n      for (var i = 2; i < tangents.length; i++, pi++) {\n        p = points[pi];\n        t = tangents[i];\n        path += \"S\" + (p[0] - t[0]) + \",\" + (p[1] - t[1]) + \",\" + p[0] + \",\" + p[1];\n      }\n    }\n    if (quad) {\n      var lp = points[pi];\n      path += \"Q\" + (p[0] + t[0] * 2 / 3) + \",\" + (p[1] + t[1] * 2 / 3) + \",\" + lp[0] + \",\" + lp[1];\n    }\n    return path;\n  }\n  function d3_svg_lineCardinalTangents(points, tension) {\n    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;\n    while (++i < n) {\n      p0 = p1;\n      p1 = p2;\n      p2 = points[i];\n      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);\n    }\n    return tangents;\n  }\n  function d3_svg_lineBasis(points) {\n    if (points.length < 3) return d3_svg_lineLinear(points);\n    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, \",\", y0, \"L\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];\n    points.push(points[n - 1]);\n    while (++i <= n) {\n      pi = points[i];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    points.pop();\n    path.push(\"L\", pi);\n    return path.join(\"\");\n  }\n  function d3_svg_lineBasisOpen(points) {\n    if (points.length < 4) return d3_svg_lineLinear(points);\n    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];\n    while (++i < 3) {\n      pi = points[i];\n      px.push(pi[0]);\n      py.push(pi[1]);\n    }\n    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + \",\" + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));\n    --i;\n    while (++i < n) {\n      pi = points[i];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBasisClosed(points) {\n    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];\n    while (++i < 4) {\n      pi = points[i % n];\n      px.push(pi[0]);\n      py.push(pi[1]);\n    }\n    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];\n    --i;\n    while (++i < m) {\n      pi = points[i % n];\n      px.shift();\n      px.push(pi[0]);\n      py.shift();\n      py.push(pi[1]);\n      d3_svg_lineBasisBezier(path, px, py);\n    }\n    return path.join(\"\");\n  }\n  function d3_svg_lineBundle(points, tension) {\n    var n = points.length - 1;\n    if (n) {\n      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;\n      while (++i <= n) {\n        p = points[i];\n        t = i / n;\n        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);\n        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);\n      }\n    }\n    return d3_svg_lineBasis(points);\n  }\n  function d3_svg_lineDot4(a, b) {\n    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n  }\n  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];\n  function d3_svg_lineBasisBezier(path, x, y) {\n    path.push(\"C\", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), \",\", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));\n  }\n  function d3_svg_lineSlope(p0, p1) {\n    return (p1[1] - p0[1]) / (p1[0] - p0[0]);\n  }\n  function d3_svg_lineFiniteDifferences(points) {\n    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);\n    while (++i < j) {\n      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;\n    }\n    m[i] = d;\n    return m;\n  }\n  function d3_svg_lineMonotoneTangents(points) {\n    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;\n    while (++i < j) {\n      d = d3_svg_lineSlope(points[i], points[i + 1]);\n      if (abs(d) < ε) {\n        m[i] = m[i + 1] = 0;\n      } else {\n        a = m[i] / d;\n        b = m[i + 1] / d;\n        s = a * a + b * b;\n        if (s > 9) {\n          s = d * 3 / Math.sqrt(s);\n          m[i] = s * a;\n          m[i + 1] = s * b;\n        }\n      }\n    }\n    i = -1;\n    while (++i <= j) {\n      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));\n      tangents.push([ s || 0, m[i] * s || 0 ]);\n    }\n    return tangents;\n  }\n  function d3_svg_lineMonotone(points) {\n    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));\n  }\n  d3.svg.line.radial = function() {\n    var line = d3_svg_line(d3_svg_lineRadial);\n    line.radius = line.x, delete line.x;\n    line.angle = line.y, delete line.y;\n    return line;\n  };\n  function d3_svg_lineRadial(points) {\n    var point, i = -1, n = points.length, r, a;\n    while (++i < n) {\n      point = points[i];\n      r = point[0];\n      a = point[1] + d3_svg_arcOffset;\n      point[0] = r * Math.cos(a);\n      point[1] = r * Math.sin(a);\n    }\n    return points;\n  }\n  function d3_svg_area(projection) {\n    var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = \"L\", tension = .7;\n    function area(data) {\n      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {\n        return x;\n      } : d3_functor(x1), fy1 = y0 === y1 ? function() {\n        return y;\n      } : d3_functor(y1), x, y;\n      function segment() {\n        segments.push(\"M\", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), \"Z\");\n      }\n      while (++i < n) {\n        if (defined.call(this, d = data[i], i)) {\n          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);\n          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);\n        } else if (points0.length) {\n          segment();\n          points0 = [];\n          points1 = [];\n        }\n      }\n      if (points0.length) segment();\n      return segments.length ? segments.join(\"\") : null;\n    }\n    area.x = function(_) {\n      if (!arguments.length) return x1;\n      x0 = x1 = _;\n      return area;\n    };\n    area.x0 = function(_) {\n      if (!arguments.length) return x0;\n      x0 = _;\n      return area;\n    };\n    area.x1 = function(_) {\n      if (!arguments.length) return x1;\n      x1 = _;\n      return area;\n    };\n    area.y = function(_) {\n      if (!arguments.length) return y1;\n      y0 = y1 = _;\n      return area;\n    };\n    area.y0 = function(_) {\n      if (!arguments.length) return y0;\n      y0 = _;\n      return area;\n    };\n    area.y1 = function(_) {\n      if (!arguments.length) return y1;\n      y1 = _;\n      return area;\n    };\n    area.defined = function(_) {\n      if (!arguments.length) return defined;\n      defined = _;\n      return area;\n    };\n    area.interpolate = function(_) {\n      if (!arguments.length) return interpolateKey;\n      if (typeof _ === \"function\") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;\n      interpolateReverse = interpolate.reverse || interpolate;\n      L = interpolate.closed ? \"M\" : \"L\";\n      return area;\n    };\n    area.tension = function(_) {\n      if (!arguments.length) return tension;\n      tension = _;\n      return area;\n    };\n    return area;\n  }\n  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;\n  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;\n  d3.svg.area = function() {\n    return d3_svg_area(d3_identity);\n  };\n  d3.svg.area.radial = function() {\n    var area = d3_svg_area(d3_svg_lineRadial);\n    area.radius = area.x, delete area.x;\n    area.innerRadius = area.x0, delete area.x0;\n    area.outerRadius = area.x1, delete area.x1;\n    area.angle = area.y, delete area.y;\n    area.startAngle = area.y0, delete area.y0;\n    area.endAngle = area.y1, delete area.y1;\n    return area;\n  };\n  d3.svg.chord = function() {\n    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;\n    function chord(d, i) {\n      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);\n      return \"M\" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + \"Z\";\n    }\n    function subgroup(self, f, d, i) {\n      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;\n      return {\n        r: r,\n        a0: a0,\n        a1: a1,\n        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],\n        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]\n      };\n    }\n    function equals(a, b) {\n      return a.a0 == b.a0 && a.a1 == b.a1;\n    }\n    function arc(r, p, a) {\n      return \"A\" + r + \",\" + r + \" 0 \" + +(a > π) + \",1 \" + p;\n    }\n    function curve(r0, p0, r1, p1) {\n      return \"Q 0,0 \" + p1;\n    }\n    chord.radius = function(v) {\n      if (!arguments.length) return radius;\n      radius = d3_functor(v);\n      return chord;\n    };\n    chord.source = function(v) {\n      if (!arguments.length) return source;\n      source = d3_functor(v);\n      return chord;\n    };\n    chord.target = function(v) {\n      if (!arguments.length) return target;\n      target = d3_functor(v);\n      return chord;\n    };\n    chord.startAngle = function(v) {\n      if (!arguments.length) return startAngle;\n      startAngle = d3_functor(v);\n      return chord;\n    };\n    chord.endAngle = function(v) {\n      if (!arguments.length) return endAngle;\n      endAngle = d3_functor(v);\n      return chord;\n    };\n    return chord;\n  };\n  function d3_svg_chordRadius(d) {\n    return d.radius;\n  }\n  d3.svg.diagonal = function() {\n    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;\n    function diagonal(d, i) {\n      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {\n        x: p0.x,\n        y: m\n      }, {\n        x: p3.x,\n        y: m\n      }, p3 ];\n      p = p.map(projection);\n      return \"M\" + p[0] + \"C\" + p[1] + \" \" + p[2] + \" \" + p[3];\n    }\n    diagonal.source = function(x) {\n      if (!arguments.length) return source;\n      source = d3_functor(x);\n      return diagonal;\n    };\n    diagonal.target = function(x) {\n      if (!arguments.length) return target;\n      target = d3_functor(x);\n      return diagonal;\n    };\n    diagonal.projection = function(x) {\n      if (!arguments.length) return projection;\n      projection = x;\n      return diagonal;\n    };\n    return diagonal;\n  };\n  function d3_svg_diagonalProjection(d) {\n    return [ d.x, d.y ];\n  }\n  d3.svg.diagonal.radial = function() {\n    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;\n    diagonal.projection = function(x) {\n      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;\n    };\n    return diagonal;\n  };\n  function d3_svg_diagonalRadialProjection(projection) {\n    return function() {\n      var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;\n      return [ r * Math.cos(a), r * Math.sin(a) ];\n    };\n  }\n  d3.svg.symbol = function() {\n    var type = d3_svg_symbolType, size = d3_svg_symbolSize;\n    function symbol(d, i) {\n      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));\n    }\n    symbol.type = function(x) {\n      if (!arguments.length) return type;\n      type = d3_functor(x);\n      return symbol;\n    };\n    symbol.size = function(x) {\n      if (!arguments.length) return size;\n      size = d3_functor(x);\n      return symbol;\n    };\n    return symbol;\n  };\n  function d3_svg_symbolSize() {\n    return 64;\n  }\n  function d3_svg_symbolType() {\n    return \"circle\";\n  }\n  function d3_svg_symbolCircle(size) {\n    var r = Math.sqrt(size / π);\n    return \"M0,\" + r + \"A\" + r + \",\" + r + \" 0 1,1 0,\" + -r + \"A\" + r + \",\" + r + \" 0 1,1 0,\" + r + \"Z\";\n  }\n  var d3_svg_symbols = d3.map({\n    circle: d3_svg_symbolCircle,\n    cross: function(size) {\n      var r = Math.sqrt(size / 5) / 2;\n      return \"M\" + -3 * r + \",\" + -r + \"H\" + -r + \"V\" + -3 * r + \"H\" + r + \"V\" + -r + \"H\" + 3 * r + \"V\" + r + \"H\" + r + \"V\" + 3 * r + \"H\" + -r + \"V\" + r + \"H\" + -3 * r + \"Z\";\n    },\n    diamond: function(size) {\n      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;\n      return \"M0,\" + -ry + \"L\" + rx + \",0\" + \" 0,\" + ry + \" \" + -rx + \",0\" + \"Z\";\n    },\n    square: function(size) {\n      var r = Math.sqrt(size) / 2;\n      return \"M\" + -r + \",\" + -r + \"L\" + r + \",\" + -r + \" \" + r + \",\" + r + \" \" + -r + \",\" + r + \"Z\";\n    },\n    \"triangle-down\": function(size) {\n      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;\n      return \"M0,\" + ry + \"L\" + rx + \",\" + -ry + \" \" + -rx + \",\" + -ry + \"Z\";\n    },\n    \"triangle-up\": function(size) {\n      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;\n      return \"M0,\" + -ry + \"L\" + rx + \",\" + ry + \" \" + -rx + \",\" + ry + \"Z\";\n    }\n  });\n  d3.svg.symbolTypes = d3_svg_symbols.keys();\n  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);\n  function d3_transition(groups, id) {\n    d3_subclass(groups, d3_transitionPrototype);\n    groups.id = id;\n    return groups;\n  }\n  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;\n  d3_transitionPrototype.call = d3_selectionPrototype.call;\n  d3_transitionPrototype.empty = d3_selectionPrototype.empty;\n  d3_transitionPrototype.node = d3_selectionPrototype.node;\n  d3_transitionPrototype.size = d3_selectionPrototype.size;\n  d3.transition = function(selection) {\n    return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();\n  };\n  d3.transition.prototype = d3_transitionPrototype;\n  d3_transitionPrototype.select = function(selector) {\n    var id = this.id, subgroups = [], subgroup, subnode, node;\n    selector = d3_selection_selector(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {\n          if (\"__data__\" in node) subnode.__data__ = node.__data__;\n          d3_transitionNode(subnode, i, id, node.__transition__[id]);\n          subgroup.push(subnode);\n        } else {\n          subgroup.push(null);\n        }\n      }\n    }\n    return d3_transition(subgroups, id);\n  };\n  d3_transitionPrototype.selectAll = function(selector) {\n    var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;\n    selector = d3_selection_selectorAll(selector);\n    for (var j = -1, m = this.length; ++j < m; ) {\n      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {\n        if (node = group[i]) {\n          transition = node.__transition__[id];\n          subnodes = selector.call(node, node.__data__, i, j);\n          subgroups.push(subgroup = []);\n          for (var k = -1, o = subnodes.length; ++k < o; ) {\n            if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition);\n            subgroup.push(subnode);\n          }\n        }\n      }\n    }\n    return d3_transition(subgroups, id);\n  };\n  d3_transitionPrototype.filter = function(filter) {\n    var subgroups = [], subgroup, group, node;\n    if (typeof filter !== \"function\") filter = d3_selection_filter(filter);\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {\n          subgroup.push(node);\n        }\n      }\n    }\n    return d3_transition(subgroups, this.id);\n  };\n  d3_transitionPrototype.tween = function(name, tween) {\n    var id = this.id;\n    if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);\n    return d3_selection_each(this, tween == null ? function(node) {\n      node.__transition__[id].tween.remove(name);\n    } : function(node) {\n      node.__transition__[id].tween.set(name, tween);\n    });\n  };\n  function d3_transition_tween(groups, name, value, tween) {\n    var id = groups.id;\n    return d3_selection_each(groups, typeof value === \"function\" ? function(node, i, j) {\n      node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));\n    } : (value = tween(value), function(node) {\n      node.__transition__[id].tween.set(name, value);\n    }));\n  }\n  d3_transitionPrototype.attr = function(nameNS, value) {\n    if (arguments.length < 2) {\n      for (value in nameNS) this.attr(value, nameNS[value]);\n      return this;\n    }\n    var interpolate = nameNS == \"transform\" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);\n    function attrNull() {\n      this.removeAttribute(name);\n    }\n    function attrNullNS() {\n      this.removeAttributeNS(name.space, name.local);\n    }\n    function attrTween(b) {\n      return b == null ? attrNull : (b += \"\", function() {\n        var a = this.getAttribute(name), i;\n        return a !== b && (i = interpolate(a, b), function(t) {\n          this.setAttribute(name, i(t));\n        });\n      });\n    }\n    function attrTweenNS(b) {\n      return b == null ? attrNullNS : (b += \"\", function() {\n        var a = this.getAttributeNS(name.space, name.local), i;\n        return a !== b && (i = interpolate(a, b), function(t) {\n          this.setAttributeNS(name.space, name.local, i(t));\n        });\n      });\n    }\n    return d3_transition_tween(this, \"attr.\" + nameNS, value, name.local ? attrTweenNS : attrTween);\n  };\n  d3_transitionPrototype.attrTween = function(nameNS, tween) {\n    var name = d3.ns.qualify(nameNS);\n    function attrTween(d, i) {\n      var f = tween.call(this, d, i, this.getAttribute(name));\n      return f && function(t) {\n        this.setAttribute(name, f(t));\n      };\n    }\n    function attrTweenNS(d, i) {\n      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));\n      return f && function(t) {\n        this.setAttributeNS(name.space, name.local, f(t));\n      };\n    }\n    return this.tween(\"attr.\" + nameNS, name.local ? attrTweenNS : attrTween);\n  };\n  d3_transitionPrototype.style = function(name, value, priority) {\n    var n = arguments.length;\n    if (n < 3) {\n      if (typeof name !== \"string\") {\n        if (n < 2) value = \"\";\n        for (priority in name) this.style(priority, name[priority], value);\n        return this;\n      }\n      priority = \"\";\n    }\n    function styleNull() {\n      this.style.removeProperty(name);\n    }\n    function styleString(b) {\n      return b == null ? styleNull : (b += \"\", function() {\n        var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;\n        return a !== b && (i = d3_interpolate(a, b), function(t) {\n          this.style.setProperty(name, i(t), priority);\n        });\n      });\n    }\n    return d3_transition_tween(this, \"style.\" + name, value, styleString);\n  };\n  d3_transitionPrototype.styleTween = function(name, tween, priority) {\n    if (arguments.length < 3) priority = \"\";\n    function styleTween(d, i) {\n      var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));\n      return f && function(t) {\n        this.style.setProperty(name, f(t), priority);\n      };\n    }\n    return this.tween(\"style.\" + name, styleTween);\n  };\n  d3_transitionPrototype.text = function(value) {\n    return d3_transition_tween(this, \"text\", value, d3_transition_text);\n  };\n  function d3_transition_text(b) {\n    if (b == null) b = \"\";\n    return function() {\n      this.textContent = b;\n    };\n  }\n  d3_transitionPrototype.remove = function() {\n    return this.each(\"end.transition\", function() {\n      var p;\n      if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this);\n    });\n  };\n  d3_transitionPrototype.ease = function(value) {\n    var id = this.id;\n    if (arguments.length < 1) return this.node().__transition__[id].ease;\n    if (typeof value !== \"function\") value = d3.ease.apply(d3, arguments);\n    return d3_selection_each(this, function(node) {\n      node.__transition__[id].ease = value;\n    });\n  };\n  d3_transitionPrototype.delay = function(value) {\n    var id = this.id;\n    if (arguments.length < 1) return this.node().__transition__[id].delay;\n    return d3_selection_each(this, typeof value === \"function\" ? function(node, i, j) {\n      node.__transition__[id].delay = +value.call(node, node.__data__, i, j);\n    } : (value = +value, function(node) {\n      node.__transition__[id].delay = value;\n    }));\n  };\n  d3_transitionPrototype.duration = function(value) {\n    var id = this.id;\n    if (arguments.length < 1) return this.node().__transition__[id].duration;\n    return d3_selection_each(this, typeof value === \"function\" ? function(node, i, j) {\n      node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j));\n    } : (value = Math.max(1, value), function(node) {\n      node.__transition__[id].duration = value;\n    }));\n  };\n  d3_transitionPrototype.each = function(type, listener) {\n    var id = this.id;\n    if (arguments.length < 2) {\n      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;\n      d3_transitionInheritId = id;\n      d3_selection_each(this, function(node, i, j) {\n        d3_transitionInherit = node.__transition__[id];\n        type.call(node, node.__data__, i, j);\n      });\n      d3_transitionInherit = inherit;\n      d3_transitionInheritId = inheritId;\n    } else {\n      d3_selection_each(this, function(node) {\n        var transition = node.__transition__[id];\n        (transition.event || (transition.event = d3.dispatch(\"start\", \"end\"))).on(type, listener);\n      });\n    }\n    return this;\n  };\n  d3_transitionPrototype.transition = function() {\n    var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;\n    for (var j = 0, m = this.length; j < m; j++) {\n      subgroups.push(subgroup = []);\n      for (var group = this[j], i = 0, n = group.length; i < n; i++) {\n        if (node = group[i]) {\n          transition = Object.create(node.__transition__[id0]);\n          transition.delay += transition.duration;\n          d3_transitionNode(node, i, id1, transition);\n        }\n        subgroup.push(node);\n      }\n    }\n    return d3_transition(subgroups, id1);\n  };\n  function d3_transitionNode(node, i, id, inherit) {\n    var lock = node.__transition__ || (node.__transition__ = {\n      active: 0,\n      count: 0\n    }), transition = lock[id];\n    if (!transition) {\n      var time = inherit.time;\n      transition = lock[id] = {\n        tween: new d3_Map(),\n        time: time,\n        ease: inherit.ease,\n        delay: inherit.delay,\n        duration: inherit.duration\n      };\n      ++lock.count;\n      d3.timer(function(elapsed) {\n        var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = [];\n        timer.t = delay + time;\n        if (delay <= elapsed) return start(elapsed - delay);\n        timer.c = start;\n        function start(elapsed) {\n          if (lock.active > id) return stop();\n          lock.active = id;\n          transition.event && transition.event.start.call(node, d, i);\n          transition.tween.forEach(function(key, value) {\n            if (value = value.call(node, d, i)) {\n              tweened.push(value);\n            }\n          });\n          d3.timer(function() {\n            timer.c = tick(elapsed || 1) ? d3_true : tick;\n            return 1;\n          }, 0, time);\n        }\n        function tick(elapsed) {\n          if (lock.active !== id) return stop();\n          var t = elapsed / duration, e = ease(t), n = tweened.length;\n          while (n > 0) {\n            tweened[--n].call(node, e);\n          }\n          if (t >= 1) {\n            transition.event && transition.event.end.call(node, d, i);\n            return stop();\n          }\n        }\n        function stop() {\n          if (--lock.count) delete lock[id]; else delete node.__transition__;\n          return 1;\n        }\n      }, 0, time);\n    }\n  }\n  d3.svg.axis = function() {\n    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;\n    function axis(g) {\n      g.each(function() {\n        var g = d3.select(this);\n        var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();\n        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(\".tick\").data(ticks, scale1), tickEnter = tick.enter().insert(\"g\", \".domain\").attr(\"class\", \"tick\").style(\"opacity\", ε), tickExit = d3.transition(tick.exit()).style(\"opacity\", ε).remove(), tickUpdate = d3.transition(tick.order()).style(\"opacity\", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform;\n        var range = d3_scaleRange(scale1), path = g.selectAll(\".domain\").data([ 0 ]), pathUpdate = (path.enter().append(\"path\").attr(\"class\", \"domain\"), \n        d3.transition(path));\n        tickEnter.append(\"line\");\n        tickEnter.append(\"text\");\n        var lineEnter = tickEnter.select(\"line\"), lineUpdate = tickUpdate.select(\"line\"), text = tick.select(\"text\").text(tickFormat), textEnter = tickEnter.select(\"text\"), textUpdate = tickUpdate.select(\"text\"), sign = orient === \"top\" || orient === \"left\" ? -1 : 1, x1, x2, y1, y2;\n        if (orient === \"bottom\" || orient === \"top\") {\n          tickTransform = d3_svg_axisX, x1 = \"x\", y1 = \"y\", x2 = \"x2\", y2 = \"y2\";\n          text.attr(\"dy\", sign < 0 ? \"0em\" : \".71em\").style(\"text-anchor\", \"middle\");\n          pathUpdate.attr(\"d\", \"M\" + range[0] + \",\" + sign * outerTickSize + \"V0H\" + range[1] + \"V\" + sign * outerTickSize);\n        } else {\n          tickTransform = d3_svg_axisY, x1 = \"y\", y1 = \"x\", x2 = \"y2\", y2 = \"x2\";\n          text.attr(\"dy\", \".32em\").style(\"text-anchor\", sign < 0 ? \"end\" : \"start\");\n          pathUpdate.attr(\"d\", \"M\" + sign * outerTickSize + \",\" + range[0] + \"H0V\" + range[1] + \"H\" + sign * outerTickSize);\n        }\n        lineEnter.attr(y2, sign * innerTickSize);\n        textEnter.attr(y1, sign * tickSpacing);\n        lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize);\n        textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing);\n        if (scale1.rangeBand) {\n          var x = scale1, dx = x.rangeBand() / 2;\n          scale0 = scale1 = function(d) {\n            return x(d) + dx;\n          };\n        } else if (scale0.rangeBand) {\n          scale0 = scale1;\n        } else {\n          tickExit.call(tickTransform, scale1, scale0);\n        }\n        tickEnter.call(tickTransform, scale0, scale1);\n        tickUpdate.call(tickTransform, scale1, scale1);\n      });\n    }\n    axis.scale = function(x) {\n      if (!arguments.length) return scale;\n      scale = x;\n      return axis;\n    };\n    axis.orient = function(x) {\n      if (!arguments.length) return orient;\n      orient = x in d3_svg_axisOrients ? x + \"\" : d3_svg_axisDefaultOrient;\n      return axis;\n    };\n    axis.ticks = function() {\n      if (!arguments.length) return tickArguments_;\n      tickArguments_ = arguments;\n      return axis;\n    };\n    axis.tickValues = function(x) {\n      if (!arguments.length) return tickValues;\n      tickValues = x;\n      return axis;\n    };\n    axis.tickFormat = function(x) {\n      if (!arguments.length) return tickFormat_;\n      tickFormat_ = x;\n      return axis;\n    };\n    axis.tickSize = function(x) {\n      var n = arguments.length;\n      if (!n) return innerTickSize;\n      innerTickSize = +x;\n      outerTickSize = +arguments[n - 1];\n      return axis;\n    };\n    axis.innerTickSize = function(x) {\n      if (!arguments.length) return innerTickSize;\n      innerTickSize = +x;\n      return axis;\n    };\n    axis.outerTickSize = function(x) {\n      if (!arguments.length) return outerTickSize;\n      outerTickSize = +x;\n      return axis;\n    };\n    axis.tickPadding = function(x) {\n      if (!arguments.length) return tickPadding;\n      tickPadding = +x;\n      return axis;\n    };\n    axis.tickSubdivide = function() {\n      return arguments.length && axis;\n    };\n    return axis;\n  };\n  var d3_svg_axisDefaultOrient = \"bottom\", d3_svg_axisOrients = {\n    top: 1,\n    right: 1,\n    bottom: 1,\n    left: 1\n  };\n  function d3_svg_axisX(selection, x0, x1) {\n    selection.attr(\"transform\", function(d) {\n      var v0 = x0(d);\n      return \"translate(\" + (isFinite(v0) ? v0 : x1(d)) + \",0)\";\n    });\n  }\n  function d3_svg_axisY(selection, y0, y1) {\n    selection.attr(\"transform\", function(d) {\n      var v0 = y0(d);\n      return \"translate(0,\" + (isFinite(v0) ? v0 : y1(d)) + \")\";\n    });\n  }\n  d3.svg.brush = function() {\n    var event = d3_eventDispatch(brush, \"brushstart\", \"brush\", \"brushend\"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];\n    function brush(g) {\n      g.each(function() {\n        var g = d3.select(this).style(\"pointer-events\", \"all\").style(\"-webkit-tap-highlight-color\", \"rgba(0,0,0,0)\").on(\"mousedown.brush\", brushstart).on(\"touchstart.brush\", brushstart);\n        var background = g.selectAll(\".background\").data([ 0 ]);\n        background.enter().append(\"rect\").attr(\"class\", \"background\").style(\"visibility\", \"hidden\").style(\"cursor\", \"crosshair\");\n        g.selectAll(\".extent\").data([ 0 ]).enter().append(\"rect\").attr(\"class\", \"extent\").style(\"cursor\", \"move\");\n        var resize = g.selectAll(\".resize\").data(resizes, d3_identity);\n        resize.exit().remove();\n        resize.enter().append(\"g\").attr(\"class\", function(d) {\n          return \"resize \" + d;\n        }).style(\"cursor\", function(d) {\n          return d3_svg_brushCursor[d];\n        }).append(\"rect\").attr(\"x\", function(d) {\n          return /[ew]$/.test(d) ? -3 : null;\n        }).attr(\"y\", function(d) {\n          return /^[ns]/.test(d) ? -3 : null;\n        }).attr(\"width\", 6).attr(\"height\", 6).style(\"visibility\", \"hidden\");\n        resize.style(\"display\", brush.empty() ? \"none\" : null);\n        var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;\n        if (x) {\n          range = d3_scaleRange(x);\n          backgroundUpdate.attr(\"x\", range[0]).attr(\"width\", range[1] - range[0]);\n          redrawX(gUpdate);\n        }\n        if (y) {\n          range = d3_scaleRange(y);\n          backgroundUpdate.attr(\"y\", range[0]).attr(\"height\", range[1] - range[0]);\n          redrawY(gUpdate);\n        }\n        redraw(gUpdate);\n      });\n    }\n    brush.event = function(g) {\n      g.each(function() {\n        var event_ = event.of(this, arguments), extent1 = {\n          x: xExtent,\n          y: yExtent,\n          i: xExtentDomain,\n          j: yExtentDomain\n        }, extent0 = this.__chart__ || extent1;\n        this.__chart__ = extent1;\n        if (d3_transitionInheritId) {\n          d3.select(this).transition().each(\"start.brush\", function() {\n            xExtentDomain = extent0.i;\n            yExtentDomain = extent0.j;\n            xExtent = extent0.x;\n            yExtent = extent0.y;\n            event_({\n              type: \"brushstart\"\n            });\n          }).tween(\"brush:brush\", function() {\n            var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);\n            xExtentDomain = yExtentDomain = null;\n            return function(t) {\n              xExtent = extent1.x = xi(t);\n              yExtent = extent1.y = yi(t);\n              event_({\n                type: \"brush\",\n                mode: \"resize\"\n              });\n            };\n          }).each(\"end.brush\", function() {\n            xExtentDomain = extent1.i;\n            yExtentDomain = extent1.j;\n            event_({\n              type: \"brush\",\n              mode: \"resize\"\n            });\n            event_({\n              type: \"brushend\"\n            });\n          });\n        } else {\n          event_({\n            type: \"brushstart\"\n          });\n          event_({\n            type: \"brush\",\n            mode: \"resize\"\n          });\n          event_({\n            type: \"brushend\"\n          });\n        }\n      });\n    };\n    function redraw(g) {\n      g.selectAll(\".resize\").attr(\"transform\", function(d) {\n        return \"translate(\" + xExtent[+/e$/.test(d)] + \",\" + yExtent[+/^s/.test(d)] + \")\";\n      });\n    }\n    function redrawX(g) {\n      g.select(\".extent\").attr(\"x\", xExtent[0]);\n      g.selectAll(\".extent,.n>rect,.s>rect\").attr(\"width\", xExtent[1] - xExtent[0]);\n    }\n    function redrawY(g) {\n      g.select(\".extent\").attr(\"y\", yExtent[0]);\n      g.selectAll(\".extent,.e>rect,.w>rect\").attr(\"height\", yExtent[1] - yExtent[0]);\n    }\n    function brushstart() {\n      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed(\"extent\"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset;\n      var w = d3.select(d3_window).on(\"keydown.brush\", keydown).on(\"keyup.brush\", keyup);\n      if (d3.event.changedTouches) {\n        w.on(\"touchmove.brush\", brushmove).on(\"touchend.brush\", brushend);\n      } else {\n        w.on(\"mousemove.brush\", brushmove).on(\"mouseup.brush\", brushend);\n      }\n      g.interrupt().selectAll(\"*\").interrupt();\n      if (dragging) {\n        origin[0] = xExtent[0] - origin[0];\n        origin[1] = yExtent[0] - origin[1];\n      } else if (resizing) {\n        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);\n        offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];\n        origin[0] = xExtent[ex];\n        origin[1] = yExtent[ey];\n      } else if (d3.event.altKey) center = origin.slice();\n      g.style(\"pointer-events\", \"none\").selectAll(\".resize\").style(\"display\", null);\n      d3.select(\"body\").style(\"cursor\", eventTarget.style(\"cursor\"));\n      event_({\n        type: \"brushstart\"\n      });\n      brushmove();\n      function keydown() {\n        if (d3.event.keyCode == 32) {\n          if (!dragging) {\n            center = null;\n            origin[0] -= xExtent[1];\n            origin[1] -= yExtent[1];\n            dragging = 2;\n          }\n          d3_eventPreventDefault();\n        }\n      }\n      function keyup() {\n        if (d3.event.keyCode == 32 && dragging == 2) {\n          origin[0] += xExtent[1];\n          origin[1] += yExtent[1];\n          dragging = 0;\n          d3_eventPreventDefault();\n        }\n      }\n      function brushmove() {\n        var point = d3.mouse(target), moved = false;\n        if (offset) {\n          point[0] += offset[0];\n          point[1] += offset[1];\n        }\n        if (!dragging) {\n          if (d3.event.altKey) {\n            if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];\n            origin[0] = xExtent[+(point[0] < center[0])];\n            origin[1] = yExtent[+(point[1] < center[1])];\n          } else center = null;\n        }\n        if (resizingX && move1(point, x, 0)) {\n          redrawX(g);\n          moved = true;\n        }\n        if (resizingY && move1(point, y, 1)) {\n          redrawY(g);\n          moved = true;\n        }\n        if (moved) {\n          redraw(g);\n          event_({\n            type: \"brush\",\n            mode: dragging ? \"move\" : \"resize\"\n          });\n        }\n      }\n      function move1(point, scale, i) {\n        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;\n        if (dragging) {\n          r0 -= position;\n          r1 -= size + position;\n        }\n        min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];\n        if (dragging) {\n          max = (min += position) + size;\n        } else {\n          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));\n          if (position < min) {\n            max = min;\n            min = position;\n          } else {\n            max = position;\n          }\n        }\n        if (extent[0] != min || extent[1] != max) {\n          if (i) yExtentDomain = null; else xExtentDomain = null;\n          extent[0] = min;\n          extent[1] = max;\n          return true;\n        }\n      }\n      function brushend() {\n        brushmove();\n        g.style(\"pointer-events\", \"all\").selectAll(\".resize\").style(\"display\", brush.empty() ? \"none\" : null);\n        d3.select(\"body\").style(\"cursor\", null);\n        w.on(\"mousemove.brush\", null).on(\"mouseup.brush\", null).on(\"touchmove.brush\", null).on(\"touchend.brush\", null).on(\"keydown.brush\", null).on(\"keyup.brush\", null);\n        dragRestore();\n        event_({\n          type: \"brushend\"\n        });\n      }\n    }\n    brush.x = function(z) {\n      if (!arguments.length) return x;\n      x = z;\n      resizes = d3_svg_brushResizes[!x << 1 | !y];\n      return brush;\n    };\n    brush.y = function(z) {\n      if (!arguments.length) return y;\n      y = z;\n      resizes = d3_svg_brushResizes[!x << 1 | !y];\n      return brush;\n    };\n    brush.clamp = function(z) {\n      if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;\n      if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;\n      return brush;\n    };\n    brush.extent = function(z) {\n      var x0, x1, y0, y1, t;\n      if (!arguments.length) {\n        if (x) {\n          if (xExtentDomain) {\n            x0 = xExtentDomain[0], x1 = xExtentDomain[1];\n          } else {\n            x0 = xExtent[0], x1 = xExtent[1];\n            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);\n            if (x1 < x0) t = x0, x0 = x1, x1 = t;\n          }\n        }\n        if (y) {\n          if (yExtentDomain) {\n            y0 = yExtentDomain[0], y1 = yExtentDomain[1];\n          } else {\n            y0 = yExtent[0], y1 = yExtent[1];\n            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);\n            if (y1 < y0) t = y0, y0 = y1, y1 = t;\n          }\n        }\n        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];\n      }\n      if (x) {\n        x0 = z[0], x1 = z[1];\n        if (y) x0 = x0[0], x1 = x1[0];\n        xExtentDomain = [ x0, x1 ];\n        if (x.invert) x0 = x(x0), x1 = x(x1);\n        if (x1 < x0) t = x0, x0 = x1, x1 = t;\n        if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];\n      }\n      if (y) {\n        y0 = z[0], y1 = z[1];\n        if (x) y0 = y0[1], y1 = y1[1];\n        yExtentDomain = [ y0, y1 ];\n        if (y.invert) y0 = y(y0), y1 = y(y1);\n        if (y1 < y0) t = y0, y0 = y1, y1 = t;\n        if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];\n      }\n      return brush;\n    };\n    brush.clear = function() {\n      if (!brush.empty()) {\n        xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];\n        xExtentDomain = yExtentDomain = null;\n      }\n      return brush;\n    };\n    brush.empty = function() {\n      return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];\n    };\n    return d3.rebind(brush, event, \"on\");\n  };\n  var d3_svg_brushCursor = {\n    n: \"ns-resize\",\n    e: \"ew-resize\",\n    s: \"ns-resize\",\n    w: \"ew-resize\",\n    nw: \"nwse-resize\",\n    ne: \"nesw-resize\",\n    se: \"nwse-resize\",\n    sw: \"nesw-resize\"\n  };\n  var d3_svg_brushResizes = [ [ \"n\", \"e\", \"s\", \"w\", \"nw\", \"ne\", \"se\", \"sw\" ], [ \"e\", \"w\" ], [ \"n\", \"s\" ], [] ];\n  var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;\n  var d3_time_formatUtc = d3_time_format.utc;\n  var d3_time_formatIso = d3_time_formatUtc(\"%Y-%m-%dT%H:%M:%S.%LZ\");\n  d3_time_format.iso = Date.prototype.toISOString && +new Date(\"2000-01-01T00:00:00.000Z\") ? d3_time_formatIsoNative : d3_time_formatIso;\n  function d3_time_formatIsoNative(date) {\n    return date.toISOString();\n  }\n  d3_time_formatIsoNative.parse = function(string) {\n    var date = new Date(string);\n    return isNaN(date) ? null : date;\n  };\n  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;\n  d3_time.second = d3_time_interval(function(date) {\n    return new d3_date(Math.floor(date / 1e3) * 1e3);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 1e3);\n  }, function(date) {\n    return date.getSeconds();\n  });\n  d3_time.seconds = d3_time.second.range;\n  d3_time.seconds.utc = d3_time.second.utc.range;\n  d3_time.minute = d3_time_interval(function(date) {\n    return new d3_date(Math.floor(date / 6e4) * 6e4);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 6e4);\n  }, function(date) {\n    return date.getMinutes();\n  });\n  d3_time.minutes = d3_time.minute.range;\n  d3_time.minutes.utc = d3_time.minute.utc.range;\n  d3_time.hour = d3_time_interval(function(date) {\n    var timezone = date.getTimezoneOffset() / 60;\n    return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);\n  }, function(date, offset) {\n    date.setTime(date.getTime() + Math.floor(offset) * 36e5);\n  }, function(date) {\n    return date.getHours();\n  });\n  d3_time.hours = d3_time.hour.range;\n  d3_time.hours.utc = d3_time.hour.utc.range;\n  d3_time.month = d3_time_interval(function(date) {\n    date = d3_time.day(date);\n    date.setDate(1);\n    return date;\n  }, function(date, offset) {\n    date.setMonth(date.getMonth() + offset);\n  }, function(date) {\n    return date.getMonth();\n  });\n  d3_time.months = d3_time.month.range;\n  d3_time.months.utc = d3_time.month.utc.range;\n  function d3_time_scale(linear, methods, format) {\n    function scale(x) {\n      return linear(x);\n    }\n    scale.invert = function(x) {\n      return d3_time_scaleDate(linear.invert(x));\n    };\n    scale.domain = function(x) {\n      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);\n      linear.domain(x);\n      return scale;\n    };\n    function tickMethod(extent, count) {\n      var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);\n      return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {\n        return d / 31536e6;\n      }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];\n    }\n    scale.nice = function(interval, skip) {\n      var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === \"number\" && tickMethod(extent, interval);\n      if (method) interval = method[0], skip = method[1];\n      function skipped(date) {\n        return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;\n      }\n      return scale.domain(d3_scale_nice(domain, skip > 1 ? {\n        floor: function(date) {\n          while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);\n          return date;\n        },\n        ceil: function(date) {\n          while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);\n          return date;\n        }\n      } : interval));\n    };\n    scale.ticks = function(interval, skip) {\n      var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === \"number\" ? tickMethod(extent, interval) : !interval.range && [ {\n        range: interval\n      }, skip ];\n      if (method) interval = method[0], skip = method[1];\n      return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);\n    };\n    scale.tickFormat = function() {\n      return format;\n    };\n    scale.copy = function() {\n      return d3_time_scale(linear.copy(), methods, format);\n    };\n    return d3_scale_linearRebind(scale, linear);\n  }\n  function d3_time_scaleDate(t) {\n    return new Date(t);\n  }\n  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];\n  var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];\n  var d3_time_scaleLocalFormat = d3_time_format.multi([ [ \".%L\", function(d) {\n    return d.getMilliseconds();\n  } ], [ \":%S\", function(d) {\n    return d.getSeconds();\n  } ], [ \"%I:%M\", function(d) {\n    return d.getMinutes();\n  } ], [ \"%I %p\", function(d) {\n    return d.getHours();\n  } ], [ \"%a %d\", function(d) {\n    return d.getDay() && d.getDate() != 1;\n  } ], [ \"%b %d\", function(d) {\n    return d.getDate() != 1;\n  } ], [ \"%B\", function(d) {\n    return d.getMonth();\n  } ], [ \"%Y\", d3_true ] ]);\n  var d3_time_scaleMilliseconds = {\n    range: function(start, stop, step) {\n      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);\n    },\n    floor: d3_identity,\n    ceil: d3_identity\n  };\n  d3_time_scaleLocalMethods.year = d3_time.year;\n  d3_time.scale = function() {\n    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);\n  };\n  var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {\n    return [ m[0].utc, m[1] ];\n  });\n  var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ \".%L\", function(d) {\n    return d.getUTCMilliseconds();\n  } ], [ \":%S\", function(d) {\n    return d.getUTCSeconds();\n  } ], [ \"%I:%M\", function(d) {\n    return d.getUTCMinutes();\n  } ], [ \"%I %p\", function(d) {\n    return d.getUTCHours();\n  } ], [ \"%a %d\", function(d) {\n    return d.getUTCDay() && d.getUTCDate() != 1;\n  } ], [ \"%b %d\", function(d) {\n    return d.getUTCDate() != 1;\n  } ], [ \"%B\", function(d) {\n    return d.getUTCMonth();\n  } ], [ \"%Y\", d3_true ] ]);\n  d3_time_scaleUtcMethods.year = d3_time.year.utc;\n  d3_time.scale.utc = function() {\n    return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);\n  };\n  d3.text = d3_xhrType(function(request) {\n    return request.responseText;\n  });\n  d3.json = function(url, callback) {\n    return d3_xhr(url, \"application/json\", d3_json, callback);\n  };\n  function d3_json(request) {\n    return JSON.parse(request.responseText);\n  }\n  d3.html = function(url, callback) {\n    return d3_xhr(url, \"text/html\", d3_html, callback);\n  };\n  function d3_html(request) {\n    var range = d3_document.createRange();\n    range.selectNode(d3_document.body);\n    return range.createContextualFragment(request.responseText);\n  }\n  d3.xml = d3_xhrType(function(request) {\n    return request.responseXML;\n  });\n  if (typeof define === \"function\" && define.amd) define(d3); else if (typeof module === \"object\" && module.exports) module.exports = d3;\n  this.d3 = d3;\n}();"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/.bower.json",
    "content": "{\n  \"name\": \"jquery\",\n  \"version\": \"2.1.3\",\n  \"main\": \"dist/jquery.js\",\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"build\",\n    \"speed\",\n    \"test\",\n    \"*.md\",\n    \"AUTHORS.txt\",\n    \"Gruntfile.js\",\n    \"package.json\"\n  ],\n  \"devDependencies\": {\n    \"sizzle\": \"2.1.1-jquery.2.1.2\",\n    \"requirejs\": \"2.1.10\",\n    \"qunit\": \"1.14.0\",\n    \"sinon\": \"1.8.1\"\n  },\n  \"keywords\": [\n    \"jquery\",\n    \"javascript\",\n    \"library\"\n  ],\n  \"homepage\": \"https://github.com/jquery/jquery\",\n  \"_release\": \"2.1.3\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"2.1.3\",\n    \"commit\": \"8f2a9d9272d6ed7f32d3a484740ab342c02541e0\"\n  },\n  \"_source\": \"git://github.com/jquery/jquery.git\",\n  \"_target\": \"~2.1.3\",\n  \"_originalSource\": \"jquery\"\n}"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/MIT-LICENSE.txt",
    "content": "Copyright 2014 jQuery Foundation and other contributors\nhttp://jquery.com/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/bower.json",
    "content": "{\n  \"name\": \"jquery\",\n  \"version\": \"2.1.3\",\n  \"main\": \"dist/jquery.js\",\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"build\",\n    \"speed\",\n    \"test\",\n    \"*.md\",\n    \"AUTHORS.txt\",\n    \"Gruntfile.js\",\n    \"package.json\"\n  ],\n  \"devDependencies\": {\n    \"sizzle\": \"2.1.1-jquery.2.1.2\",\n    \"requirejs\": \"2.1.10\",\n    \"qunit\": \"1.14.0\",\n    \"sinon\": \"1.8.1\"\n  },\n  \"keywords\": [\n    \"jquery\",\n    \"javascript\",\n    \"library\"\n  ]\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/dist/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v2.1.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-18T15:11Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Support: Firefox 18+\n// Can't be in strict mode, several libs including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n//\n\nvar arr = [];\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\tversion = \"2.1.3\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android<4.1\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\treturn !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\t// Support: Android<4.0, iOS<6 (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE9-11+\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android<4.1\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: Date.now,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\tnodeType = context.nodeType;\n\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\tif ( !seed && documentIsHTML ) {\n\n\t\t// Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType !== 1 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = attrs.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\tparent = doc.defaultView;\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Support tests\n\t---------------------------------------------------------------------- */\n\tdocumentIsHTML = !isXML( doc );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\f]' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = doc.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn doc;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (oldCache = outerCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\touterCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is no seed and only one group\n\tif ( match.length === 1 ) {\n\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"<input/>\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t});\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t});\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( indexOf.call( qualifier, elem ) >= 0 ) !== not;\n\t});\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t}));\n};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tlen = this.length,\n\t\t\tret = [],\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], true) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n});\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[0] === \"<\" && selector[ selector.length - 1 ] === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Support: Blackberry 4.6\n\t\t\t\t\t// gEBID returns nodes no longer in the document (#6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\nfunction sibling( cur, dir ) {\n\twhile ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\nvar rnotwhite = (/\\S+/g);\n\n\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// Add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\n\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n});\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\twindow.removeEventListener( \"load\", completed, false );\n\tjQuery.ready();\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// We once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Kick off the DOM ready check even if the user does not\njQuery.ready.promise();\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlen ? fn( elems[0], key ) : emptyGet;\n};\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( owner ) {\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\t/* jshint -W018 */\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\nfunction Data() {\n\t// Support: Android<4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\nData.accepts = jQuery.acceptData;\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android<4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\nvar data_priv = new Data();\n\nvar data_user = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend({\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdata_priv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( this, key );\n\t\t});\n\t}\n});\n\n\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = data_priv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = data_priv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar pnum = (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Safari<=5.1\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Safari<=5.1, Android<4.2\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<=11+\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n})();\nvar strundefined = typeof undefined;\n\n\n\nsupport.focusinBubbles = \"onfocusin\" in window;\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && jQuery.acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( data_priv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome<28\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\t\t\t\t// Support: Android<4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// Support: Chrome 15+\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// Support: Firefox, Chrome, Safari\n// Create \"bubbling\" focus and blur events\nif ( !support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdata_priv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdata_priv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdata_priv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n\n\nvar\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\n\t\t// Support: IE9\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE9\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: 1.x compatibility\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement(\"tbody\") ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [],\n\t\t\ti = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type, key,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( jQuery.acceptData( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each(function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map(function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( node.textContent.replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: QtWebKit\n\t\t\t// .get() because push.apply(_, arraylike) throws\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar style,\n\t\telem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?\n\n\t\t\t// Use of this method is a temporary fix (more like optimization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\tstyle.display : jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = (iframe || jQuery( \"<iframe frameborder='0' width='0' height='0'/>\" )).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = iframe[ 0 ].contentDocument;\n\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\nvar rmargin = (/^margin/);\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tif ( elem.ownerDocument.defaultView.opener ) {\n\t\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t\t}\n\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// Support: IE9\n\t// getPropertyValue is only needed for .css('filter') (#12537)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\t}\n\n\tif ( computed ) {\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// Support: iOS < 6\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn (this.get = hookFn).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\n(function() {\n\tvar pixelPositionVal, boxSizingReliableVal,\n\t\tdocElem = document.documentElement,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE9-11+\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tcontainer.style.cssText = \"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;\" +\n\t\t\"position:absolute\";\n\tcontainer.appendChild( div );\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computePixelPositionAndBoxSizingReliable() {\n\t\tdiv.style.cssText =\n\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;\" +\n\t\t\t\"box-sizing:border-box;display:block;margin-top:1%;top:1%;\" +\n\t\t\t\"border:1px;padding:1px;width:4px;position:absolute\";\n\t\tdiv.innerHTML = \"\";\n\t\tdocElem.appendChild( container );\n\n\t\tvar divStyle = window.getComputedStyle( div, null );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\tdocElem.removeChild( container );\n\t}\n\n\t// Support: node.js jsdom\n\t// Don't assume that getComputedStyle is a property of the global object\n\tif ( window.getComputedStyle ) {\n\t\tjQuery.extend( support, {\n\t\t\tpixelPosition: function() {\n\n\t\t\t\t// This test is executed only once but we still do memoizing\n\t\t\t\t// since we can use the boxSizingReliable pre-computing.\n\t\t\t\t// No need to check if the test was already performed, though.\n\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\treturn pixelPositionVal;\n\t\t\t},\n\t\t\tboxSizingReliable: function() {\n\t\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\t}\n\t\t\t\treturn boxSizingReliableVal;\n\t\t\t},\n\t\t\treliableMarginRight: function() {\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// This support function is only executed once so no memoizing is needed.\n\t\t\t\tvar ret,\n\t\t\t\t\tmarginDiv = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\t\tmarginDiv.style.cssText = div.style.cssText =\n\t\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\t\tdiv.style.width = \"1px\";\n\t\t\t\tdocElem.appendChild( container );\n\n\t\t\t\tret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );\n\n\t\t\t\tdocElem.removeChild( container );\n\t\t\t\tdiv.removeChild( marginDiv );\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t});\n\t}\n})();\n\n\n// A method for quickly swapping in/out CSS properties to get correct calculations.\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar\n\t// Swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + pnum + \")\", \"i\" ),\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// Check for vendor prefixed names\n\tvar capName = name[0].toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// Both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// At this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// At this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// At this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// Some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// Check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox &&\n\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// Use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = data_priv.get( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = data_priv.access( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display !== \"none\" || !hidden ) {\n\t\t\t\tdata_priv.set( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.extend({\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t\"float\": \"cssFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n});\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) && elem.offsetWidth === 0 ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\n// Support: Android 2.3\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE9\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t}\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +target ) &&\n\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( start && start[ 3 ] !== unit ) {\n\t\t\t\t// Trust units reported by jQuery.css\n\t\t\t\tunit = unit || start[ 3 ];\n\n\t\t\t\t// Make sure we update the tween properties later on\n\t\t\t\tparts = parts || [];\n\n\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\tstart = +target || 1;\n\n\t\t\t\tdo {\n\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t// Adjust and apply\n\t\t\t\t\tstart = start / scale;\n\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur(),\n\t\t\t\t// break the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t}\n\n\t\t\t// Update tween properties\n\t\t\tif ( parts ) {\n\t\t\t\tstart = tween.start = +start || +target || 0;\n\t\t\t\ttween.unit = unit;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[ 1 ] ?\n\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n\t\t\t\t\t+parts[ 2 ];\n\t\t\t}\n\n\t\t\treturn tween;\n\t\t} ]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( (tween = collection[ index ].call( animation, prop, value )) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = data_priv.get( elem, \"fxshow\" );\n\n\t// Handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// Height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE9-10 do not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tdata_priv.get( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\t\t\tstyle.display = \"inline-block\";\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always(function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t});\n\t}\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = data_priv.access( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// Store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\n\t\t\tdata_priv.remove( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( (display === \"none\" ? defaultDisplay( elem.nodeName ) : display) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || data_priv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = data_priv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = data_priv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\tclearTimeout( timeout );\n\t\t};\n\t});\n};\n\n\n(function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: iOS<=5.1, Android<=4.2+\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE<=11+\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: Android<=2.3\n\t// Options inside disabled selects are incorrectly marked as disabled\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<=11+\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n})();\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tjQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle;\n\t\tif ( !isXML ) {\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ name ];\n\t\t\tattrHandle[ name ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tname.toLowerCase() :\n\t\t\t\tnull;\n\t\t\tattrHandle[ name ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n});\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i;\n\njQuery.fn.extend({\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\treturn hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n\t\t\t\tret :\n\t\t\t\t( elem[ name ] = value );\n\n\t\t} else {\n\t\t\treturn hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ?\n\t\t\t\tret :\n\t\t\t\telem[ name ];\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.hasAttribute( \"tabindex\" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n\t\t\t\t\telem.tabIndex :\n\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n\n\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\njQuery.fn.extend({\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// Toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tdata_priv.set( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : data_priv.get( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n});\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend({\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// Handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\tjQuery.trim( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// IE6-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( support.optDisabled ? !option.disabled : option.getAttribute( \"disabled\" ) === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\t\t\t\t\tif ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Radios and checkboxes getter/setter\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t};\n\t}\n});\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.extend({\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n\n\nvar nonce = jQuery.now();\n\nvar rquery = (/\\?/);\n\n\n\n// Support: Android 2.3\n// Workaround failure to string-cast null input\njQuery.parseJSON = function( data ) {\n\treturn JSON.parse( data + \"\" );\n};\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml, tmp;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE9\n\ttry {\n\t\ttmp = new DOMParser();\n\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Document location\n\tajaxLocation = window.location.href,\n\n\t// Segment location into parts\n\tajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t});\n};\n\n\njQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[ 0 ] ) {\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\n\n\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0;\n};\njQuery.expr.filters.visible = function( elem ) {\n\treturn !jQuery.expr.filters.hidden( elem );\n};\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function() {\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new XMLHttpRequest();\n\t} catch( e ) {}\n};\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSuccessStatus = {\n\t\t// file protocol always yields status code 0, assume 200\n\t\t0: 200,\n\t\t// Support: IE9\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE9\n// Open requests must be manually aborted on unload (#5280)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]();\n\t\t}\n\t});\n}\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport(function( options ) {\n\tvar callback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t// file: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\t\t\t\t\t\t\t\t\t// Support: IE9\n\t\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === \"string\" ? {\n\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n\t\t\t\t\t\t\t\t\t} : undefined,\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\txhr.onerror = callback(\"error\");\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = xhrCallbacks[ id ] = callback(\"abort\");\n\n\t\t\t\ttry {\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery(\"<script>\").prop({\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t}).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// data: string of html\n// context (optional): If specified, the fragment will be created in this context, defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\tcontext = context || document;\n\n\tvar parsed = rsingleTag.exec( data ),\n\t\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[1] ) ];\n\t}\n\n\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = jQuery.trim( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n});\n\n\n\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t}).length;\n};\n\n\n\n\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf(\"auto\") > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend({\n\toffset: function( options ) {\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each(function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t});\n\t\t}\n\n\t\tvar docElem, win,\n\t\t\telem = this[ 0 ],\n\t\t\tbox = { top: 0, left: 0 },\n\t\t\tdoc = elem && elem.ownerDocument;\n\n\t\tif ( !doc ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure it's not a disconnected DOM node\n\t\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box;\n\t\t}\n\n\t\t// Support: BlackBerry 5, iOS 3 (original iPhone)\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\tif ( typeof elem.getBoundingClientRect !== strundefined ) {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t}\n\t\twin = getWindow( doc );\n\t\treturn {\n\t\t\ttop: box.top + win.pageYOffset - docElem.clientTop,\n\t\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\n\t\t};\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : window.pageXOffset,\n\t\t\t\t\ttop ? val : window.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\n// Support: Safari<7+, Chrome<37+\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n});\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t});\n}\n\n\n\n\nvar\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === strundefined ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n\n}));\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/jsonp.js",
    "content": "define([\n\t\"../core\",\n\t\"./var/nonce\",\n\t\"./var/rquery\",\n\t\"../ajax\"\n], function( jQuery, nonce, rquery ) {\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/load.js",
    "content": "define([\n\t\"../core\",\n\t\"../core/parseHTML\",\n\t\"../ajax\",\n\t\"../traversing\",\n\t\"../manipulation\",\n\t\"../selector\",\n\t// Optional event/alias dependency\n\t\"../event/alias\"\n], function( jQuery ) {\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = jQuery.trim( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/parseJSON.js",
    "content": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Support: Android 2.3\n// Workaround failure to string-cast null input\njQuery.parseJSON = function( data ) {\n\treturn JSON.parse( data + \"\" );\n};\n\nreturn jQuery.parseJSON;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/parseXML.js",
    "content": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml, tmp;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE9\n\ttry {\n\t\ttmp = new DOMParser();\n\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\nreturn jQuery.parseXML;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/script.js",
    "content": "define([\n\t\"../core\",\n\t\"../ajax\"\n], function( jQuery ) {\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery(\"<script>\").prop({\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t}).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/var/nonce.js",
    "content": "define([\n\t\"../../core\"\n], function( jQuery ) {\n\treturn jQuery.now();\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/var/rquery.js",
    "content": "define(function() {\n\treturn (/\\?/);\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax/xhr.js",
    "content": "define([\n\t\"../core\",\n\t\"../var/support\",\n\t\"../ajax\"\n], function( jQuery, support ) {\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new XMLHttpRequest();\n\t} catch( e ) {}\n};\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSuccessStatus = {\n\t\t// file protocol always yields status code 0, assume 200\n\t\t0: 200,\n\t\t// Support: IE9\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE9\n// Open requests must be manually aborted on unload (#5280)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]();\n\t\t}\n\t});\n}\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport(function( options ) {\n\tvar callback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t// file: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\t\t\t\t\t\t\t\t\t// Support: IE9\n\t\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === \"string\" ? {\n\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n\t\t\t\t\t\t\t\t\t} : undefined,\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\txhr.onerror = callback(\"error\");\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = xhrCallbacks[ id ] = callback(\"abort\");\n\n\t\t\t\ttry {\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/ajax.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/rnotwhite\",\n\t\"./ajax/var/nonce\",\n\t\"./ajax/var/rquery\",\n\t\"./core/init\",\n\t\"./ajax/parseJSON\",\n\t\"./ajax/parseXML\",\n\t\"./deferred\"\n], function( jQuery, rnotwhite, nonce, rquery ) {\n\nvar\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Document location\n\tajaxLocation = window.location.href,\n\n\t// Segment location into parts\n\tajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/attributes/attr.js",
    "content": "define([\n\t\"../core\",\n\t\"../var/rnotwhite\",\n\t\"../var/strundefined\",\n\t\"../core/access\",\n\t\"./support\",\n\t\"../selector\"\n], function( jQuery, rnotwhite, strundefined, access, support ) {\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tjQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle;\n\t\tif ( !isXML ) {\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ name ];\n\t\t\tattrHandle[ name ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tname.toLowerCase() :\n\t\t\t\tnull;\n\t\t\tattrHandle[ name ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/attributes/classes.js",
    "content": "define([\n\t\"../core\",\n\t\"../var/rnotwhite\",\n\t\"../var/strundefined\",\n\t\"../data/var/data_priv\",\n\t\"../core/init\"\n], function( jQuery, rnotwhite, strundefined, data_priv ) {\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\njQuery.fn.extend({\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// Toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tdata_priv.set( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : data_priv.get( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/attributes/prop.js",
    "content": "define([\n\t\"../core\",\n\t\"../core/access\",\n\t\"./support\"\n], function( jQuery, access, support ) {\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i;\n\njQuery.fn.extend({\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\treturn hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n\t\t\t\tret :\n\t\t\t\t( elem[ name ] = value );\n\n\t\t} else {\n\t\t\treturn hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ?\n\t\t\t\tret :\n\t\t\t\telem[ name ];\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.hasAttribute( \"tabindex\" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n\t\t\t\t\telem.tabIndex :\n\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/attributes/support.js",
    "content": "define([\n\t\"../var/support\"\n], function( support ) {\n\n(function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: iOS<=5.1, Android<=4.2+\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE<=11+\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: Android<=2.3\n\t// Options inside disabled selects are incorrectly marked as disabled\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<=11+\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n})();\n\nreturn support;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/attributes/val.js",
    "content": "define([\n\t\"../core\",\n\t\"./support\",\n\t\"../core/init\"\n], function( jQuery, support ) {\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend({\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// Handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\tjQuery.trim( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// IE6-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( support.optDisabled ? !option.disabled : option.getAttribute( \"disabled\" ) === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\t\t\t\t\tif ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Radios and checkboxes getter/setter\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t};\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/attributes.js",
    "content": "define([\n\t\"./core\",\n\t\"./attributes/attr\",\n\t\"./attributes/prop\",\n\t\"./attributes/classes\",\n\t\"./attributes/val\"\n], function( jQuery ) {\n\n// Return jQuery for attributes-only inclusion\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/callbacks.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/rnotwhite\"\n], function( jQuery, rnotwhite ) {\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/core/access.js",
    "content": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlen ? fn( elems[0], key ) : emptyGet;\n};\n\nreturn access;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/core/init.js",
    "content": "// Initialize a jQuery object\ndefine([\n\t\"../core\",\n\t\"./var/rsingleTag\",\n\t\"../traversing/findFilter\"\n], function( jQuery, rsingleTag ) {\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[0] === \"<\" && selector[ selector.length - 1 ] === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Support: Blackberry 4.6\n\t\t\t\t\t// gEBID returns nodes no longer in the document (#6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\nreturn init;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/core/parseHTML.js",
    "content": "define([\n\t\"../core\",\n\t\"./var/rsingleTag\",\n\t\"../manipulation\" // buildFragment\n], function( jQuery, rsingleTag ) {\n\n// data: string of html\n// context (optional): If specified, the fragment will be created in this context, defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\tcontext = context || document;\n\n\tvar parsed = rsingleTag.exec( data ),\n\t\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[1] ) ];\n\t}\n\n\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\nreturn jQuery.parseHTML;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/core/ready.js",
    "content": "define([\n\t\"../core\",\n\t\"../core/init\",\n\t\"../deferred\"\n], function( jQuery ) {\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n});\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\twindow.removeEventListener( \"load\", completed, false );\n\tjQuery.ready();\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// We once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Kick off the DOM ready check even if the user does not\njQuery.ready.promise();\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/core/var/rsingleTag.js",
    "content": "define(function() {\n\t// Match a standalone tag\n\treturn (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/core.js",
    "content": "define([\n\t\"./var/arr\",\n\t\"./var/slice\",\n\t\"./var/concat\",\n\t\"./var/push\",\n\t\"./var/indexOf\",\n\t\"./var/class2type\",\n\t\"./var/toString\",\n\t\"./var/hasOwn\",\n\t\"./var/support\"\n], function( arr, slice, concat, push, indexOf, class2type, toString, hasOwn, support ) {\n\nvar\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\tversion = \"@VERSION\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android<4.1\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\treturn !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\t// Support: Android<4.0, iOS<6 (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE9-11+\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android<4.1\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: Date.now,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/addGetHookIf.js",
    "content": "define(function() {\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn (this.get = hookFn).apply( this, arguments );\n\t\t}\n\t};\n}\n\nreturn addGetHookIf;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/curCSS.js",
    "content": "define([\n\t\"../core\",\n\t\"./var/rnumnonpx\",\n\t\"./var/rmargin\",\n\t\"./var/getStyles\",\n\t\"../selector\" // contains\n], function( jQuery, rnumnonpx, rmargin, getStyles ) {\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// Support: IE9\n\t// getPropertyValue is only needed for .css('filter') (#12537)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\t}\n\n\tif ( computed ) {\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// Support: iOS < 6\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\nreturn curCSS;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/defaultDisplay.js",
    "content": "define([\n\t\"../core\",\n\t\"../manipulation\" // appendTo\n], function( jQuery ) {\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar style,\n\t\telem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?\n\n\t\t\t// Use of this method is a temporary fix (more like optimization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\tstyle.display : jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = (iframe || jQuery( \"<iframe frameborder='0' width='0' height='0'/>\" )).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = iframe[ 0 ].contentDocument;\n\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\n\nreturn defaultDisplay;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/hiddenVisibleSelectors.js",
    "content": "define([\n\t\"../core\",\n\t\"../selector\"\n], function( jQuery ) {\n\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0;\n};\njQuery.expr.filters.visible = function( elem ) {\n\treturn !jQuery.expr.filters.hidden( elem );\n};\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/support.js",
    "content": "define([\n\t\"../core\",\n\t\"../var/support\"\n], function( jQuery, support ) {\n\n(function() {\n\tvar pixelPositionVal, boxSizingReliableVal,\n\t\tdocElem = document.documentElement,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE9-11+\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tcontainer.style.cssText = \"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;\" +\n\t\t\"position:absolute\";\n\tcontainer.appendChild( div );\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computePixelPositionAndBoxSizingReliable() {\n\t\tdiv.style.cssText =\n\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;\" +\n\t\t\t\"box-sizing:border-box;display:block;margin-top:1%;top:1%;\" +\n\t\t\t\"border:1px;padding:1px;width:4px;position:absolute\";\n\t\tdiv.innerHTML = \"\";\n\t\tdocElem.appendChild( container );\n\n\t\tvar divStyle = window.getComputedStyle( div, null );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\tdocElem.removeChild( container );\n\t}\n\n\t// Support: node.js jsdom\n\t// Don't assume that getComputedStyle is a property of the global object\n\tif ( window.getComputedStyle ) {\n\t\tjQuery.extend( support, {\n\t\t\tpixelPosition: function() {\n\n\t\t\t\t// This test is executed only once but we still do memoizing\n\t\t\t\t// since we can use the boxSizingReliable pre-computing.\n\t\t\t\t// No need to check if the test was already performed, though.\n\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\treturn pixelPositionVal;\n\t\t\t},\n\t\t\tboxSizingReliable: function() {\n\t\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\t}\n\t\t\t\treturn boxSizingReliableVal;\n\t\t\t},\n\t\t\treliableMarginRight: function() {\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// This support function is only executed once so no memoizing is needed.\n\t\t\t\tvar ret,\n\t\t\t\t\tmarginDiv = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\t\tmarginDiv.style.cssText = div.style.cssText =\n\t\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\t\tdiv.style.width = \"1px\";\n\t\t\t\tdocElem.appendChild( container );\n\n\t\t\t\tret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );\n\n\t\t\t\tdocElem.removeChild( container );\n\t\t\t\tdiv.removeChild( marginDiv );\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t});\n\t}\n})();\n\nreturn support;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/swap.js",
    "content": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// A method for quickly swapping in/out CSS properties to get correct calculations.\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\nreturn jQuery.swap;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/var/cssExpand.js",
    "content": "define(function() {\n\treturn [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/var/getStyles.js",
    "content": "define(function() {\n\treturn function( elem ) {\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tif ( elem.ownerDocument.defaultView.opener ) {\n\t\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t\t}\n\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/var/isHidden.js",
    "content": "define([\n\t\"../../core\",\n\t\"../../selector\"\n\t// css is assumed\n], function( jQuery ) {\n\n\treturn function( elem, el ) {\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/var/rmargin.js",
    "content": "define(function() {\n\treturn (/^margin/);\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css/var/rnumnonpx.js",
    "content": "define([\n\t\"../../var/pnum\"\n], function( pnum ) {\n\treturn new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/css.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/pnum\",\n\t\"./core/access\",\n\t\"./css/var/rmargin\",\n\t\"./css/var/rnumnonpx\",\n\t\"./css/var/cssExpand\",\n\t\"./css/var/isHidden\",\n\t\"./css/var/getStyles\",\n\t\"./css/curCSS\",\n\t\"./css/defaultDisplay\",\n\t\"./css/addGetHookIf\",\n\t\"./css/support\",\n\t\"./data/var/data_priv\",\n\n\t\"./core/init\",\n\t\"./css/swap\",\n\t\"./core/ready\",\n\t\"./selector\" // contains\n], function( jQuery, pnum, access, rmargin, rnumnonpx, cssExpand, isHidden,\n\tgetStyles, curCSS, defaultDisplay, addGetHookIf, support, data_priv ) {\n\nvar\n\t// Swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + pnum + \")\", \"i\" ),\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// Check for vendor prefixed names\n\tvar capName = name[0].toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// Both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// At this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// At this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// At this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// Some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// Check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox &&\n\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// Use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = data_priv.get( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = data_priv.access( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display !== \"none\" || !hidden ) {\n\t\t\t\tdata_priv.set( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.extend({\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t\"float\": \"cssFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n});\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) && elem.offsetWidth === 0 ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\n// Support: Android 2.3\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/data/Data.js",
    "content": "define([\n\t\"../core\",\n\t\"../var/rnotwhite\",\n\t\"./accepts\"\n], function( jQuery, rnotwhite ) {\n\nfunction Data() {\n\t// Support: Android<4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\nData.accepts = jQuery.acceptData;\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android<4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\n\nreturn Data;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/data/accepts.js",
    "content": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( owner ) {\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\t/* jshint -W018 */\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\nreturn jQuery.acceptData;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/data/var/data_priv.js",
    "content": "define([\n\t\"../Data\"\n], function( Data ) {\n\treturn new Data();\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/data/var/data_user.js",
    "content": "define([\n\t\"../Data\"\n], function( Data ) {\n\treturn new Data();\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/data.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/rnotwhite\",\n\t\"./core/access\",\n\t\"./data/var/data_priv\",\n\t\"./data/var/data_user\"\n], function( jQuery, rnotwhite, access, data_priv, data_user ) {\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend({\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdata_priv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( this, key );\n\t\t});\n\t}\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/deferred.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/slice\",\n\t\"./callbacks\"\n], function( jQuery, slice ) {\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// Add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/deprecated.js",
    "content": "define([\n\t\"./core\",\n\t\"./traversing\"\n], function( jQuery ) {\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/dimensions.js",
    "content": "define([\n\t\"./core\",\n\t\"./core/access\",\n\t\"./css\"\n], function( jQuery, access ) {\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/effects/Tween.js",
    "content": "define([\n\t\"../core\",\n\t\"../css\"\n], function( jQuery ) {\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE9\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t}\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/effects/animatedSelector.js",
    "content": "define([\n\t\"../core\",\n\t\"../selector\",\n\t\"../effects\"\n], function( jQuery ) {\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t}).length;\n};\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/effects.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/pnum\",\n\t\"./css/var/cssExpand\",\n\t\"./css/var/isHidden\",\n\t\"./css/defaultDisplay\",\n\t\"./data/var/data_priv\",\n\n\t\"./core/init\",\n\t\"./effects/Tween\",\n\t\"./queue\",\n\t\"./css\",\n\t\"./deferred\",\n\t\"./traversing\"\n], function( jQuery, pnum, cssExpand, isHidden, defaultDisplay, data_priv ) {\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +target ) &&\n\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( start && start[ 3 ] !== unit ) {\n\t\t\t\t// Trust units reported by jQuery.css\n\t\t\t\tunit = unit || start[ 3 ];\n\n\t\t\t\t// Make sure we update the tween properties later on\n\t\t\t\tparts = parts || [];\n\n\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\tstart = +target || 1;\n\n\t\t\t\tdo {\n\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t// Adjust and apply\n\t\t\t\t\tstart = start / scale;\n\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur(),\n\t\t\t\t// break the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t}\n\n\t\t\t// Update tween properties\n\t\t\tif ( parts ) {\n\t\t\t\tstart = tween.start = +start || +target || 0;\n\t\t\t\ttween.unit = unit;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[ 1 ] ?\n\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n\t\t\t\t\t+parts[ 2 ];\n\t\t\t}\n\n\t\t\treturn tween;\n\t\t} ]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( (tween = collection[ index ].call( animation, prop, value )) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = data_priv.get( elem, \"fxshow\" );\n\n\t// Handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// Height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE9-10 do not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tdata_priv.get( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\t\t\tstyle.display = \"inline-block\";\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always(function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t});\n\t}\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = data_priv.access( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// Store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\n\t\t\tdata_priv.remove( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( (display === \"none\" ? defaultDisplay( elem.nodeName ) : display) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || data_priv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = data_priv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = data_priv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/event/ajax.js",
    "content": "define([\n\t\"../core\",\n\t\"../event\"\n], function( jQuery ) {\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/event/alias.js",
    "content": "define([\n\t\"../core\",\n\t\"../event\"\n], function( jQuery ) {\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.extend({\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/event/support.js",
    "content": "define([\n\t\"../var/support\"\n], function( support ) {\n\nsupport.focusinBubbles = \"onfocusin\" in window;\n\nreturn support;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/event.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/strundefined\",\n\t\"./var/rnotwhite\",\n\t\"./var/hasOwn\",\n\t\"./var/slice\",\n\t\"./event/support\",\n\t\"./data/var/data_priv\",\n\n\t\"./core/init\",\n\t\"./data/accepts\",\n\t\"./selector\"\n], function( jQuery, strundefined, rnotwhite, hasOwn, slice, support, data_priv ) {\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && jQuery.acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( data_priv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome<28\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\t\t\t\t// Support: Android<4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// Support: Chrome 15+\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// Support: Firefox, Chrome, Safari\n// Create \"bubbling\" focus and blur events\nif ( !support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdata_priv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdata_priv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdata_priv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/exports/amd.js",
    "content": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t});\n}\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/exports/global.js",
    "content": "define([\n\t\"../core\",\n\t\"../var/strundefined\"\n], function( jQuery, strundefined ) {\n\nvar\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === strundefined ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/intro.js",
    "content": "/*!\n * jQuery JavaScript Library v@VERSION\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: @DATE\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Support: Firefox 18+\n// Can't be in strict mode, several libs including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n//\"use strict\";\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/jquery.js",
    "content": "define([\n\t\"./core\",\n\t\"./selector\",\n\t\"./traversing\",\n\t\"./callbacks\",\n\t\"./deferred\",\n\t\"./core/ready\",\n\t\"./data\",\n\t\"./queue\",\n\t\"./queue/delay\",\n\t\"./attributes\",\n\t\"./event\",\n\t\"./event/alias\",\n\t\"./manipulation\",\n\t\"./manipulation/_evalUrl\",\n\t\"./wrap\",\n\t\"./css\",\n\t\"./css/hiddenVisibleSelectors\",\n\t\"./serialize\",\n\t\"./ajax\",\n\t\"./ajax/xhr\",\n\t\"./ajax/script\",\n\t\"./ajax/jsonp\",\n\t\"./ajax/load\",\n\t\"./event/ajax\",\n\t\"./effects\",\n\t\"./effects/animatedSelector\",\n\t\"./offset\",\n\t\"./dimensions\",\n\t\"./deprecated\",\n\t\"./exports/amd\",\n\t\"./exports/global\"\n], function( jQuery ) {\n\nreturn jQuery;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/manipulation/_evalUrl.js",
    "content": "define([\n\t\"../ajax\"\n], function( jQuery ) {\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t});\n};\n\nreturn jQuery._evalUrl;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/manipulation/support.js",
    "content": "define([\n\t\"../var/support\"\n], function( support ) {\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Safari<=5.1\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Safari<=5.1, Android<4.2\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<=11+\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n})();\n\nreturn support;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/manipulation/var/rcheckableType.js",
    "content": "define(function() {\n\treturn (/^(?:checkbox|radio)$/i);\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/manipulation.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/concat\",\n\t\"./var/push\",\n\t\"./core/access\",\n\t\"./manipulation/var/rcheckableType\",\n\t\"./manipulation/support\",\n\t\"./data/var/data_priv\",\n\t\"./data/var/data_user\",\n\n\t\"./core/init\",\n\t\"./data/accepts\",\n\t\"./traversing\",\n\t\"./selector\",\n\t\"./event\"\n], function( jQuery, concat, push, access, rcheckableType, support, data_priv, data_user ) {\n\nvar\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\n\t\t// Support: IE9\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE9\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: 1.x compatibility\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement(\"tbody\") ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [],\n\t\t\ti = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type, key,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( jQuery.acceptData( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each(function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map(function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( node.textContent.replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: QtWebKit\n\t\t\t// .get() because push.apply(_, arraylike) throws\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/offset.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/strundefined\",\n\t\"./core/access\",\n\t\"./css/var/rnumnonpx\",\n\t\"./css/curCSS\",\n\t\"./css/addGetHookIf\",\n\t\"./css/support\",\n\n\t\"./core/init\",\n\t\"./css\",\n\t\"./selector\" // contains\n], function( jQuery, strundefined, access, rnumnonpx, curCSS, addGetHookIf, support ) {\n\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf(\"auto\") > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend({\n\toffset: function( options ) {\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each(function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t});\n\t\t}\n\n\t\tvar docElem, win,\n\t\t\telem = this[ 0 ],\n\t\t\tbox = { top: 0, left: 0 },\n\t\t\tdoc = elem && elem.ownerDocument;\n\n\t\tif ( !doc ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure it's not a disconnected DOM node\n\t\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box;\n\t\t}\n\n\t\t// Support: BlackBerry 5, iOS 3 (original iPhone)\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\tif ( typeof elem.getBoundingClientRect !== strundefined ) {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t}\n\t\twin = getWindow( doc );\n\t\treturn {\n\t\t\ttop: box.top + win.pageYOffset - docElem.clientTop,\n\t\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\n\t\t};\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : window.pageXOffset,\n\t\t\t\t\ttop ? val : window.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\n// Support: Safari<7+, Chrome<37+\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/outro.js",
    "content": "}));\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/queue/delay.js",
    "content": "define([\n\t\"../core\",\n\t\"../queue\",\n\t\"../effects\" // Delay is optional because of this dependency\n], function( jQuery ) {\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\tclearTimeout( timeout );\n\t\t};\n\t});\n};\n\nreturn jQuery.fn.delay;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/queue.js",
    "content": "define([\n\t\"./core\",\n\t\"./data/var/data_priv\",\n\t\"./deferred\",\n\t\"./callbacks\"\n], function( jQuery, data_priv ) {\n\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = data_priv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = data_priv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/selector-native.js",
    "content": "define([\n\t\"./core\"\n], function( jQuery ) {\n\n/*\n * Optional (non-Sizzle) selector module for custom builds.\n *\n * Note that this DOES NOT SUPPORT many documented jQuery\n * features in exchange for its smaller size:\n *\n * Attribute not equal selector\n * Positional selectors (:first; :eq(n); :odd; etc.)\n * Type selectors (:input; :checkbox; :button; etc.)\n * State-based selectors (:animated; :visible; :hidden; etc.)\n * :has(selector)\n * :not(complex selector)\n * custom selectors via Sizzle extensions\n * Leading combinators (e.g., $collection.find(\"> *\"))\n * Reliable functionality on XML fragments\n * Requiring all parts of a selector to match elements under context\n *   (e.g., $div.find(\"div > *\") now matches children of $div)\n * Matching against non-elements\n * Reliable sorting of disconnected nodes\n * querySelectorAll bug fixes (e.g., unreliable :focus on WebKit)\n *\n * If any of these are unacceptable tradeoffs, either use Sizzle or\n * customize this stub for the project's specific needs.\n */\n\nvar docElem = window.document.documentElement,\n\tselector_hasDuplicate,\n\tmatches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector,\n\tselector_sortOrder = function( a, b ) {\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\tselector_hasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );\n\n\t\tif ( compare ) {\n\t\t\t// Disconnected nodes\n\t\t\tif ( compare & 1 ) {\n\n\t\t\t\t// Choose the first element that is related to our document\n\t\t\t\tif ( a === document || jQuery.contains(document, a) ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( b === document || jQuery.contains(document, b) ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\t// Maintain original order\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn compare & 4 ? -1 : 1;\n\t\t}\n\n\t\t// Not directly comparable, sort on existence of method\n\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t};\n\njQuery.extend({\n\tfind: function( selector, context, results, seed ) {\n\t\tvar elem, nodeType,\n\t\t\ti = 0;\n\n\t\tresults = results || [];\n\t\tcontext = context || document;\n\n\t\t// Same basic safeguard as Sizzle\n\t\tif ( !selector || typeof selector !== \"string\" ) {\n\t\t\treturn results;\n\t\t}\n\n\t\t// Early return if context is not an element or document\n\t\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\twhile ( (elem = seed[i++]) ) {\n\t\t\t\tif ( jQuery.find.matchesSelector(elem, selector) ) {\n\t\t\t\t\tresults.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tjQuery.merge( results, context.querySelectorAll(selector) );\n\t\t}\n\n\t\treturn results;\n\t},\n\tunique: function( results ) {\n\t\tvar elem,\n\t\t\tduplicates = [],\n\t\t\ti = 0,\n\t\t\tj = 0;\n\n\t\tselector_hasDuplicate = false;\n\t\tresults.sort( selector_sortOrder );\n\n\t\tif ( selector_hasDuplicate ) {\n\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\t\tj = duplicates.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile ( j-- ) {\n\t\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t\t}\n\t\t}\n\n\t\treturn results;\n\t},\n\ttext: function( elem ) {\n\t\tvar node,\n\t\t\tret = \"\",\n\t\t\ti = 0,\n\t\t\tnodeType = elem.nodeType;\n\n\t\tif ( !nodeType ) {\n\t\t\t// If no nodeType, this is expected to be an array\n\t\t\twhile ( (node = elem[i++]) ) {\n\t\t\t\t// Do not traverse comment nodes\n\t\t\t\tret += jQuery.text( node );\n\t\t\t}\n\t\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent for elements\n\t\t\treturn elem.textContent;\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t\t// Do not include comment or processing instruction nodes\n\n\t\treturn ret;\n\t},\n\tcontains: function( a, b ) {\n\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\tbup = b && b.parentNode;\n\t\treturn a === bup || !!( bup && bup.nodeType === 1 && adown.contains(bup) );\n\t},\n\tisXMLDoc: function( elem ) {\n\t\treturn (elem.ownerDocument || elem).documentElement.nodeName !== \"HTML\";\n\t},\n\texpr: {\n\t\tattrHandle: {},\n\t\tmatch: {\n\t\t\tbool: /^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$/i,\n\t\t\tneedsContext: /^[\\x20\\t\\r\\n\\f]*[>+~]/\n\t\t}\n\t}\n});\n\njQuery.extend( jQuery.find, {\n\tmatches: function( expr, elements ) {\n\t\treturn jQuery.find( expr, null, null, elements );\n\t},\n\tmatchesSelector: function( elem, expr ) {\n\t\treturn matches.call( elem, expr );\n\t},\n\tattr: function( elem, name ) {\n\t\treturn elem.getAttribute( name );\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/selector-sizzle.js",
    "content": "define([\n\t\"./core\",\n\t\"sizzle\"\n], function( jQuery, Sizzle ) {\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/selector.js",
    "content": "define([ \"./selector-sizzle\" ]);\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/serialize.js",
    "content": "define([\n\t\"./core\",\n\t\"./manipulation/var/rcheckableType\",\n\t\"./core/init\",\n\t\"./traversing\", // filter\n\t\"./attributes/prop\"\n], function( jQuery, rcheckableType ) {\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function() {\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/sizzle/dist/sizzle.js",
    "content": "/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\tnodeType = context.nodeType;\n\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\tif ( !seed && documentIsHTML ) {\n\n\t\t// Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType !== 1 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = attrs.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\tparent = doc.defaultView;\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Support tests\n\t---------------------------------------------------------------------- */\n\tdocumentIsHTML = !isXML( doc );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\f]' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = doc.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn doc;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (oldCache = outerCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\touterCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is no seed and only one group\n\tif ( match.length === 1 ) {\n\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"<input/>\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\n// EXPOSE\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine(function() { return Sizzle; });\n// Sizzle requires that there be a global window in Common-JS like environments\n} else if ( typeof module !== \"undefined\" && module.exports ) {\n\tmodule.exports = Sizzle;\n} else {\n\twindow.Sizzle = Sizzle;\n}\n// EXPOSE\n\n})( window );\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/traversing/findFilter.js",
    "content": "define([\n\t\"../core\",\n\t\"../var/indexOf\",\n\t\"./var/rneedsContext\",\n\t\"../selector\"\n], function( jQuery, indexOf, rneedsContext ) {\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t});\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t});\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( indexOf.call( qualifier, elem ) >= 0 ) !== not;\n\t});\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t}));\n};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tlen = this.length,\n\t\t\tret = [],\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], true) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n});\n\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/traversing/var/rneedsContext.js",
    "content": "define([\n\t\"../../core\",\n\t\"../../selector\"\n], function( jQuery ) {\n\treturn jQuery.expr.match.needsContext;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/traversing.js",
    "content": "define([\n\t\"./core\",\n\t\"./var/indexOf\",\n\t\"./traversing/var/rneedsContext\",\n\t\"./core/init\",\n\t\"./traversing/findFilter\",\n\t\"./selector\"\n], function( jQuery, indexOf, rneedsContext ) {\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\nfunction sibling( cur, dir ) {\n\twhile ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/arr.js",
    "content": "define(function() {\n\treturn [];\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/class2type.js",
    "content": "define(function() {\n\t// [[Class]] -> type pairs\n\treturn {};\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/concat.js",
    "content": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.concat;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/hasOwn.js",
    "content": "define([\n\t\"./class2type\"\n], function( class2type ) {\n\treturn class2type.hasOwnProperty;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/indexOf.js",
    "content": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.indexOf;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/pnum.js",
    "content": "define(function() {\n\treturn (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/push.js",
    "content": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.push;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/rnotwhite.js",
    "content": "define(function() {\n\treturn (/\\S+/g);\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/slice.js",
    "content": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.slice;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/strundefined.js",
    "content": "define(function() {\n\treturn typeof undefined;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/support.js",
    "content": "define(function() {\n\t// All support tests are defined in their respective modules.\n\treturn {};\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/var/toString.js",
    "content": "define([\n\t\"./class2type\"\n], function( class2type ) {\n\treturn class2type.toString;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/jquery/src/wrap.js",
    "content": "define([\n\t\"./core\",\n\t\"./core/init\",\n\t\"./manipulation\", // clone\n\t\"./traversing\" // parent, contents\n], function( jQuery ) {\n\njQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[ 0 ] ) {\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\n\nreturn jQuery;\n});\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/.bower.json",
    "content": "{\n  \"name\": \"marked\",\n  \"homepage\": \"https://github.com/chjj/marked\",\n  \"version\": \"0.3.2\",\n  \"_release\": \"0.3.2\",\n  \"_resolution\": {\n    \"type\": \"version\",\n    \"tag\": \"v0.3.2\",\n    \"commit\": \"43db549e31af5ff6e4a3b12e41a23513b9f88c99\"\n  },\n  \"_source\": \"git://github.com/chjj/marked.git\",\n  \"_target\": \"~0.3.1\",\n  \"_originalSource\": \"marked\"\n}"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/.gitignore",
    "content": "node_modules/\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/.npmignore",
    "content": ".git*\ntest/\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/.travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"0.10\"\n  - \"0.8\"\n  - \"0.6\"\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/LICENSE",
    "content": "Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/Makefile",
    "content": "all:\n\t@cp lib/marked.js marked.js\n\t@uglifyjs -o marked.min.js marked.js\n\nclean:\n\t@rm marked.js\n\t@rm marked.min.js\n\nbench:\n\t@node test --bench\n\n.PHONY: clean all\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/README.md",
    "content": "# marked\n\n> A full-featured markdown parser and compiler, written in JavaScript. Built\n> for speed.\n\n[![NPM version](https://badge.fury.io/js/marked.png)][badge]\n\n## Install\n\n``` bash\nnpm install marked --save\n```\n\n## Usage\n\nMinimal usage:\n\n```js\nvar marked = require('marked');\nconsole.log(marked('I am using __markdown__.'));\n// Outputs: <p>I am using <strong>markdown</strong>.</p>\n```\n\nExample setting options with default values:\n\n```js\nvar marked = require('marked');\nmarked.setOptions({\n  renderer: new marked.Renderer(),\n  gfm: true,\n  tables: true,\n  breaks: false,\n  pedantic: false,\n  sanitize: true,\n  smartLists: true,\n  smartypants: false\n});\n\nconsole.log(marked('I am using __markdown__.'));\n```\n\n## marked(markdownString [,options] [,callback])\n\n### markdownString\n\nType: `string`\n\nString of markdown source to be compiled.\n\n### options\n\nType: `object`\n\nHash of options. Can also be set using the `marked.setOptions` method as seen\nabove.\n\n### callback\n\nType: `function`\n\nFunction called when the `markdownString` has been fully parsed when using\nasync highlighting. If the `options` argument is omitted, this can be used as\nthe second argument.\n\n## Options\n\n### highlight\n\nType: `function`\n\nA function to highlight code blocks. The first example below uses async highlighting with\n[node-pygmentize-bundled][pygmentize], and the second is a synchronous example using\n[highlight.js][highlight]:\n\n```js\nvar marked = require('marked');\n\nvar markdownString = '```js\\n console.log(\"hello\"); \\n```';\n\n// Async highlighting with pygmentize-bundled\nmarked.setOptions({\n  highlight: function (code, lang, callback) {\n    require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) {\n      callback(err, result.toString());\n    });\n  }\n});\n\n// Using async version of marked\nmarked(markdownString, function (err, content) {\n  if (err) throw err;\n  console.log(content);\n});\n\n// Synchronous highlighting with highlight.js\nmarked.setOptions({\n  highlight: function (code) {\n    return require('highlight.js').highlightAuto(code).value;\n  }\n});\n\nconsole.log(marked(markdownString));\n```\n\n#### highlight arguments\n\n`code`\n\nType: `string`\n\nThe section of code to pass to the highlighter.\n\n`lang`\n\nType: `string`\n\nThe programming language specified in the code block.\n\n`callback`\n\nType: `function`\n\nThe callback function to call when using an async highlighter.\n\n### renderer\n\nType: `object`\nDefault: `new Renderer()`\n\nAn object containing functions to render tokens to HTML.\n\n#### Overriding renderer methods\n\nThe renderer option allows you to render tokens in a custom manor. Here is an\nexample of overriding the default heading token rendering by adding an embedded anchor tag like on GitHub:\n\n```javascript\nvar marked = require('marked');\nvar renderer = new marked.Renderer();\n\nrenderer.heading = function (text, level) {\n  var escapedText = text.toLowerCase().replace(/[^\\w]+/g, '-');\n\n  return '<h' + level + '><a name=\"' +\n                escapedText +\n                 '\" class=\"anchor\" href=\"#' +\n                 escapedText +\n                 '\"><span class=\"header-link\"></span></a>' +\n                  text + '</h' + level + '>';\n},\n\nconsole.log(marked('# heading+', { renderer: renderer }));\n```\nThis code will output the following HTML:\n```html\n<h1>\n  <a name=\"heading-\" class=\"anchor\" href=\"#heading-\">\n    <span class=\"header-link\"></span>\n  </a>\n  heading+\n</h1>\n```\n\n#### Block level renderer methods\n\n- code(*string* code, *string* language)\n- blockquote(*string* quote)\n- html(*string* html)\n- heading(*string* text, *number*  level)\n- hr()\n- list(*string* body, *boolean* ordered)\n- listitem(*string*  text)\n- paragraph(*string* text)\n- table(*string* header, *string* body)\n- tablerow(*string* content)\n- tablecell(*string* content, *object* flags)\n\n`flags` has the following properties:\n\n```js\n{\n    header: true || false,\n    align: 'center' || 'left' || 'right'\n}\n```\n\n#### Inline level renderer methods\n\n- strong(*string* text)\n- em(*string* text)\n- codespan(*string* code)\n- br()\n- del(*string* text)\n- link(*string* href, *string* title, *string* text)\n- image(*string* href, *string* title, *string* text)\n\n### gfm\n\nType: `boolean`\nDefault: `true`\n\nEnable [GitHub flavored markdown][gfm].\n\n### tables\n\nType: `boolean`\nDefault: `true`\n\nEnable GFM [tables][tables].\nThis option requires the `gfm` option to be true.\n\n### breaks\n\nType: `boolean`\nDefault: `false`\n\nEnable GFM [line breaks][breaks].\nThis option requires the `gfm` option to be true.\n\n### pedantic\n\nType: `boolean`\nDefault: `false`\n\nConform to obscure parts of `markdown.pl` as much as possible. Don't fix any of\nthe original markdown bugs or poor behavior.\n\n### sanitize\n\nType: `boolean`\nDefault: `false`\n\nSanitize the output. Ignore any HTML that has been input.\n\n### smartLists\n\nType: `boolean`\nDefault: `true`\n\nUse smarter list behavior than the original markdown. May eventually be\ndefault with the old behavior moved into `pedantic`.\n\n### smartypants\n\nType: `boolean`\nDefault: `false`\n\nUse \"smart\" typograhic punctuation for things like quotes and dashes.\n\n## Access to lexer and parser\n\nYou also have direct access to the lexer and parser if you so desire.\n\n``` js\nvar tokens = marked.lexer(text, options);\nconsole.log(marked.parser(tokens));\n```\n\n``` js\nvar lexer = new marked.Lexer(options);\nvar tokens = lexer.lex(text);\nconsole.log(tokens);\nconsole.log(lexer.rules);\n```\n\n## CLI\n\n``` bash\n$ marked -o hello.html\nhello world\n^D\n$ cat hello.html\n<p>hello world</p>\n```\n\n## Philosophy behind marked\n\nThe point of marked was to create a markdown compiler where it was possible to\nfrequently parse huge chunks of markdown without having to worry about\ncaching the compiled output somehow...or blocking for an unnecesarily long time.\n\nmarked is very concise and still implements all markdown features. It is also\nnow fully compatible with the client-side.\n\nmarked more or less passes the official markdown test suite in its\nentirety. This is important because a surprising number of markdown compilers\ncannot pass more than a few tests. It was very difficult to get marked as\ncompliant as it is. It could have cut corners in several areas for the sake\nof performance, but did not in order to be exactly what you expect in terms\nof a markdown rendering. In fact, this is why marked could be considered at a\ndisadvantage in the benchmarks above.\n\nAlong with implementing every markdown feature, marked also implements [GFM\nfeatures][gfmf].\n\n## Benchmarks\n\nnode v0.8.x\n\n``` bash\n$ node test --bench\nmarked completed in 3411ms.\nmarked (gfm) completed in 3727ms.\nmarked (pedantic) completed in 3201ms.\nrobotskirt completed in 808ms.\nshowdown (reuse converter) completed in 11954ms.\nshowdown (new converter) completed in 17774ms.\nmarkdown-js completed in 17191ms.\n```\n\n__Marked is now faster than Discount, which is written in C.__\n\nFor those feeling skeptical: These benchmarks run the entire markdown test suite 1000 times. The test suite tests every feature. It doesn't cater to specific aspects.\n\n### Pro level\n\nYou also have direct access to the lexer and parser if you so desire.\n\n``` js\nvar tokens = marked.lexer(text, options);\nconsole.log(marked.parser(tokens));\n```\n\n``` js\nvar lexer = new marked.Lexer(options);\nvar tokens = lexer.lex(text);\nconsole.log(tokens);\nconsole.log(lexer.rules);\n```\n\n``` bash\n$ node\n> require('marked').lexer('> i am using marked.')\n[ { type: 'blockquote_start' },\n  { type: 'paragraph',\n    text: 'i am using marked.' },\n  { type: 'blockquote_end' },\n  links: {} ]\n```\n\n## Running Tests & Contributing\n\nIf you want to submit a pull request, make sure your changes pass the test\nsuite. If you're adding a new feature, be sure to add your own test.\n\nThe marked test suite is set up slightly strangely: `test/new` is for all tests\nthat are not part of the original markdown.pl test suite (this is where your\ntest should go if you make one). `test/original` is only for the original\nmarkdown.pl tests. `test/tests` houses both types of tests after they have been\ncombined and moved/generated by running `node test --fix` or `marked --test\n--fix`.\n\nIn other words, if you have a test to add, add it to `test/new/` and then\nregenerate the tests with `node test --fix`. Commit the result. If your test\nuses a certain feature, for example, maybe it assumes GFM is *not* enabled, you\ncan add `.nogfm` to the filename. So, `my-test.text` becomes\n`my-test.nogfm.text`. You can do this with any marked option. Say you want\nline breaks and smartypants enabled, your filename should be:\n`my-test.breaks.smartypants.text`.\n\nTo run the tests:\n\n``` bash\ncd marked/\nnode test\n```\n\n### Contribution and License Agreement\n\nIf you contribute code to this project, you are implicitly allowing your code\nto be distributed under the MIT license. You are also implicitly verifying that\nall code is your original work. `</legalese>`\n\n## License\n\nCopyright (c) 2011-2014, Christopher Jeffrey. (MIT License)\n\nSee LICENSE for more info.\n\n[gfm]: https://help.github.com/articles/github-flavored-markdown\n[gfmf]: http://github.github.com/github-flavored-markdown/\n[pygmentize]: https://github.com/rvagg/node-pygmentize-bundled\n[highlight]: https://github.com/isagalaev/highlight.js\n[badge]: http://badge.fury.io/js/marked\n[tables]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables\n[breaks]: https://help.github.com/articles/github-flavored-markdown#newlines\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/bin/marked",
    "content": "#!/usr/bin/env node\n\n/**\n * Marked CLI\n * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License)\n */\n\nvar fs = require('fs')\n  , util = require('util')\n  , marked = require('../');\n\n/**\n * Man Page\n */\n\nfunction help() {\n  var spawn = require('child_process').spawn;\n\n  var options = {\n    cwd: process.cwd(),\n    env: process.env,\n    setsid: false,\n    customFds: [0, 1, 2]\n  };\n\n  spawn('man',\n    [__dirname + '/../man/marked.1'],\n    options);\n}\n\n/**\n * Main\n */\n\nfunction main(argv, callback) {\n  var files = []\n    , options = {}\n    , input\n    , output\n    , arg\n    , tokens\n    , opt;\n\n  function getarg() {\n    var arg = argv.shift();\n\n    if (arg.indexOf('--') === 0) {\n      // e.g. --opt\n      arg = arg.split('=');\n      if (arg.length > 1) {\n        // e.g. --opt=val\n        argv.unshift(arg.slice(1).join('='));\n      }\n      arg = arg[0];\n    } else if (arg[0] === '-') {\n      if (arg.length > 2) {\n        // e.g. -abc\n        argv = arg.substring(1).split('').map(function(ch) {\n          return '-' + ch;\n        }).concat(argv);\n        arg = argv.shift();\n      } else {\n        // e.g. -a\n      }\n    } else {\n      // e.g. foo\n    }\n\n    return arg;\n  }\n\n  while (argv.length) {\n    arg = getarg();\n    switch (arg) {\n      case '--test':\n        return require('../test').main(process.argv.slice());\n      case '-o':\n      case '--output':\n        output = argv.shift();\n        break;\n      case '-i':\n      case '--input':\n        input = argv.shift();\n        break;\n      case '-t':\n      case '--tokens':\n        tokens = true;\n        break;\n      case '-h':\n      case '--help':\n        return help();\n      default:\n        if (arg.indexOf('--') === 0) {\n          opt = camelize(arg.replace(/^--(no-)?/, ''));\n          if (!marked.defaults.hasOwnProperty(opt)) {\n            continue;\n          }\n          if (arg.indexOf('--no-') === 0) {\n            options[opt] = typeof marked.defaults[opt] !== 'boolean'\n              ? null\n              : false;\n          } else {\n            options[opt] = typeof marked.defaults[opt] !== 'boolean'\n              ? argv.shift()\n              : true;\n          }\n        } else {\n          files.push(arg);\n        }\n        break;\n    }\n  }\n\n  function getData(callback) {\n    if (!input) {\n      if (files.length <= 2) {\n        return getStdin(callback);\n      }\n      input = files.pop();\n    }\n    return fs.readFile(input, 'utf8', callback);\n  }\n\n  return getData(function(err, data) {\n    if (err) return callback(err);\n\n    data = tokens\n      ? JSON.stringify(marked.lexer(data, options), null, 2)\n      : marked(data, options);\n\n    if (!output) {\n      process.stdout.write(data + '\\n');\n      return callback();\n    }\n\n    return fs.writeFile(output, data, callback);\n  });\n}\n\n/**\n * Helpers\n */\n\nfunction getStdin(callback) {\n  var stdin = process.stdin\n    , buff = '';\n\n  stdin.setEncoding('utf8');\n\n  stdin.on('data', function(data) {\n    buff += data;\n  });\n\n  stdin.on('error', function(err) {\n    return callback(err);\n  });\n\n  stdin.on('end', function() {\n    return callback(null, buff);\n  });\n\n  try {\n    stdin.resume();\n  } catch (e) {\n    callback(e);\n  }\n}\n\nfunction camelize(text) {\n  return text.replace(/(\\w)-(\\w)/g, function(_, a, b) {\n    return a + b.toUpperCase();\n  });\n}\n\n/**\n * Expose / Entry Point\n */\n\nif (!module.parent) {\n  process.title = 'marked';\n  main(process.argv.slice(), function(err, code) {\n    if (err) throw err;\n    return process.exit(code || 0);\n  });\n} else {\n  module.exports = main;\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/component.json",
    "content": "{\n  \"name\": \"marked\",\n  \"version\": \"0.3.2\",\n  \"repo\": \"chjj/marked\",\n  \"description\": \"A markdown parser built for speed\",\n  \"keywords\": [\"markdown\", \"markup\", \"html\"],\n  \"scripts\": [\"lib/marked.js\"],\n  \"main\": \"lib/marked.js\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/doc/broken.md",
    "content": "# Markdown is broken\n\nI have a lot of scraps of markdown engine oddities that I've collected over the\nyears. What you see below is slightly messy, but it's what I've managed to\ncobble together to illustrate the differences between markdown engines, and\nwhy, if there ever is a markdown specification, it has to be absolutely\nthorough. There are a lot more of these little differences I have documented\nelsewhere. I know I will find them lingering on my disk one day, but until\nthen, I'll continue to add whatever strange nonsensical things I find.\n\nSome of these examples may only mention a particular engine compared to marked.\nHowever, the examples with markdown.pl could easily be swapped out for\ndiscount, upskirt, or markdown.js, and you would very easily see even more\ninconsistencies.\n\nA lot of this was written when I was very unsatisfied with the inconsistencies\nbetween markdown engines. Please excuse the frustration noticeable in my\nwriting.\n\n## Examples of markdown's \"stupid\" list parsing\n\n```\n$ markdown.pl\n\n  * item1\n\n    * item2\n\n  text\n^D\n<ul>\n<li><p>item1</p>\n\n<ul>\n<li>item2</li>\n</ul>\n\n<p><p>text</p></li>\n</ul></p>\n```\n\n\n```\n$ marked\n  * item1\n\n    * item2\n\n  text\n^D\n<ul>\n<li><p>item1</p>\n<ul>\n<li>item2</li>\n</ul>\n<p>text</p>\n</li>\n</ul>\n```\n\nWhich looks correct to you?\n\n- - -\n\n```\n$ markdown.pl\n* hello\n  > world\n^D\n<p><ul>\n<li>hello</p>\n\n<blockquote>\n  <p>world</li>\n</ul></p>\n</blockquote>\n```\n\n```\n$ marked\n* hello\n  > world\n^D\n<ul>\n<li>hello<blockquote>\n<p>world</p>\n</blockquote>\n</li>\n</ul>\n```\n\nAgain, which looks correct to you?\n\n- - -\n\nEXAMPLE:\n\n```\n$ markdown.pl\n* hello\n  * world\n    * hi\n          code\n^D\n<ul>\n<li>hello\n<ul>\n<li>world</li>\n<li>hi\n  code</li>\n</ul></li>\n</ul>\n```\n\nThe code isn't a code block even though it's after the bullet margin. I know,\nlets give it two more spaces, effectively making it 8 spaces past the bullet.\n\n```\n$ markdown.pl\n* hello\n  * world\n    * hi\n            code\n^D\n<ul>\n<li>hello\n<ul>\n<li>world</li>\n<li>hi\n    code</li>\n</ul></li>\n</ul>\n```\n\nAnd, it's still not a code block. Did you also notice that the 3rd item isn't\neven its own list? Markdown screws that up too because of its indentation\nunaware parsing.\n\n- - -\n\nLet's look at some more examples of markdown's list parsing:\n\n```\n$ markdown.pl\n\n  * item1\n\n    * item2\n\n  text\n^D\n<ul>\n<li><p>item1</p>\n\n<ul>\n<li>item2</li>\n</ul>\n\n<p><p>text</p></li>\n</ul></p>\n```\n\nMisnested tags.\n\n\n```\n$ marked\n  * item1\n\n    * item2\n\n  text\n^D\n<ul>\n<li><p>item1</p>\n<ul>\n<li>item2</li>\n</ul>\n<p>text</p>\n</li>\n</ul>\n```\n\nWhich looks correct to you?\n\n- - -\n\n```\n$ markdown.pl\n* hello\n  > world\n^D\n<p><ul>\n<li>hello</p>\n\n<blockquote>\n  <p>world</li>\n</ul></p>\n</blockquote>\n```\n\nMore misnested tags.\n\n\n```\n$ marked\n* hello\n  > world\n^D\n<ul>\n<li>hello<blockquote>\n<p>world</p>\n</blockquote>\n</li>\n</ul>\n```\n\nAgain, which looks correct to you?\n\n- - -\n\n# Why quality matters - Part 2\n\n``` bash\n$ markdown.pl\n* hello\n  > world\n^D\n<p><ul>\n<li>hello</p>\n\n<blockquote>\n  <p>world</li>\n</ul></p>\n</blockquote>\n```\n\n``` bash\n$ sundown # upskirt\n* hello\n  > world\n^D\n<ul>\n<li>hello\n&gt; world</li>\n</ul>\n```\n\n``` bash\n$ marked\n* hello\n  > world\n^D\n<ul><li>hello <blockquote><p>world</p></blockquote></li></ul>\n```\n\nWhich looks correct to you?\n\n- - -\n\nSee: https://github.com/evilstreak/markdown-js/issues/23\n\n``` bash\n$ markdown.pl # upskirt/markdown.js/discount\n* hello\n      var a = 1;\n* world\n^D\n<ul>\n<li>hello\nvar a = 1;</li>\n<li>world</li>\n</ul>\n```\n\n``` bash\n$ marked\n* hello\n      var a = 1;\n* world\n^D\n<ul><li>hello\n<pre>code>var a = 1;</code></pre></li>\n<li>world</li></ul>\n```\n\nWhich looks more reasonable? Why shouldn't code blocks be able to appear in\nlist items in a sane way?\n\n- - -\n\n``` bash\n$ markdown.js\n<div>hello</div>\n\n<span>hello</span>\n^D\n<p>&lt;div&gt;hello&lt;/div&gt;</p>\n\n<p>&lt;span&gt;hello&lt;/span&gt;</p>\n```\n\n``` bash\n$ marked\n<div>hello</div>\n\n<span>hello</span>\n^D\n<div>hello</div>\n\n\n<p><span>hello</span>\n</p>\n```\n\n- - -\n\nSee: https://github.com/evilstreak/markdown-js/issues/27\n\n``` bash\n$ markdown.js\n[![an image](/image)](/link)\n^D\n<p><a href=\"/image)](/link\">![an image</a></p>\n```\n\n``` bash\n$ marked\n[![an image](/image)](/link)\n^D\n<p><a href=\"/link\"><img src=\"/image\" alt=\"an image\"></a>\n</p>\n```\n\n- - -\n\nSee: https://github.com/evilstreak/markdown-js/issues/24\n\n``` bash\n$ markdown.js\n> a\n\n> b\n\n> c\n^D\n<blockquote><p>a</p><p>bundefined&gt; c</p></blockquote>\n```\n\n``` bash\n$ marked\n> a\n\n> b\n\n> c\n^D\n<blockquote><p>a\n\n</p></blockquote>\n<blockquote><p>b\n\n</p></blockquote>\n<blockquote><p>c\n</p></blockquote>\n```\n\n- - -\n\n``` bash\n$ markdown.pl\n* hello\n  * world\n    how\n\n    are\n    you\n\n  * today\n* hi\n^D\n<ul>\n<li><p>hello</p>\n\n<ul>\n<li>world\nhow</li>\n</ul>\n\n<p>are\nyou</p>\n\n<ul>\n<li>today</li>\n</ul></li>\n<li>hi</li>\n</ul>\n```\n\n``` bash\n$ marked\n* hello\n  * world\n    how\n\n    are\n    you\n\n  * today\n* hi\n^D\n<ul>\n<li><p>hello</p>\n<ul>\n<li><p>world\nhow</p>\n<p>are\nyou</p>\n</li>\n<li><p>today</p>\n</li>\n</ul>\n</li>\n<li>hi</li>\n</ul>\n```\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/doc/todo.md",
    "content": "# Todo\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/index.js",
    "content": "module.exports = require('./lib/marked');\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/lib/marked.js",
    "content": "/**\n * marked - a markdown parser\n * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)\n * https://github.com/chjj/marked\n */\n\n;(function() {\n\n/**\n * Block-Level Grammar\n */\n\nvar block = {\n  newline: /^\\n+/,\n  code: /^( {4}[^\\n]+\\n*)+/,\n  fences: noop,\n  hr: /^( *[-*_]){3,} *(?:\\n+|$)/,\n  heading: /^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)/,\n  nptable: noop,\n  lheading: /^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,\n  blockquote: /^( *>[^\\n]+(\\n(?!def)[^\\n]+)*\\n*)+/,\n  list: /^( *)(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,\n  html: /^ *(?:comment|closed|closing) *(?:\\n{2,}|\\s*$)/,\n  def: /^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)/,\n  table: noop,\n  paragraph: /^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*/,\n  text: /^[^\\n]+/\n};\n\nblock.bullet = /(?:[*+-]|\\d+\\.)/;\nblock.item = /^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*/;\nblock.item = replace(block.item, 'gm')\n  (/bull/g, block.bullet)\n  ();\n\nblock.list = replace(block.list)\n  (/bull/g, block.bullet)\n  ('hr', '\\\\n+(?=\\\\1?(?:[-*_] *){3,}(?:\\\\n+|$))')\n  ('def', '\\\\n+(?=' + block.def.source + ')')\n  ();\n\nblock.blockquote = replace(block.blockquote)\n  ('def', block.def)\n  ();\n\nblock._tag = '(?!(?:'\n  + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'\n  + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'\n  + '|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:/|[^\\\\w\\\\s@]*@)\\\\b';\n\nblock.html = replace(block.html)\n  ('comment', /<!--[\\s\\S]*?-->/)\n  ('closed', /<(tag)[\\s\\S]+?<\\/\\1>/)\n  ('closing', /<tag(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/)\n  (/tag/g, block._tag)\n  ();\n\nblock.paragraph = replace(block.paragraph)\n  ('hr', block.hr)\n  ('heading', block.heading)\n  ('lheading', block.lheading)\n  ('blockquote', block.blockquote)\n  ('tag', '<' + block._tag)\n  ('def', block.def)\n  ();\n\n/**\n * Normal Block Grammar\n */\n\nblock.normal = merge({}, block);\n\n/**\n * GFM Block Grammar\n */\n\nblock.gfm = merge({}, block.normal, {\n  fences: /^ *(`{3,}|~{3,}) *(\\S+)? *\\n([\\s\\S]+?)\\s*\\1 *(?:\\n+|$)/,\n  paragraph: /^/\n});\n\nblock.gfm.paragraph = replace(block.paragraph)\n  ('(?!', '(?!'\n    + block.gfm.fences.source.replace('\\\\1', '\\\\2') + '|'\n    + block.list.source.replace('\\\\1', '\\\\3') + '|')\n  ();\n\n/**\n * GFM + Tables Block Grammar\n */\n\nblock.tables = merge({}, block.gfm, {\n  nptable: /^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*/,\n  table: /^ *\\|(.+)\\n *\\|( *[-:]+[-| :]*)\\n((?: *\\|.*(?:\\n|$))*)\\n*/\n});\n\n/**\n * Block Lexer\n */\n\nfunction Lexer(options) {\n  this.tokens = [];\n  this.tokens.links = {};\n  this.options = options || marked.defaults;\n  this.rules = block.normal;\n\n  if (this.options.gfm) {\n    if (this.options.tables) {\n      this.rules = block.tables;\n    } else {\n      this.rules = block.gfm;\n    }\n  }\n}\n\n/**\n * Expose Block Rules\n */\n\nLexer.rules = block;\n\n/**\n * Static Lex Method\n */\n\nLexer.lex = function(src, options) {\n  var lexer = new Lexer(options);\n  return lexer.lex(src);\n};\n\n/**\n * Preprocessing\n */\n\nLexer.prototype.lex = function(src) {\n  src = src\n    .replace(/\\r\\n|\\r/g, '\\n')\n    .replace(/\\t/g, '    ')\n    .replace(/\\u00a0/g, ' ')\n    .replace(/\\u2424/g, '\\n');\n\n  return this.token(src, true);\n};\n\n/**\n * Lexing\n */\n\nLexer.prototype.token = function(src, top, bq) {\n  var src = src.replace(/^ +$/gm, '')\n    , next\n    , loose\n    , cap\n    , bull\n    , b\n    , item\n    , space\n    , i\n    , l;\n\n  while (src) {\n    // newline\n    if (cap = this.rules.newline.exec(src)) {\n      src = src.substring(cap[0].length);\n      if (cap[0].length > 1) {\n        this.tokens.push({\n          type: 'space'\n        });\n      }\n    }\n\n    // code\n    if (cap = this.rules.code.exec(src)) {\n      src = src.substring(cap[0].length);\n      cap = cap[0].replace(/^ {4}/gm, '');\n      this.tokens.push({\n        type: 'code',\n        text: !this.options.pedantic\n          ? cap.replace(/\\n+$/, '')\n          : cap\n      });\n      continue;\n    }\n\n    // fences (gfm)\n    if (cap = this.rules.fences.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'code',\n        lang: cap[2],\n        text: cap[3]\n      });\n      continue;\n    }\n\n    // heading\n    if (cap = this.rules.heading.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'heading',\n        depth: cap[1].length,\n        text: cap[2]\n      });\n      continue;\n    }\n\n    // table no leading pipe (gfm)\n    if (top && (cap = this.rules.nptable.exec(src))) {\n      src = src.substring(cap[0].length);\n\n      item = {\n        type: 'table',\n        header: cap[1].replace(/^ *| *\\| *$/g, '').split(/ *\\| */),\n        align: cap[2].replace(/^ *|\\| *$/g, '').split(/ *\\| */),\n        cells: cap[3].replace(/\\n$/, '').split('\\n')\n      };\n\n      for (i = 0; i < item.align.length; i++) {\n        if (/^ *-+: *$/.test(item.align[i])) {\n          item.align[i] = 'right';\n        } else if (/^ *:-+: *$/.test(item.align[i])) {\n          item.align[i] = 'center';\n        } else if (/^ *:-+ *$/.test(item.align[i])) {\n          item.align[i] = 'left';\n        } else {\n          item.align[i] = null;\n        }\n      }\n\n      for (i = 0; i < item.cells.length; i++) {\n        item.cells[i] = item.cells[i].split(/ *\\| */);\n      }\n\n      this.tokens.push(item);\n\n      continue;\n    }\n\n    // lheading\n    if (cap = this.rules.lheading.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'heading',\n        depth: cap[2] === '=' ? 1 : 2,\n        text: cap[1]\n      });\n      continue;\n    }\n\n    // hr\n    if (cap = this.rules.hr.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'hr'\n      });\n      continue;\n    }\n\n    // blockquote\n    if (cap = this.rules.blockquote.exec(src)) {\n      src = src.substring(cap[0].length);\n\n      this.tokens.push({\n        type: 'blockquote_start'\n      });\n\n      cap = cap[0].replace(/^ *> ?/gm, '');\n\n      // Pass `top` to keep the current\n      // \"toplevel\" state. This is exactly\n      // how markdown.pl works.\n      this.token(cap, top, true);\n\n      this.tokens.push({\n        type: 'blockquote_end'\n      });\n\n      continue;\n    }\n\n    // list\n    if (cap = this.rules.list.exec(src)) {\n      src = src.substring(cap[0].length);\n      bull = cap[2];\n\n      this.tokens.push({\n        type: 'list_start',\n        ordered: bull.length > 1\n      });\n\n      // Get each top-level item.\n      cap = cap[0].match(this.rules.item);\n\n      next = false;\n      l = cap.length;\n      i = 0;\n\n      for (; i < l; i++) {\n        item = cap[i];\n\n        // Remove the list item's bullet\n        // so it is seen as the next token.\n        space = item.length;\n        item = item.replace(/^ *([*+-]|\\d+\\.) +/, '');\n\n        // Outdent whatever the\n        // list item contains. Hacky.\n        if (~item.indexOf('\\n ')) {\n          space -= item.length;\n          item = !this.options.pedantic\n            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')\n            : item.replace(/^ {1,4}/gm, '');\n        }\n\n        // Determine whether the next list item belongs here.\n        // Backpedal if it does not belong in this list.\n        if (this.options.smartLists && i !== l - 1) {\n          b = block.bullet.exec(cap[i + 1])[0];\n          if (bull !== b && !(bull.length > 1 && b.length > 1)) {\n            src = cap.slice(i + 1).join('\\n') + src;\n            i = l - 1;\n          }\n        }\n\n        // Determine whether item is loose or not.\n        // Use: /(^|\\n)(?! )[^\\n]+\\n\\n(?!\\s*$)/\n        // for discount behavior.\n        loose = next || /\\n\\n(?!\\s*$)/.test(item);\n        if (i !== l - 1) {\n          next = item.charAt(item.length - 1) === '\\n';\n          if (!loose) loose = next;\n        }\n\n        this.tokens.push({\n          type: loose\n            ? 'loose_item_start'\n            : 'list_item_start'\n        });\n\n        // Recurse.\n        this.token(item, false, bq);\n\n        this.tokens.push({\n          type: 'list_item_end'\n        });\n      }\n\n      this.tokens.push({\n        type: 'list_end'\n      });\n\n      continue;\n    }\n\n    // html\n    if (cap = this.rules.html.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: this.options.sanitize\n          ? 'paragraph'\n          : 'html',\n        pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',\n        text: cap[0]\n      });\n      continue;\n    }\n\n    // def\n    if ((!bq && top) && (cap = this.rules.def.exec(src))) {\n      src = src.substring(cap[0].length);\n      this.tokens.links[cap[1].toLowerCase()] = {\n        href: cap[2],\n        title: cap[3]\n      };\n      continue;\n    }\n\n    // table (gfm)\n    if (top && (cap = this.rules.table.exec(src))) {\n      src = src.substring(cap[0].length);\n\n      item = {\n        type: 'table',\n        header: cap[1].replace(/^ *| *\\| *$/g, '').split(/ *\\| */),\n        align: cap[2].replace(/^ *|\\| *$/g, '').split(/ *\\| */),\n        cells: cap[3].replace(/(?: *\\| *)?\\n$/, '').split('\\n')\n      };\n\n      for (i = 0; i < item.align.length; i++) {\n        if (/^ *-+: *$/.test(item.align[i])) {\n          item.align[i] = 'right';\n        } else if (/^ *:-+: *$/.test(item.align[i])) {\n          item.align[i] = 'center';\n        } else if (/^ *:-+ *$/.test(item.align[i])) {\n          item.align[i] = 'left';\n        } else {\n          item.align[i] = null;\n        }\n      }\n\n      for (i = 0; i < item.cells.length; i++) {\n        item.cells[i] = item.cells[i]\n          .replace(/^ *\\| *| *\\| *$/g, '')\n          .split(/ *\\| */);\n      }\n\n      this.tokens.push(item);\n\n      continue;\n    }\n\n    // top-level paragraph\n    if (top && (cap = this.rules.paragraph.exec(src))) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'paragraph',\n        text: cap[1].charAt(cap[1].length - 1) === '\\n'\n          ? cap[1].slice(0, -1)\n          : cap[1]\n      });\n      continue;\n    }\n\n    // text\n    if (cap = this.rules.text.exec(src)) {\n      // Top-level should never reach here.\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'text',\n        text: cap[0]\n      });\n      continue;\n    }\n\n    if (src) {\n      throw new\n        Error('Infinite loop on byte: ' + src.charCodeAt(0));\n    }\n  }\n\n  return this.tokens;\n};\n\n/**\n * Inline-Level Grammar\n */\n\nvar inline = {\n  escape: /^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])/,\n  autolink: /^<([^ >]+(@|:\\/)[^ >]+)>/,\n  url: noop,\n  tag: /^<!--[\\s\\S]*?-->|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/,\n  link: /^!?\\[(inside)\\]\\(href\\)/,\n  reflink: /^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]/,\n  nolink: /^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]/,\n  strong: /^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)/,\n  em: /^\\b_((?:__|[\\s\\S])+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/,\n  code: /^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)/,\n  br: /^ {2,}\\n(?!\\s*$)/,\n  del: noop,\n  text: /^[\\s\\S]+?(?=[\\\\<!\\[_*`]| {2,}\\n|$)/\n};\n\ninline._inside = /(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*/;\ninline._href = /\\s*<?([\\s\\S]*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*/;\n\ninline.link = replace(inline.link)\n  ('inside', inline._inside)\n  ('href', inline._href)\n  ();\n\ninline.reflink = replace(inline.reflink)\n  ('inside', inline._inside)\n  ();\n\n/**\n * Normal Inline Grammar\n */\n\ninline.normal = merge({}, inline);\n\n/**\n * Pedantic Inline Grammar\n */\n\ninline.pedantic = merge({}, inline.normal, {\n  strong: /^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,\n  em: /^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/\n});\n\n/**\n * GFM Inline Grammar\n */\n\ninline.gfm = merge({}, inline.normal, {\n  escape: replace(inline.escape)('])', '~|])')(),\n  url: /^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/,\n  del: /^~~(?=\\S)([\\s\\S]*?\\S)~~/,\n  text: replace(inline.text)\n    (']|', '~]|')\n    ('|', '|https?://|')\n    ()\n});\n\n/**\n * GFM + Line Breaks Inline Grammar\n */\n\ninline.breaks = merge({}, inline.gfm, {\n  br: replace(inline.br)('{2,}', '*')(),\n  text: replace(inline.gfm.text)('{2,}', '*')()\n});\n\n/**\n * Inline Lexer & Compiler\n */\n\nfunction InlineLexer(links, options) {\n  this.options = options || marked.defaults;\n  this.links = links;\n  this.rules = inline.normal;\n  this.renderer = this.options.renderer || new Renderer;\n  this.renderer.options = this.options;\n\n  if (!this.links) {\n    throw new\n      Error('Tokens array requires a `links` property.');\n  }\n\n  if (this.options.gfm) {\n    if (this.options.breaks) {\n      this.rules = inline.breaks;\n    } else {\n      this.rules = inline.gfm;\n    }\n  } else if (this.options.pedantic) {\n    this.rules = inline.pedantic;\n  }\n}\n\n/**\n * Expose Inline Rules\n */\n\nInlineLexer.rules = inline;\n\n/**\n * Static Lexing/Compiling Method\n */\n\nInlineLexer.output = function(src, links, options) {\n  var inline = new InlineLexer(links, options);\n  return inline.output(src);\n};\n\n/**\n * Lexing/Compiling\n */\n\nInlineLexer.prototype.output = function(src) {\n  var out = ''\n    , link\n    , text\n    , href\n    , cap;\n\n  while (src) {\n    // escape\n    if (cap = this.rules.escape.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += cap[1];\n      continue;\n    }\n\n    // autolink\n    if (cap = this.rules.autolink.exec(src)) {\n      src = src.substring(cap[0].length);\n      if (cap[2] === '@') {\n        text = cap[1].charAt(6) === ':'\n          ? this.mangle(cap[1].substring(7))\n          : this.mangle(cap[1]);\n        href = this.mangle('mailto:') + text;\n      } else {\n        text = escape(cap[1]);\n        href = text;\n      }\n      out += this.renderer.link(href, null, text);\n      continue;\n    }\n\n    // url (gfm)\n    if (!this.inLink && (cap = this.rules.url.exec(src))) {\n      src = src.substring(cap[0].length);\n      text = escape(cap[1]);\n      href = text;\n      out += this.renderer.link(href, null, text);\n      continue;\n    }\n\n    // tag\n    if (cap = this.rules.tag.exec(src)) {\n      if (!this.inLink && /^<a /i.test(cap[0])) {\n        this.inLink = true;\n      } else if (this.inLink && /^<\\/a>/i.test(cap[0])) {\n        this.inLink = false;\n      }\n      src = src.substring(cap[0].length);\n      out += this.options.sanitize\n        ? escape(cap[0])\n        : cap[0];\n      continue;\n    }\n\n    // link\n    if (cap = this.rules.link.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.inLink = true;\n      out += this.outputLink(cap, {\n        href: cap[2],\n        title: cap[3]\n      });\n      this.inLink = false;\n      continue;\n    }\n\n    // reflink, nolink\n    if ((cap = this.rules.reflink.exec(src))\n        || (cap = this.rules.nolink.exec(src))) {\n      src = src.substring(cap[0].length);\n      link = (cap[2] || cap[1]).replace(/\\s+/g, ' ');\n      link = this.links[link.toLowerCase()];\n      if (!link || !link.href) {\n        out += cap[0].charAt(0);\n        src = cap[0].substring(1) + src;\n        continue;\n      }\n      this.inLink = true;\n      out += this.outputLink(cap, link);\n      this.inLink = false;\n      continue;\n    }\n\n    // strong\n    if (cap = this.rules.strong.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.strong(this.output(cap[2] || cap[1]));\n      continue;\n    }\n\n    // em\n    if (cap = this.rules.em.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.em(this.output(cap[2] || cap[1]));\n      continue;\n    }\n\n    // code\n    if (cap = this.rules.code.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.codespan(escape(cap[2], true));\n      continue;\n    }\n\n    // br\n    if (cap = this.rules.br.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.br();\n      continue;\n    }\n\n    // del (gfm)\n    if (cap = this.rules.del.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.del(this.output(cap[1]));\n      continue;\n    }\n\n    // text\n    if (cap = this.rules.text.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += escape(this.smartypants(cap[0]));\n      continue;\n    }\n\n    if (src) {\n      throw new\n        Error('Infinite loop on byte: ' + src.charCodeAt(0));\n    }\n  }\n\n  return out;\n};\n\n/**\n * Compile Link\n */\n\nInlineLexer.prototype.outputLink = function(cap, link) {\n  var href = escape(link.href)\n    , title = link.title ? escape(link.title) : null;\n\n  return cap[0].charAt(0) !== '!'\n    ? this.renderer.link(href, title, this.output(cap[1]))\n    : this.renderer.image(href, title, escape(cap[1]));\n};\n\n/**\n * Smartypants Transformations\n */\n\nInlineLexer.prototype.smartypants = function(text) {\n  if (!this.options.smartypants) return text;\n  return text\n    // em-dashes\n    .replace(/--/g, '\\u2014')\n    // opening singles\n    .replace(/(^|[-\\u2014/(\\[{\"\\s])'/g, '$1\\u2018')\n    // closing singles & apostrophes\n    .replace(/'/g, '\\u2019')\n    // opening doubles\n    .replace(/(^|[-\\u2014/(\\[{\\u2018\\s])\"/g, '$1\\u201c')\n    // closing doubles\n    .replace(/\"/g, '\\u201d')\n    // ellipses\n    .replace(/\\.{3}/g, '\\u2026');\n};\n\n/**\n * Mangle Links\n */\n\nInlineLexer.prototype.mangle = function(text) {\n  var out = ''\n    , l = text.length\n    , i = 0\n    , ch;\n\n  for (; i < l; i++) {\n    ch = text.charCodeAt(i);\n    if (Math.random() > 0.5) {\n      ch = 'x' + ch.toString(16);\n    }\n    out += '&#' + ch + ';';\n  }\n\n  return out;\n};\n\n/**\n * Renderer\n */\n\nfunction Renderer(options) {\n  this.options = options || {};\n}\n\nRenderer.prototype.code = function(code, lang, escaped) {\n  if (this.options.highlight) {\n    var out = this.options.highlight(code, lang);\n    if (out != null && out !== code) {\n      escaped = true;\n      code = out;\n    }\n  }\n\n  if (!lang) {\n    return '<pre><code>'\n      + (escaped ? code : escape(code, true))\n      + '\\n</code></pre>';\n  }\n\n  return '<pre><code class=\"'\n    + this.options.langPrefix\n    + escape(lang, true)\n    + '\">'\n    + (escaped ? code : escape(code, true))\n    + '\\n</code></pre>\\n';\n};\n\nRenderer.prototype.blockquote = function(quote) {\n  return '<blockquote>\\n' + quote + '</blockquote>\\n';\n};\n\nRenderer.prototype.html = function(html) {\n  return html;\n};\n\nRenderer.prototype.heading = function(text, level, raw) {\n  return '<h'\n    + level\n    + ' id=\"'\n    + this.options.headerPrefix\n    + raw.toLowerCase().replace(/[^\\w]+/g, '-')\n    + '\">'\n    + text\n    + '</h'\n    + level\n    + '>\\n';\n};\n\nRenderer.prototype.hr = function() {\n  return this.options.xhtml ? '<hr/>\\n' : '<hr>\\n';\n};\n\nRenderer.prototype.list = function(body, ordered) {\n  var type = ordered ? 'ol' : 'ul';\n  return '<' + type + '>\\n' + body + '</' + type + '>\\n';\n};\n\nRenderer.prototype.listitem = function(text) {\n  return '<li>' + text + '</li>\\n';\n};\n\nRenderer.prototype.paragraph = function(text) {\n  return '<p>' + text + '</p>\\n';\n};\n\nRenderer.prototype.table = function(header, body) {\n  return '<table>\\n'\n    + '<thead>\\n'\n    + header\n    + '</thead>\\n'\n    + '<tbody>\\n'\n    + body\n    + '</tbody>\\n'\n    + '</table>\\n';\n};\n\nRenderer.prototype.tablerow = function(content) {\n  return '<tr>\\n' + content + '</tr>\\n';\n};\n\nRenderer.prototype.tablecell = function(content, flags) {\n  var type = flags.header ? 'th' : 'td';\n  var tag = flags.align\n    ? '<' + type + ' style=\"text-align:' + flags.align + '\">'\n    : '<' + type + '>';\n  return tag + content + '</' + type + '>\\n';\n};\n\n// span level renderer\nRenderer.prototype.strong = function(text) {\n  return '<strong>' + text + '</strong>';\n};\n\nRenderer.prototype.em = function(text) {\n  return '<em>' + text + '</em>';\n};\n\nRenderer.prototype.codespan = function(text) {\n  return '<code>' + text + '</code>';\n};\n\nRenderer.prototype.br = function() {\n  return this.options.xhtml ? '<br/>' : '<br>';\n};\n\nRenderer.prototype.del = function(text) {\n  return '<del>' + text + '</del>';\n};\n\nRenderer.prototype.link = function(href, title, text) {\n  if (this.options.sanitize) {\n    try {\n      var prot = decodeURIComponent(unescape(href))\n        .replace(/[^\\w:]/g, '')\n        .toLowerCase();\n    } catch (e) {\n      return '';\n    }\n    if (prot.indexOf('javascript:') === 0) {\n      return '';\n    }\n  }\n  var out = '<a href=\"' + href + '\"';\n  if (title) {\n    out += ' title=\"' + title + '\"';\n  }\n  out += '>' + text + '</a>';\n  return out;\n};\n\nRenderer.prototype.image = function(href, title, text) {\n  var out = '<img src=\"' + href + '\" alt=\"' + text + '\"';\n  if (title) {\n    out += ' title=\"' + title + '\"';\n  }\n  out += this.options.xhtml ? '/>' : '>';\n  return out;\n};\n\n/**\n * Parsing & Compiling\n */\n\nfunction Parser(options) {\n  this.tokens = [];\n  this.token = null;\n  this.options = options || marked.defaults;\n  this.options.renderer = this.options.renderer || new Renderer;\n  this.renderer = this.options.renderer;\n  this.renderer.options = this.options;\n}\n\n/**\n * Static Parse Method\n */\n\nParser.parse = function(src, options, renderer) {\n  var parser = new Parser(options, renderer);\n  return parser.parse(src);\n};\n\n/**\n * Parse Loop\n */\n\nParser.prototype.parse = function(src) {\n  this.inline = new InlineLexer(src.links, this.options, this.renderer);\n  this.tokens = src.reverse();\n\n  var out = '';\n  while (this.next()) {\n    out += this.tok();\n  }\n\n  return out;\n};\n\n/**\n * Next Token\n */\n\nParser.prototype.next = function() {\n  return this.token = this.tokens.pop();\n};\n\n/**\n * Preview Next Token\n */\n\nParser.prototype.peek = function() {\n  return this.tokens[this.tokens.length - 1] || 0;\n};\n\n/**\n * Parse Text Tokens\n */\n\nParser.prototype.parseText = function() {\n  var body = this.token.text;\n\n  while (this.peek().type === 'text') {\n    body += '\\n' + this.next().text;\n  }\n\n  return this.inline.output(body);\n};\n\n/**\n * Parse Current Token\n */\n\nParser.prototype.tok = function() {\n  switch (this.token.type) {\n    case 'space': {\n      return '';\n    }\n    case 'hr': {\n      return this.renderer.hr();\n    }\n    case 'heading': {\n      return this.renderer.heading(\n        this.inline.output(this.token.text),\n        this.token.depth,\n        this.token.text);\n    }\n    case 'code': {\n      return this.renderer.code(this.token.text,\n        this.token.lang,\n        this.token.escaped);\n    }\n    case 'table': {\n      var header = ''\n        , body = ''\n        , i\n        , row\n        , cell\n        , flags\n        , j;\n\n      // header\n      cell = '';\n      for (i = 0; i < this.token.header.length; i++) {\n        flags = { header: true, align: this.token.align[i] };\n        cell += this.renderer.tablecell(\n          this.inline.output(this.token.header[i]),\n          { header: true, align: this.token.align[i] }\n        );\n      }\n      header += this.renderer.tablerow(cell);\n\n      for (i = 0; i < this.token.cells.length; i++) {\n        row = this.token.cells[i];\n\n        cell = '';\n        for (j = 0; j < row.length; j++) {\n          cell += this.renderer.tablecell(\n            this.inline.output(row[j]),\n            { header: false, align: this.token.align[j] }\n          );\n        }\n\n        body += this.renderer.tablerow(cell);\n      }\n      return this.renderer.table(header, body);\n    }\n    case 'blockquote_start': {\n      var body = '';\n\n      while (this.next().type !== 'blockquote_end') {\n        body += this.tok();\n      }\n\n      return this.renderer.blockquote(body);\n    }\n    case 'list_start': {\n      var body = ''\n        , ordered = this.token.ordered;\n\n      while (this.next().type !== 'list_end') {\n        body += this.tok();\n      }\n\n      return this.renderer.list(body, ordered);\n    }\n    case 'list_item_start': {\n      var body = '';\n\n      while (this.next().type !== 'list_item_end') {\n        body += this.token.type === 'text'\n          ? this.parseText()\n          : this.tok();\n      }\n\n      return this.renderer.listitem(body);\n    }\n    case 'loose_item_start': {\n      var body = '';\n\n      while (this.next().type !== 'list_item_end') {\n        body += this.tok();\n      }\n\n      return this.renderer.listitem(body);\n    }\n    case 'html': {\n      var html = !this.token.pre && !this.options.pedantic\n        ? this.inline.output(this.token.text)\n        : this.token.text;\n      return this.renderer.html(html);\n    }\n    case 'paragraph': {\n      return this.renderer.paragraph(this.inline.output(this.token.text));\n    }\n    case 'text': {\n      return this.renderer.paragraph(this.parseText());\n    }\n  }\n};\n\n/**\n * Helpers\n */\n\nfunction escape(html, encode) {\n  return html\n    .replace(!encode ? /&(?!#?\\w+;)/g : /&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#39;');\n}\n\nfunction unescape(html) {\n  return html.replace(/&([#\\w]+);/g, function(_, n) {\n    n = n.toLowerCase();\n    if (n === 'colon') return ':';\n    if (n.charAt(0) === '#') {\n      return n.charAt(1) === 'x'\n        ? String.fromCharCode(parseInt(n.substring(2), 16))\n        : String.fromCharCode(+n.substring(1));\n    }\n    return '';\n  });\n}\n\nfunction replace(regex, opt) {\n  regex = regex.source;\n  opt = opt || '';\n  return function self(name, val) {\n    if (!name) return new RegExp(regex, opt);\n    val = val.source || val;\n    val = val.replace(/(^|[^\\[])\\^/g, '$1');\n    regex = regex.replace(name, val);\n    return self;\n  };\n}\n\nfunction noop() {}\nnoop.exec = noop;\n\nfunction merge(obj) {\n  var i = 1\n    , target\n    , key;\n\n  for (; i < arguments.length; i++) {\n    target = arguments[i];\n    for (key in target) {\n      if (Object.prototype.hasOwnProperty.call(target, key)) {\n        obj[key] = target[key];\n      }\n    }\n  }\n\n  return obj;\n}\n\n\n/**\n * Marked\n */\n\nfunction marked(src, opt, callback) {\n  if (callback || typeof opt === 'function') {\n    if (!callback) {\n      callback = opt;\n      opt = null;\n    }\n\n    opt = merge({}, marked.defaults, opt || {});\n\n    var highlight = opt.highlight\n      , tokens\n      , pending\n      , i = 0;\n\n    try {\n      tokens = Lexer.lex(src, opt)\n    } catch (e) {\n      return callback(e);\n    }\n\n    pending = tokens.length;\n\n    var done = function() {\n      var out, err;\n\n      try {\n        out = Parser.parse(tokens, opt);\n      } catch (e) {\n        err = e;\n      }\n\n      opt.highlight = highlight;\n\n      return err\n        ? callback(err)\n        : callback(null, out);\n    };\n\n    if (!highlight || highlight.length < 3) {\n      return done();\n    }\n\n    delete opt.highlight;\n\n    if (!pending) return done();\n\n    for (; i < tokens.length; i++) {\n      (function(token) {\n        if (token.type !== 'code') {\n          return --pending || done();\n        }\n        return highlight(token.text, token.lang, function(err, code) {\n          if (code == null || code === token.text) {\n            return --pending || done();\n          }\n          token.text = code;\n          token.escaped = true;\n          --pending || done();\n        });\n      })(tokens[i]);\n    }\n\n    return;\n  }\n  try {\n    if (opt) opt = merge({}, marked.defaults, opt);\n    return Parser.parse(Lexer.lex(src, opt), opt);\n  } catch (e) {\n    e.message += '\\nPlease report this to https://github.com/chjj/marked.';\n    if ((opt || marked.defaults).silent) {\n      return '<p>An error occured:</p><pre>'\n        + escape(e.message + '', true)\n        + '</pre>';\n    }\n    throw e;\n  }\n}\n\n/**\n * Options\n */\n\nmarked.options =\nmarked.setOptions = function(opt) {\n  merge(marked.defaults, opt);\n  return marked;\n};\n\nmarked.defaults = {\n  gfm: true,\n  tables: true,\n  breaks: false,\n  pedantic: false,\n  sanitize: false,\n  smartLists: false,\n  silent: false,\n  highlight: null,\n  langPrefix: 'lang-',\n  smartypants: false,\n  headerPrefix: '',\n  renderer: new Renderer,\n  xhtml: false\n};\n\n/**\n * Expose\n */\n\nmarked.Parser = Parser;\nmarked.parser = Parser.parse;\n\nmarked.Renderer = Renderer;\n\nmarked.Lexer = Lexer;\nmarked.lexer = Lexer.lex;\n\nmarked.InlineLexer = InlineLexer;\nmarked.inlineLexer = InlineLexer.output;\n\nmarked.parse = marked;\n\nif (typeof exports === 'object') {\n  module.exports = marked;\n} else if (typeof define === 'function' && define.amd) {\n  define(function() { return marked; });\n} else {\n  this.marked = marked;\n}\n\n}).call(function() {\n  return this || (typeof window !== 'undefined' ? window : global);\n}());\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/man/marked.1",
    "content": ".ds q \\N'34'\n.TH marked 1 \"2014-01-31\" \"v0.3.1\" \"marked.js\"\n\n.SH NAME\nmarked \\- a javascript markdown parser\n\n.SH SYNOPSIS\n.B marked\n[\\-o \\fI<output>\\fP] [\\-i \\fI<input>\\fP] [\\-\\-help]\n[\\-\\-tokens] [\\-\\-pedantic] [\\-\\-gfm]\n[\\-\\-breaks] [\\-\\-tables] [\\-\\-sanitize]\n[\\-\\-smart\\-lists] [\\-\\-lang\\-prefix \\fI<prefix>\\fP]\n[\\-\\-no\\-etc...] [\\-\\-silent] [\\fIfilename\\fP]\n\n.SH DESCRIPTION\n.B marked\nis a full-featured javascript markdown parser, built for speed. It also includes\nmultiple GFM features.\n\n.SH EXAMPLES\n.TP\ncat in.md | marked > out.html\n.TP\necho \"hello *world*\" | marked\n.TP\nmarked \\-o out.html in.md \\-\\-gfm\n.TP\nmarked \\-\\-output=\"hello world.html\" \\-i in.md \\-\\-no-breaks\n\n.SH OPTIONS\n.TP\n.BI \\-o,\\ \\-\\-output\\ [\\fIoutput\\fP]\nSpecify file output. If none is specified, write to stdout.\n.TP\n.BI \\-i,\\ \\-\\-input\\ [\\fIinput\\fP]\nSpecify file input, otherwise use last argument as input file. If no input file\nis specified, read from stdin.\n.TP\n.BI \\-t,\\ \\-\\-tokens\nOutput a token stream instead of html.\n.TP\n.BI \\-\\-pedantic\nConform to obscure parts of markdown.pl as much as possible. Don't fix original\nmarkdown bugs.\n.TP\n.BI \\-\\-gfm\nEnable github flavored markdown.\n.TP\n.BI \\-\\-breaks\nEnable GFM line breaks. Only works with the gfm option.\n.TP\n.BI \\-\\-tables\nEnable GFM tables. Only works with the gfm option.\n.TP\n.BI \\-\\-sanitize\nSanitize output. Ignore any HTML input.\n.TP\n.BI \\-\\-smart\\-lists\nUse smarter list behavior than the original markdown.\n.TP\n.BI \\-\\-lang\\-prefix\\ [\\fIprefix\\fP]\nSet the prefix for code block classes.\n.TP\n.BI \\-\\-no\\-sanitize,\\ \\-no-etc...\nThe inverse of any of the marked options above.\n.TP\n.BI \\-\\-silent\nSilence error output.\n.TP\n.BI \\-h,\\ \\-\\-help\nDisplay help information.\n\n.SH CONFIGURATION\nFor configuring and running programmatically.\n\n.B Example\n\n    require('marked')('*foo*', { gfm: true });\n\n.SH BUGS\nPlease report any bugs to https://github.com/chjj/marked.\n\n.SH LICENSE\nCopyright (c) 2011-2014, Christopher Jeffrey (MIT License).\n\n.SH \"SEE ALSO\"\n.BR markdown(1),\n.BR node.js(1)\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/package.json",
    "content": "{\n  \"name\": \"marked\",\n  \"description\": \"A markdown parser built for speed\",\n  \"author\": \"Christopher Jeffrey\",\n  \"version\": \"0.3.2\",\n  \"main\": \"./lib/marked.js\",\n  \"bin\": \"./bin/marked\",\n  \"man\": \"./man/marked.1\",\n  \"preferGlobal\": true,\n  \"repository\": \"git://github.com/chjj/marked.git\",\n  \"homepage\": \"https://github.com/chjj/marked\",\n  \"bugs\": { \"url\": \"http://github.com/chjj/marked/issues\" },\n  \"license\": \"MIT\",\n  \"keywords\": [\"markdown\", \"markup\", \"html\"],\n  \"tags\": [\"markdown\", \"markup\", \"html\"],\n  \"devDependencies\": {\n    \"markdown\": \"*\",\n    \"showdown\": \"*\",\n    \"robotskirt\": \"*\"\n  },\n  \"scripts\": { \"test\": \"node test\", \"bench\": \"node test --bench\" }\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/README",
    "content": "In this directory:\n\n#\n# MarkdownTester -- Run tests for Markdown implementations\n#\n# Copyright (c) 2004-2005 John Gruber\n# <http://daringfireball.net/projects/markdown/>\n#\n\nPartially modified for testing purposes.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/browser/index.html",
    "content": "<!doctype html>\n<title>marked tests</title>\n<p>testing...</p>\n<script src=\"marked.js\"></script>\n<script src=\"test.js\"></script>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/browser/index.js",
    "content": "var fs = require('fs');\n\nvar test = require('../')\n  , runTests = test.runTests\n  , load = test.load;\n\nvar express = require('express')\n  , app = express();\n\napp.use(function(req, res, next) {\n  var setHeader = res.setHeader;\n  res.setHeader = function(name) {\n    switch (name) {\n      case 'Cache-Control':\n      case 'Last-Modified':\n      case 'ETag':\n        return;\n    }\n    return setHeader.apply(res, arguments);\n  };\n  next();\n});\n\nvar dir = __dirname + '/../tests'\n  , files = {};\n\napp.get('/test.js', function(req, res, next) {\n  var test = fs.readFileSync(__dirname + '/test.js', 'utf8')\n    , files = load();\n\n  test = test.replace('__TESTS__', JSON.stringify(files));\n  test = test.replace('__MAIN__', runTests + '');\n\n  res.contentType('.js');\n  res.send(test);\n});\n\napp.use(express.static(__dirname + '/../../lib'));\napp.use(express.static(__dirname));\n\napp.listen(8080);\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/browser/test.js",
    "content": ";(function() {\n\nvar console = {}\n  , files = __TESTS__;\n\nconsole.log = function(text) {\n  var args = Array.prototype.slice.call(arguments, 1)\n    , i = 0;\n\n  text = text.replace(/%\\w/g, function() {\n    return args[i++] || '';\n  });\n\n  if (window.console) window.console.log(text);\n  document.body.innerHTML += '<pre>' + escape(text) + '</pre>';\n};\n\nif (!Object.keys) {\n  Object.keys = function(obj) {\n    var out = []\n      , key;\n\n    for (key in obj) {\n      if (Object.prototype.hasOwnProperty.call(obj, key)) {\n        out.push(key);\n      }\n    }\n\n    return out;\n  };\n}\n\nif (!Array.prototype.forEach) {\n  Array.prototype.forEach = function(callback, context) {\n    for (var i = 0; i < this.length; i++) {\n      callback.call(context || null, this[i], i, obj);\n    }\n  };\n}\n\nif (!String.prototype.trim) {\n  String.prototype.trim = function() {\n    return this.replace(/^\\s+|\\s+$/g, '');\n  };\n}\n\nfunction load() {\n  return files;\n}\n\nfunction escape(html, encode) {\n  return html\n    .replace(!encode ? /&(?!#?\\w+;)/g : /&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#39;');\n}\n\n(__MAIN__)();\n\n}).call(this);\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/index.js",
    "content": "#!/usr/bin/env node\n\n/**\n * marked tests\n * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)\n * https://github.com/chjj/marked\n */\n\n/**\n * Modules\n */\n\nvar fs = require('fs')\n  , path = require('path')\n  , marked = require('../');\n\n/**\n * Load Tests\n */\n\nfunction load() {\n  var dir = __dirname + '/tests'\n    , files = {}\n    , list\n    , file\n    , i\n    , l;\n\n  list = fs\n    .readdirSync(dir)\n    .filter(function(file) {\n      return path.extname(file) !== '.html';\n    })\n    .sort(function(a, b) {\n      a = path.basename(a).toLowerCase().charCodeAt(0);\n      b = path.basename(b).toLowerCase().charCodeAt(0);\n      return a > b ? 1 : (a < b ? -1 : 0);\n    });\n\n  i = 0;\n  l = list.length;\n\n  for (; i < l; i++) {\n    file = path.join(dir, list[i]);\n    files[path.basename(file)] = {\n      text: fs.readFileSync(file, 'utf8'),\n      html: fs.readFileSync(file.replace(/[^.]+$/, 'html'), 'utf8')\n    };\n  }\n\n  return files;\n}\n\n/**\n * Test Runner\n */\n\nfunction runTests(engine, options) {\n  if (typeof engine !== 'function') {\n    options = engine;\n    engine = null;\n  }\n\n  var engine = engine || marked\n    , options = options || {}\n    , files = options.files || load()\n    , complete = 0\n    , failed = 0\n    , failures = []\n    , keys = Object.keys(files)\n    , i = 0\n    , len = keys.length\n    , filename\n    , file\n    , flags\n    , text\n    , html\n    , j\n    , l;\n\n  if (options.marked) {\n    marked.setOptions(options.marked);\n  }\n\nmain:\n  for (; i < len; i++) {\n    filename = keys[i];\n    file = files[filename];\n\n    if (marked._original) {\n      marked.defaults = marked._original;\n      delete marked._original;\n    }\n\n    flags = filename.split('.').slice(1, -1);\n    if (flags.length) {\n      marked._original = marked.defaults;\n      marked.defaults = {};\n      Object.keys(marked._original).forEach(function(key) {\n        marked.defaults[key] = marked._original[key];\n      });\n      flags.forEach(function(key) {\n        var val = true;\n        if (key.indexOf('no') === 0) {\n          key = key.substring(2);\n          val = false;\n        }\n        if (marked.defaults.hasOwnProperty(key)) {\n          marked.defaults[key] = val;\n        }\n      });\n    }\n\n    try {\n      text = engine(file.text).replace(/\\s/g, '');\n      html = file.html.replace(/\\s/g, '');\n    } catch(e) {\n      console.log('%s failed.', filename);\n      throw e;\n    }\n\n    j = 0;\n    l = html.length;\n\n    for (; j < l; j++) {\n      if (text[j] !== html[j]) {\n        failed++;\n        failures.push(filename);\n\n        text = text.substring(\n          Math.max(j - 30, 0),\n          Math.min(j + 30, text.length));\n\n        html = html.substring(\n          Math.max(j - 30, 0),\n          Math.min(j + 30, html.length));\n\n        console.log(\n          '\\n#%d. %s failed at offset %d. Near: \"%s\".\\n',\n          i + 1, filename, j, text);\n\n        console.log('\\nGot:\\n%s\\n', text.trim() || text);\n        console.log('\\nExpected:\\n%s\\n', html.trim() || html);\n\n        if (options.stop) {\n          break main;\n        }\n\n        continue main;\n      }\n    }\n\n    complete++;\n    console.log('#%d. %s completed.', i + 1, filename);\n  }\n\n  console.log('%d/%d tests completed successfully.', complete, len);\n  if (failed) console.log('%d/%d tests failed.', failed, len);\n\n  // Tests currently failing.\n  if (~failures.indexOf('def_blocks.text')\n      && ~failures.indexOf('double_link.text')\n      && ~failures.indexOf('gfm_code_hr_list.text')) {\n    failed -= 3;\n  }\n\n  return !failed;\n}\n\n/**\n * Benchmark a function\n */\n\nfunction bench(name, func) {\n  var files = bench.files || load();\n\n  if (!bench.files) {\n    bench.files = files;\n\n    // Change certain tests to allow\n    // comparison to older benchmark times.\n    fs.readdirSync(__dirname + '/new').forEach(function(name) {\n      if (path.extname(name) === '.html') return;\n      if (name === 'main.text') return;\n      delete files[name];\n    });\n\n    files['backslash_escapes.text'] = {\n      text: 'hello world \\\\[how](are you) today'\n    };\n\n    files['main.text'].text = files['main.text'].text.replace('* * *\\n\\n', '');\n  }\n\n  var start = Date.now()\n    , times = 1000\n    , keys = Object.keys(files)\n    , i\n    , l = keys.length\n    , filename\n    , file;\n\n  while (times--) {\n    for (i = 0; i < l; i++) {\n      filename = keys[i];\n      file = files[filename];\n      func(file.text);\n    }\n  }\n\n  console.log('%s completed in %dms.', name, Date.now() - start);\n}\n\n/**\n * Benchmark all engines\n */\n\nfunction runBench(options) {\n  var options = options || {};\n\n  // Non-GFM, Non-pedantic\n  marked.setOptions({\n    gfm: false,\n    tables: false,\n    breaks: false,\n    pedantic: false,\n    sanitize: false,\n    smartLists: false\n  });\n  if (options.marked) {\n    marked.setOptions(options.marked);\n  }\n  bench('marked', marked);\n\n  // GFM\n  marked.setOptions({\n    gfm: true,\n    tables: false,\n    breaks: false,\n    pedantic: false,\n    sanitize: false,\n    smartLists: false\n  });\n  if (options.marked) {\n    marked.setOptions(options.marked);\n  }\n  bench('marked (gfm)', marked);\n\n  // Pedantic\n  marked.setOptions({\n    gfm: false,\n    tables: false,\n    breaks: false,\n    pedantic: true,\n    sanitize: false,\n    smartLists: false\n  });\n  if (options.marked) {\n    marked.setOptions(options.marked);\n  }\n  bench('marked (pedantic)', marked);\n\n  // robotskirt\n  try {\n    bench('robotskirt', (function() {\n      var rs = require('robotskirt');\n      return function(text) {\n        var parser = rs.Markdown.std();\n        return parser.render(text);\n      };\n    })());\n  } catch (e) {\n    console.log('Could not bench robotskirt.');\n  }\n\n  // showdown\n  try {\n    bench('showdown (reuse converter)', (function() {\n      var Showdown = require('showdown');\n      var convert = new Showdown.converter();\n      return function(text) {\n        return convert.makeHtml(text);\n      };\n    })());\n    bench('showdown (new converter)', (function() {\n      var Showdown = require('showdown');\n      return function(text) {\n        var convert = new Showdown.converter();\n        return convert.makeHtml(text);\n      };\n    })());\n  } catch (e) {\n    console.log('Could not bench showdown.');\n  }\n\n  // markdown.js\n  try {\n    bench('markdown.js', require('markdown').parse);\n  } catch (e) {\n    console.log('Could not bench markdown.js.');\n  }\n}\n\n/**\n * A simple one-time benchmark\n */\n\nfunction time(options) {\n  var options = options || {};\n  if (options.marked) {\n    marked.setOptions(options.marked);\n  }\n  bench('marked', marked);\n}\n\n/**\n * Markdown Test Suite Fixer\n *   This function is responsible for \"fixing\"\n *   the markdown test suite. There are\n *   certain aspects of the suite that\n *   are strange or might make tests\n *   fail for reasons unrelated to\n *   conformance.\n */\n\nfunction fix(options) {\n  ['tests', 'original', 'new'].forEach(function(dir) {\n    try {\n      fs.mkdirSync(path.resolve(__dirname, dir), 0755);\n    } catch (e) {\n      ;\n    }\n  });\n\n  // rm -rf tests\n  fs.readdirSync(path.resolve(__dirname, 'tests')).forEach(function(file) {\n    fs.unlinkSync(path.resolve(__dirname, 'tests', file));\n  });\n\n  // cp -r original tests\n  fs.readdirSync(path.resolve(__dirname, 'original')).forEach(function(file) {\n    var nfile = file;\n    if (file.indexOf('hard_wrapped_paragraphs_with_list_like_lines.') === 0) {\n      nfile = file.replace(/\\.(text|html)$/, '.nogfm.$1');\n    }\n    fs.writeFileSync(path.resolve(__dirname, 'tests', nfile),\n      fs.readFileSync(path.resolve(__dirname, 'original', file)));\n  });\n\n  // node fix.js\n  var dir = __dirname + '/tests';\n\n  fs.readdirSync(dir).filter(function(file) {\n    return path.extname(file) === '.html';\n  }).forEach(function(file) {\n    var file = path.join(dir, file)\n      , html = fs.readFileSync(file, 'utf8');\n\n    // fix unencoded quotes\n    html = html\n      .replace(/='([^\\n']*)'(?=[^<>\\n]*>)/g, '=&__APOS__;$1&__APOS__;')\n      .replace(/=\"([^\\n\"]*)\"(?=[^<>\\n]*>)/g, '=&__QUOT__;$1&__QUOT__;')\n      .replace(/\"/g, '&quot;')\n      .replace(/'/g, '&#39;')\n      .replace(/&__QUOT__;/g, '\"')\n      .replace(/&__APOS__;/g, '\\'');\n\n    // add heading id's\n    html = html.replace(/<(h[1-6])>([^<]+)<\\/\\1>/g, function(s, h, text) {\n      var id = text\n        .replace(/&#39;/g, '\\'')\n        .replace(/&quot;/g, '\"')\n        .replace(/&gt;/g, '>')\n        .replace(/&lt;/g, '<')\n        .replace(/&amp;/g, '&');\n\n      id = id.toLowerCase().replace(/[^\\w]+/g, '-');\n\n      return '<' + h + ' id=\"' + id + '\">' + text + '</' + h + '>';\n    });\n\n    fs.writeFileSync(file, html);\n  });\n\n  // turn <hr /> into <hr>\n  fs.readdirSync(dir).forEach(function(file) {\n    var file = path.join(dir, file)\n      , text = fs.readFileSync(file, 'utf8');\n\n    text = text.replace(/(<|&lt;)hr\\s*\\/(>|&gt;)/g, '$1hr$2');\n\n    fs.writeFileSync(file, text);\n  });\n\n  // markdown does some strange things.\n  // it does not encode naked `>`, marked does.\n  (function() {\n    var file = dir + '/amps_and_angles_encoding.html';\n    var html = fs.readFileSync(file, 'utf8')\n      .replace('6 > 5.', '6 &gt; 5.');\n\n    fs.writeFileSync(file, html);\n  })();\n\n  // cp new/* tests/\n  fs.readdirSync(path.resolve(__dirname, 'new')).forEach(function(file) {\n    fs.writeFileSync(path.resolve(__dirname, 'tests', file),\n      fs.readFileSync(path.resolve(__dirname, 'new', file)));\n  });\n}\n\n/**\n * Argument Parsing\n */\n\nfunction parseArg(argv) {\n  var argv = process.argv.slice(2)\n    , options = {}\n    , orphans = []\n    , arg;\n\n  function getarg() {\n    var arg = argv.shift();\n\n    if (arg.indexOf('--') === 0) {\n      // e.g. --opt\n      arg = arg.split('=');\n      if (arg.length > 1) {\n        // e.g. --opt=val\n        argv.unshift(arg.slice(1).join('='));\n      }\n      arg = arg[0];\n    } else if (arg[0] === '-') {\n      if (arg.length > 2) {\n        // e.g. -abc\n        argv = arg.substring(1).split('').map(function(ch) {\n          return '-' + ch;\n        }).concat(argv);\n        arg = argv.shift();\n      } else {\n        // e.g. -a\n      }\n    } else {\n      // e.g. foo\n    }\n\n    return arg;\n  }\n\n  while (argv.length) {\n    arg = getarg();\n    switch (arg) {\n      case '-f':\n      case '--fix':\n      case 'fix':\n        options.fix = true;\n        break;\n      case '-b':\n      case '--bench':\n        options.bench = true;\n        break;\n      case '-s':\n      case '--stop':\n        options.stop = true;\n        break;\n      case '-t':\n      case '--time':\n        options.time = true;\n        break;\n      default:\n        if (arg.indexOf('--') === 0) {\n          opt = camelize(arg.replace(/^--(no-)?/, ''));\n          if (!marked.defaults.hasOwnProperty(opt)) {\n            continue;\n          }\n          options.marked = options.marked || {};\n          if (arg.indexOf('--no-') === 0) {\n            options.marked[opt] = typeof marked.defaults[opt] !== 'boolean'\n              ? null\n              : false;\n          } else {\n            options.marked[opt] = typeof marked.defaults[opt] !== 'boolean'\n              ? argv.shift()\n              : true;\n          }\n        } else {\n          orphans.push(arg);\n        }\n        break;\n    }\n  }\n\n  return options;\n}\n\n/**\n * Helpers\n */\n\nfunction camelize(text) {\n  return text.replace(/(\\w)-(\\w)/g, function(_, a, b) {\n    return a + b.toUpperCase();\n  });\n}\n\n/**\n * Main\n */\n\nfunction main(argv) {\n  var opt = parseArg();\n\n  if (opt.fix) {\n    return fix(opt);\n  }\n\n  if (opt.bench) {\n    return runBench(opt);\n  }\n\n  if (opt.time) {\n    return time(opt);\n  }\n\n  return runTests(opt);\n}\n\n/**\n * Execute\n */\n\nif (!module.parent) {\n  process.title = 'marked';\n  process.exit(main(process.argv.slice()) ? 0 : 1);\n} else {\n  exports = main;\n  exports.main = main;\n  exports.runTests = runTests;\n  exports.runBench = runBench;\n  exports.load = load;\n  exports.bench = bench;\n  module.exports = exports;\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/autolink_lines.html",
    "content": "<p>hello world\n<a href=\"http://example.com\">http://example.com</a>\n</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/autolink_lines.text",
    "content": "hello world\n<http://example.com>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/blockquote_list_item.html",
    "content": "<p>This fails in markdown.pl and upskirt:</p>\n\n<ul><li>hello<blockquote><p>world</p></blockquote></li></ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/blockquote_list_item.text",
    "content": "This fails in markdown.pl and upskirt:\n\n* hello\n  > world\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/case_insensitive_refs.html",
    "content": "<p><a href=\"/url\">hi</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/case_insensitive_refs.text",
    "content": "[hi]\n\n[HI]: /url\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/def_blocks.html",
    "content": "<blockquote>\n  <p>hello\n[1]: hello</p>\n</blockquote>\n\n<hr>\n\n<blockquote>\n  <p>hello</p>\n</blockquote>\n\n\n<ul>\n<li>hello</li>\n<li>[3]: hello</li>\n</ul>\n\n\n<ul>\n<li>hello</li>\n</ul>\n\n\n<blockquote>\n  <p>foo\nbar\nbar</p>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/def_blocks.text",
    "content": "> hello\n> [1]: hello\n\n* * *\n\n> hello\n[2]: hello\n\n\n* hello\n* [3]: hello\n\n\n* hello\n[4]: hello\n\n\n> foo\n> bar\n[1]: foo\n> bar\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/double_link.html",
    "content": "<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>Already linked: <a href=\"http://example.com/\"><strong>http://example.com/</strong></a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/double_link.text",
    "content": "<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\nAlready linked: [http://example.com/](http://example.com/).\n\nAlready linked: <a href=\"http://example.com/\">**http://example.com/**</a>.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/escaped_angles.html",
    "content": "<p>></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/escaped_angles.text",
    "content": "\\>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_break.breaks.html",
    "content": "<p>Look at the<br>pretty line<br>breaks.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_break.breaks.text",
    "content": "Look at the\npretty line\nbreaks.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_code.html",
    "content": "<pre><code class=\"lang-js\">var a = &#39;hello&#39;;\nconsole.log(a + &#39; world&#39;);</code></pre>\n<pre><code class=\"lang-bash\">echo &quot;hello, ${WORLD}&quot;</code></pre>\n<pre><code class=\"lang-longfence\">Q: What do you call a tall person who sells stolen goods?</code></pre>\n<pre><code class=\"lang-ManyTildes\">A longfence!</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_code.text",
    "content": "``` js\nvar a = 'hello';\nconsole.log(a + ' world');\n```\n\n~~~bash\necho \"hello, ${WORLD}\"\n~~~\n\n```````longfence\nQ: What do you call a tall person who sells stolen goods?\n```````\n\n~~~~~~~~~~  ManyTildes\nA longfence!\n~~~~~~~~~~\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_code_hr_list.html",
    "content": "<h2 id=\"foo\">foo</h2>\n<ol>\n<li><p>bar:</p>\n<blockquote>\n<ul>\n<li>one<ul>\n<li>two<ul>\n<li>three</li>\n<li>four</li>\n<li>five</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</blockquote>\n</li>\n<li><p>foo:</p>\n<pre><code> line 1\n line 2</code></pre>\n</li>\n<li><p>foo:</p>\n<ol>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code class=\"lang-erb\"> some code here\n</code></pre>\n</li>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code class=\"lang-erb\"> foo\n ---\n bar\n ---\n foo\n bar</code></pre>\n</li>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code class=\"lang-html\"> ---\n foo\n foo\n ---\n bar</code></pre>\n</li>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code> foo\n ---\n bar</code></pre>\n</li>\n<li><p>foo</p>\n</li>\n</ol>\n</li>\n</ol>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_code_hr_list.text",
    "content": "## foo\n\n1. bar:\n\n    > - one\n        - two\n            - three\n            - four\n            - five\n\n1. foo:\n\n    ```\n    line 1\n    line 2\n    ```\n\n1. foo:\n\n    1. foo `bar` bar:\n\n        ``` erb\n        some code here\n        ```\n\n    2. foo `bar` bar:\n\n        ``` erb\n        foo\n        ---\n        bar\n        ---\n        foo\n        bar\n        ```\n\n    3. foo `bar` bar:\n\n        ``` html\n        ---\n        foo\n        foo\n        ---\n        bar\n        ```\n\n    4. foo `bar` bar:\n\n            foo\n            ---\n            bar\n\n    5. foo\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_del.html",
    "content": "<p>hello <del>hi</del> world</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_del.text",
    "content": "hello ~~hi~~ world\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_em.html",
    "content": "<p>These words should_not_be_emphasized.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_em.text",
    "content": "These words should_not_be_emphasized.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_links.html",
    "content": "<p>This should be a link:\n<a href=\"http://example.com/hello-world\">http://example.com/hello-world</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_links.text",
    "content": "This should be a link: http://example.com/hello-world.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_tables.html",
    "content": "<table>\n\t<thead>\n\t\t<tr><th>Heading 1</th><th>Heading 2</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td>Cell 1</td><td>Cell 2</td></tr>\n\t\t<tr><td>Cell 3</td><td>Cell 4</td></tr>\n\t</tbody>\n</table>\n<table>\n\t<thead>\n\t\t<tr><th style=\"text-align:center\">Header 1</th><th style=\"text-align:right\">Header 2</th><th style=\"text-align:left\">Header 3</th><th>Header 4</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td style=\"text-align:center\">Cell 1</td><td style=\"text-align:right\">Cell 2</td><td style=\"text-align:left\">Cell 3</td><td>Cell 4</td></tr>\n\t\t<tr><td style=\"text-align:center\">Cell 5</td><td style=\"text-align:right\">Cell 6</td><td style=\"text-align:left\">Cell 7</td><td>Cell 8</td></tr>\n\t</tbody>\n</table>\n<pre><code>Test code</code></pre>\n<table>\n\t<thead>\n\t\t<tr><th>Header 1</th><th>Header 2</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td>Cell 1</td><td>Cell 2</td></tr>\n\t\t<tr><td>Cell 3</td><td>Cell 4</td></tr>\n\t</tbody>\n</table>\n<table>\n\t<thead>\n\t\t<tr><th style=\"text-align:left\">Header 1</th><th style=\"text-align:center\">Header 2</th><th style=\"text-align:right\">Header 3</th><th>Header 4</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td style=\"text-align:left\">Cell 1</td><td style=\"text-align:center\">Cell 2</td><td style=\"text-align:right\">Cell 3</td><td>Cell 4</td></tr>\n\t\t<tr><td style=\"text-align:left\"><em>Cell 5</em></td><td style=\"text-align:center\">Cell 6</td><td style=\"text-align:right\">Cell 7</td><td>Cell 8</td></tr>\n\t</tbody>\n</table>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/gfm_tables.text",
    "content": "| Heading 1 | Heading 2\n| --------- | ---------\n| Cell 1    | Cell 2\n| Cell 3    | Cell 4\n\n| Header 1 | Header 2 | Header 3 | Header 4 |\n| :------: | -------: | :------- | -------- |\n| Cell 1   | Cell 2   | Cell 3   | Cell 4   |\n| Cell 5   | Cell 6   | Cell 7   | Cell 8   |\n\n    Test code\n\nHeader 1 | Header 2\n-------- | --------\nCell 1   | Cell 2\nCell 3   | Cell 4\n\nHeader 1|Header 2|Header 3|Header 4\n:-------|:------:|-------:|--------\nCell 1  |Cell 2  |Cell 3  |Cell 4\n*Cell 5*|Cell 6  |Cell 7  |Cell 8\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/hr_list_break.html",
    "content": "<ul>\n<li>hello\nworld</li>\n<li>how\nare</li>\n</ul>\n\n<hr>\n\n<p>you today?</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/hr_list_break.text",
    "content": "* hello\nworld\n* how\nare\n* * *\nyou today?\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/lazy_blockquotes.html",
    "content": "<blockquote>\n  <p>hi there\nbud</p>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/lazy_blockquotes.text",
    "content": "> hi there\nbud\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/list_item_text.html",
    "content": "<ul><li><p>item1</p>  <ul><li>item2 </li></ul> <p>text</p> </li></ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/list_item_text.text",
    "content": "  * item1\n\n    * item2\n\n  text\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/loose_lists.html",
    "content": "<ul>\n<li><p>hello\nworld </p>\n\n<p>how\nare</p></li>\n<li>you </li>\n</ul>\n\n\n\n<p>better behavior:</p>\n\n<ul><li><p>hello</p> <ul><li><p>world\nhow</p>  <p>are\nyou</p></li><li><p>today</p></li></ul></li><li>hi</li></ul>\n\n\n\n<ul>\n<li><p>hello</p></li>\n<li><p>world</p></li>\n<li>hi</li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li><p>world</p></li>\n<li><p>hi</p></li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li><p>world</p>\n\n<p>how</p></li>\n<li>hi</li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li>world</li>\n<li><p>how</p>\n\n<p>are</p></li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li><p>world</p></li>\n<li><p>how</p>\n\n<p>are</p></li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/loose_lists.text",
    "content": "* hello\n  world\n\n  how\n  are\n* you\n\n\n\nbetter behavior:\n\n* hello\n  * world\n    how\n\n    are\n    you\n\n  * today\n* hi\n\n\n\n* hello\n\n* world\n* hi\n\n\n\n* hello\n* world\n\n* hi\n\n\n\n* hello\n* world\n\n  how\n* hi\n\n\n\n* hello\n* world\n* how\n\n  are\n\n\n\n* hello\n* world\n\n* how\n\n  are\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/main.html",
    "content": "<h1 id=\"a-heading\">A heading</h1> <p>Just a note, I&#39;ve found that I can&#39;t test my markdown parser vs others. For example, both markdown.js and showdown code blocks in lists wrong. They&#39;re  also completely <a href=\"http://google.com/\" title=\"Google\">inconsistent</a> with regards to paragraphs in list items.</p> <p>A link. Not anymore.</p> <aside>This will make me fail the test because\nmarkdown.js doesnt acknowledge arbitrary html blocks =/</aside> <ul><li><p>List Item 1</p></li><li><p>List Item 2 </p><ul><li>New List Item 1 Hi, this is a list item.</li><li>New List Item 2 Another item <pre><code>Code goes here.\nLots of it...</code></pre></li><li>New List Item 3 The last item</li></ul></li><li><p>List Item 3 The final item.</p></li><li><p>List Item 4 The real final item.</p></li></ul> <p>Paragraph.</p> <blockquote><ul><li>bq Item 1</li><li>bq Item 2 <ul><li>New bq Item 1</li><li>New bq Item 2 Text here</li></ul></li></ul></blockquote> <hr> <blockquote><p> Another blockquote!  I really need to get  more creative with  mockup text..  markdown.js breaks here again</p></blockquote> <h2 id=\"another-heading\">Another Heading</h2> <p>Hello <em>world</em>. Here is a <a href=\"//hello\">link</a>. And an image <img src=\"src\" alt=\"alt\">.</p> <pre><code>Code goes here.\nLots of it...</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/main.text",
    "content": "[test]: http://google.com/ \"Google\"\n\n# A heading\n\nJust a note, I've found that I can't test my markdown parser vs others.\nFor example, both markdown.js and showdown code blocks in lists wrong. They're\nalso completely [inconsistent][test] with regards to paragraphs in list items.\n\nA link. Not anymore.\n\n<aside>This will make me fail the test because\nmarkdown.js doesnt acknowledge arbitrary html blocks =/</aside>\n\n* List Item 1\n\n* List Item 2\n  * New List Item 1\n    Hi, this is a list item.\n  * New List Item 2\n    Another item\n        Code goes here.\n        Lots of it...\n  * New List Item 3\n    The last item\n\n* List Item 3\nThe final item.\n\n* List Item 4\nThe real final item.\n\nParagraph.\n\n> * bq Item 1\n> * bq Item 2\n>   * New bq Item 1\n>   * New bq Item 2\n>   Text here\n\n* * *\n\n> Another blockquote!\n> I really need to get\n> more creative with\n> mockup text..\n> markdown.js breaks here again\n\nAnother Heading\n-------------\n\nHello *world*. Here is a [link](//hello).\nAnd an image ![alt](src).\n\n    Code goes here.\n    Lots of it...\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/nested_code.html",
    "content": "<p><code>hi ther `` ok ```</code></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/nested_code.text",
    "content": "````` hi ther `` ok ``` `````\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/nested_em.html",
    "content": "<p><em>test <strong>test</strong> test</em></p>\n\n<p><em>test <strong>test</strong> test</em></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/nested_em.text",
    "content": "*test **test** test*\n\n_test __test__ test_\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/nested_square_link.html",
    "content": "<p><a href=\"/url\">the <code>]</code> character</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/nested_square_link.text",
    "content": "[the `]` character](/url)\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/not_a_link.html",
    "content": "<p>[test](not a link)</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/not_a_link.text",
    "content": "\\[test](not a link)\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/ref_paren.html",
    "content": "<p><a href=\"/url\" title=\"there\">hi</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/ref_paren.text",
    "content": "[hi]\n\n[hi]: /url (there)\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/same_bullet.html",
    "content": "<ul>\n<li>test</li>\n<li>test</li>\n<li>test</li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/same_bullet.text",
    "content": "* test\n+ test\n- test\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/text.smartypants.html",
    "content": "<p>Hello world ‘how’ “are” you — today…</p>\n\n<p>“It’s a more ‘challenging’ smartypants test…”</p>\n\n<p>‘And,’ as a bonus — “one\nmultiline” test!</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/text.smartypants.text",
    "content": "Hello world 'how' \"are\" you -- today...\n\n\"It's a more 'challenging' smartypants test...\"\n\n'And,' as a bonus -- \"one\nmultiline\" test!\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/toplevel_paragraphs.gfm.html",
    "content": "<p>hello world\n    how are you\n    how are you</p>\n\n<p>hello world</p>\n<pre><code>how are you</code></pre>\n\n<p>hello world</p>\n<hr>\n\n<p>hello world</p>\n<h1 id=\"how-are-you\">how are you</h1>\n\n<p>hello world</p>\n<h1 id=\"how-are-you\">how are you</h1>\n\n<p>hello world</p>\n<blockquote><p>how are you</p></blockquote>\n\n<p>hello world</p>\n<ul><li>how are you</li></ul>\n\n<p>hello world</p>\n<div>how are you</div>\n\n<p>hello world\n<span>how are you</span></p>\n\n<p>hello <a href=\"/are/you\">world</a>\n</p>\n\n<div>hello</div>\n\n<p><span>hello</span></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/toplevel_paragraphs.gfm.text",
    "content": "hello world\n    how are you\n    how are you\n\nhello world\n```\nhow are you\n```\n\nhello world\n* * *\n\nhello world\n# how are you\n\nhello world\nhow are you\n===========\n\nhello world\n> how are you\n\nhello world\n* how are you\n\nhello world\n<div>how are you</div>\n\nhello world\n<span>how are you</span>\n\nhello [world][how]\n[how]: /are/you\n\n<div>hello</div>\n\n<span>hello</span>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/tricky_list.html",
    "content": "<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>hello world</li>\n</ul>\n\n<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>hello world</li>\n</ul>\n\n<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>Hello world</li>\n</ul>\n\n<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>hello world</li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/new/tricky_list.text",
    "content": "**hello** _world_\n\n* hello world\n\n**hello** _world_\n\n* hello world\n\n**hello** _world_\n\n* Hello world\n\n**hello** _world_\n\n* hello world\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/amps_and_angles_encoding.html",
    "content": "<p>AT&amp;T has an ampersand in their name.</p>\n\n<p>AT&amp;T is another way to write it.</p>\n\n<p>This &amp; that.</p>\n\n<p>4 &lt; 5.</p>\n\n<p>6 > 5.</p>\n\n<p>Here's a <a href=\"http://example.com/?foo=1&amp;bar=2\">link</a> with an ampersand in the URL.</p>\n\n<p>Here's a link with an amersand in the link text: <a href=\"http://att.com/\" title=\"AT&amp;T\">AT&amp;T</a>.</p>\n\n<p>Here's an inline <a href=\"/script?foo=1&amp;bar=2\">link</a>.</p>\n\n<p>Here's an inline <a href=\"/script?foo=1&amp;bar=2\">link</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/amps_and_angles_encoding.text",
    "content": "AT&T has an ampersand in their name.\n\nAT&amp;T is another way to write it.\n\nThis & that.\n\n4 < 5.\n\n6 > 5.\n\nHere's a [link] [1] with an ampersand in the URL.\n\nHere's a link with an amersand in the link text: [AT&T] [2].\n\nHere's an inline [link](/script?foo=1&bar=2).\n\nHere's an inline [link](</script?foo=1&bar=2>).\n\n\n[1]: http://example.com/?foo=1&bar=2\n[2]: http://att.com/  \"AT&T\"\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/auto_links.html",
    "content": "<p>Link: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>With an ampersand: <a href=\"http://example.com/?foo=1&amp;bar=2\">http://example.com/?foo=1&amp;bar=2</a></p>\n\n<ul>\n<li>In a list?</li>\n<li><a href=\"http://example.com/\">http://example.com/</a></li>\n<li>It should.</li>\n</ul>\n\n<blockquote>\n  <p>Blockquoted: <a href=\"http://example.com/\">http://example.com/</a></p>\n</blockquote>\n\n<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>\n\n<pre><code>or here: &lt;http://example.com/&gt;\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/auto_links.text",
    "content": "Link: <http://example.com/>.\n\nWith an ampersand: <http://example.com/?foo=1&bar=2>\n\n* In a list?\n* <http://example.com/>\n* It should.\n\n> Blockquoted: <http://example.com/>\n\nAuto-links should not occur here: `<http://example.com/>`\n\n\tor here: <http://example.com/>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/backslash_escapes.html",
    "content": "<p>These should all get escaped:</p>\n\n<p>Backslash: \\</p>\n\n<p>Backtick: `</p>\n\n<p>Asterisk: *</p>\n\n<p>Underscore: _</p>\n\n<p>Left brace: {</p>\n\n<p>Right brace: }</p>\n\n<p>Left bracket: [</p>\n\n<p>Right bracket: ]</p>\n\n<p>Left paren: (</p>\n\n<p>Right paren: )</p>\n\n<p>Greater-than: ></p>\n\n<p>Hash: #</p>\n\n<p>Period: .</p>\n\n<p>Bang: !</p>\n\n<p>Plus: +</p>\n\n<p>Minus: -</p>\n\n<p>These should not, because they occur within a code block:</p>\n\n<pre><code>Backslash: \\\\\n\nBacktick: \\`\n\nAsterisk: \\*\n\nUnderscore: \\_\n\nLeft brace: \\{\n\nRight brace: \\}\n\nLeft bracket: \\[\n\nRight bracket: \\]\n\nLeft paren: \\(\n\nRight paren: \\)\n\nGreater-than: \\&gt;\n\nHash: \\#\n\nPeriod: \\.\n\nBang: \\!\n\nPlus: \\+\n\nMinus: \\-\n</code></pre>\n\n<p>Nor should these, which occur in code spans:</p>\n\n<p>Backslash: <code>\\\\</code></p>\n\n<p>Backtick: <code>\\`</code></p>\n\n<p>Asterisk: <code>\\*</code></p>\n\n<p>Underscore: <code>\\_</code></p>\n\n<p>Left brace: <code>\\{</code></p>\n\n<p>Right brace: <code>\\}</code></p>\n\n<p>Left bracket: <code>\\[</code></p>\n\n<p>Right bracket: <code>\\]</code></p>\n\n<p>Left paren: <code>\\(</code></p>\n\n<p>Right paren: <code>\\)</code></p>\n\n<p>Greater-than: <code>\\&gt;</code></p>\n\n<p>Hash: <code>\\#</code></p>\n\n<p>Period: <code>\\.</code></p>\n\n<p>Bang: <code>\\!</code></p>\n\n<p>Plus: <code>\\+</code></p>\n\n<p>Minus: <code>\\-</code></p>\n\n\n<p>These should get escaped, even though they're matching pairs for\nother Markdown constructs:</p>\n\n<p>*asterisks*</p>\n\n<p>_underscores_</p>\n\n<p>`backticks`</p>\n\n<p>This is a code span with a literal backslash-backtick sequence: <code>\\`</code></p>\n\n<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p>\n\n<p>This is a tag with backslashes <span attr='\\\\backslashes\\\\'>bar</span>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/backslash_escapes.text",
    "content": "These should all get escaped:\n\nBackslash: \\\\\n\nBacktick: \\`\n\nAsterisk: \\*\n\nUnderscore: \\_\n\nLeft brace: \\{\n\nRight brace: \\}\n\nLeft bracket: \\[\n\nRight bracket: \\]\n\nLeft paren: \\(\n\nRight paren: \\)\n\nGreater-than: \\>\n\nHash: \\#\n\nPeriod: \\.\n\nBang: \\!\n\nPlus: \\+\n\nMinus: \\-\n\n\n\nThese should not, because they occur within a code block:\n\n\tBackslash: \\\\\n\n\tBacktick: \\`\n\n\tAsterisk: \\*\n\n\tUnderscore: \\_\n\n\tLeft brace: \\{\n\n\tRight brace: \\}\n\n\tLeft bracket: \\[\n\n\tRight bracket: \\]\n\n\tLeft paren: \\(\n\n\tRight paren: \\)\n\n\tGreater-than: \\>\n\n\tHash: \\#\n\n\tPeriod: \\.\n\n\tBang: \\!\n\n\tPlus: \\+\n\n\tMinus: \\-\n\n\nNor should these, which occur in code spans:\n\nBackslash: `\\\\`\n\nBacktick: `` \\` ``\n\nAsterisk: `\\*`\n\nUnderscore: `\\_`\n\nLeft brace: `\\{`\n\nRight brace: `\\}`\n\nLeft bracket: `\\[`\n\nRight bracket: `\\]`\n\nLeft paren: `\\(`\n\nRight paren: `\\)`\n\nGreater-than: `\\>`\n\nHash: `\\#`\n\nPeriod: `\\.`\n\nBang: `\\!`\n\nPlus: `\\+`\n\nMinus: `\\-`\n\n\nThese should get escaped, even though they're matching pairs for\nother Markdown constructs:\n\n\\*asterisks\\*\n\n\\_underscores\\_\n\n\\`backticks\\`\n\nThis is a code span with a literal backslash-backtick sequence: `` \\` ``\n\nThis is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.\n\nThis is a tag with backslashes <span attr='\\\\backslashes\\\\'>bar</span>.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/blockquotes_with_code_blocks.html",
    "content": "<blockquote>\n  <p>Example:</p>\n\n<pre><code>sub status {\n    print \"working\";\n}\n</code></pre>\n  \n  <p>Or:</p>\n\n<pre><code>sub status {\n    return \"working\";\n}\n</code></pre>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/blockquotes_with_code_blocks.text",
    "content": "> Example:\n> \n>     sub status {\n>         print \"working\";\n>     }\n> \n> Or:\n> \n>     sub status {\n>         return \"working\";\n>     }\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/code_blocks.html",
    "content": "<pre><code>code block on the first line\n</code></pre>\n\n<p>Regular text.</p>\n\n<pre><code>code block indented by spaces\n</code></pre>\n\n<p>Regular text.</p>\n\n<pre><code>the lines in this block  \nall contain trailing spaces  \n</code></pre>\n\n<p>Regular Text.</p>\n\n<pre><code>code block on the last line\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/code_blocks.text",
    "content": "\tcode block on the first line\n\t\nRegular text.\n\n    code block indented by spaces\n\nRegular text.\n\n\tthe lines in this block  \n\tall contain trailing spaces  \n\nRegular Text.\n\n\tcode block on the last line\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/code_spans.html",
    "content": "<p><code>&lt;test a=\"</code> content of attribute <code>\"&gt;</code></p>\n\n<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p>\n\n<p>Here's how you put <code>`backticks`</code> in a code span.</p>\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/code_spans.text",
    "content": "`<test a=\"` content of attribute `\">`\n\nFix for backticks within HTML tag: <span attr='`ticks`'>like this</span>\n\nHere's how you put `` `backticks` `` in a code span.\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/hard_wrapped_paragraphs_with_list_like_lines.html",
    "content": "<p>In Markdown 1.0.0 and earlier. Version\n8. This line turns into a list item.\nBecause a hard-wrapped line in the\nmiddle of a paragraph looked like a\nlist item.</p>\n\n<p>Here's one with a bullet.\n* criminey.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/hard_wrapped_paragraphs_with_list_like_lines.text",
    "content": "In Markdown 1.0.0 and earlier. Version\n8. This line turns into a list item.\nBecause a hard-wrapped line in the\nmiddle of a paragraph looked like a\nlist item.\n\nHere's one with a bullet.\n* criminey.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/horizontal_rules.html",
    "content": "<p>Dashes:</p>\n\n<hr />\n\n<hr />\n\n<hr />\n\n<hr />\n\n<pre><code>---\n</code></pre>\n\n<hr />\n\n<hr />\n\n<hr />\n\n<hr />\n\n<pre><code>- - -\n</code></pre>\n\n<p>Asterisks:</p>\n\n<hr />\n\n<hr />\n\n<hr />\n\n<hr />\n\n<pre><code>***\n</code></pre>\n\n<hr />\n\n<hr />\n\n<hr />\n\n<hr />\n\n<pre><code>* * *\n</code></pre>\n\n<p>Underscores:</p>\n\n<hr />\n\n<hr />\n\n<hr />\n\n<hr />\n\n<pre><code>___\n</code></pre>\n\n<hr />\n\n<hr />\n\n<hr />\n\n<hr />\n\n<pre><code>_ _ _\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/horizontal_rules.text",
    "content": "Dashes:\n\n---\n\n ---\n \n  ---\n\n   ---\n\n\t---\n\n- - -\n\n - - -\n \n  - - -\n\n   - - -\n\n\t- - -\n\n\nAsterisks:\n\n***\n\n ***\n \n  ***\n\n   ***\n\n\t***\n\n* * *\n\n * * *\n \n  * * *\n\n   * * *\n\n\t* * *\n\n\nUnderscores:\n\n___\n\n ___\n \n  ___\n\n   ___\n\n    ___\n\n_ _ _\n\n _ _ _\n \n  _ _ _\n\n   _ _ _\n\n    _ _ _\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/inline_html_advanced.html",
    "content": "<p>Simple block on one line:</p>\n\n<div>foo</div>\n\n<p>And nested without indentation:</p>\n\n<div>\n<div>\n<div>\nfoo\n</div>\n<div style=\">\"/>\n</div>\n<div>bar</div>\n</div>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/inline_html_advanced.text",
    "content": "Simple block on one line:\n\n<div>foo</div>\n\nAnd nested without indentation:\n\n<div>\n<div>\n<div>\nfoo\n</div>\n<div style=\">\"/>\n</div>\n<div>bar</div>\n</div>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/inline_html_comments.html",
    "content": "<p>Paragraph one.</p>\n\n<!-- This is a simple comment -->\n\n<!--\n    This is another comment.\n-->\n\n<p>Paragraph two.</p>\n\n<!-- one comment block -- -- with two comments -->\n\n<p>The end.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/inline_html_comments.text",
    "content": "Paragraph one.\n\n<!-- This is a simple comment -->\n\n<!--\n\tThis is another comment.\n-->\n\nParagraph two.\n\n<!-- one comment block -- -- with two comments -->\n\nThe end.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/inline_html_simple.html",
    "content": "<p>Here's a simple block:</p>\n\n<div>\n    foo\n</div>\n\n<p>This should be a code block, though:</p>\n\n<pre><code>&lt;div&gt;\n    foo\n&lt;/div&gt;\n</code></pre>\n\n<p>As should this:</p>\n\n<pre><code>&lt;div&gt;foo&lt;/div&gt;\n</code></pre>\n\n<p>Now, nested:</p>\n\n<div>\n    <div>\n        <div>\n            foo\n        </div>\n    </div>\n</div>\n\n<p>This should just be an HTML comment:</p>\n\n<!-- Comment -->\n\n<p>Multiline:</p>\n\n<!--\nBlah\nBlah\n-->\n\n<p>Code block:</p>\n\n<pre><code>&lt;!-- Comment --&gt;\n</code></pre>\n\n<p>Just plain comment, with trailing spaces on the line:</p>\n\n<!-- foo -->   \n\n<p>Code:</p>\n\n<pre><code>&lt;hr /&gt;\n</code></pre>\n\n<p>Hr's:</p>\n\n<hr>\n\n<hr/>\n\n<hr />\n\n<hr>   \n\n<hr/>  \n\n<hr /> \n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\"/>\n\n<hr class=\"foo\" id=\"bar\" >\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/inline_html_simple.text",
    "content": "Here's a simple block:\n\n<div>\n\tfoo\n</div>\n\nThis should be a code block, though:\n\n\t<div>\n\t\tfoo\n\t</div>\n\nAs should this:\n\n\t<div>foo</div>\n\nNow, nested:\n\n<div>\n\t<div>\n\t\t<div>\n\t\t\tfoo\n\t\t</div>\n\t</div>\n</div>\n\nThis should just be an HTML comment:\n\n<!-- Comment -->\n\nMultiline:\n\n<!--\nBlah\nBlah\n-->\n\nCode block:\n\n\t<!-- Comment -->\n\nJust plain comment, with trailing spaces on the line:\n\n<!-- foo -->   \n\nCode:\n\n\t<hr />\n\t\nHr's:\n\n<hr>\n\n<hr/>\n\n<hr />\n\n<hr>   \n\n<hr/>  \n\n<hr /> \n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\"/>\n\n<hr class=\"foo\" id=\"bar\" >\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/links_inline_style.html",
    "content": "<p>Just a <a href=\"/url/\">URL</a>.</p>\n\n<p><a href=\"/url/\" title=\"title\">URL and title</a>.</p>\n\n<p><a href=\"/url/\" title=\"title preceded by two spaces\">URL and title</a>.</p>\n\n<p><a href=\"/url/\" title=\"title preceded by a tab\">URL and title</a>.</p>\n\n<p><a href=\"/url/\" title=\"title has spaces afterward\">URL and title</a>.</p>\n\n<p><a href=\"/url/has space\">URL and title</a>.</p>\n\n<p><a href=\"/url/has space/\" title=\"url has space and title\">URL and title</a>.</p>\n\n<p><a href=\"\">Empty</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/links_inline_style.text",
    "content": "Just a [URL](/url/).\n\n[URL and title](/url/ \"title\").\n\n[URL and title](/url/  \"title preceded by two spaces\").\n\n[URL and title](/url/\t\"title preceded by a tab\").\n\n[URL and title](/url/ \"title has spaces afterward\"  ).\n\n[URL and title]( /url/has space ).\n\n[URL and title]( /url/has space/ \"url has space and title\").\n\n[Empty]().\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/links_reference_style.html",
    "content": "<p>Foo <a href=\"/url/\" title=\"Title\">bar</a>.</p>\n\n<p>Foo <a href=\"/url/\" title=\"Title\">bar</a>.</p>\n\n<p>Foo <a href=\"/url/\" title=\"Title\">bar</a>.</p>\n\n<p>With <a href=\"/url/\">embedded [brackets]</a>.</p>\n\n<p>Indented <a href=\"/url\">once</a>.</p>\n\n<p>Indented <a href=\"/url\">twice</a>.</p>\n\n<p>Indented <a href=\"/url\">thrice</a>.</p>\n\n<p>Indented [four][] times.</p>\n\n<pre><code>[four]: /url\n</code></pre>\n\n<hr />\n\n<p><a href=\"foo\">this</a> should work</p>\n\n<p>So should <a href=\"foo\">this</a>.</p>\n\n<p>And <a href=\"foo\">this</a>.</p>\n\n<p>And <a href=\"foo\">this</a>.</p>\n\n<p>And <a href=\"foo\">this</a>.</p>\n\n<p>But not [that] [].</p>\n\n<p>Nor [that][].</p>\n\n<p>Nor [that].</p>\n\n<p>[Something in brackets like <a href=\"foo\">this</a> should work]</p>\n\n<p>[Same with <a href=\"foo\">this</a>.]</p>\n\n<p>In this case, <a href=\"/somethingelse/\">this</a> points to something else.</p>\n\n<p>Backslashing should suppress [this] and [this].</p>\n\n<hr />\n\n<p>Here's one where the <a href=\"/url/\">link\nbreaks</a> across lines.</p>\n\n<p>Here's another where the <a href=\"/url/\">link \nbreaks</a> across lines, but with a line-ending space.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/links_reference_style.text",
    "content": "Foo [bar] [1].\n\nFoo [bar][1].\n\nFoo [bar]\n[1].\n\n[1]: /url/  \"Title\"\n\n\nWith [embedded [brackets]] [b].\n\n\nIndented [once][].\n\nIndented [twice][].\n\nIndented [thrice][].\n\nIndented [four][] times.\n\n [once]: /url\n\n  [twice]: /url\n\n   [thrice]: /url\n\n    [four]: /url\n\n\n[b]: /url/\n\n* * *\n\n[this] [this] should work\n\nSo should [this][this].\n\nAnd [this] [].\n\nAnd [this][].\n\nAnd [this].\n\nBut not [that] [].\n\nNor [that][].\n\nNor [that].\n\n[Something in brackets like [this][] should work]\n\n[Same with [this].]\n\nIn this case, [this](/somethingelse/) points to something else.\n\nBackslashing should suppress \\[this] and [this\\].\n\n[this]: foo\n\n\n* * *\n\nHere's one where the [link\nbreaks] across lines.\n\nHere's another where the [link \nbreaks] across lines, but with a line-ending space.\n\n\n[link breaks]: /url/\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/links_shortcut_references.html",
    "content": "<p>This is the <a href=\"/simple\">simple case</a>.</p>\n\n<p>This one has a <a href=\"/foo\">line\nbreak</a>.</p>\n\n<p>This one has a <a href=\"/foo\">line \nbreak</a> with a line-ending space.</p>\n\n<p><a href=\"/that\">this</a> and the <a href=\"/other\">other</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/links_shortcut_references.text",
    "content": "This is the [simple case].\n\n[simple case]: /simple\n\n\n\nThis one has a [line\nbreak].\n\nThis one has a [line \nbreak] with a line-ending space.\n\n[line break]: /foo\n\n\n[this] [that] and the [other]\n\n[this]: /this\n[that]: /that\n[other]: /other\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/literal_quotes_in_titles.html",
    "content": "<p>Foo <a href=\"/url/\" title=\"Title with &quot;quotes&quot; inside\">bar</a>.</p>\n\n<p>Foo <a href=\"/url/\" title=\"Title with &quot;quotes&quot; inside\">bar</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/literal_quotes_in_titles.text",
    "content": "Foo [bar][].\n\nFoo [bar](/url/ \"Title with \"quotes\" inside\").\n\n\n  [bar]: /url/ \"Title with \"quotes\" inside\"\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/markdown_documentation_basics.html",
    "content": "<h1>Markdown: Basics</h1>\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a class=\"selected\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n<h2>Getting the Gist of Markdown's Formatting Syntax</h2>\n\n<p>This page offers a brief overview of what it's like to use Markdown.\nThe <a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax\">syntax page</a> provides complete, detailed documentation for\nevery feature, but Markdown should be very easy to pick up simply by\nlooking at a few examples of it in action. The examples on this page\nare written in a before/after style, showing example syntax and the\nHTML output produced by Markdown.</p>\n\n<p>It's also helpful to simply try Markdown out; the <a href=\"/projects/markdown/dingus\" title=\"Markdown Dingus\">Dingus</a> is a\nweb application that allows you type your own Markdown-formatted text\nand translate it to XHTML.</p>\n\n<p><strong>Note:</strong> This document is itself written using Markdown; you\ncan <a href=\"/projects/markdown/basics.text\">see the source for it by adding '.text' to the URL</a>.</p>\n\n<h2>Paragraphs, Headers, Blockquotes</h2>\n\n<p>A paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.</p>\n\n<p>Markdown offers two styles of headers: <em>Setext</em> and <em>atx</em>.\nSetext-style headers for <code>&lt;h1&gt;</code> and <code>&lt;h2&gt;</code> are created by\n\"underlining\" with equal signs (<code>=</code>) and hyphens (<code>-</code>), respectively.\nTo create an atx-style header, you put 1-6 hash marks (<code>#</code>) at the\nbeginning of the line -- the number of hashes equals the resulting\nHTML header level.</p>\n\n<p>Blockquotes are indicated using email-style '<code>&gt;</code>' angle brackets.</p>\n\n<p>Markdown:</p>\n\n<pre><code>A First Level Header\n====================\n\nA Second Level Header\n---------------------\n\nNow is the time for all good men to come to\nthe aid of their country. This is just a\nregular paragraph.\n\nThe quick brown fox jumped over the lazy\ndog's back.\n\n### Header 3\n\n&gt; This is a blockquote.\n&gt; \n&gt; This is the second paragraph in the blockquote.\n&gt;\n&gt; ## This is an H2 in a blockquote\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;h1&gt;A First Level Header&lt;/h1&gt;\n\n&lt;h2&gt;A Second Level Header&lt;/h2&gt;\n\n&lt;p&gt;Now is the time for all good men to come to\nthe aid of their country. This is just a\nregular paragraph.&lt;/p&gt;\n\n&lt;p&gt;The quick brown fox jumped over the lazy\ndog's back.&lt;/p&gt;\n\n&lt;h3&gt;Header 3&lt;/h3&gt;\n\n&lt;blockquote&gt;\n    &lt;p&gt;This is a blockquote.&lt;/p&gt;\n\n    &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;\n\n    &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;\n&lt;/blockquote&gt;\n</code></pre>\n\n<h3>Phrase Emphasis</h3>\n\n<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p>\n\n<p>Markdown:</p>\n\n<pre><code>Some of these words *are emphasized*.\nSome of these words _are emphasized also_.\n\nUse two asterisks for **strong emphasis**.\nOr, if you prefer, __use two underscores instead__.\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.\nSome of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;\n\n&lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.\nOr, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;\n</code></pre>\n\n<h2>Lists</h2>\n\n<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>,\n<code>+</code>, and <code>-</code>) as list markers. These three markers are\ninterchangable; this:</p>\n\n<pre><code>*   Candy.\n*   Gum.\n*   Booze.\n</code></pre>\n\n<p>this:</p>\n\n<pre><code>+   Candy.\n+   Gum.\n+   Booze.\n</code></pre>\n\n<p>and this:</p>\n\n<pre><code>-   Candy.\n-   Gum.\n-   Booze.\n</code></pre>\n\n<p>all produce the same output:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;Candy.&lt;/li&gt;\n&lt;li&gt;Gum.&lt;/li&gt;\n&lt;li&gt;Booze.&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<p>Ordered (numbered) lists use regular numbers, followed by periods, as\nlist markers:</p>\n\n<pre><code>1.  Red\n2.  Green\n3.  Blue\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;ol&gt;\n&lt;li&gt;Red&lt;/li&gt;\n&lt;li&gt;Green&lt;/li&gt;\n&lt;li&gt;Blue&lt;/li&gt;\n&lt;/ol&gt;\n</code></pre>\n\n<p>If you put blank lines between items, you'll get <code>&lt;p&gt;</code> tags for the\nlist item text. You can create multi-paragraph list items by indenting\nthe paragraphs by 4 spaces or 1 tab:</p>\n\n<pre><code>*   A list item.\n\n    With multiple paragraphs.\n\n*   Another item in the list.\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;\n&lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;\n&lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<h3>Links</h3>\n\n<p>Markdown supports two styles for creating links: <em>inline</em> and\n<em>reference</em>. With both styles, you use square brackets to delimit the\ntext you want to turn into a link.</p>\n\n<p>Inline-style links use parentheses immediately after the link text.\nFor example:</p>\n\n<pre><code>This is an [example link](http://example.com/).\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;This is an &lt;a href=\"http://example.com/\"&gt;\nexample link&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>Optionally, you may include a title attribute in the parentheses:</p>\n\n<pre><code>This is an [example link](http://example.com/ \"With a Title\").\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;This is an &lt;a href=\"http://example.com/\" title=\"With a Title\"&gt;\nexample link&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>Reference-style links allow you to refer to your links by names, which\nyou define elsewhere in your document:</p>\n\n<pre><code>I get 10 times more traffic from [Google][1] than from\n[Yahoo][2] or [MSN][3].\n\n[1]: http://google.com/        \"Google\"\n[2]: http://search.yahoo.com/  \"Yahoo Search\"\n[3]: http://search.msn.com/    \"MSN Search\"\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href=\"http://google.com/\"\ntitle=\"Google\"&gt;Google&lt;/a&gt; than from &lt;a href=\"http://search.yahoo.com/\"\ntitle=\"Yahoo Search\"&gt;Yahoo&lt;/a&gt; or &lt;a href=\"http://search.msn.com/\"\ntitle=\"MSN Search\"&gt;MSN&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>The title attribute is optional. Link names may contain letters,\nnumbers and spaces, but are <em>not</em> case sensitive:</p>\n\n<pre><code>I start my morning with a cup of coffee and\n[The New York Times][NY Times].\n\n[ny times]: http://www.nytimes.com/\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;I start my morning with a cup of coffee and\n&lt;a href=\"http://www.nytimes.com/\"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<h3>Images</h3>\n\n<p>Image syntax is very much like link syntax.</p>\n\n<p>Inline (titles are optional):</p>\n\n<pre><code>![alt text](/path/to/img.jpg \"Title\")\n</code></pre>\n\n<p>Reference-style:</p>\n\n<pre><code>![alt text][id]\n\n[id]: /path/to/img.jpg \"Title\"\n</code></pre>\n\n<p>Both of the above examples produce the same output:</p>\n\n<pre><code>&lt;img src=\"/path/to/img.jpg\" alt=\"alt text\" title=\"Title\" /&gt;\n</code></pre>\n\n<h3>Code</h3>\n\n<p>In a regular paragraph, you can create code span by wrapping text in\nbacktick quotes. Any ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> or\n<code>&gt;</code>) will automatically be translated into HTML entities. This makes\nit easy to use Markdown to write about HTML example code:</p>\n\n<pre><code>I strongly recommend against using any `&lt;blink&gt;` tags.\n\nI wish SmartyPants used named entities like `&amp;mdash;`\ninstead of decimal-encoded entites like `&amp;#8212;`.\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;I strongly recommend against using any\n&lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;\n\n&lt;p&gt;I wish SmartyPants used named entities like\n&lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded\nentites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>To specify an entire block of pre-formatted code, indent every line of\nthe block by 4 spaces or 1 tab. Just like with code spans, <code>&amp;</code>, <code>&lt;</code>,\nand <code>&gt;</code> characters will be escaped automatically.</p>\n\n<p>Markdown:</p>\n\n<pre><code>If you want your page to validate under XHTML 1.0 Strict,\nyou've got to put paragraph tags in your blockquotes:\n\n    &lt;blockquote&gt;\n        &lt;p&gt;For example.&lt;/p&gt;\n    &lt;/blockquote&gt;\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,\nyou've got to put paragraph tags in your blockquotes:&lt;/p&gt;\n\n&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;\n    &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;\n&amp;lt;/blockquote&amp;gt;\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/markdown_documentation_basics.text",
    "content": "Markdown: Basics\n================\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a class=\"selected\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n\nGetting the Gist of Markdown's Formatting Syntax\n------------------------------------------------\n\nThis page offers a brief overview of what it's like to use Markdown.\nThe [syntax page] [s] provides complete, detailed documentation for\nevery feature, but Markdown should be very easy to pick up simply by\nlooking at a few examples of it in action. The examples on this page\nare written in a before/after style, showing example syntax and the\nHTML output produced by Markdown.\n\nIt's also helpful to simply try Markdown out; the [Dingus] [d] is a\nweb application that allows you type your own Markdown-formatted text\nand translate it to XHTML.\n\n**Note:** This document is itself written using Markdown; you\ncan [see the source for it by adding '.text' to the URL] [src].\n\n  [s]: /projects/markdown/syntax  \"Markdown Syntax\"\n  [d]: /projects/markdown/dingus  \"Markdown Dingus\"\n  [src]: /projects/markdown/basics.text\n\n\n## Paragraphs, Headers, Blockquotes ##\n\nA paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.\n\nMarkdown offers two styles of headers: *Setext* and *atx*.\nSetext-style headers for `<h1>` and `<h2>` are created by\n\"underlining\" with equal signs (`=`) and hyphens (`-`), respectively.\nTo create an atx-style header, you put 1-6 hash marks (`#`) at the\nbeginning of the line -- the number of hashes equals the resulting\nHTML header level.\n\nBlockquotes are indicated using email-style '`>`' angle brackets.\n\nMarkdown:\n\n    A First Level Header\n    ====================\n    \n    A Second Level Header\n    ---------------------\n\n    Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.\n\n    The quick brown fox jumped over the lazy\n    dog's back.\n    \n    ### Header 3\n\n    > This is a blockquote.\n    > \n    > This is the second paragraph in the blockquote.\n    >\n    > ## This is an H2 in a blockquote\n\n\nOutput:\n\n    <h1>A First Level Header</h1>\n    \n    <h2>A Second Level Header</h2>\n    \n    <p>Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.</p>\n    \n    <p>The quick brown fox jumped over the lazy\n    dog's back.</p>\n    \n    <h3>Header 3</h3>\n    \n    <blockquote>\n        <p>This is a blockquote.</p>\n        \n        <p>This is the second paragraph in the blockquote.</p>\n        \n        <h2>This is an H2 in a blockquote</h2>\n    </blockquote>\n\n\n\n### Phrase Emphasis ###\n\nMarkdown uses asterisks and underscores to indicate spans of emphasis.\n\nMarkdown:\n\n    Some of these words *are emphasized*.\n    Some of these words _are emphasized also_.\n    \n    Use two asterisks for **strong emphasis**.\n    Or, if you prefer, __use two underscores instead__.\n\nOutput:\n\n    <p>Some of these words <em>are emphasized</em>.\n    Some of these words <em>are emphasized also</em>.</p>\n    \n    <p>Use two asterisks for <strong>strong emphasis</strong>.\n    Or, if you prefer, <strong>use two underscores instead</strong>.</p>\n   \n\n\n## Lists ##\n\nUnordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,\n`+`, and `-`) as list markers. These three markers are\ninterchangable; this:\n\n    *   Candy.\n    *   Gum.\n    *   Booze.\n\nthis:\n\n    +   Candy.\n    +   Gum.\n    +   Booze.\n\nand this:\n\n    -   Candy.\n    -   Gum.\n    -   Booze.\n\nall produce the same output:\n\n    <ul>\n    <li>Candy.</li>\n    <li>Gum.</li>\n    <li>Booze.</li>\n    </ul>\n\nOrdered (numbered) lists use regular numbers, followed by periods, as\nlist markers:\n\n    1.  Red\n    2.  Green\n    3.  Blue\n\nOutput:\n\n    <ol>\n    <li>Red</li>\n    <li>Green</li>\n    <li>Blue</li>\n    </ol>\n\nIf you put blank lines between items, you'll get `<p>` tags for the\nlist item text. You can create multi-paragraph list items by indenting\nthe paragraphs by 4 spaces or 1 tab:\n\n    *   A list item.\n    \n        With multiple paragraphs.\n\n    *   Another item in the list.\n\nOutput:\n\n    <ul>\n    <li><p>A list item.</p>\n    <p>With multiple paragraphs.</p></li>\n    <li><p>Another item in the list.</p></li>\n    </ul>\n    \n\n\n### Links ###\n\nMarkdown supports two styles for creating links: *inline* and\n*reference*. With both styles, you use square brackets to delimit the\ntext you want to turn into a link.\n\nInline-style links use parentheses immediately after the link text.\nFor example:\n\n    This is an [example link](http://example.com/).\n\nOutput:\n\n    <p>This is an <a href=\"http://example.com/\">\n    example link</a>.</p>\n\nOptionally, you may include a title attribute in the parentheses:\n\n    This is an [example link](http://example.com/ \"With a Title\").\n\nOutput:\n\n    <p>This is an <a href=\"http://example.com/\" title=\"With a Title\">\n    example link</a>.</p>\n\nReference-style links allow you to refer to your links by names, which\nyou define elsewhere in your document:\n\n    I get 10 times more traffic from [Google][1] than from\n    [Yahoo][2] or [MSN][3].\n\n    [1]: http://google.com/        \"Google\"\n    [2]: http://search.yahoo.com/  \"Yahoo Search\"\n    [3]: http://search.msn.com/    \"MSN Search\"\n\nOutput:\n\n    <p>I get 10 times more traffic from <a href=\"http://google.com/\"\n    title=\"Google\">Google</a> than from <a href=\"http://search.yahoo.com/\"\n    title=\"Yahoo Search\">Yahoo</a> or <a href=\"http://search.msn.com/\"\n    title=\"MSN Search\">MSN</a>.</p>\n\nThe title attribute is optional. Link names may contain letters,\nnumbers and spaces, but are *not* case sensitive:\n\n    I start my morning with a cup of coffee and\n    [The New York Times][NY Times].\n\n    [ny times]: http://www.nytimes.com/\n\nOutput:\n\n    <p>I start my morning with a cup of coffee and\n    <a href=\"http://www.nytimes.com/\">The New York Times</a>.</p>\n\n\n### Images ###\n\nImage syntax is very much like link syntax.\n\nInline (titles are optional):\n\n    ![alt text](/path/to/img.jpg \"Title\")\n\nReference-style:\n\n    ![alt text][id]\n\n    [id]: /path/to/img.jpg \"Title\"\n\nBoth of the above examples produce the same output:\n\n    <img src=\"/path/to/img.jpg\" alt=\"alt text\" title=\"Title\" />\n\n\n\n### Code ###\n\nIn a regular paragraph, you can create code span by wrapping text in\nbacktick quotes. Any ampersands (`&`) and angle brackets (`<` or\n`>`) will automatically be translated into HTML entities. This makes\nit easy to use Markdown to write about HTML example code:\n\n    I strongly recommend against using any `<blink>` tags.\n\n    I wish SmartyPants used named entities like `&mdash;`\n    instead of decimal-encoded entites like `&#8212;`.\n\nOutput:\n\n    <p>I strongly recommend against using any\n    <code>&lt;blink&gt;</code> tags.</p>\n    \n    <p>I wish SmartyPants used named entities like\n    <code>&amp;mdash;</code> instead of decimal-encoded\n    entites like <code>&amp;#8212;</code>.</p>\n\n\nTo specify an entire block of pre-formatted code, indent every line of\nthe block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`,\nand `>` characters will be escaped automatically.\n\nMarkdown:\n\n    If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:\n\n        <blockquote>\n            <p>For example.</p>\n        </blockquote>\n\nOutput:\n\n    <p>If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:</p>\n    \n    <pre><code>&lt;blockquote&gt;\n        &lt;p&gt;For example.&lt;/p&gt;\n    &lt;/blockquote&gt;\n    </code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/markdown_documentation_syntax.html",
    "content": "<h1>Markdown: Syntax</h1>\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a href=\"/projects/markdown/basics\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a class=\"selected\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n<ul>\n<li><a href=\"#overview\">Overview</a>\n<ul>\n<li><a href=\"#philosophy\">Philosophy</a></li>\n<li><a href=\"#html\">Inline HTML</a></li>\n<li><a href=\"#autoescape\">Automatic Escaping for Special Characters</a></li>\n</ul></li>\n<li><a href=\"#block\">Block Elements</a>\n<ul>\n<li><a href=\"#p\">Paragraphs and Line Breaks</a></li>\n<li><a href=\"#header\">Headers</a></li>\n<li><a href=\"#blockquote\">Blockquotes</a></li>\n<li><a href=\"#list\">Lists</a></li>\n<li><a href=\"#precode\">Code Blocks</a></li>\n<li><a href=\"#hr\">Horizontal Rules</a></li>\n</ul></li>\n<li><a href=\"#span\">Span Elements</a>\n<ul>\n<li><a href=\"#link\">Links</a></li>\n<li><a href=\"#em\">Emphasis</a></li>\n<li><a href=\"#code\">Code</a></li>\n<li><a href=\"#img\">Images</a></li>\n</ul></li>\n<li><a href=\"#misc\">Miscellaneous</a>\n<ul>\n<li><a href=\"#backslash\">Backslash Escapes</a></li>\n<li><a href=\"#autolink\">Automatic Links</a></li>\n</ul></li>\n</ul>\n\n<p><strong>Note:</strong> This document is itself written using Markdown; you\ncan <a href=\"/projects/markdown/syntax.text\">see the source for it by adding '.text' to the URL</a>.</p>\n\n<hr />\n\n<h2 id=\"overview\">Overview</h2>\n\n<h3 id=\"philosophy\">Philosophy</h3>\n\n<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>\n\n<p>Readability, however, is emphasized above all else. A Markdown-formatted\ndocument should be publishable as-is, as plain text, without looking\nlike it's been marked up with tags or formatting instructions. While\nMarkdown's syntax has been influenced by several existing text-to-HTML\nfilters -- including <a href=\"http://docutils.sourceforge.net/mirror/setext.html\">Setext</a>, <a href=\"http://www.aaronsw.com/2002/atx/\">atx</a>, <a href=\"http://textism.com/tools/textile/\">Textile</a>, <a href=\"http://docutils.sourceforge.net/rst.html\">reStructuredText</a>,\n<a href=\"http://www.triptico.com/software/grutatxt.html\">Grutatext</a>, and <a href=\"http://ettext.taint.org/doc/\">EtText</a> -- the single biggest source of\ninspiration for Markdown's syntax is the format of plain text email.</p>\n\n<p>To this end, Markdown's syntax is comprised entirely of punctuation\ncharacters, which punctuation characters have been carefully chosen so\nas to look like what they mean. E.g., asterisks around a word actually\nlook like *emphasis*. Markdown lists look like, well, lists. Even\nblockquotes look like quoted passages of text, assuming you've ever\nused email.</p>\n\n<h3 id=\"html\">Inline HTML</h3>\n\n<p>Markdown's syntax is intended for one purpose: to be used as a\nformat for <em>writing</em> for the web.</p>\n\n<p>Markdown is not a replacement for HTML, or even close to it. Its\nsyntax is very small, corresponding only to a very small subset of\nHTML tags. The idea is <em>not</em> to create a syntax that makes it easier\nto insert HTML tags. In my opinion, HTML tags are already easy to\ninsert. The idea for Markdown is to make it easy to read, write, and\nedit prose. HTML is a <em>publishing</em> format; Markdown is a <em>writing</em>\nformat. Thus, Markdown's formatting syntax only addresses issues that\ncan be conveyed in plain text.</p>\n\n<p>For any markup that is not covered by Markdown's syntax, you simply\nuse HTML itself. There's no need to preface it or delimit it to\nindicate that you're switching from Markdown to HTML; you just use\nthe tags.</p>\n\n<p>The only restrictions are that block-level HTML elements -- e.g. <code>&lt;div&gt;</code>,\n<code>&lt;table&gt;</code>, <code>&lt;pre&gt;</code>, <code>&lt;p&gt;</code>, etc. -- must be separated from surrounding\ncontent by blank lines, and the start and end tags of the block should\nnot be indented with tabs or spaces. Markdown is smart enough not\nto add extra (unwanted) <code>&lt;p&gt;</code> tags around HTML block-level tags.</p>\n\n<p>For example, to add an HTML table to a Markdown article:</p>\n\n<pre><code>This is a regular paragraph.\n\n&lt;table&gt;\n    &lt;tr&gt;\n        &lt;td&gt;Foo&lt;/td&gt;\n    &lt;/tr&gt;\n&lt;/table&gt;\n\nThis is another regular paragraph.\n</code></pre>\n\n<p>Note that Markdown formatting syntax is not processed within block-level\nHTML tags. E.g., you can't use Markdown-style <code>*emphasis*</code> inside an\nHTML block.</p>\n\n<p>Span-level HTML tags -- e.g. <code>&lt;span&gt;</code>, <code>&lt;cite&gt;</code>, or <code>&lt;del&gt;</code> -- can be\nused anywhere in a Markdown paragraph, list item, or header. If you\nwant, you can even use HTML tags instead of Markdown formatting; e.g. if\nyou'd prefer to use HTML <code>&lt;a&gt;</code> or <code>&lt;img&gt;</code> tags instead of Markdown's\nlink or image syntax, go right ahead.</p>\n\n<p>Unlike block-level HTML tags, Markdown syntax <em>is</em> processed within\nspan-level tags.</p>\n\n<h3 id=\"autoescape\">Automatic Escaping for Special Characters</h3>\n\n<p>In HTML, there are two characters that demand special treatment: <code>&lt;</code>\nand <code>&amp;</code>. Left angle brackets are used to start tags; ampersands are\nused to denote HTML entities. If you want to use them as literal\ncharacters, you must escape them as entities, e.g. <code>&amp;lt;</code>, and\n<code>&amp;amp;</code>.</p>\n\n<p>Ampersands in particular are bedeviling for web writers. If you want to\nwrite about 'AT&amp;T', you need to write '<code>AT&amp;amp;T</code>'. You even need to\nescape ampersands within URLs. Thus, if you want to link to:</p>\n\n<pre><code>http://images.google.com/images?num=30&amp;q=larry+bird\n</code></pre>\n\n<p>you need to encode the URL as:</p>\n\n<pre><code>http://images.google.com/images?num=30&amp;amp;q=larry+bird\n</code></pre>\n\n<p>in your anchor tag <code>href</code> attribute. Needless to say, this is easy to\nforget, and is probably the single most common source of HTML validation\nerrors in otherwise well-marked-up web sites.</p>\n\n<p>Markdown allows you to use these characters naturally, taking care of\nall the necessary escaping for you. If you use an ampersand as part of\nan HTML entity, it remains unchanged; otherwise it will be translated\ninto <code>&amp;amp;</code>.</p>\n\n<p>So, if you want to include a copyright symbol in your article, you can write:</p>\n\n<pre><code>&amp;copy;\n</code></pre>\n\n<p>and Markdown will leave it alone. But if you write:</p>\n\n<pre><code>AT&amp;T\n</code></pre>\n\n<p>Markdown will translate it to:</p>\n\n<pre><code>AT&amp;amp;T\n</code></pre>\n\n<p>Similarly, because Markdown supports <a href=\"#html\">inline HTML</a>, if you use\nangle brackets as delimiters for HTML tags, Markdown will treat them as\nsuch. But if you write:</p>\n\n<pre><code>4 &lt; 5\n</code></pre>\n\n<p>Markdown will translate it to:</p>\n\n<pre><code>4 &amp;lt; 5\n</code></pre>\n\n<p>However, inside Markdown code spans and blocks, angle brackets and\nampersands are <em>always</em> encoded automatically. This makes it easy to use\nMarkdown to write about HTML code. (As opposed to raw HTML, which is a\nterrible format for writing about HTML syntax, because every single <code>&lt;</code>\nand <code>&amp;</code> in your example code needs to be escaped.)</p>\n\n<hr />\n\n<h2 id=\"block\">Block Elements</h2>\n\n<h3 id=\"p\">Paragraphs and Line Breaks</h3>\n\n<p>A paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing but spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.</p>\n\n<p>The implication of the \"one or more consecutive lines of text\" rule is\nthat Markdown supports \"hard-wrapped\" text paragraphs. This differs\nsignificantly from most other text-to-HTML formatters (including Movable\nType's \"Convert Line Breaks\" option) which translate every line break\ncharacter in a paragraph into a <code>&lt;br /&gt;</code> tag.</p>\n\n<p>When you <em>do</em> want to insert a <code>&lt;br /&gt;</code> break tag using Markdown, you\nend a line with two or more spaces, then type return.</p>\n\n<p>Yes, this takes a tad more effort to create a <code>&lt;br /&gt;</code>, but a simplistic\n\"every line break is a <code>&lt;br /&gt;</code>\" rule wouldn't work for Markdown.\nMarkdown's email-style <a href=\"#blockquote\">blockquoting</a> and multi-paragraph <a href=\"#list\">list items</a>\nwork best -- and look better -- when you format them with hard breaks.</p>\n\n<h3 id=\"header\">Headers</h3>\n\n<p>Markdown supports two styles of headers, <a href=\"http://docutils.sourceforge.net/mirror/setext.html\">Setext</a> and <a href=\"http://www.aaronsw.com/2002/atx/\">atx</a>.</p>\n\n<p>Setext-style headers are \"underlined\" using equal signs (for first-level\nheaders) and dashes (for second-level headers). For example:</p>\n\n<pre><code>This is an H1\n=============\n\nThis is an H2\n-------------\n</code></pre>\n\n<p>Any number of underlining <code>=</code>'s or <code>-</code>'s will work.</p>\n\n<p>Atx-style headers use 1-6 hash characters at the start of the line,\ncorresponding to header levels 1-6. For example:</p>\n\n<pre><code># This is an H1\n\n## This is an H2\n\n###### This is an H6\n</code></pre>\n\n<p>Optionally, you may \"close\" atx-style headers. This is purely\ncosmetic -- you can use this if you think it looks better. The\nclosing hashes don't even need to match the number of hashes\nused to open the header. (The number of opening hashes\ndetermines the header level.) :</p>\n\n<pre><code># This is an H1 #\n\n## This is an H2 ##\n\n### This is an H3 ######\n</code></pre>\n\n<h3 id=\"blockquote\">Blockquotes</h3>\n\n<p>Markdown uses email-style <code>&gt;</code> characters for blockquoting. If you're\nfamiliar with quoting passages of text in an email message, then you\nknow how to create a blockquote in Markdown. It looks best if you hard\nwrap the text and put a <code>&gt;</code> before every line:</p>\n\n<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n&gt; consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n&gt; Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n&gt; \n&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n&gt; id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>Markdown allows you to be lazy and only put the <code>&gt;</code> before the first\nline of a hard-wrapped paragraph:</p>\n\n<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\nconsectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\nVestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n\n&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\nid sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by\nadding additional levels of <code>&gt;</code>:</p>\n\n<pre><code>&gt; This is the first level of quoting.\n&gt;\n&gt; &gt; This is nested blockquote.\n&gt;\n&gt; Back to the first level.\n</code></pre>\n\n<p>Blockquotes can contain other Markdown elements, including headers, lists,\nand code blocks:</p>\n\n<pre><code>&gt; ## This is a header.\n&gt; \n&gt; 1.   This is the first list item.\n&gt; 2.   This is the second list item.\n&gt; \n&gt; Here's some example code:\n&gt; \n&gt;     return shell_exec(\"echo $input | $markdown_script\");\n</code></pre>\n\n<p>Any decent text editor should make email-style quoting easy. For\nexample, with BBEdit, you can make a selection and choose Increase\nQuote Level from the Text menu.</p>\n\n<h3 id=\"list\">Lists</h3>\n\n<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p>\n\n<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably\n-- as list markers:</p>\n\n<pre><code>*   Red\n*   Green\n*   Blue\n</code></pre>\n\n<p>is equivalent to:</p>\n\n<pre><code>+   Red\n+   Green\n+   Blue\n</code></pre>\n\n<p>and:</p>\n\n<pre><code>-   Red\n-   Green\n-   Blue\n</code></pre>\n\n<p>Ordered lists use numbers followed by periods:</p>\n\n<pre><code>1.  Bird\n2.  McHale\n3.  Parish\n</code></pre>\n\n<p>It's important to note that the actual numbers you use to mark the\nlist have no effect on the HTML output Markdown produces. The HTML\nMarkdown produces from the above list is:</p>\n\n<pre><code>&lt;ol&gt;\n&lt;li&gt;Bird&lt;/li&gt;\n&lt;li&gt;McHale&lt;/li&gt;\n&lt;li&gt;Parish&lt;/li&gt;\n&lt;/ol&gt;\n</code></pre>\n\n<p>If you instead wrote the list in Markdown like this:</p>\n\n<pre><code>1.  Bird\n1.  McHale\n1.  Parish\n</code></pre>\n\n<p>or even:</p>\n\n<pre><code>3. Bird\n1. McHale\n8. Parish\n</code></pre>\n\n<p>you'd get the exact same HTML output. The point is, if you want to,\nyou can use ordinal numbers in your ordered Markdown lists, so that\nthe numbers in your source match the numbers in your published HTML.\nBut if you want to be lazy, you don't have to.</p>\n\n<p>If you do use lazy list numbering, however, you should still start the\nlist with the number 1. At some point in the future, Markdown may support\nstarting ordered lists at an arbitrary number.</p>\n\n<p>List markers typically start at the left margin, but may be indented by\nup to three spaces. List markers must be followed by one or more spaces\nor a tab.</p>\n\n<p>To make lists look nice, you can wrap items with hanging indents:</p>\n\n<pre><code>*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n    viverra nec, fringilla in, laoreet vitae, risus.\n*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n    Suspendisse id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>But if you want to be lazy, you don't have to:</p>\n\n<pre><code>*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\nAliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\nviverra nec, fringilla in, laoreet vitae, risus.\n*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\nSuspendisse id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>If list items are separated by blank lines, Markdown will wrap the\nitems in <code>&lt;p&gt;</code> tags in the HTML output. For example, this input:</p>\n\n<pre><code>*   Bird\n*   Magic\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;Bird&lt;/li&gt;\n&lt;li&gt;Magic&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<p>But this:</p>\n\n<pre><code>*   Bird\n\n*   Magic\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;&lt;p&gt;Bird&lt;/p&gt;&lt;/li&gt;\n&lt;li&gt;&lt;p&gt;Magic&lt;/p&gt;&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<p>List items may consist of multiple paragraphs. Each subsequent\nparagraph in a list item must be intended by either 4 spaces\nor one tab:</p>\n\n<pre><code>1.  This is a list item with two paragraphs. Lorem ipsum dolor\n    sit amet, consectetuer adipiscing elit. Aliquam hendrerit\n    mi posuere lectus.\n\n    Vestibulum enim wisi, viverra nec, fringilla in, laoreet\n    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum\n    sit amet velit.\n\n2.  Suspendisse id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>It looks nice if you indent every line of the subsequent\nparagraphs, but here again, Markdown will allow you to be\nlazy:</p>\n\n<pre><code>*   This is a list item with two paragraphs.\n\n    This is the second paragraph in the list item. You're\nonly required to indent the first line. Lorem ipsum dolor\nsit amet, consectetuer adipiscing elit.\n\n*   Another item in the same list.\n</code></pre>\n\n<p>To put a blockquote within a list item, the blockquote's <code>&gt;</code>\ndelimiters need to be indented:</p>\n\n<pre><code>*   A list item with a blockquote:\n\n    &gt; This is a blockquote\n    &gt; inside a list item.\n</code></pre>\n\n<p>To put a code block within a list item, the code block needs\nto be indented <em>twice</em> -- 8 spaces or two tabs:</p>\n\n<pre><code>*   A list item with a code block:\n\n        &lt;code goes here&gt;\n</code></pre>\n\n<p>It's worth noting that it's possible to trigger an ordered list by\naccident, by writing something like this:</p>\n\n<pre><code>1986. What a great season.\n</code></pre>\n\n<p>In other words, a <em>number-period-space</em> sequence at the beginning of a\nline. To avoid this, you can backslash-escape the period:</p>\n\n<pre><code>1986\\. What a great season.\n</code></pre>\n\n<h3 id=\"precode\">Code Blocks</h3>\n\n<p>Pre-formatted code blocks are used for writing about programming or\nmarkup source code. Rather than forming normal paragraphs, the lines\nof a code block are interpreted literally. Markdown wraps a code block\nin both <code>&lt;pre&gt;</code> and <code>&lt;code&gt;</code> tags.</p>\n\n<p>To produce a code block in Markdown, simply indent every line of the\nblock by at least 4 spaces or 1 tab. For example, given this input:</p>\n\n<pre><code>This is a normal paragraph:\n\n    This is a code block.\n</code></pre>\n\n<p>Markdown will generate:</p>\n\n<pre><code>&lt;p&gt;This is a normal paragraph:&lt;/p&gt;\n\n&lt;pre&gt;&lt;code&gt;This is a code block.\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n\n<p>One level of indentation -- 4 spaces or 1 tab -- is removed from each\nline of the code block. For example, this:</p>\n\n<pre><code>Here is an example of AppleScript:\n\n    tell application \"Foo\"\n        beep\n    end tell\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;p&gt;Here is an example of AppleScript:&lt;/p&gt;\n\n&lt;pre&gt;&lt;code&gt;tell application \"Foo\"\n    beep\nend tell\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n\n<p>A code block continues until it reaches a line that is not indented\n(or the end of the article).</p>\n\n<p>Within a code block, ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> and <code>&gt;</code>)\nare automatically converted into HTML entities. This makes it very\neasy to include example HTML source code using Markdown -- just paste\nit and indent it, and Markdown will handle the hassle of encoding the\nampersands and angle brackets. For example, this:</p>\n\n<pre><code>    &lt;div class=\"footer\"&gt;\n        &amp;copy; 2004 Foo Corporation\n    &lt;/div&gt;\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;pre&gt;&lt;code&gt;&amp;lt;div class=\"footer\"&amp;gt;\n    &amp;amp;copy; 2004 Foo Corporation\n&amp;lt;/div&amp;gt;\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n\n<p>Regular Markdown syntax is not processed within code blocks. E.g.,\nasterisks are just literal asterisks within a code block. This means\nit's also easy to use Markdown to write about Markdown's own syntax.</p>\n\n<h3 id=\"hr\">Horizontal Rules</h3>\n\n<p>You can produce a horizontal rule tag (<code>&lt;hr /&gt;</code>) by placing three or\nmore hyphens, asterisks, or underscores on a line by themselves. If you\nwish, you may use spaces between the hyphens or asterisks. Each of the\nfollowing lines will produce a horizontal rule:</p>\n\n<pre><code>* * *\n\n***\n\n*****\n\n- - -\n\n---------------------------------------\n\n_ _ _\n</code></pre>\n\n<hr />\n\n<h2 id=\"span\">Span Elements</h2>\n\n<h3 id=\"link\">Links</h3>\n\n<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p>\n\n<p>In both styles, the link text is delimited by [square brackets].</p>\n\n<p>To create an inline link, use a set of regular parentheses immediately\nafter the link text's closing square bracket. Inside the parentheses,\nput the URL where you want the link to point, along with an <em>optional</em>\ntitle for the link, surrounded in quotes. For example:</p>\n\n<pre><code>This is [an example](http://example.com/ \"Title\") inline link.\n\n[This link](http://example.net/) has no title attribute.\n</code></pre>\n\n<p>Will produce:</p>\n\n<pre><code>&lt;p&gt;This is &lt;a href=\"http://example.com/\" title=\"Title\"&gt;\nan example&lt;/a&gt; inline link.&lt;/p&gt;\n\n&lt;p&gt;&lt;a href=\"http://example.net/\"&gt;This link&lt;/a&gt; has no\ntitle attribute.&lt;/p&gt;\n</code></pre>\n\n<p>If you're referring to a local resource on the same server, you can\nuse relative paths:</p>\n\n<pre><code>See my [About](/about/) page for details.\n</code></pre>\n\n<p>Reference-style links use a second set of square brackets, inside\nwhich you place a label of your choosing to identify the link:</p>\n\n<pre><code>This is [an example][id] reference-style link.\n</code></pre>\n\n<p>You can optionally use a space to separate the sets of brackets:</p>\n\n<pre><code>This is [an example] [id] reference-style link.\n</code></pre>\n\n<p>Then, anywhere in the document, you define your link label like this,\non a line by itself:</p>\n\n<pre><code>[id]: http://example.com/  \"Optional Title Here\"\n</code></pre>\n\n<p>That is:</p>\n\n<ul>\n<li>Square brackets containing the link identifier (optionally\nindented from the left margin using up to three spaces);</li>\n<li>followed by a colon;</li>\n<li>followed by one or more spaces (or tabs);</li>\n<li>followed by the URL for the link;</li>\n<li>optionally followed by a title attribute for the link, enclosed\nin double or single quotes.</li>\n</ul>\n\n<p>The link URL may, optionally, be surrounded by angle brackets:</p>\n\n<pre><code>[id]: &lt;http://example.com/&gt;  \"Optional Title Here\"\n</code></pre>\n\n<p>You can put the title attribute on the next line and use extra spaces\nor tabs for padding, which tends to look better with longer URLs:</p>\n\n<pre><code>[id]: http://example.com/longish/path/to/resource/here\n    \"Optional Title Here\"\n</code></pre>\n\n<p>Link definitions are only used for creating links during Markdown\nprocessing, and are stripped from your document in the HTML output.</p>\n\n<p>Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are <em>not</em> case sensitive. E.g. these two links:</p>\n\n<pre><code>[link text][a]\n[link text][A]\n</code></pre>\n\n<p>are equivalent.</p>\n\n<p>The <em>implicit link name</em> shortcut allows you to omit the name of the\nlink, in which case the link text itself is used as the name.\nJust use an empty set of square brackets -- e.g., to link the word\n\"Google\" to the google.com web site, you could simply write:</p>\n\n<pre><code>[Google][]\n</code></pre>\n\n<p>And then define the link:</p>\n\n<pre><code>[Google]: http://google.com/\n</code></pre>\n\n<p>Because link names may contain spaces, this shortcut even works for\nmultiple words in the link text:</p>\n\n<pre><code>Visit [Daring Fireball][] for more information.\n</code></pre>\n\n<p>And then define the link:</p>\n\n<pre><code>[Daring Fireball]: http://daringfireball.net/\n</code></pre>\n\n<p>Link definitions can be placed anywhere in your Markdown document. I\ntend to put them immediately after each paragraph in which they're\nused, but if you want, you can put them all at the end of your\ndocument, sort of like footnotes.</p>\n\n<p>Here's an example of reference links in action:</p>\n\n<pre><code>I get 10 times more traffic from [Google] [1] than from\n[Yahoo] [2] or [MSN] [3].\n\n  [1]: http://google.com/        \"Google\"\n  [2]: http://search.yahoo.com/  \"Yahoo Search\"\n  [3]: http://search.msn.com/    \"MSN Search\"\n</code></pre>\n\n<p>Using the implicit link name shortcut, you could instead write:</p>\n\n<pre><code>I get 10 times more traffic from [Google][] than from\n[Yahoo][] or [MSN][].\n\n  [google]: http://google.com/        \"Google\"\n  [yahoo]:  http://search.yahoo.com/  \"Yahoo Search\"\n  [msn]:    http://search.msn.com/    \"MSN Search\"\n</code></pre>\n\n<p>Both of the above examples will produce the following HTML output:</p>\n\n<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href=\"http://google.com/\"\ntitle=\"Google\"&gt;Google&lt;/a&gt; than from\n&lt;a href=\"http://search.yahoo.com/\" title=\"Yahoo Search\"&gt;Yahoo&lt;/a&gt;\nor &lt;a href=\"http://search.msn.com/\" title=\"MSN Search\"&gt;MSN&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>For comparison, here is the same paragraph written using\nMarkdown's inline link style:</p>\n\n<pre><code>I get 10 times more traffic from [Google](http://google.com/ \"Google\")\nthan from [Yahoo](http://search.yahoo.com/ \"Yahoo Search\") or\n[MSN](http://search.msn.com/ \"MSN Search\").\n</code></pre>\n\n<p>The point of reference-style links is not that they're easier to\nwrite. The point is that with reference-style links, your document\nsource is vastly more readable. Compare the above examples: using\nreference-style links, the paragraph itself is only 81 characters\nlong; with inline-style links, it's 176 characters; and as raw HTML,\nit's 234 characters. In the raw HTML, there's more markup than there\nis text.</p>\n\n<p>With Markdown's reference-style links, a source document much more\nclosely resembles the final output, as rendered in a browser. By\nallowing you to move the markup-related metadata out of the paragraph,\nyou can add links without interrupting the narrative flow of your\nprose.</p>\n\n<h3 id=\"em\">Emphasis</h3>\n\n<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of\nemphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an\nHTML <code>&lt;em&gt;</code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML\n<code>&lt;strong&gt;</code> tag. E.g., this input:</p>\n\n<pre><code>*single asterisks*\n\n_single underscores_\n\n**double asterisks**\n\n__double underscores__\n</code></pre>\n\n<p>will produce:</p>\n\n<pre><code>&lt;em&gt;single asterisks&lt;/em&gt;\n\n&lt;em&gt;single underscores&lt;/em&gt;\n\n&lt;strong&gt;double asterisks&lt;/strong&gt;\n\n&lt;strong&gt;double underscores&lt;/strong&gt;\n</code></pre>\n\n<p>You can use whichever style you prefer; the lone restriction is that\nthe same character must be used to open and close an emphasis span.</p>\n\n<p>Emphasis can be used in the middle of a word:</p>\n\n<pre><code>un*fucking*believable\n</code></pre>\n\n<p>But if you surround an <code>*</code> or <code>_</code> with spaces, it'll be treated as a\nliteral asterisk or underscore.</p>\n\n<p>To produce a literal asterisk or underscore at a position where it\nwould otherwise be used as an emphasis delimiter, you can backslash\nescape it:</p>\n\n<pre><code>\\*this text is surrounded by literal asterisks\\*\n</code></pre>\n\n<h3 id=\"code\">Code</h3>\n\n<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>).\nUnlike a pre-formatted code block, a code span indicates code within a\nnormal paragraph. For example:</p>\n\n<pre><code>Use the `printf()` function.\n</code></pre>\n\n<p>will produce:</p>\n\n<pre><code>&lt;p&gt;Use the &lt;code&gt;printf()&lt;/code&gt; function.&lt;/p&gt;\n</code></pre>\n\n<p>To include a literal backtick character within a code span, you can use\nmultiple backticks as the opening and closing delimiters:</p>\n\n<pre><code>``There is a literal backtick (`) here.``\n</code></pre>\n\n<p>which will produce this:</p>\n\n<pre><code>&lt;p&gt;&lt;code&gt;There is a literal backtick (`) here.&lt;/code&gt;&lt;/p&gt;\n</code></pre>\n\n<p>The backtick delimiters surrounding a code span may include spaces --\none after the opening, one before the closing. This allows you to place\nliteral backtick characters at the beginning or end of a code span:</p>\n\n<pre><code>A single backtick in a code span: `` ` ``\n\nA backtick-delimited string in a code span: `` `foo` ``\n</code></pre>\n\n<p>will produce:</p>\n\n<pre><code>&lt;p&gt;A single backtick in a code span: &lt;code&gt;`&lt;/code&gt;&lt;/p&gt;\n\n&lt;p&gt;A backtick-delimited string in a code span: &lt;code&gt;`foo`&lt;/code&gt;&lt;/p&gt;\n</code></pre>\n\n<p>With a code span, ampersands and angle brackets are encoded as HTML\nentities automatically, which makes it easy to include example HTML\ntags. Markdown will turn this:</p>\n\n<pre><code>Please don't use any `&lt;blink&gt;` tags.\n</code></pre>\n\n<p>into:</p>\n\n<pre><code>&lt;p&gt;Please don't use any &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;\n</code></pre>\n\n<p>You can write this:</p>\n\n<pre><code>`&amp;#8212;` is the decimal-encoded equivalent of `&amp;mdash;`.\n</code></pre>\n\n<p>to produce:</p>\n\n<pre><code>&lt;p&gt;&lt;code&gt;&amp;amp;#8212;&lt;/code&gt; is the decimal-encoded\nequivalent of &lt;code&gt;&amp;amp;mdash;&lt;/code&gt;.&lt;/p&gt;\n</code></pre>\n\n<h3 id=\"img\">Images</h3>\n\n<p>Admittedly, it's fairly difficult to devise a \"natural\" syntax for\nplacing images into a plain text document format.</p>\n\n<p>Markdown uses an image syntax that is intended to resemble the syntax\nfor links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p>\n\n<p>Inline image syntax looks like this:</p>\n\n<pre><code>![Alt text](/path/to/img.jpg)\n\n![Alt text](/path/to/img.jpg \"Optional title\")\n</code></pre>\n\n<p>That is:</p>\n\n<ul>\n<li>An exclamation mark: <code>!</code>;</li>\n<li>followed by a set of square brackets, containing the <code>alt</code>\nattribute text for the image;</li>\n<li>followed by a set of parentheses, containing the URL or path to\nthe image, and an optional <code>title</code> attribute enclosed in double\nor single quotes.</li>\n</ul>\n\n<p>Reference-style image syntax looks like this:</p>\n\n<pre><code>![Alt text][id]\n</code></pre>\n\n<p>Where \"id\" is the name of a defined image reference. Image references\nare defined using syntax identical to link references:</p>\n\n<pre><code>[id]: url/to/image  \"Optional title attribute\"\n</code></pre>\n\n<p>As of this writing, Markdown has no syntax for specifying the\ndimensions of an image; if this is important to you, you can simply\nuse regular HTML <code>&lt;img&gt;</code> tags.</p>\n\n<hr />\n\n<h2 id=\"misc\">Miscellaneous</h2>\n\n<h3 id=\"autolink\">Automatic Links</h3>\n\n<p>Markdown supports a shortcut style for creating \"automatic\" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:</p>\n\n<pre><code>&lt;http://example.com/&gt;\n</code></pre>\n\n<p>Markdown will turn this into:</p>\n\n<pre><code>&lt;a href=\"http://example.com/\"&gt;http://example.com/&lt;/a&gt;\n</code></pre>\n\n<p>Automatic links for email addresses work similarly, except that\nMarkdown will also perform a bit of randomized decimal and hex\nentity-encoding to help obscure your address from address-harvesting\nspambots. For example, Markdown will turn this:</p>\n\n<pre><code>&lt;address@example.com&gt;\n</code></pre>\n\n<p>into something like this:</p>\n\n<pre><code>&lt;a href=\"&amp;#x6D;&amp;#x61;i&amp;#x6C;&amp;#x74;&amp;#x6F;:&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;\n&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;\n&amp;#109;\"&gt;&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;\n&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;&amp;#109;&lt;/a&gt;\n</code></pre>\n\n<p>which will render in a browser as a clickable link to \"address@example.com\".</p>\n\n<p>(This sort of entity-encoding trick will indeed fool many, if not\nmost, address-harvesting bots, but it definitely won't fool all of\nthem. It's better than nothing, but an address published in this way\nwill probably eventually start receiving spam.)</p>\n\n<h3 id=\"backslash\">Backslash Escapes</h3>\n\n<p>Markdown allows you to use backslash escapes to generate literal\ncharacters which would otherwise have special meaning in Markdown's\nformatting syntax. For example, if you wanted to surround a word with\nliteral asterisks (instead of an HTML <code>&lt;em&gt;</code> tag), you can backslashes\nbefore the asterisks, like this:</p>\n\n<pre><code>\\*literal asterisks\\*\n</code></pre>\n\n<p>Markdown provides backslash escapes for the following characters:</p>\n\n<pre><code>\\   backslash\n`   backtick\n*   asterisk\n_   underscore\n{}  curly braces\n[]  square brackets\n()  parentheses\n#   hash mark\n+   plus sign\n-   minus sign (hyphen)\n.   dot\n!   exclamation mark\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/markdown_documentation_syntax.text",
    "content": "Markdown: Syntax\n================\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a href=\"/projects/markdown/basics\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a class=\"selected\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n\n*   [Overview](#overview)\n    *   [Philosophy](#philosophy)\n    *   [Inline HTML](#html)\n    *   [Automatic Escaping for Special Characters](#autoescape)\n*   [Block Elements](#block)\n    *   [Paragraphs and Line Breaks](#p)\n    *   [Headers](#header)\n    *   [Blockquotes](#blockquote)\n    *   [Lists](#list)\n    *   [Code Blocks](#precode)\n    *   [Horizontal Rules](#hr)\n*   [Span Elements](#span)\n    *   [Links](#link)\n    *   [Emphasis](#em)\n    *   [Code](#code)\n    *   [Images](#img)\n*   [Miscellaneous](#misc)\n    *   [Backslash Escapes](#backslash)\n    *   [Automatic Links](#autolink)\n\n\n**Note:** This document is itself written using Markdown; you\ncan [see the source for it by adding '.text' to the URL][src].\n\n  [src]: /projects/markdown/syntax.text\n\n* * *\n\n<h2 id=\"overview\">Overview</h2>\n\n<h3 id=\"philosophy\">Philosophy</h3>\n\nMarkdown is intended to be as easy-to-read and easy-to-write as is feasible.\n\nReadability, however, is emphasized above all else. A Markdown-formatted\ndocument should be publishable as-is, as plain text, without looking\nlike it's been marked up with tags or formatting instructions. While\nMarkdown's syntax has been influenced by several existing text-to-HTML\nfilters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4],\n[Grutatext] [5], and [EtText] [6] -- the single biggest source of\ninspiration for Markdown's syntax is the format of plain text email.\n\n  [1]: http://docutils.sourceforge.net/mirror/setext.html\n  [2]: http://www.aaronsw.com/2002/atx/\n  [3]: http://textism.com/tools/textile/\n  [4]: http://docutils.sourceforge.net/rst.html\n  [5]: http://www.triptico.com/software/grutatxt.html\n  [6]: http://ettext.taint.org/doc/\n\nTo this end, Markdown's syntax is comprised entirely of punctuation\ncharacters, which punctuation characters have been carefully chosen so\nas to look like what they mean. E.g., asterisks around a word actually\nlook like \\*emphasis\\*. Markdown lists look like, well, lists. Even\nblockquotes look like quoted passages of text, assuming you've ever\nused email.\n\n\n\n<h3 id=\"html\">Inline HTML</h3>\n\nMarkdown's syntax is intended for one purpose: to be used as a\nformat for *writing* for the web.\n\nMarkdown is not a replacement for HTML, or even close to it. Its\nsyntax is very small, corresponding only to a very small subset of\nHTML tags. The idea is *not* to create a syntax that makes it easier\nto insert HTML tags. In my opinion, HTML tags are already easy to\ninsert. The idea for Markdown is to make it easy to read, write, and\nedit prose. HTML is a *publishing* format; Markdown is a *writing*\nformat. Thus, Markdown's formatting syntax only addresses issues that\ncan be conveyed in plain text.\n\nFor any markup that is not covered by Markdown's syntax, you simply\nuse HTML itself. There's no need to preface it or delimit it to\nindicate that you're switching from Markdown to HTML; you just use\nthe tags.\n\nThe only restrictions are that block-level HTML elements -- e.g. `<div>`,\n`<table>`, `<pre>`, `<p>`, etc. -- must be separated from surrounding\ncontent by blank lines, and the start and end tags of the block should\nnot be indented with tabs or spaces. Markdown is smart enough not\nto add extra (unwanted) `<p>` tags around HTML block-level tags.\n\nFor example, to add an HTML table to a Markdown article:\n\n    This is a regular paragraph.\n\n    <table>\n        <tr>\n            <td>Foo</td>\n        </tr>\n    </table>\n\n    This is another regular paragraph.\n\nNote that Markdown formatting syntax is not processed within block-level\nHTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an\nHTML block.\n\nSpan-level HTML tags -- e.g. `<span>`, `<cite>`, or `<del>` -- can be\nused anywhere in a Markdown paragraph, list item, or header. If you\nwant, you can even use HTML tags instead of Markdown formatting; e.g. if\nyou'd prefer to use HTML `<a>` or `<img>` tags instead of Markdown's\nlink or image syntax, go right ahead.\n\nUnlike block-level HTML tags, Markdown syntax *is* processed within\nspan-level tags.\n\n\n<h3 id=\"autoescape\">Automatic Escaping for Special Characters</h3>\n\nIn HTML, there are two characters that demand special treatment: `<`\nand `&`. Left angle brackets are used to start tags; ampersands are\nused to denote HTML entities. If you want to use them as literal\ncharacters, you must escape them as entities, e.g. `&lt;`, and\n`&amp;`.\n\nAmpersands in particular are bedeviling for web writers. If you want to\nwrite about 'AT&T', you need to write '`AT&amp;T`'. You even need to\nescape ampersands within URLs. Thus, if you want to link to:\n\n    http://images.google.com/images?num=30&q=larry+bird\n\nyou need to encode the URL as:\n\n    http://images.google.com/images?num=30&amp;q=larry+bird\n\nin your anchor tag `href` attribute. Needless to say, this is easy to\nforget, and is probably the single most common source of HTML validation\nerrors in otherwise well-marked-up web sites.\n\nMarkdown allows you to use these characters naturally, taking care of\nall the necessary escaping for you. If you use an ampersand as part of\nan HTML entity, it remains unchanged; otherwise it will be translated\ninto `&amp;`.\n\nSo, if you want to include a copyright symbol in your article, you can write:\n\n    &copy;\n\nand Markdown will leave it alone. But if you write:\n\n    AT&T\n\nMarkdown will translate it to:\n\n    AT&amp;T\n\nSimilarly, because Markdown supports [inline HTML](#html), if you use\nangle brackets as delimiters for HTML tags, Markdown will treat them as\nsuch. But if you write:\n\n    4 < 5\n\nMarkdown will translate it to:\n\n    4 &lt; 5\n\nHowever, inside Markdown code spans and blocks, angle brackets and\nampersands are *always* encoded automatically. This makes it easy to use\nMarkdown to write about HTML code. (As opposed to raw HTML, which is a\nterrible format for writing about HTML syntax, because every single `<`\nand `&` in your example code needs to be escaped.)\n\n\n* * *\n\n\n<h2 id=\"block\">Block Elements</h2>\n\n\n<h3 id=\"p\">Paragraphs and Line Breaks</h3>\n\nA paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing but spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.\n\nThe implication of the \"one or more consecutive lines of text\" rule is\nthat Markdown supports \"hard-wrapped\" text paragraphs. This differs\nsignificantly from most other text-to-HTML formatters (including Movable\nType's \"Convert Line Breaks\" option) which translate every line break\ncharacter in a paragraph into a `<br />` tag.\n\nWhen you *do* want to insert a `<br />` break tag using Markdown, you\nend a line with two or more spaces, then type return.\n\nYes, this takes a tad more effort to create a `<br />`, but a simplistic\n\"every line break is a `<br />`\" rule wouldn't work for Markdown.\nMarkdown's email-style [blockquoting][bq] and multi-paragraph [list items][l]\nwork best -- and look better -- when you format them with hard breaks.\n\n  [bq]: #blockquote\n  [l]:  #list\n\n\n\n<h3 id=\"header\">Headers</h3>\n\nMarkdown supports two styles of headers, [Setext] [1] and [atx] [2].\n\nSetext-style headers are \"underlined\" using equal signs (for first-level\nheaders) and dashes (for second-level headers). For example:\n\n    This is an H1\n    =============\n\n    This is an H2\n    -------------\n\nAny number of underlining `=`'s or `-`'s will work.\n\nAtx-style headers use 1-6 hash characters at the start of the line,\ncorresponding to header levels 1-6. For example:\n\n    # This is an H1\n\n    ## This is an H2\n\n    ###### This is an H6\n\nOptionally, you may \"close\" atx-style headers. This is purely\ncosmetic -- you can use this if you think it looks better. The\nclosing hashes don't even need to match the number of hashes\nused to open the header. (The number of opening hashes\ndetermines the header level.) :\n\n    # This is an H1 #\n\n    ## This is an H2 ##\n\n    ### This is an H3 ######\n\n\n<h3 id=\"blockquote\">Blockquotes</h3>\n\nMarkdown uses email-style `>` characters for blockquoting. If you're\nfamiliar with quoting passages of text in an email message, then you\nknow how to create a blockquote in Markdown. It looks best if you hard\nwrap the text and put a `>` before every line:\n\n    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n    > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n    > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n    > \n    > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n    > id sem consectetuer libero luctus adipiscing.\n\nMarkdown allows you to be lazy and only put the `>` before the first\nline of a hard-wrapped paragraph:\n\n    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n    consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n    Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n\n    > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n    id sem consectetuer libero luctus adipiscing.\n\nBlockquotes can be nested (i.e. a blockquote-in-a-blockquote) by\nadding additional levels of `>`:\n\n    > This is the first level of quoting.\n    >\n    > > This is nested blockquote.\n    >\n    > Back to the first level.\n\nBlockquotes can contain other Markdown elements, including headers, lists,\nand code blocks:\n\n\t> ## This is a header.\n\t> \n\t> 1.   This is the first list item.\n\t> 2.   This is the second list item.\n\t> \n\t> Here's some example code:\n\t> \n\t>     return shell_exec(\"echo $input | $markdown_script\");\n\nAny decent text editor should make email-style quoting easy. For\nexample, with BBEdit, you can make a selection and choose Increase\nQuote Level from the Text menu.\n\n\n<h3 id=\"list\">Lists</h3>\n\nMarkdown supports ordered (numbered) and unordered (bulleted) lists.\n\nUnordered lists use asterisks, pluses, and hyphens -- interchangably\n-- as list markers:\n\n    *   Red\n    *   Green\n    *   Blue\n\nis equivalent to:\n\n    +   Red\n    +   Green\n    +   Blue\n\nand:\n\n    -   Red\n    -   Green\n    -   Blue\n\nOrdered lists use numbers followed by periods:\n\n    1.  Bird\n    2.  McHale\n    3.  Parish\n\nIt's important to note that the actual numbers you use to mark the\nlist have no effect on the HTML output Markdown produces. The HTML\nMarkdown produces from the above list is:\n\n    <ol>\n    <li>Bird</li>\n    <li>McHale</li>\n    <li>Parish</li>\n    </ol>\n\nIf you instead wrote the list in Markdown like this:\n\n    1.  Bird\n    1.  McHale\n    1.  Parish\n\nor even:\n\n    3. Bird\n    1. McHale\n    8. Parish\n\nyou'd get the exact same HTML output. The point is, if you want to,\nyou can use ordinal numbers in your ordered Markdown lists, so that\nthe numbers in your source match the numbers in your published HTML.\nBut if you want to be lazy, you don't have to.\n\nIf you do use lazy list numbering, however, you should still start the\nlist with the number 1. At some point in the future, Markdown may support\nstarting ordered lists at an arbitrary number.\n\nList markers typically start at the left margin, but may be indented by\nup to three spaces. List markers must be followed by one or more spaces\nor a tab.\n\nTo make lists look nice, you can wrap items with hanging indents:\n\n    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n        Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n        viverra nec, fringilla in, laoreet vitae, risus.\n    *   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n        Suspendisse id sem consectetuer libero luctus adipiscing.\n\nBut if you want to be lazy, you don't have to:\n\n    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n    viverra nec, fringilla in, laoreet vitae, risus.\n    *   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n    Suspendisse id sem consectetuer libero luctus adipiscing.\n\nIf list items are separated by blank lines, Markdown will wrap the\nitems in `<p>` tags in the HTML output. For example, this input:\n\n    *   Bird\n    *   Magic\n\nwill turn into:\n\n    <ul>\n    <li>Bird</li>\n    <li>Magic</li>\n    </ul>\n\nBut this:\n\n    *   Bird\n\n    *   Magic\n\nwill turn into:\n\n    <ul>\n    <li><p>Bird</p></li>\n    <li><p>Magic</p></li>\n    </ul>\n\nList items may consist of multiple paragraphs. Each subsequent\nparagraph in a list item must be intended by either 4 spaces\nor one tab:\n\n    1.  This is a list item with two paragraphs. Lorem ipsum dolor\n        sit amet, consectetuer adipiscing elit. Aliquam hendrerit\n        mi posuere lectus.\n\n        Vestibulum enim wisi, viverra nec, fringilla in, laoreet\n        vitae, risus. Donec sit amet nisl. Aliquam semper ipsum\n        sit amet velit.\n\n    2.  Suspendisse id sem consectetuer libero luctus adipiscing.\n\nIt looks nice if you indent every line of the subsequent\nparagraphs, but here again, Markdown will allow you to be\nlazy:\n\n    *   This is a list item with two paragraphs.\n\n        This is the second paragraph in the list item. You're\n    only required to indent the first line. Lorem ipsum dolor\n    sit amet, consectetuer adipiscing elit.\n\n    *   Another item in the same list.\n\nTo put a blockquote within a list item, the blockquote's `>`\ndelimiters need to be indented:\n\n    *   A list item with a blockquote:\n\n        > This is a blockquote\n        > inside a list item.\n\nTo put a code block within a list item, the code block needs\nto be indented *twice* -- 8 spaces or two tabs:\n\n    *   A list item with a code block:\n\n            <code goes here>\n\n\nIt's worth noting that it's possible to trigger an ordered list by\naccident, by writing something like this:\n\n    1986. What a great season.\n\nIn other words, a *number-period-space* sequence at the beginning of a\nline. To avoid this, you can backslash-escape the period:\n\n    1986\\. What a great season.\n\n\n\n<h3 id=\"precode\">Code Blocks</h3>\n\nPre-formatted code blocks are used for writing about programming or\nmarkup source code. Rather than forming normal paragraphs, the lines\nof a code block are interpreted literally. Markdown wraps a code block\nin both `<pre>` and `<code>` tags.\n\nTo produce a code block in Markdown, simply indent every line of the\nblock by at least 4 spaces or 1 tab. For example, given this input:\n\n    This is a normal paragraph:\n\n        This is a code block.\n\nMarkdown will generate:\n\n    <p>This is a normal paragraph:</p>\n\n    <pre><code>This is a code block.\n    </code></pre>\n\nOne level of indentation -- 4 spaces or 1 tab -- is removed from each\nline of the code block. For example, this:\n\n    Here is an example of AppleScript:\n\n        tell application \"Foo\"\n            beep\n        end tell\n\nwill turn into:\n\n    <p>Here is an example of AppleScript:</p>\n\n    <pre><code>tell application \"Foo\"\n        beep\n    end tell\n    </code></pre>\n\nA code block continues until it reaches a line that is not indented\n(or the end of the article).\n\nWithin a code block, ampersands (`&`) and angle brackets (`<` and `>`)\nare automatically converted into HTML entities. This makes it very\neasy to include example HTML source code using Markdown -- just paste\nit and indent it, and Markdown will handle the hassle of encoding the\nampersands and angle brackets. For example, this:\n\n        <div class=\"footer\">\n            &copy; 2004 Foo Corporation\n        </div>\n\nwill turn into:\n\n    <pre><code>&lt;div class=\"footer\"&gt;\n        &amp;copy; 2004 Foo Corporation\n    &lt;/div&gt;\n    </code></pre>\n\nRegular Markdown syntax is not processed within code blocks. E.g.,\nasterisks are just literal asterisks within a code block. This means\nit's also easy to use Markdown to write about Markdown's own syntax.\n\n\n\n<h3 id=\"hr\">Horizontal Rules</h3>\n\nYou can produce a horizontal rule tag (`<hr />`) by placing three or\nmore hyphens, asterisks, or underscores on a line by themselves. If you\nwish, you may use spaces between the hyphens or asterisks. Each of the\nfollowing lines will produce a horizontal rule:\n\n    * * *\n\n    ***\n\n    *****\n\t\n    - - -\n\n    ---------------------------------------\n\n\t_ _ _\n\n\n* * *\n\n<h2 id=\"span\">Span Elements</h2>\n\n<h3 id=\"link\">Links</h3>\n\nMarkdown supports two style of links: *inline* and *reference*.\n\nIn both styles, the link text is delimited by [square brackets].\n\nTo create an inline link, use a set of regular parentheses immediately\nafter the link text's closing square bracket. Inside the parentheses,\nput the URL where you want the link to point, along with an *optional*\ntitle for the link, surrounded in quotes. For example:\n\n    This is [an example](http://example.com/ \"Title\") inline link.\n\n    [This link](http://example.net/) has no title attribute.\n\nWill produce:\n\n    <p>This is <a href=\"http://example.com/\" title=\"Title\">\n    an example</a> inline link.</p>\n\n    <p><a href=\"http://example.net/\">This link</a> has no\n    title attribute.</p>\n\nIf you're referring to a local resource on the same server, you can\nuse relative paths:\n\n    See my [About](/about/) page for details.\n\nReference-style links use a second set of square brackets, inside\nwhich you place a label of your choosing to identify the link:\n\n    This is [an example][id] reference-style link.\n\nYou can optionally use a space to separate the sets of brackets:\n\n    This is [an example] [id] reference-style link.\n\nThen, anywhere in the document, you define your link label like this,\non a line by itself:\n\n    [id]: http://example.com/  \"Optional Title Here\"\n\nThat is:\n\n*   Square brackets containing the link identifier (optionally\n    indented from the left margin using up to three spaces);\n*   followed by a colon;\n*   followed by one or more spaces (or tabs);\n*   followed by the URL for the link;\n*   optionally followed by a title attribute for the link, enclosed\n    in double or single quotes.\n\nThe link URL may, optionally, be surrounded by angle brackets:\n\n    [id]: <http://example.com/>  \"Optional Title Here\"\n\nYou can put the title attribute on the next line and use extra spaces\nor tabs for padding, which tends to look better with longer URLs:\n\n    [id]: http://example.com/longish/path/to/resource/here\n        \"Optional Title Here\"\n\nLink definitions are only used for creating links during Markdown\nprocessing, and are stripped from your document in the HTML output.\n\nLink definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links:\n\n\t[link text][a]\n\t[link text][A]\n\nare equivalent.\n\nThe *implicit link name* shortcut allows you to omit the name of the\nlink, in which case the link text itself is used as the name.\nJust use an empty set of square brackets -- e.g., to link the word\n\"Google\" to the google.com web site, you could simply write:\n\n\t[Google][]\n\nAnd then define the link:\n\n\t[Google]: http://google.com/\n\nBecause link names may contain spaces, this shortcut even works for\nmultiple words in the link text:\n\n\tVisit [Daring Fireball][] for more information.\n\nAnd then define the link:\n\t\n\t[Daring Fireball]: http://daringfireball.net/\n\nLink definitions can be placed anywhere in your Markdown document. I\ntend to put them immediately after each paragraph in which they're\nused, but if you want, you can put them all at the end of your\ndocument, sort of like footnotes.\n\nHere's an example of reference links in action:\n\n    I get 10 times more traffic from [Google] [1] than from\n    [Yahoo] [2] or [MSN] [3].\n\n      [1]: http://google.com/        \"Google\"\n      [2]: http://search.yahoo.com/  \"Yahoo Search\"\n      [3]: http://search.msn.com/    \"MSN Search\"\n\nUsing the implicit link name shortcut, you could instead write:\n\n    I get 10 times more traffic from [Google][] than from\n    [Yahoo][] or [MSN][].\n\n      [google]: http://google.com/        \"Google\"\n      [yahoo]:  http://search.yahoo.com/  \"Yahoo Search\"\n      [msn]:    http://search.msn.com/    \"MSN Search\"\n\nBoth of the above examples will produce the following HTML output:\n\n    <p>I get 10 times more traffic from <a href=\"http://google.com/\"\n    title=\"Google\">Google</a> than from\n    <a href=\"http://search.yahoo.com/\" title=\"Yahoo Search\">Yahoo</a>\n    or <a href=\"http://search.msn.com/\" title=\"MSN Search\">MSN</a>.</p>\n\nFor comparison, here is the same paragraph written using\nMarkdown's inline link style:\n\n    I get 10 times more traffic from [Google](http://google.com/ \"Google\")\n    than from [Yahoo](http://search.yahoo.com/ \"Yahoo Search\") or\n    [MSN](http://search.msn.com/ \"MSN Search\").\n\nThe point of reference-style links is not that they're easier to\nwrite. The point is that with reference-style links, your document\nsource is vastly more readable. Compare the above examples: using\nreference-style links, the paragraph itself is only 81 characters\nlong; with inline-style links, it's 176 characters; and as raw HTML,\nit's 234 characters. In the raw HTML, there's more markup than there\nis text.\n\nWith Markdown's reference-style links, a source document much more\nclosely resembles the final output, as rendered in a browser. By\nallowing you to move the markup-related metadata out of the paragraph,\nyou can add links without interrupting the narrative flow of your\nprose.\n\n\n<h3 id=\"em\">Emphasis</h3>\n\nMarkdown treats asterisks (`*`) and underscores (`_`) as indicators of\nemphasis. Text wrapped with one `*` or `_` will be wrapped with an\nHTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML\n`<strong>` tag. E.g., this input:\n\n    *single asterisks*\n\n    _single underscores_\n\n    **double asterisks**\n\n    __double underscores__\n\nwill produce:\n\n    <em>single asterisks</em>\n\n    <em>single underscores</em>\n\n    <strong>double asterisks</strong>\n\n    <strong>double underscores</strong>\n\nYou can use whichever style you prefer; the lone restriction is that\nthe same character must be used to open and close an emphasis span.\n\nEmphasis can be used in the middle of a word:\n\n    un*fucking*believable\n\nBut if you surround an `*` or `_` with spaces, it'll be treated as a\nliteral asterisk or underscore.\n\nTo produce a literal asterisk or underscore at a position where it\nwould otherwise be used as an emphasis delimiter, you can backslash\nescape it:\n\n    \\*this text is surrounded by literal asterisks\\*\n\n\n\n<h3 id=\"code\">Code</h3>\n\nTo indicate a span of code, wrap it with backtick quotes (`` ` ``).\nUnlike a pre-formatted code block, a code span indicates code within a\nnormal paragraph. For example:\n\n    Use the `printf()` function.\n\nwill produce:\n\n    <p>Use the <code>printf()</code> function.</p>\n\nTo include a literal backtick character within a code span, you can use\nmultiple backticks as the opening and closing delimiters:\n\n    ``There is a literal backtick (`) here.``\n\nwhich will produce this:\n\n    <p><code>There is a literal backtick (`) here.</code></p>\n\nThe backtick delimiters surrounding a code span may include spaces --\none after the opening, one before the closing. This allows you to place\nliteral backtick characters at the beginning or end of a code span:\n\n\tA single backtick in a code span: `` ` ``\n\t\n\tA backtick-delimited string in a code span: `` `foo` ``\n\nwill produce:\n\n\t<p>A single backtick in a code span: <code>`</code></p>\n\t\n\t<p>A backtick-delimited string in a code span: <code>`foo`</code></p>\n\nWith a code span, ampersands and angle brackets are encoded as HTML\nentities automatically, which makes it easy to include example HTML\ntags. Markdown will turn this:\n\n    Please don't use any `<blink>` tags.\n\ninto:\n\n    <p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>\n\nYou can write this:\n\n    `&#8212;` is the decimal-encoded equivalent of `&mdash;`.\n\nto produce:\n\n    <p><code>&amp;#8212;</code> is the decimal-encoded\n    equivalent of <code>&amp;mdash;</code>.</p>\n\n\n\n<h3 id=\"img\">Images</h3>\n\nAdmittedly, it's fairly difficult to devise a \"natural\" syntax for\nplacing images into a plain text document format.\n\nMarkdown uses an image syntax that is intended to resemble the syntax\nfor links, allowing for two styles: *inline* and *reference*.\n\nInline image syntax looks like this:\n\n    ![Alt text](/path/to/img.jpg)\n\n    ![Alt text](/path/to/img.jpg \"Optional title\")\n\nThat is:\n\n*   An exclamation mark: `!`;\n*   followed by a set of square brackets, containing the `alt`\n    attribute text for the image;\n*   followed by a set of parentheses, containing the URL or path to\n    the image, and an optional `title` attribute enclosed in double\n    or single quotes.\n\nReference-style image syntax looks like this:\n\n    ![Alt text][id]\n\nWhere \"id\" is the name of a defined image reference. Image references\nare defined using syntax identical to link references:\n\n    [id]: url/to/image  \"Optional title attribute\"\n\nAs of this writing, Markdown has no syntax for specifying the\ndimensions of an image; if this is important to you, you can simply\nuse regular HTML `<img>` tags.\n\n\n* * *\n\n\n<h2 id=\"misc\">Miscellaneous</h2>\n\n<h3 id=\"autolink\">Automatic Links</h3>\n\nMarkdown supports a shortcut style for creating \"automatic\" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:\n\n    <http://example.com/>\n    \nMarkdown will turn this into:\n\n    <a href=\"http://example.com/\">http://example.com/</a>\n\nAutomatic links for email addresses work similarly, except that\nMarkdown will also perform a bit of randomized decimal and hex\nentity-encoding to help obscure your address from address-harvesting\nspambots. For example, Markdown will turn this:\n\n    <address@example.com>\n\ninto something like this:\n\n    <a href=\"&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;\n    &#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;\n    &#109;\">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;\n    &#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>\n\nwhich will render in a browser as a clickable link to \"address@example.com\".\n\n(This sort of entity-encoding trick will indeed fool many, if not\nmost, address-harvesting bots, but it definitely won't fool all of\nthem. It's better than nothing, but an address published in this way\nwill probably eventually start receiving spam.)\n\n\n\n<h3 id=\"backslash\">Backslash Escapes</h3>\n\nMarkdown allows you to use backslash escapes to generate literal\ncharacters which would otherwise have special meaning in Markdown's\nformatting syntax. For example, if you wanted to surround a word with\nliteral asterisks (instead of an HTML `<em>` tag), you can backslashes\nbefore the asterisks, like this:\n\n    \\*literal asterisks\\*\n\nMarkdown provides backslash escapes for the following characters:\n\n    \\   backslash\n    `   backtick\n    *   asterisk\n    _   underscore\n    {}  curly braces\n    []  square brackets\n    ()  parentheses\n    #   hash mark\n\t+\tplus sign\n\t-\tminus sign (hyphen)\n    .   dot\n    !   exclamation mark\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/nested_blockquotes.html",
    "content": "<blockquote>\n  <p>foo</p>\n  \n  <blockquote>\n    <p>bar</p>\n  </blockquote>\n  \n  <p>foo</p>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/nested_blockquotes.text",
    "content": "> foo\n>\n> > bar\n>\n> foo\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/ordered_and_unordered_lists.html",
    "content": "<h2>Unordered</h2>\n\n<p>Asterisks tight:</p>\n\n<ul>\n<li>asterisk 1</li>\n<li>asterisk 2</li>\n<li>asterisk 3</li>\n</ul>\n\n<p>Asterisks loose:</p>\n\n<ul>\n<li><p>asterisk 1</p></li>\n<li><p>asterisk 2</p></li>\n<li><p>asterisk 3</p></li>\n</ul>\n\n<hr />\n\n<p>Pluses tight:</p>\n\n<ul>\n<li>Plus 1</li>\n<li>Plus 2</li>\n<li>Plus 3</li>\n</ul>\n\n<p>Pluses loose:</p>\n\n<ul>\n<li><p>Plus 1</p></li>\n<li><p>Plus 2</p></li>\n<li><p>Plus 3</p></li>\n</ul>\n\n<hr />\n\n<p>Minuses tight:</p>\n\n<ul>\n<li>Minus 1</li>\n<li>Minus 2</li>\n<li>Minus 3</li>\n</ul>\n\n<p>Minuses loose:</p>\n\n<ul>\n<li><p>Minus 1</p></li>\n<li><p>Minus 2</p></li>\n<li><p>Minus 3</p></li>\n</ul>\n\n<h2>Ordered</h2>\n\n<p>Tight:</p>\n\n<ol>\n<li>First</li>\n<li>Second</li>\n<li>Third</li>\n</ol>\n\n<p>and:</p>\n\n<ol>\n<li>One</li>\n<li>Two</li>\n<li>Three</li>\n</ol>\n\n<p>Loose using tabs:</p>\n\n<ol>\n<li><p>First</p></li>\n<li><p>Second</p></li>\n<li><p>Third</p></li>\n</ol>\n\n<p>and using spaces:</p>\n\n<ol>\n<li><p>One</p></li>\n<li><p>Two</p></li>\n<li><p>Three</p></li>\n</ol>\n\n<p>Multiple paragraphs:</p>\n\n<ol>\n<li><p>Item 1, graf one.</p>\n\n<p>Item 2. graf two. The quick brown fox jumped over the lazy dog's\nback.</p></li>\n<li><p>Item 2.</p></li>\n<li><p>Item 3.</p></li>\n</ol>\n\n<h2>Nested</h2>\n\n<ul>\n<li>Tab\n<ul>\n<li>Tab\n<ul>\n<li>Tab</li>\n</ul></li>\n</ul></li>\n</ul>\n\n<p>Here's another:</p>\n\n<ol>\n<li>First</li>\n<li>Second:\n<ul>\n<li>Fee</li>\n<li>Fie</li>\n<li>Foe</li>\n</ul></li>\n<li>Third</li>\n</ol>\n\n<p>Same thing but with paragraphs:</p>\n\n<ol>\n<li><p>First</p></li>\n<li><p>Second:</p>\n\n<ul>\n<li>Fee</li>\n<li>Fie</li>\n<li>Foe</li>\n</ul></li>\n<li><p>Third</p></li>\n</ol>\n\n\n<p>This was an error in Markdown 1.0.1:</p>\n\n<ul>\n<li><p>this</p>\n\n<ul><li>sub</li></ul>\n\n<p>that</p></li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/ordered_and_unordered_lists.text",
    "content": "## Unordered\n\nAsterisks tight:\n\n*\tasterisk 1\n*\tasterisk 2\n*\tasterisk 3\n\n\nAsterisks loose:\n\n*\tasterisk 1\n\n*\tasterisk 2\n\n*\tasterisk 3\n\n* * *\n\nPluses tight:\n\n+\tPlus 1\n+\tPlus 2\n+\tPlus 3\n\n\nPluses loose:\n\n+\tPlus 1\n\n+\tPlus 2\n\n+\tPlus 3\n\n* * *\n\n\nMinuses tight:\n\n-\tMinus 1\n-\tMinus 2\n-\tMinus 3\n\n\nMinuses loose:\n\n-\tMinus 1\n\n-\tMinus 2\n\n-\tMinus 3\n\n\n## Ordered\n\nTight:\n\n1.\tFirst\n2.\tSecond\n3.\tThird\n\nand:\n\n1. One\n2. Two\n3. Three\n\n\nLoose using tabs:\n\n1.\tFirst\n\n2.\tSecond\n\n3.\tThird\n\nand using spaces:\n\n1. One\n\n2. Two\n\n3. Three\n\nMultiple paragraphs:\n\n1.\tItem 1, graf one.\n\n\tItem 2. graf two. The quick brown fox jumped over the lazy dog's\n\tback.\n\t\n2.\tItem 2.\n\n3.\tItem 3.\n\n\n\n## Nested\n\n*\tTab\n\t*\tTab\n\t\t*\tTab\n\nHere's another:\n\n1. First\n2. Second:\n\t* Fee\n\t* Fie\n\t* Foe\n3. Third\n\nSame thing but with paragraphs:\n\n1. First\n\n2. Second:\n\t* Fee\n\t* Fie\n\t* Foe\n\n3. Third\n\n\nThis was an error in Markdown 1.0.1:\n\n*\tthis\n\n\t*\tsub\n\n\tthat\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/strong_and_em_together.html",
    "content": "<p><strong><em>This is strong and em.</em></strong></p>\n\n<p>So is <strong><em>this</em></strong> word.</p>\n\n<p><strong><em>This is strong and em.</em></strong></p>\n\n<p>So is <strong><em>this</em></strong> word.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/strong_and_em_together.text",
    "content": "***This is strong and em.***\n\nSo is ***this*** word.\n\n___This is strong and em.___\n\nSo is ___this___ word.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/tabs.html",
    "content": "<ul>\n<li><p>this is a list item\nindented with tabs</p></li>\n<li><p>this is a list item\nindented with spaces</p></li>\n</ul>\n\n<p>Code:</p>\n\n<pre><code>this code block is indented by one tab\n</code></pre>\n\n<p>And:</p>\n\n<pre><code>    this code block is indented by two tabs\n</code></pre>\n\n<p>And:</p>\n\n<pre><code>+   this is an example list item\n    indented with tabs\n\n+   this is an example list item\n    indented with spaces\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/tabs.text",
    "content": "+\tthis is a list item\n\tindented with tabs\n\n+   this is a list item\n    indented with spaces\n\nCode:\n\n\tthis code block is indented by one tab\n\nAnd:\n\n\t\tthis code block is indented by two tabs\n\nAnd:\n\n\t+\tthis is an example list item\n\t\tindented with tabs\n\t\n\t+   this is an example list item\n\t    indented with spaces\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/tidyness.html",
    "content": "<blockquote>\n<p>A list within a blockquote:</p>\n<ul>\n<li>asterisk 1</li>\n<li>asterisk 2</li>\n<li>asterisk 3</li>\n</ul>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/original/tidyness.text",
    "content": "> A list within a blockquote:\n> \n> *\tasterisk 1\n> *\tasterisk 2\n> *\tasterisk 3\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/amps_and_angles_encoding.html",
    "content": "<p>AT&amp;T has an ampersand in their name.</p>\n\n<p>AT&amp;T is another way to write it.</p>\n\n<p>This &amp; that.</p>\n\n<p>4 &lt; 5.</p>\n\n<p>6 &gt; 5.</p>\n\n<p>Here&#39;s a <a href=\"http://example.com/?foo=1&amp;bar=2\">link</a> with an ampersand in the URL.</p>\n\n<p>Here&#39;s a link with an amersand in the link text: <a href=\"http://att.com/\" title=\"AT&amp;T\">AT&amp;T</a>.</p>\n\n<p>Here&#39;s an inline <a href=\"/script?foo=1&amp;bar=2\">link</a>.</p>\n\n<p>Here&#39;s an inline <a href=\"/script?foo=1&amp;bar=2\">link</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/amps_and_angles_encoding.text",
    "content": "AT&T has an ampersand in their name.\n\nAT&amp;T is another way to write it.\n\nThis & that.\n\n4 < 5.\n\n6 > 5.\n\nHere's a [link] [1] with an ampersand in the URL.\n\nHere's a link with an amersand in the link text: [AT&T] [2].\n\nHere's an inline [link](/script?foo=1&bar=2).\n\nHere's an inline [link](</script?foo=1&bar=2>).\n\n\n[1]: http://example.com/?foo=1&bar=2\n[2]: http://att.com/  \"AT&T\"\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/auto_links.html",
    "content": "<p>Link: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>With an ampersand: <a href=\"http://example.com/?foo=1&amp;bar=2\">http://example.com/?foo=1&amp;bar=2</a></p>\n\n<ul>\n<li>In a list?</li>\n<li><a href=\"http://example.com/\">http://example.com/</a></li>\n<li>It should.</li>\n</ul>\n\n<blockquote>\n  <p>Blockquoted: <a href=\"http://example.com/\">http://example.com/</a></p>\n</blockquote>\n\n<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>\n\n<pre><code>or here: &lt;http://example.com/&gt;\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/auto_links.text",
    "content": "Link: <http://example.com/>.\n\nWith an ampersand: <http://example.com/?foo=1&bar=2>\n\n* In a list?\n* <http://example.com/>\n* It should.\n\n> Blockquoted: <http://example.com/>\n\nAuto-links should not occur here: `<http://example.com/>`\n\n\tor here: <http://example.com/>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/autolink_lines.html",
    "content": "<p>hello world\n<a href=\"http://example.com\">http://example.com</a>\n</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/autolink_lines.text",
    "content": "hello world\n<http://example.com>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/backslash_escapes.html",
    "content": "<p>These should all get escaped:</p>\n\n<p>Backslash: \\</p>\n\n<p>Backtick: `</p>\n\n<p>Asterisk: *</p>\n\n<p>Underscore: _</p>\n\n<p>Left brace: {</p>\n\n<p>Right brace: }</p>\n\n<p>Left bracket: [</p>\n\n<p>Right bracket: ]</p>\n\n<p>Left paren: (</p>\n\n<p>Right paren: )</p>\n\n<p>Greater-than: ></p>\n\n<p>Hash: #</p>\n\n<p>Period: .</p>\n\n<p>Bang: !</p>\n\n<p>Plus: +</p>\n\n<p>Minus: -</p>\n\n<p>These should not, because they occur within a code block:</p>\n\n<pre><code>Backslash: \\\\\n\nBacktick: \\`\n\nAsterisk: \\*\n\nUnderscore: \\_\n\nLeft brace: \\{\n\nRight brace: \\}\n\nLeft bracket: \\[\n\nRight bracket: \\]\n\nLeft paren: \\(\n\nRight paren: \\)\n\nGreater-than: \\&gt;\n\nHash: \\#\n\nPeriod: \\.\n\nBang: \\!\n\nPlus: \\+\n\nMinus: \\-\n</code></pre>\n\n<p>Nor should these, which occur in code spans:</p>\n\n<p>Backslash: <code>\\\\</code></p>\n\n<p>Backtick: <code>\\`</code></p>\n\n<p>Asterisk: <code>\\*</code></p>\n\n<p>Underscore: <code>\\_</code></p>\n\n<p>Left brace: <code>\\{</code></p>\n\n<p>Right brace: <code>\\}</code></p>\n\n<p>Left bracket: <code>\\[</code></p>\n\n<p>Right bracket: <code>\\]</code></p>\n\n<p>Left paren: <code>\\(</code></p>\n\n<p>Right paren: <code>\\)</code></p>\n\n<p>Greater-than: <code>\\&gt;</code></p>\n\n<p>Hash: <code>\\#</code></p>\n\n<p>Period: <code>\\.</code></p>\n\n<p>Bang: <code>\\!</code></p>\n\n<p>Plus: <code>\\+</code></p>\n\n<p>Minus: <code>\\-</code></p>\n\n\n<p>These should get escaped, even though they&#39;re matching pairs for\nother Markdown constructs:</p>\n\n<p>*asterisks*</p>\n\n<p>_underscores_</p>\n\n<p>`backticks`</p>\n\n<p>This is a code span with a literal backslash-backtick sequence: <code>\\`</code></p>\n\n<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p>\n\n<p>This is a tag with backslashes <span attr='\\\\backslashes\\\\'>bar</span>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/backslash_escapes.text",
    "content": "These should all get escaped:\n\nBackslash: \\\\\n\nBacktick: \\`\n\nAsterisk: \\*\n\nUnderscore: \\_\n\nLeft brace: \\{\n\nRight brace: \\}\n\nLeft bracket: \\[\n\nRight bracket: \\]\n\nLeft paren: \\(\n\nRight paren: \\)\n\nGreater-than: \\>\n\nHash: \\#\n\nPeriod: \\.\n\nBang: \\!\n\nPlus: \\+\n\nMinus: \\-\n\n\n\nThese should not, because they occur within a code block:\n\n\tBackslash: \\\\\n\n\tBacktick: \\`\n\n\tAsterisk: \\*\n\n\tUnderscore: \\_\n\n\tLeft brace: \\{\n\n\tRight brace: \\}\n\n\tLeft bracket: \\[\n\n\tRight bracket: \\]\n\n\tLeft paren: \\(\n\n\tRight paren: \\)\n\n\tGreater-than: \\>\n\n\tHash: \\#\n\n\tPeriod: \\.\n\n\tBang: \\!\n\n\tPlus: \\+\n\n\tMinus: \\-\n\n\nNor should these, which occur in code spans:\n\nBackslash: `\\\\`\n\nBacktick: `` \\` ``\n\nAsterisk: `\\*`\n\nUnderscore: `\\_`\n\nLeft brace: `\\{`\n\nRight brace: `\\}`\n\nLeft bracket: `\\[`\n\nRight bracket: `\\]`\n\nLeft paren: `\\(`\n\nRight paren: `\\)`\n\nGreater-than: `\\>`\n\nHash: `\\#`\n\nPeriod: `\\.`\n\nBang: `\\!`\n\nPlus: `\\+`\n\nMinus: `\\-`\n\n\nThese should get escaped, even though they're matching pairs for\nother Markdown constructs:\n\n\\*asterisks\\*\n\n\\_underscores\\_\n\n\\`backticks\\`\n\nThis is a code span with a literal backslash-backtick sequence: `` \\` ``\n\nThis is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.\n\nThis is a tag with backslashes <span attr='\\\\backslashes\\\\'>bar</span>.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/blockquote_list_item.html",
    "content": "<p>This fails in markdown.pl and upskirt:</p>\n\n<ul><li>hello<blockquote><p>world</p></blockquote></li></ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/blockquote_list_item.text",
    "content": "This fails in markdown.pl and upskirt:\n\n* hello\n  > world\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/blockquotes_with_code_blocks.html",
    "content": "<blockquote>\n  <p>Example:</p>\n\n<pre><code>sub status {\n    print &quot;working&quot;;\n}\n</code></pre>\n  \n  <p>Or:</p>\n\n<pre><code>sub status {\n    return &quot;working&quot;;\n}\n</code></pre>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/blockquotes_with_code_blocks.text",
    "content": "> Example:\n> \n>     sub status {\n>         print \"working\";\n>     }\n> \n> Or:\n> \n>     sub status {\n>         return \"working\";\n>     }\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/case_insensitive_refs.html",
    "content": "<p><a href=\"/url\">hi</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/case_insensitive_refs.text",
    "content": "[hi]\n\n[HI]: /url\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/code_blocks.html",
    "content": "<pre><code>code block on the first line\n</code></pre>\n\n<p>Regular text.</p>\n\n<pre><code>code block indented by spaces\n</code></pre>\n\n<p>Regular text.</p>\n\n<pre><code>the lines in this block  \nall contain trailing spaces  \n</code></pre>\n\n<p>Regular Text.</p>\n\n<pre><code>code block on the last line\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/code_blocks.text",
    "content": "\tcode block on the first line\n\t\nRegular text.\n\n    code block indented by spaces\n\nRegular text.\n\n\tthe lines in this block  \n\tall contain trailing spaces  \n\nRegular Text.\n\n\tcode block on the last line\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/code_spans.html",
    "content": "<p><code>&lt;test a=&quot;</code> content of attribute <code>&quot;&gt;</code></p>\n\n<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p>\n\n<p>Here&#39;s how you put <code>`backticks`</code> in a code span.</p>\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/code_spans.text",
    "content": "`<test a=\"` content of attribute `\">`\n\nFix for backticks within HTML tag: <span attr='`ticks`'>like this</span>\n\nHere's how you put `` `backticks` `` in a code span.\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/def_blocks.html",
    "content": "<blockquote>\n  <p>hello\n[1]: hello</p>\n</blockquote>\n\n<hr>\n\n<blockquote>\n  <p>hello</p>\n</blockquote>\n\n\n<ul>\n<li>hello</li>\n<li>[3]: hello</li>\n</ul>\n\n\n<ul>\n<li>hello</li>\n</ul>\n\n\n<blockquote>\n  <p>foo\nbar\nbar</p>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/def_blocks.text",
    "content": "> hello\n> [1]: hello\n\n* * *\n\n> hello\n[2]: hello\n\n\n* hello\n* [3]: hello\n\n\n* hello\n[4]: hello\n\n\n> foo\n> bar\n[1]: foo\n> bar\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/double_link.html",
    "content": "<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>Already linked: <a href=\"http://example.com/\"><strong>http://example.com/</strong></a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/double_link.text",
    "content": "<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\nAlready linked: [http://example.com/](http://example.com/).\n\nAlready linked: <a href=\"http://example.com/\">**http://example.com/**</a>.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/escaped_angles.html",
    "content": "<p>></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/escaped_angles.text",
    "content": "\\>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_break.breaks.html",
    "content": "<p>Look at the<br>pretty line<br>breaks.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_break.breaks.text",
    "content": "Look at the\npretty line\nbreaks.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_code.html",
    "content": "<pre><code class=\"lang-js\">var a = &#39;hello&#39;;\nconsole.log(a + &#39; world&#39;);</code></pre>\n<pre><code class=\"lang-bash\">echo &quot;hello, ${WORLD}&quot;</code></pre>\n<pre><code class=\"lang-longfence\">Q: What do you call a tall person who sells stolen goods?</code></pre>\n<pre><code class=\"lang-ManyTildes\">A longfence!</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_code.text",
    "content": "``` js\nvar a = 'hello';\nconsole.log(a + ' world');\n```\n\n~~~bash\necho \"hello, ${WORLD}\"\n~~~\n\n```````longfence\nQ: What do you call a tall person who sells stolen goods?\n```````\n\n~~~~~~~~~~  ManyTildes\nA longfence!\n~~~~~~~~~~\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_code_hr_list.html",
    "content": "<h2 id=\"foo\">foo</h2>\n<ol>\n<li><p>bar:</p>\n<blockquote>\n<ul>\n<li>one<ul>\n<li>two<ul>\n<li>three</li>\n<li>four</li>\n<li>five</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</blockquote>\n</li>\n<li><p>foo:</p>\n<pre><code> line 1\n line 2</code></pre>\n</li>\n<li><p>foo:</p>\n<ol>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code class=\"lang-erb\"> some code here\n</code></pre>\n</li>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code class=\"lang-erb\"> foo\n ---\n bar\n ---\n foo\n bar</code></pre>\n</li>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code class=\"lang-html\"> ---\n foo\n foo\n ---\n bar</code></pre>\n</li>\n<li><p>foo <code>bar</code> bar:</p>\n<pre><code> foo\n ---\n bar</code></pre>\n</li>\n<li><p>foo</p>\n</li>\n</ol>\n</li>\n</ol>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_code_hr_list.text",
    "content": "## foo\n\n1. bar:\n\n    > - one\n        - two\n            - three\n            - four\n            - five\n\n1. foo:\n\n    ```\n    line 1\n    line 2\n    ```\n\n1. foo:\n\n    1. foo `bar` bar:\n\n        ``` erb\n        some code here\n        ```\n\n    2. foo `bar` bar:\n\n        ``` erb\n        foo\n        ---\n        bar\n        ---\n        foo\n        bar\n        ```\n\n    3. foo `bar` bar:\n\n        ``` html\n        ---\n        foo\n        foo\n        ---\n        bar\n        ```\n\n    4. foo `bar` bar:\n\n            foo\n            ---\n            bar\n\n    5. foo\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_del.html",
    "content": "<p>hello <del>hi</del> world</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_del.text",
    "content": "hello ~~hi~~ world\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_em.html",
    "content": "<p>These words should_not_be_emphasized.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_em.text",
    "content": "These words should_not_be_emphasized.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_links.html",
    "content": "<p>This should be a link:\n<a href=\"http://example.com/hello-world\">http://example.com/hello-world</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_links.text",
    "content": "This should be a link: http://example.com/hello-world.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_tables.html",
    "content": "<table>\n\t<thead>\n\t\t<tr><th>Heading 1</th><th>Heading 2</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td>Cell 1</td><td>Cell 2</td></tr>\n\t\t<tr><td>Cell 3</td><td>Cell 4</td></tr>\n\t</tbody>\n</table>\n<table>\n\t<thead>\n\t\t<tr><th style=\"text-align:center\">Header 1</th><th style=\"text-align:right\">Header 2</th><th style=\"text-align:left\">Header 3</th><th>Header 4</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td style=\"text-align:center\">Cell 1</td><td style=\"text-align:right\">Cell 2</td><td style=\"text-align:left\">Cell 3</td><td>Cell 4</td></tr>\n\t\t<tr><td style=\"text-align:center\">Cell 5</td><td style=\"text-align:right\">Cell 6</td><td style=\"text-align:left\">Cell 7</td><td>Cell 8</td></tr>\n\t</tbody>\n</table>\n<pre><code>Test code</code></pre>\n<table>\n\t<thead>\n\t\t<tr><th>Header 1</th><th>Header 2</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td>Cell 1</td><td>Cell 2</td></tr>\n\t\t<tr><td>Cell 3</td><td>Cell 4</td></tr>\n\t</tbody>\n</table>\n<table>\n\t<thead>\n\t\t<tr><th style=\"text-align:left\">Header 1</th><th style=\"text-align:center\">Header 2</th><th style=\"text-align:right\">Header 3</th><th>Header 4</th></tr>\n\t</thead>\n\t<tbody>\n\t\t<tr><td style=\"text-align:left\">Cell 1</td><td style=\"text-align:center\">Cell 2</td><td style=\"text-align:right\">Cell 3</td><td>Cell 4</td></tr>\n\t\t<tr><td style=\"text-align:left\"><em>Cell 5</em></td><td style=\"text-align:center\">Cell 6</td><td style=\"text-align:right\">Cell 7</td><td>Cell 8</td></tr>\n\t</tbody>\n</table>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/gfm_tables.text",
    "content": "| Heading 1 | Heading 2\n| --------- | ---------\n| Cell 1    | Cell 2\n| Cell 3    | Cell 4\n\n| Header 1 | Header 2 | Header 3 | Header 4 |\n| :------: | -------: | :------- | -------- |\n| Cell 1   | Cell 2   | Cell 3   | Cell 4   |\n| Cell 5   | Cell 6   | Cell 7   | Cell 8   |\n\n    Test code\n\nHeader 1 | Header 2\n-------- | --------\nCell 1   | Cell 2\nCell 3   | Cell 4\n\nHeader 1|Header 2|Header 3|Header 4\n:-------|:------:|-------:|--------\nCell 1  |Cell 2  |Cell 3  |Cell 4\n*Cell 5*|Cell 6  |Cell 7  |Cell 8\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.html",
    "content": "<p>In Markdown 1.0.0 and earlier. Version\n8. This line turns into a list item.\nBecause a hard-wrapped line in the\nmiddle of a paragraph looked like a\nlist item.</p>\n\n<p>Here&#39;s one with a bullet.\n* criminey.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/hard_wrapped_paragraphs_with_list_like_lines.nogfm.text",
    "content": "In Markdown 1.0.0 and earlier. Version\n8. This line turns into a list item.\nBecause a hard-wrapped line in the\nmiddle of a paragraph looked like a\nlist item.\n\nHere's one with a bullet.\n* criminey.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/horizontal_rules.html",
    "content": "<p>Dashes:</p>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<pre><code>---\n</code></pre>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<pre><code>- - -\n</code></pre>\n\n<p>Asterisks:</p>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<pre><code>***\n</code></pre>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<pre><code>* * *\n</code></pre>\n\n<p>Underscores:</p>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<pre><code>___\n</code></pre>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<pre><code>_ _ _\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/horizontal_rules.text",
    "content": "Dashes:\n\n---\n\n ---\n \n  ---\n\n   ---\n\n\t---\n\n- - -\n\n - - -\n \n  - - -\n\n   - - -\n\n\t- - -\n\n\nAsterisks:\n\n***\n\n ***\n \n  ***\n\n   ***\n\n\t***\n\n* * *\n\n * * *\n \n  * * *\n\n   * * *\n\n\t* * *\n\n\nUnderscores:\n\n___\n\n ___\n \n  ___\n\n   ___\n\n    ___\n\n_ _ _\n\n _ _ _\n \n  _ _ _\n\n   _ _ _\n\n    _ _ _\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/hr_list_break.html",
    "content": "<ul>\n<li>hello\nworld</li>\n<li>how\nare</li>\n</ul>\n\n<hr>\n\n<p>you today?</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/hr_list_break.text",
    "content": "* hello\nworld\n* how\nare\n* * *\nyou today?\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/inline_html_advanced.html",
    "content": "<p>Simple block on one line:</p>\n\n<div>foo</div>\n\n<p>And nested without indentation:</p>\n\n<div>\n<div>\n<div>\nfoo\n</div>\n<div style=\">\"/>\n</div>\n<div>bar</div>\n</div>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/inline_html_advanced.text",
    "content": "Simple block on one line:\n\n<div>foo</div>\n\nAnd nested without indentation:\n\n<div>\n<div>\n<div>\nfoo\n</div>\n<div style=\">\"/>\n</div>\n<div>bar</div>\n</div>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/inline_html_comments.html",
    "content": "<p>Paragraph one.</p>\n\n<!-- This is a simple comment -->\n\n<!--\n    This is another comment.\n-->\n\n<p>Paragraph two.</p>\n\n<!-- one comment block -- -- with two comments -->\n\n<p>The end.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/inline_html_comments.text",
    "content": "Paragraph one.\n\n<!-- This is a simple comment -->\n\n<!--\n\tThis is another comment.\n-->\n\nParagraph two.\n\n<!-- one comment block -- -- with two comments -->\n\nThe end.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/inline_html_simple.html",
    "content": "<p>Here&#39;s a simple block:</p>\n\n<div>\n    foo\n</div>\n\n<p>This should be a code block, though:</p>\n\n<pre><code>&lt;div&gt;\n    foo\n&lt;/div&gt;\n</code></pre>\n\n<p>As should this:</p>\n\n<pre><code>&lt;div&gt;foo&lt;/div&gt;\n</code></pre>\n\n<p>Now, nested:</p>\n\n<div>\n    <div>\n        <div>\n            foo\n        </div>\n    </div>\n</div>\n\n<p>This should just be an HTML comment:</p>\n\n<!-- Comment -->\n\n<p>Multiline:</p>\n\n<!--\nBlah\nBlah\n-->\n\n<p>Code block:</p>\n\n<pre><code>&lt;!-- Comment --&gt;\n</code></pre>\n\n<p>Just plain comment, with trailing spaces on the line:</p>\n\n<!-- foo -->   \n\n<p>Code:</p>\n\n<pre><code>&lt;hr&gt;\n</code></pre>\n\n<p>Hr&#39;s:</p>\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>   \n\n<hr>  \n\n<hr> \n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\"/>\n\n<hr class=\"foo\" id=\"bar\" >\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/inline_html_simple.text",
    "content": "Here's a simple block:\n\n<div>\n\tfoo\n</div>\n\nThis should be a code block, though:\n\n\t<div>\n\t\tfoo\n\t</div>\n\nAs should this:\n\n\t<div>foo</div>\n\nNow, nested:\n\n<div>\n\t<div>\n\t\t<div>\n\t\t\tfoo\n\t\t</div>\n\t</div>\n</div>\n\nThis should just be an HTML comment:\n\n<!-- Comment -->\n\nMultiline:\n\n<!--\nBlah\nBlah\n-->\n\nCode block:\n\n\t<!-- Comment -->\n\nJust plain comment, with trailing spaces on the line:\n\n<!-- foo -->   \n\nCode:\n\n\t<hr>\n\t\nHr's:\n\n<hr>\n\n<hr>\n\n<hr>\n\n<hr>   \n\n<hr>  \n\n<hr> \n\n<hr class=\"foo\" id=\"bar\" />\n\n<hr class=\"foo\" id=\"bar\"/>\n\n<hr class=\"foo\" id=\"bar\" >\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/lazy_blockquotes.html",
    "content": "<blockquote>\n  <p>hi there\nbud</p>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/lazy_blockquotes.text",
    "content": "> hi there\nbud\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/links_inline_style.html",
    "content": "<p>Just a <a href=\"/url/\">URL</a>.</p>\n\n<p><a href=\"/url/\" title=\"title\">URL and title</a>.</p>\n\n<p><a href=\"/url/\" title=\"title preceded by two spaces\">URL and title</a>.</p>\n\n<p><a href=\"/url/\" title=\"title preceded by a tab\">URL and title</a>.</p>\n\n<p><a href=\"/url/\" title=\"title has spaces afterward\">URL and title</a>.</p>\n\n<p><a href=\"/url/has space\">URL and title</a>.</p>\n\n<p><a href=\"/url/has space/\" title=\"url has space and title\">URL and title</a>.</p>\n\n<p><a href=\"\">Empty</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/links_inline_style.text",
    "content": "Just a [URL](/url/).\n\n[URL and title](/url/ \"title\").\n\n[URL and title](/url/  \"title preceded by two spaces\").\n\n[URL and title](/url/\t\"title preceded by a tab\").\n\n[URL and title](/url/ \"title has spaces afterward\"  ).\n\n[URL and title]( /url/has space ).\n\n[URL and title]( /url/has space/ \"url has space and title\").\n\n[Empty]().\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/links_reference_style.html",
    "content": "<p>Foo <a href=\"/url/\" title=\"Title\">bar</a>.</p>\n\n<p>Foo <a href=\"/url/\" title=\"Title\">bar</a>.</p>\n\n<p>Foo <a href=\"/url/\" title=\"Title\">bar</a>.</p>\n\n<p>With <a href=\"/url/\">embedded [brackets]</a>.</p>\n\n<p>Indented <a href=\"/url\">once</a>.</p>\n\n<p>Indented <a href=\"/url\">twice</a>.</p>\n\n<p>Indented <a href=\"/url\">thrice</a>.</p>\n\n<p>Indented [four][] times.</p>\n\n<pre><code>[four]: /url\n</code></pre>\n\n<hr>\n\n<p><a href=\"foo\">this</a> should work</p>\n\n<p>So should <a href=\"foo\">this</a>.</p>\n\n<p>And <a href=\"foo\">this</a>.</p>\n\n<p>And <a href=\"foo\">this</a>.</p>\n\n<p>And <a href=\"foo\">this</a>.</p>\n\n<p>But not [that] [].</p>\n\n<p>Nor [that][].</p>\n\n<p>Nor [that].</p>\n\n<p>[Something in brackets like <a href=\"foo\">this</a> should work]</p>\n\n<p>[Same with <a href=\"foo\">this</a>.]</p>\n\n<p>In this case, <a href=\"/somethingelse/\">this</a> points to something else.</p>\n\n<p>Backslashing should suppress [this] and [this].</p>\n\n<hr>\n\n<p>Here&#39;s one where the <a href=\"/url/\">link\nbreaks</a> across lines.</p>\n\n<p>Here&#39;s another where the <a href=\"/url/\">link \nbreaks</a> across lines, but with a line-ending space.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/links_reference_style.text",
    "content": "Foo [bar] [1].\n\nFoo [bar][1].\n\nFoo [bar]\n[1].\n\n[1]: /url/  \"Title\"\n\n\nWith [embedded [brackets]] [b].\n\n\nIndented [once][].\n\nIndented [twice][].\n\nIndented [thrice][].\n\nIndented [four][] times.\n\n [once]: /url\n\n  [twice]: /url\n\n   [thrice]: /url\n\n    [four]: /url\n\n\n[b]: /url/\n\n* * *\n\n[this] [this] should work\n\nSo should [this][this].\n\nAnd [this] [].\n\nAnd [this][].\n\nAnd [this].\n\nBut not [that] [].\n\nNor [that][].\n\nNor [that].\n\n[Something in brackets like [this][] should work]\n\n[Same with [this].]\n\nIn this case, [this](/somethingelse/) points to something else.\n\nBackslashing should suppress \\[this] and [this\\].\n\n[this]: foo\n\n\n* * *\n\nHere's one where the [link\nbreaks] across lines.\n\nHere's another where the [link \nbreaks] across lines, but with a line-ending space.\n\n\n[link breaks]: /url/\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/links_shortcut_references.html",
    "content": "<p>This is the <a href=\"/simple\">simple case</a>.</p>\n\n<p>This one has a <a href=\"/foo\">line\nbreak</a>.</p>\n\n<p>This one has a <a href=\"/foo\">line \nbreak</a> with a line-ending space.</p>\n\n<p><a href=\"/that\">this</a> and the <a href=\"/other\">other</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/links_shortcut_references.text",
    "content": "This is the [simple case].\n\n[simple case]: /simple\n\n\n\nThis one has a [line\nbreak].\n\nThis one has a [line \nbreak] with a line-ending space.\n\n[line break]: /foo\n\n\n[this] [that] and the [other]\n\n[this]: /this\n[that]: /that\n[other]: /other\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/list_item_text.html",
    "content": "<ul><li><p>item1</p>  <ul><li>item2 </li></ul> <p>text</p> </li></ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/list_item_text.text",
    "content": "  * item1\n\n    * item2\n\n  text\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/literal_quotes_in_titles.html",
    "content": "<p>Foo <a href=\"/url/\" title=\"Title with &quot;quotes&quot; inside\">bar</a>.</p>\n\n<p>Foo <a href=\"/url/\" title=\"Title with &quot;quotes&quot; inside\">bar</a>.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/literal_quotes_in_titles.text",
    "content": "Foo [bar][].\n\nFoo [bar](/url/ \"Title with \"quotes\" inside\").\n\n\n  [bar]: /url/ \"Title with \"quotes\" inside\"\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/loose_lists.html",
    "content": "<ul>\n<li><p>hello\nworld </p>\n\n<p>how\nare</p></li>\n<li>you </li>\n</ul>\n\n\n\n<p>better behavior:</p>\n\n<ul><li><p>hello</p> <ul><li><p>world\nhow</p>  <p>are\nyou</p></li><li><p>today</p></li></ul></li><li>hi</li></ul>\n\n\n\n<ul>\n<li><p>hello</p></li>\n<li><p>world</p></li>\n<li>hi</li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li><p>world</p></li>\n<li><p>hi</p></li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li><p>world</p>\n\n<p>how</p></li>\n<li>hi</li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li>world</li>\n<li><p>how</p>\n\n<p>are</p></li>\n</ul>\n\n\n\n<ul>\n<li>hello</li>\n<li><p>world</p></li>\n<li><p>how</p>\n\n<p>are</p></li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/loose_lists.text",
    "content": "* hello\n  world\n\n  how\n  are\n* you\n\n\n\nbetter behavior:\n\n* hello\n  * world\n    how\n\n    are\n    you\n\n  * today\n* hi\n\n\n\n* hello\n\n* world\n* hi\n\n\n\n* hello\n* world\n\n* hi\n\n\n\n* hello\n* world\n\n  how\n* hi\n\n\n\n* hello\n* world\n* how\n\n  are\n\n\n\n* hello\n* world\n\n* how\n\n  are\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/main.html",
    "content": "<h1 id=\"a-heading\">A heading</h1> <p>Just a note, I&#39;ve found that I can&#39;t test my markdown parser vs others. For example, both markdown.js and showdown code blocks in lists wrong. They&#39;re  also completely <a href=\"http://google.com/\" title=\"Google\">inconsistent</a> with regards to paragraphs in list items.</p> <p>A link. Not anymore.</p> <aside>This will make me fail the test because\nmarkdown.js doesnt acknowledge arbitrary html blocks =/</aside> <ul><li><p>List Item 1</p></li><li><p>List Item 2 </p><ul><li>New List Item 1 Hi, this is a list item.</li><li>New List Item 2 Another item <pre><code>Code goes here.\nLots of it...</code></pre></li><li>New List Item 3 The last item</li></ul></li><li><p>List Item 3 The final item.</p></li><li><p>List Item 4 The real final item.</p></li></ul> <p>Paragraph.</p> <blockquote><ul><li>bq Item 1</li><li>bq Item 2 <ul><li>New bq Item 1</li><li>New bq Item 2 Text here</li></ul></li></ul></blockquote> <hr> <blockquote><p> Another blockquote!  I really need to get  more creative with  mockup text..  markdown.js breaks here again</p></blockquote> <h2 id=\"another-heading\">Another Heading</h2> <p>Hello <em>world</em>. Here is a <a href=\"//hello\">link</a>. And an image <img src=\"src\" alt=\"alt\">.</p> <pre><code>Code goes here.\nLots of it...</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/main.text",
    "content": "[test]: http://google.com/ \"Google\"\n\n# A heading\n\nJust a note, I've found that I can't test my markdown parser vs others.\nFor example, both markdown.js and showdown code blocks in lists wrong. They're\nalso completely [inconsistent][test] with regards to paragraphs in list items.\n\nA link. Not anymore.\n\n<aside>This will make me fail the test because\nmarkdown.js doesnt acknowledge arbitrary html blocks =/</aside>\n\n* List Item 1\n\n* List Item 2\n  * New List Item 1\n    Hi, this is a list item.\n  * New List Item 2\n    Another item\n        Code goes here.\n        Lots of it...\n  * New List Item 3\n    The last item\n\n* List Item 3\nThe final item.\n\n* List Item 4\nThe real final item.\n\nParagraph.\n\n> * bq Item 1\n> * bq Item 2\n>   * New bq Item 1\n>   * New bq Item 2\n>   Text here\n\n* * *\n\n> Another blockquote!\n> I really need to get\n> more creative with\n> mockup text..\n> markdown.js breaks here again\n\nAnother Heading\n-------------\n\nHello *world*. Here is a [link](//hello).\nAnd an image ![alt](src).\n\n    Code goes here.\n    Lots of it...\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/markdown_documentation_basics.html",
    "content": "<h1 id=\"markdown-basics\">Markdown: Basics</h1>\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a class=\"selected\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n<h2 id=\"getting-the-gist-of-markdown-s-formatting-syntax\">Getting the Gist of Markdown&#39;s Formatting Syntax</h2>\n\n<p>This page offers a brief overview of what it&#39;s like to use Markdown.\nThe <a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax\">syntax page</a> provides complete, detailed documentation for\nevery feature, but Markdown should be very easy to pick up simply by\nlooking at a few examples of it in action. The examples on this page\nare written in a before/after style, showing example syntax and the\nHTML output produced by Markdown.</p>\n\n<p>It&#39;s also helpful to simply try Markdown out; the <a href=\"/projects/markdown/dingus\" title=\"Markdown Dingus\">Dingus</a> is a\nweb application that allows you type your own Markdown-formatted text\nand translate it to XHTML.</p>\n\n<p><strong>Note:</strong> This document is itself written using Markdown; you\ncan <a href=\"/projects/markdown/basics.text\">see the source for it by adding &#39;.text&#39; to the URL</a>.</p>\n\n<h2 id=\"paragraphs-headers-blockquotes\">Paragraphs, Headers, Blockquotes</h2>\n\n<p>A paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.</p>\n\n<p>Markdown offers two styles of headers: <em>Setext</em> and <em>atx</em>.\nSetext-style headers for <code>&lt;h1&gt;</code> and <code>&lt;h2&gt;</code> are created by\n&quot;underlining&quot; with equal signs (<code>=</code>) and hyphens (<code>-</code>), respectively.\nTo create an atx-style header, you put 1-6 hash marks (<code>#</code>) at the\nbeginning of the line -- the number of hashes equals the resulting\nHTML header level.</p>\n\n<p>Blockquotes are indicated using email-style &#39;<code>&gt;</code>&#39; angle brackets.</p>\n\n<p>Markdown:</p>\n\n<pre><code>A First Level Header\n====================\n\nA Second Level Header\n---------------------\n\nNow is the time for all good men to come to\nthe aid of their country. This is just a\nregular paragraph.\n\nThe quick brown fox jumped over the lazy\ndog&#39;s back.\n\n### Header 3\n\n&gt; This is a blockquote.\n&gt; \n&gt; This is the second paragraph in the blockquote.\n&gt;\n&gt; ## This is an H2 in a blockquote\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;h1&gt;A First Level Header&lt;/h1&gt;\n\n&lt;h2&gt;A Second Level Header&lt;/h2&gt;\n\n&lt;p&gt;Now is the time for all good men to come to\nthe aid of their country. This is just a\nregular paragraph.&lt;/p&gt;\n\n&lt;p&gt;The quick brown fox jumped over the lazy\ndog&#39;s back.&lt;/p&gt;\n\n&lt;h3&gt;Header 3&lt;/h3&gt;\n\n&lt;blockquote&gt;\n    &lt;p&gt;This is a blockquote.&lt;/p&gt;\n\n    &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;\n\n    &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;\n&lt;/blockquote&gt;\n</code></pre>\n\n<h3 id=\"phrase-emphasis\">Phrase Emphasis</h3>\n\n<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p>\n\n<p>Markdown:</p>\n\n<pre><code>Some of these words *are emphasized*.\nSome of these words _are emphasized also_.\n\nUse two asterisks for **strong emphasis**.\nOr, if you prefer, __use two underscores instead__.\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.\nSome of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;\n\n&lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.\nOr, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;\n</code></pre>\n\n<h2 id=\"lists\">Lists</h2>\n\n<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>,\n<code>+</code>, and <code>-</code>) as list markers. These three markers are\ninterchangable; this:</p>\n\n<pre><code>*   Candy.\n*   Gum.\n*   Booze.\n</code></pre>\n\n<p>this:</p>\n\n<pre><code>+   Candy.\n+   Gum.\n+   Booze.\n</code></pre>\n\n<p>and this:</p>\n\n<pre><code>-   Candy.\n-   Gum.\n-   Booze.\n</code></pre>\n\n<p>all produce the same output:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;Candy.&lt;/li&gt;\n&lt;li&gt;Gum.&lt;/li&gt;\n&lt;li&gt;Booze.&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<p>Ordered (numbered) lists use regular numbers, followed by periods, as\nlist markers:</p>\n\n<pre><code>1.  Red\n2.  Green\n3.  Blue\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;ol&gt;\n&lt;li&gt;Red&lt;/li&gt;\n&lt;li&gt;Green&lt;/li&gt;\n&lt;li&gt;Blue&lt;/li&gt;\n&lt;/ol&gt;\n</code></pre>\n\n<p>If you put blank lines between items, you&#39;ll get <code>&lt;p&gt;</code> tags for the\nlist item text. You can create multi-paragraph list items by indenting\nthe paragraphs by 4 spaces or 1 tab:</p>\n\n<pre><code>*   A list item.\n\n    With multiple paragraphs.\n\n*   Another item in the list.\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;\n&lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;\n&lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<h3 id=\"links\">Links</h3>\n\n<p>Markdown supports two styles for creating links: <em>inline</em> and\n<em>reference</em>. With both styles, you use square brackets to delimit the\ntext you want to turn into a link.</p>\n\n<p>Inline-style links use parentheses immediately after the link text.\nFor example:</p>\n\n<pre><code>This is an [example link](http://example.com/).\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;This is an &lt;a href=&quot;http://example.com/&quot;&gt;\nexample link&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>Optionally, you may include a title attribute in the parentheses:</p>\n\n<pre><code>This is an [example link](http://example.com/ &quot;With a Title&quot;).\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;This is an &lt;a href=&quot;http://example.com/&quot; title=&quot;With a Title&quot;&gt;\nexample link&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>Reference-style links allow you to refer to your links by names, which\nyou define elsewhere in your document:</p>\n\n<pre><code>I get 10 times more traffic from [Google][1] than from\n[Yahoo][2] or [MSN][3].\n\n[1]: http://google.com/        &quot;Google&quot;\n[2]: http://search.yahoo.com/  &quot;Yahoo Search&quot;\n[3]: http://search.msn.com/    &quot;MSN Search&quot;\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href=&quot;http://google.com/&quot;\ntitle=&quot;Google&quot;&gt;Google&lt;/a&gt; than from &lt;a href=&quot;http://search.yahoo.com/&quot;\ntitle=&quot;Yahoo Search&quot;&gt;Yahoo&lt;/a&gt; or &lt;a href=&quot;http://search.msn.com/&quot;\ntitle=&quot;MSN Search&quot;&gt;MSN&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>The title attribute is optional. Link names may contain letters,\nnumbers and spaces, but are <em>not</em> case sensitive:</p>\n\n<pre><code>I start my morning with a cup of coffee and\n[The New York Times][NY Times].\n\n[ny times]: http://www.nytimes.com/\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;I start my morning with a cup of coffee and\n&lt;a href=&quot;http://www.nytimes.com/&quot;&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<h3 id=\"images\">Images</h3>\n\n<p>Image syntax is very much like link syntax.</p>\n\n<p>Inline (titles are optional):</p>\n\n<pre><code>![alt text](/path/to/img.jpg &quot;Title&quot;)\n</code></pre>\n\n<p>Reference-style:</p>\n\n<pre><code>![alt text][id]\n\n[id]: /path/to/img.jpg &quot;Title&quot;\n</code></pre>\n\n<p>Both of the above examples produce the same output:</p>\n\n<pre><code>&lt;img src=&quot;/path/to/img.jpg&quot; alt=&quot;alt text&quot; title=&quot;Title&quot; /&gt;\n</code></pre>\n\n<h3 id=\"code\">Code</h3>\n\n<p>In a regular paragraph, you can create code span by wrapping text in\nbacktick quotes. Any ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> or\n<code>&gt;</code>) will automatically be translated into HTML entities. This makes\nit easy to use Markdown to write about HTML example code:</p>\n\n<pre><code>I strongly recommend against using any `&lt;blink&gt;` tags.\n\nI wish SmartyPants used named entities like `&amp;mdash;`\ninstead of decimal-encoded entites like `&amp;#8212;`.\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;I strongly recommend against using any\n&lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;\n\n&lt;p&gt;I wish SmartyPants used named entities like\n&lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded\nentites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>To specify an entire block of pre-formatted code, indent every line of\nthe block by 4 spaces or 1 tab. Just like with code spans, <code>&amp;</code>, <code>&lt;</code>,\nand <code>&gt;</code> characters will be escaped automatically.</p>\n\n<p>Markdown:</p>\n\n<pre><code>If you want your page to validate under XHTML 1.0 Strict,\nyou&#39;ve got to put paragraph tags in your blockquotes:\n\n    &lt;blockquote&gt;\n        &lt;p&gt;For example.&lt;/p&gt;\n    &lt;/blockquote&gt;\n</code></pre>\n\n<p>Output:</p>\n\n<pre><code>&lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,\nyou&#39;ve got to put paragraph tags in your blockquotes:&lt;/p&gt;\n\n&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;\n    &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;\n&amp;lt;/blockquote&amp;gt;\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/markdown_documentation_basics.text",
    "content": "Markdown: Basics\n================\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a class=\"selected\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n\nGetting the Gist of Markdown's Formatting Syntax\n------------------------------------------------\n\nThis page offers a brief overview of what it's like to use Markdown.\nThe [syntax page] [s] provides complete, detailed documentation for\nevery feature, but Markdown should be very easy to pick up simply by\nlooking at a few examples of it in action. The examples on this page\nare written in a before/after style, showing example syntax and the\nHTML output produced by Markdown.\n\nIt's also helpful to simply try Markdown out; the [Dingus] [d] is a\nweb application that allows you type your own Markdown-formatted text\nand translate it to XHTML.\n\n**Note:** This document is itself written using Markdown; you\ncan [see the source for it by adding '.text' to the URL] [src].\n\n  [s]: /projects/markdown/syntax  \"Markdown Syntax\"\n  [d]: /projects/markdown/dingus  \"Markdown Dingus\"\n  [src]: /projects/markdown/basics.text\n\n\n## Paragraphs, Headers, Blockquotes ##\n\nA paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.\n\nMarkdown offers two styles of headers: *Setext* and *atx*.\nSetext-style headers for `<h1>` and `<h2>` are created by\n\"underlining\" with equal signs (`=`) and hyphens (`-`), respectively.\nTo create an atx-style header, you put 1-6 hash marks (`#`) at the\nbeginning of the line -- the number of hashes equals the resulting\nHTML header level.\n\nBlockquotes are indicated using email-style '`>`' angle brackets.\n\nMarkdown:\n\n    A First Level Header\n    ====================\n    \n    A Second Level Header\n    ---------------------\n\n    Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.\n\n    The quick brown fox jumped over the lazy\n    dog's back.\n    \n    ### Header 3\n\n    > This is a blockquote.\n    > \n    > This is the second paragraph in the blockquote.\n    >\n    > ## This is an H2 in a blockquote\n\n\nOutput:\n\n    <h1>A First Level Header</h1>\n    \n    <h2>A Second Level Header</h2>\n    \n    <p>Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.</p>\n    \n    <p>The quick brown fox jumped over the lazy\n    dog's back.</p>\n    \n    <h3>Header 3</h3>\n    \n    <blockquote>\n        <p>This is a blockquote.</p>\n        \n        <p>This is the second paragraph in the blockquote.</p>\n        \n        <h2>This is an H2 in a blockquote</h2>\n    </blockquote>\n\n\n\n### Phrase Emphasis ###\n\nMarkdown uses asterisks and underscores to indicate spans of emphasis.\n\nMarkdown:\n\n    Some of these words *are emphasized*.\n    Some of these words _are emphasized also_.\n    \n    Use two asterisks for **strong emphasis**.\n    Or, if you prefer, __use two underscores instead__.\n\nOutput:\n\n    <p>Some of these words <em>are emphasized</em>.\n    Some of these words <em>are emphasized also</em>.</p>\n    \n    <p>Use two asterisks for <strong>strong emphasis</strong>.\n    Or, if you prefer, <strong>use two underscores instead</strong>.</p>\n   \n\n\n## Lists ##\n\nUnordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,\n`+`, and `-`) as list markers. These three markers are\ninterchangable; this:\n\n    *   Candy.\n    *   Gum.\n    *   Booze.\n\nthis:\n\n    +   Candy.\n    +   Gum.\n    +   Booze.\n\nand this:\n\n    -   Candy.\n    -   Gum.\n    -   Booze.\n\nall produce the same output:\n\n    <ul>\n    <li>Candy.</li>\n    <li>Gum.</li>\n    <li>Booze.</li>\n    </ul>\n\nOrdered (numbered) lists use regular numbers, followed by periods, as\nlist markers:\n\n    1.  Red\n    2.  Green\n    3.  Blue\n\nOutput:\n\n    <ol>\n    <li>Red</li>\n    <li>Green</li>\n    <li>Blue</li>\n    </ol>\n\nIf you put blank lines between items, you'll get `<p>` tags for the\nlist item text. You can create multi-paragraph list items by indenting\nthe paragraphs by 4 spaces or 1 tab:\n\n    *   A list item.\n    \n        With multiple paragraphs.\n\n    *   Another item in the list.\n\nOutput:\n\n    <ul>\n    <li><p>A list item.</p>\n    <p>With multiple paragraphs.</p></li>\n    <li><p>Another item in the list.</p></li>\n    </ul>\n    \n\n\n### Links ###\n\nMarkdown supports two styles for creating links: *inline* and\n*reference*. With both styles, you use square brackets to delimit the\ntext you want to turn into a link.\n\nInline-style links use parentheses immediately after the link text.\nFor example:\n\n    This is an [example link](http://example.com/).\n\nOutput:\n\n    <p>This is an <a href=\"http://example.com/\">\n    example link</a>.</p>\n\nOptionally, you may include a title attribute in the parentheses:\n\n    This is an [example link](http://example.com/ \"With a Title\").\n\nOutput:\n\n    <p>This is an <a href=\"http://example.com/\" title=\"With a Title\">\n    example link</a>.</p>\n\nReference-style links allow you to refer to your links by names, which\nyou define elsewhere in your document:\n\n    I get 10 times more traffic from [Google][1] than from\n    [Yahoo][2] or [MSN][3].\n\n    [1]: http://google.com/        \"Google\"\n    [2]: http://search.yahoo.com/  \"Yahoo Search\"\n    [3]: http://search.msn.com/    \"MSN Search\"\n\nOutput:\n\n    <p>I get 10 times more traffic from <a href=\"http://google.com/\"\n    title=\"Google\">Google</a> than from <a href=\"http://search.yahoo.com/\"\n    title=\"Yahoo Search\">Yahoo</a> or <a href=\"http://search.msn.com/\"\n    title=\"MSN Search\">MSN</a>.</p>\n\nThe title attribute is optional. Link names may contain letters,\nnumbers and spaces, but are *not* case sensitive:\n\n    I start my morning with a cup of coffee and\n    [The New York Times][NY Times].\n\n    [ny times]: http://www.nytimes.com/\n\nOutput:\n\n    <p>I start my morning with a cup of coffee and\n    <a href=\"http://www.nytimes.com/\">The New York Times</a>.</p>\n\n\n### Images ###\n\nImage syntax is very much like link syntax.\n\nInline (titles are optional):\n\n    ![alt text](/path/to/img.jpg \"Title\")\n\nReference-style:\n\n    ![alt text][id]\n\n    [id]: /path/to/img.jpg \"Title\"\n\nBoth of the above examples produce the same output:\n\n    <img src=\"/path/to/img.jpg\" alt=\"alt text\" title=\"Title\" />\n\n\n\n### Code ###\n\nIn a regular paragraph, you can create code span by wrapping text in\nbacktick quotes. Any ampersands (`&`) and angle brackets (`<` or\n`>`) will automatically be translated into HTML entities. This makes\nit easy to use Markdown to write about HTML example code:\n\n    I strongly recommend against using any `<blink>` tags.\n\n    I wish SmartyPants used named entities like `&mdash;`\n    instead of decimal-encoded entites like `&#8212;`.\n\nOutput:\n\n    <p>I strongly recommend against using any\n    <code>&lt;blink&gt;</code> tags.</p>\n    \n    <p>I wish SmartyPants used named entities like\n    <code>&amp;mdash;</code> instead of decimal-encoded\n    entites like <code>&amp;#8212;</code>.</p>\n\n\nTo specify an entire block of pre-formatted code, indent every line of\nthe block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`,\nand `>` characters will be escaped automatically.\n\nMarkdown:\n\n    If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:\n\n        <blockquote>\n            <p>For example.</p>\n        </blockquote>\n\nOutput:\n\n    <p>If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:</p>\n    \n    <pre><code>&lt;blockquote&gt;\n        &lt;p&gt;For example.&lt;/p&gt;\n    &lt;/blockquote&gt;\n    </code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/markdown_documentation_syntax.html",
    "content": "<h1 id=\"markdown-syntax\">Markdown: Syntax</h1>\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a href=\"/projects/markdown/basics\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a class=\"selected\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n<ul>\n<li><a href=\"#overview\">Overview</a>\n<ul>\n<li><a href=\"#philosophy\">Philosophy</a></li>\n<li><a href=\"#html\">Inline HTML</a></li>\n<li><a href=\"#autoescape\">Automatic Escaping for Special Characters</a></li>\n</ul></li>\n<li><a href=\"#block\">Block Elements</a>\n<ul>\n<li><a href=\"#p\">Paragraphs and Line Breaks</a></li>\n<li><a href=\"#header\">Headers</a></li>\n<li><a href=\"#blockquote\">Blockquotes</a></li>\n<li><a href=\"#list\">Lists</a></li>\n<li><a href=\"#precode\">Code Blocks</a></li>\n<li><a href=\"#hr\">Horizontal Rules</a></li>\n</ul></li>\n<li><a href=\"#span\">Span Elements</a>\n<ul>\n<li><a href=\"#link\">Links</a></li>\n<li><a href=\"#em\">Emphasis</a></li>\n<li><a href=\"#code\">Code</a></li>\n<li><a href=\"#img\">Images</a></li>\n</ul></li>\n<li><a href=\"#misc\">Miscellaneous</a>\n<ul>\n<li><a href=\"#backslash\">Backslash Escapes</a></li>\n<li><a href=\"#autolink\">Automatic Links</a></li>\n</ul></li>\n</ul>\n\n<p><strong>Note:</strong> This document is itself written using Markdown; you\ncan <a href=\"/projects/markdown/syntax.text\">see the source for it by adding &#39;.text&#39; to the URL</a>.</p>\n\n<hr>\n\n<h2 id=\"overview\">Overview</h2>\n\n<h3 id=\"philosophy\">Philosophy</h3>\n\n<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>\n\n<p>Readability, however, is emphasized above all else. A Markdown-formatted\ndocument should be publishable as-is, as plain text, without looking\nlike it&#39;s been marked up with tags or formatting instructions. While\nMarkdown&#39;s syntax has been influenced by several existing text-to-HTML\nfilters -- including <a href=\"http://docutils.sourceforge.net/mirror/setext.html\">Setext</a>, <a href=\"http://www.aaronsw.com/2002/atx/\">atx</a>, <a href=\"http://textism.com/tools/textile/\">Textile</a>, <a href=\"http://docutils.sourceforge.net/rst.html\">reStructuredText</a>,\n<a href=\"http://www.triptico.com/software/grutatxt.html\">Grutatext</a>, and <a href=\"http://ettext.taint.org/doc/\">EtText</a> -- the single biggest source of\ninspiration for Markdown&#39;s syntax is the format of plain text email.</p>\n\n<p>To this end, Markdown&#39;s syntax is comprised entirely of punctuation\ncharacters, which punctuation characters have been carefully chosen so\nas to look like what they mean. E.g., asterisks around a word actually\nlook like *emphasis*. Markdown lists look like, well, lists. Even\nblockquotes look like quoted passages of text, assuming you&#39;ve ever\nused email.</p>\n\n<h3 id=\"html\">Inline HTML</h3>\n\n<p>Markdown&#39;s syntax is intended for one purpose: to be used as a\nformat for <em>writing</em> for the web.</p>\n\n<p>Markdown is not a replacement for HTML, or even close to it. Its\nsyntax is very small, corresponding only to a very small subset of\nHTML tags. The idea is <em>not</em> to create a syntax that makes it easier\nto insert HTML tags. In my opinion, HTML tags are already easy to\ninsert. The idea for Markdown is to make it easy to read, write, and\nedit prose. HTML is a <em>publishing</em> format; Markdown is a <em>writing</em>\nformat. Thus, Markdown&#39;s formatting syntax only addresses issues that\ncan be conveyed in plain text.</p>\n\n<p>For any markup that is not covered by Markdown&#39;s syntax, you simply\nuse HTML itself. There&#39;s no need to preface it or delimit it to\nindicate that you&#39;re switching from Markdown to HTML; you just use\nthe tags.</p>\n\n<p>The only restrictions are that block-level HTML elements -- e.g. <code>&lt;div&gt;</code>,\n<code>&lt;table&gt;</code>, <code>&lt;pre&gt;</code>, <code>&lt;p&gt;</code>, etc. -- must be separated from surrounding\ncontent by blank lines, and the start and end tags of the block should\nnot be indented with tabs or spaces. Markdown is smart enough not\nto add extra (unwanted) <code>&lt;p&gt;</code> tags around HTML block-level tags.</p>\n\n<p>For example, to add an HTML table to a Markdown article:</p>\n\n<pre><code>This is a regular paragraph.\n\n&lt;table&gt;\n    &lt;tr&gt;\n        &lt;td&gt;Foo&lt;/td&gt;\n    &lt;/tr&gt;\n&lt;/table&gt;\n\nThis is another regular paragraph.\n</code></pre>\n\n<p>Note that Markdown formatting syntax is not processed within block-level\nHTML tags. E.g., you can&#39;t use Markdown-style <code>*emphasis*</code> inside an\nHTML block.</p>\n\n<p>Span-level HTML tags -- e.g. <code>&lt;span&gt;</code>, <code>&lt;cite&gt;</code>, or <code>&lt;del&gt;</code> -- can be\nused anywhere in a Markdown paragraph, list item, or header. If you\nwant, you can even use HTML tags instead of Markdown formatting; e.g. if\nyou&#39;d prefer to use HTML <code>&lt;a&gt;</code> or <code>&lt;img&gt;</code> tags instead of Markdown&#39;s\nlink or image syntax, go right ahead.</p>\n\n<p>Unlike block-level HTML tags, Markdown syntax <em>is</em> processed within\nspan-level tags.</p>\n\n<h3 id=\"autoescape\">Automatic Escaping for Special Characters</h3>\n\n<p>In HTML, there are two characters that demand special treatment: <code>&lt;</code>\nand <code>&amp;</code>. Left angle brackets are used to start tags; ampersands are\nused to denote HTML entities. If you want to use them as literal\ncharacters, you must escape them as entities, e.g. <code>&amp;lt;</code>, and\n<code>&amp;amp;</code>.</p>\n\n<p>Ampersands in particular are bedeviling for web writers. If you want to\nwrite about &#39;AT&amp;T&#39;, you need to write &#39;<code>AT&amp;amp;T</code>&#39;. You even need to\nescape ampersands within URLs. Thus, if you want to link to:</p>\n\n<pre><code>http://images.google.com/images?num=30&amp;q=larry+bird\n</code></pre>\n\n<p>you need to encode the URL as:</p>\n\n<pre><code>http://images.google.com/images?num=30&amp;amp;q=larry+bird\n</code></pre>\n\n<p>in your anchor tag <code>href</code> attribute. Needless to say, this is easy to\nforget, and is probably the single most common source of HTML validation\nerrors in otherwise well-marked-up web sites.</p>\n\n<p>Markdown allows you to use these characters naturally, taking care of\nall the necessary escaping for you. If you use an ampersand as part of\nan HTML entity, it remains unchanged; otherwise it will be translated\ninto <code>&amp;amp;</code>.</p>\n\n<p>So, if you want to include a copyright symbol in your article, you can write:</p>\n\n<pre><code>&amp;copy;\n</code></pre>\n\n<p>and Markdown will leave it alone. But if you write:</p>\n\n<pre><code>AT&amp;T\n</code></pre>\n\n<p>Markdown will translate it to:</p>\n\n<pre><code>AT&amp;amp;T\n</code></pre>\n\n<p>Similarly, because Markdown supports <a href=\"#html\">inline HTML</a>, if you use\nangle brackets as delimiters for HTML tags, Markdown will treat them as\nsuch. But if you write:</p>\n\n<pre><code>4 &lt; 5\n</code></pre>\n\n<p>Markdown will translate it to:</p>\n\n<pre><code>4 &amp;lt; 5\n</code></pre>\n\n<p>However, inside Markdown code spans and blocks, angle brackets and\nampersands are <em>always</em> encoded automatically. This makes it easy to use\nMarkdown to write about HTML code. (As opposed to raw HTML, which is a\nterrible format for writing about HTML syntax, because every single <code>&lt;</code>\nand <code>&amp;</code> in your example code needs to be escaped.)</p>\n\n<hr>\n\n<h2 id=\"block\">Block Elements</h2>\n\n<h3 id=\"p\">Paragraphs and Line Breaks</h3>\n\n<p>A paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing but spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.</p>\n\n<p>The implication of the &quot;one or more consecutive lines of text&quot; rule is\nthat Markdown supports &quot;hard-wrapped&quot; text paragraphs. This differs\nsignificantly from most other text-to-HTML formatters (including Movable\nType&#39;s &quot;Convert Line Breaks&quot; option) which translate every line break\ncharacter in a paragraph into a <code>&lt;br /&gt;</code> tag.</p>\n\n<p>When you <em>do</em> want to insert a <code>&lt;br /&gt;</code> break tag using Markdown, you\nend a line with two or more spaces, then type return.</p>\n\n<p>Yes, this takes a tad more effort to create a <code>&lt;br /&gt;</code>, but a simplistic\n&quot;every line break is a <code>&lt;br /&gt;</code>&quot; rule wouldn&#39;t work for Markdown.\nMarkdown&#39;s email-style <a href=\"#blockquote\">blockquoting</a> and multi-paragraph <a href=\"#list\">list items</a>\nwork best -- and look better -- when you format them with hard breaks.</p>\n\n<h3 id=\"header\">Headers</h3>\n\n<p>Markdown supports two styles of headers, <a href=\"http://docutils.sourceforge.net/mirror/setext.html\">Setext</a> and <a href=\"http://www.aaronsw.com/2002/atx/\">atx</a>.</p>\n\n<p>Setext-style headers are &quot;underlined&quot; using equal signs (for first-level\nheaders) and dashes (for second-level headers). For example:</p>\n\n<pre><code>This is an H1\n=============\n\nThis is an H2\n-------------\n</code></pre>\n\n<p>Any number of underlining <code>=</code>&#39;s or <code>-</code>&#39;s will work.</p>\n\n<p>Atx-style headers use 1-6 hash characters at the start of the line,\ncorresponding to header levels 1-6. For example:</p>\n\n<pre><code># This is an H1\n\n## This is an H2\n\n###### This is an H6\n</code></pre>\n\n<p>Optionally, you may &quot;close&quot; atx-style headers. This is purely\ncosmetic -- you can use this if you think it looks better. The\nclosing hashes don&#39;t even need to match the number of hashes\nused to open the header. (The number of opening hashes\ndetermines the header level.) :</p>\n\n<pre><code># This is an H1 #\n\n## This is an H2 ##\n\n### This is an H3 ######\n</code></pre>\n\n<h3 id=\"blockquote\">Blockquotes</h3>\n\n<p>Markdown uses email-style <code>&gt;</code> characters for blockquoting. If you&#39;re\nfamiliar with quoting passages of text in an email message, then you\nknow how to create a blockquote in Markdown. It looks best if you hard\nwrap the text and put a <code>&gt;</code> before every line:</p>\n\n<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n&gt; consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n&gt; Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n&gt; \n&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n&gt; id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>Markdown allows you to be lazy and only put the <code>&gt;</code> before the first\nline of a hard-wrapped paragraph:</p>\n\n<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\nconsectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\nVestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n\n&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\nid sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by\nadding additional levels of <code>&gt;</code>:</p>\n\n<pre><code>&gt; This is the first level of quoting.\n&gt;\n&gt; &gt; This is nested blockquote.\n&gt;\n&gt; Back to the first level.\n</code></pre>\n\n<p>Blockquotes can contain other Markdown elements, including headers, lists,\nand code blocks:</p>\n\n<pre><code>&gt; ## This is a header.\n&gt; \n&gt; 1.   This is the first list item.\n&gt; 2.   This is the second list item.\n&gt; \n&gt; Here&#39;s some example code:\n&gt; \n&gt;     return shell_exec(&quot;echo $input | $markdown_script&quot;);\n</code></pre>\n\n<p>Any decent text editor should make email-style quoting easy. For\nexample, with BBEdit, you can make a selection and choose Increase\nQuote Level from the Text menu.</p>\n\n<h3 id=\"list\">Lists</h3>\n\n<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p>\n\n<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably\n-- as list markers:</p>\n\n<pre><code>*   Red\n*   Green\n*   Blue\n</code></pre>\n\n<p>is equivalent to:</p>\n\n<pre><code>+   Red\n+   Green\n+   Blue\n</code></pre>\n\n<p>and:</p>\n\n<pre><code>-   Red\n-   Green\n-   Blue\n</code></pre>\n\n<p>Ordered lists use numbers followed by periods:</p>\n\n<pre><code>1.  Bird\n2.  McHale\n3.  Parish\n</code></pre>\n\n<p>It&#39;s important to note that the actual numbers you use to mark the\nlist have no effect on the HTML output Markdown produces. The HTML\nMarkdown produces from the above list is:</p>\n\n<pre><code>&lt;ol&gt;\n&lt;li&gt;Bird&lt;/li&gt;\n&lt;li&gt;McHale&lt;/li&gt;\n&lt;li&gt;Parish&lt;/li&gt;\n&lt;/ol&gt;\n</code></pre>\n\n<p>If you instead wrote the list in Markdown like this:</p>\n\n<pre><code>1.  Bird\n1.  McHale\n1.  Parish\n</code></pre>\n\n<p>or even:</p>\n\n<pre><code>3. Bird\n1. McHale\n8. Parish\n</code></pre>\n\n<p>you&#39;d get the exact same HTML output. The point is, if you want to,\nyou can use ordinal numbers in your ordered Markdown lists, so that\nthe numbers in your source match the numbers in your published HTML.\nBut if you want to be lazy, you don&#39;t have to.</p>\n\n<p>If you do use lazy list numbering, however, you should still start the\nlist with the number 1. At some point in the future, Markdown may support\nstarting ordered lists at an arbitrary number.</p>\n\n<p>List markers typically start at the left margin, but may be indented by\nup to three spaces. List markers must be followed by one or more spaces\nor a tab.</p>\n\n<p>To make lists look nice, you can wrap items with hanging indents:</p>\n\n<pre><code>*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n    viverra nec, fringilla in, laoreet vitae, risus.\n*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n    Suspendisse id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>But if you want to be lazy, you don&#39;t have to:</p>\n\n<pre><code>*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\nAliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\nviverra nec, fringilla in, laoreet vitae, risus.\n*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\nSuspendisse id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>If list items are separated by blank lines, Markdown will wrap the\nitems in <code>&lt;p&gt;</code> tags in the HTML output. For example, this input:</p>\n\n<pre><code>*   Bird\n*   Magic\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;Bird&lt;/li&gt;\n&lt;li&gt;Magic&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<p>But this:</p>\n\n<pre><code>*   Bird\n\n*   Magic\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;ul&gt;\n&lt;li&gt;&lt;p&gt;Bird&lt;/p&gt;&lt;/li&gt;\n&lt;li&gt;&lt;p&gt;Magic&lt;/p&gt;&lt;/li&gt;\n&lt;/ul&gt;\n</code></pre>\n\n<p>List items may consist of multiple paragraphs. Each subsequent\nparagraph in a list item must be intended by either 4 spaces\nor one tab:</p>\n\n<pre><code>1.  This is a list item with two paragraphs. Lorem ipsum dolor\n    sit amet, consectetuer adipiscing elit. Aliquam hendrerit\n    mi posuere lectus.\n\n    Vestibulum enim wisi, viverra nec, fringilla in, laoreet\n    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum\n    sit amet velit.\n\n2.  Suspendisse id sem consectetuer libero luctus adipiscing.\n</code></pre>\n\n<p>It looks nice if you indent every line of the subsequent\nparagraphs, but here again, Markdown will allow you to be\nlazy:</p>\n\n<pre><code>*   This is a list item with two paragraphs.\n\n    This is the second paragraph in the list item. You&#39;re\nonly required to indent the first line. Lorem ipsum dolor\nsit amet, consectetuer adipiscing elit.\n\n*   Another item in the same list.\n</code></pre>\n\n<p>To put a blockquote within a list item, the blockquote&#39;s <code>&gt;</code>\ndelimiters need to be indented:</p>\n\n<pre><code>*   A list item with a blockquote:\n\n    &gt; This is a blockquote\n    &gt; inside a list item.\n</code></pre>\n\n<p>To put a code block within a list item, the code block needs\nto be indented <em>twice</em> -- 8 spaces or two tabs:</p>\n\n<pre><code>*   A list item with a code block:\n\n        &lt;code goes here&gt;\n</code></pre>\n\n<p>It&#39;s worth noting that it&#39;s possible to trigger an ordered list by\naccident, by writing something like this:</p>\n\n<pre><code>1986. What a great season.\n</code></pre>\n\n<p>In other words, a <em>number-period-space</em> sequence at the beginning of a\nline. To avoid this, you can backslash-escape the period:</p>\n\n<pre><code>1986\\. What a great season.\n</code></pre>\n\n<h3 id=\"precode\">Code Blocks</h3>\n\n<p>Pre-formatted code blocks are used for writing about programming or\nmarkup source code. Rather than forming normal paragraphs, the lines\nof a code block are interpreted literally. Markdown wraps a code block\nin both <code>&lt;pre&gt;</code> and <code>&lt;code&gt;</code> tags.</p>\n\n<p>To produce a code block in Markdown, simply indent every line of the\nblock by at least 4 spaces or 1 tab. For example, given this input:</p>\n\n<pre><code>This is a normal paragraph:\n\n    This is a code block.\n</code></pre>\n\n<p>Markdown will generate:</p>\n\n<pre><code>&lt;p&gt;This is a normal paragraph:&lt;/p&gt;\n\n&lt;pre&gt;&lt;code&gt;This is a code block.\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n\n<p>One level of indentation -- 4 spaces or 1 tab -- is removed from each\nline of the code block. For example, this:</p>\n\n<pre><code>Here is an example of AppleScript:\n\n    tell application &quot;Foo&quot;\n        beep\n    end tell\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;p&gt;Here is an example of AppleScript:&lt;/p&gt;\n\n&lt;pre&gt;&lt;code&gt;tell application &quot;Foo&quot;\n    beep\nend tell\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n\n<p>A code block continues until it reaches a line that is not indented\n(or the end of the article).</p>\n\n<p>Within a code block, ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> and <code>&gt;</code>)\nare automatically converted into HTML entities. This makes it very\neasy to include example HTML source code using Markdown -- just paste\nit and indent it, and Markdown will handle the hassle of encoding the\nampersands and angle brackets. For example, this:</p>\n\n<pre><code>    &lt;div class=&quot;footer&quot;&gt;\n        &amp;copy; 2004 Foo Corporation\n    &lt;/div&gt;\n</code></pre>\n\n<p>will turn into:</p>\n\n<pre><code>&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;footer&quot;&amp;gt;\n    &amp;amp;copy; 2004 Foo Corporation\n&amp;lt;/div&amp;gt;\n&lt;/code&gt;&lt;/pre&gt;\n</code></pre>\n\n<p>Regular Markdown syntax is not processed within code blocks. E.g.,\nasterisks are just literal asterisks within a code block. This means\nit&#39;s also easy to use Markdown to write about Markdown&#39;s own syntax.</p>\n\n<h3 id=\"hr\">Horizontal Rules</h3>\n\n<p>You can produce a horizontal rule tag (<code>&lt;hr&gt;</code>) by placing three or\nmore hyphens, asterisks, or underscores on a line by themselves. If you\nwish, you may use spaces between the hyphens or asterisks. Each of the\nfollowing lines will produce a horizontal rule:</p>\n\n<pre><code>* * *\n\n***\n\n*****\n\n- - -\n\n---------------------------------------\n\n_ _ _\n</code></pre>\n\n<hr>\n\n<h2 id=\"span\">Span Elements</h2>\n\n<h3 id=\"link\">Links</h3>\n\n<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p>\n\n<p>In both styles, the link text is delimited by [square brackets].</p>\n\n<p>To create an inline link, use a set of regular parentheses immediately\nafter the link text&#39;s closing square bracket. Inside the parentheses,\nput the URL where you want the link to point, along with an <em>optional</em>\ntitle for the link, surrounded in quotes. For example:</p>\n\n<pre><code>This is [an example](http://example.com/ &quot;Title&quot;) inline link.\n\n[This link](http://example.net/) has no title attribute.\n</code></pre>\n\n<p>Will produce:</p>\n\n<pre><code>&lt;p&gt;This is &lt;a href=&quot;http://example.com/&quot; title=&quot;Title&quot;&gt;\nan example&lt;/a&gt; inline link.&lt;/p&gt;\n\n&lt;p&gt;&lt;a href=&quot;http://example.net/&quot;&gt;This link&lt;/a&gt; has no\ntitle attribute.&lt;/p&gt;\n</code></pre>\n\n<p>If you&#39;re referring to a local resource on the same server, you can\nuse relative paths:</p>\n\n<pre><code>See my [About](/about/) page for details.\n</code></pre>\n\n<p>Reference-style links use a second set of square brackets, inside\nwhich you place a label of your choosing to identify the link:</p>\n\n<pre><code>This is [an example][id] reference-style link.\n</code></pre>\n\n<p>You can optionally use a space to separate the sets of brackets:</p>\n\n<pre><code>This is [an example] [id] reference-style link.\n</code></pre>\n\n<p>Then, anywhere in the document, you define your link label like this,\non a line by itself:</p>\n\n<pre><code>[id]: http://example.com/  &quot;Optional Title Here&quot;\n</code></pre>\n\n<p>That is:</p>\n\n<ul>\n<li>Square brackets containing the link identifier (optionally\nindented from the left margin using up to three spaces);</li>\n<li>followed by a colon;</li>\n<li>followed by one or more spaces (or tabs);</li>\n<li>followed by the URL for the link;</li>\n<li>optionally followed by a title attribute for the link, enclosed\nin double or single quotes.</li>\n</ul>\n\n<p>The link URL may, optionally, be surrounded by angle brackets:</p>\n\n<pre><code>[id]: &lt;http://example.com/&gt;  &quot;Optional Title Here&quot;\n</code></pre>\n\n<p>You can put the title attribute on the next line and use extra spaces\nor tabs for padding, which tends to look better with longer URLs:</p>\n\n<pre><code>[id]: http://example.com/longish/path/to/resource/here\n    &quot;Optional Title Here&quot;\n</code></pre>\n\n<p>Link definitions are only used for creating links during Markdown\nprocessing, and are stripped from your document in the HTML output.</p>\n\n<p>Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are <em>not</em> case sensitive. E.g. these two links:</p>\n\n<pre><code>[link text][a]\n[link text][A]\n</code></pre>\n\n<p>are equivalent.</p>\n\n<p>The <em>implicit link name</em> shortcut allows you to omit the name of the\nlink, in which case the link text itself is used as the name.\nJust use an empty set of square brackets -- e.g., to link the word\n&quot;Google&quot; to the google.com web site, you could simply write:</p>\n\n<pre><code>[Google][]\n</code></pre>\n\n<p>And then define the link:</p>\n\n<pre><code>[Google]: http://google.com/\n</code></pre>\n\n<p>Because link names may contain spaces, this shortcut even works for\nmultiple words in the link text:</p>\n\n<pre><code>Visit [Daring Fireball][] for more information.\n</code></pre>\n\n<p>And then define the link:</p>\n\n<pre><code>[Daring Fireball]: http://daringfireball.net/\n</code></pre>\n\n<p>Link definitions can be placed anywhere in your Markdown document. I\ntend to put them immediately after each paragraph in which they&#39;re\nused, but if you want, you can put them all at the end of your\ndocument, sort of like footnotes.</p>\n\n<p>Here&#39;s an example of reference links in action:</p>\n\n<pre><code>I get 10 times more traffic from [Google] [1] than from\n[Yahoo] [2] or [MSN] [3].\n\n  [1]: http://google.com/        &quot;Google&quot;\n  [2]: http://search.yahoo.com/  &quot;Yahoo Search&quot;\n  [3]: http://search.msn.com/    &quot;MSN Search&quot;\n</code></pre>\n\n<p>Using the implicit link name shortcut, you could instead write:</p>\n\n<pre><code>I get 10 times more traffic from [Google][] than from\n[Yahoo][] or [MSN][].\n\n  [google]: http://google.com/        &quot;Google&quot;\n  [yahoo]:  http://search.yahoo.com/  &quot;Yahoo Search&quot;\n  [msn]:    http://search.msn.com/    &quot;MSN Search&quot;\n</code></pre>\n\n<p>Both of the above examples will produce the following HTML output:</p>\n\n<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href=&quot;http://google.com/&quot;\ntitle=&quot;Google&quot;&gt;Google&lt;/a&gt; than from\n&lt;a href=&quot;http://search.yahoo.com/&quot; title=&quot;Yahoo Search&quot;&gt;Yahoo&lt;/a&gt;\nor &lt;a href=&quot;http://search.msn.com/&quot; title=&quot;MSN Search&quot;&gt;MSN&lt;/a&gt;.&lt;/p&gt;\n</code></pre>\n\n<p>For comparison, here is the same paragraph written using\nMarkdown&#39;s inline link style:</p>\n\n<pre><code>I get 10 times more traffic from [Google](http://google.com/ &quot;Google&quot;)\nthan from [Yahoo](http://search.yahoo.com/ &quot;Yahoo Search&quot;) or\n[MSN](http://search.msn.com/ &quot;MSN Search&quot;).\n</code></pre>\n\n<p>The point of reference-style links is not that they&#39;re easier to\nwrite. The point is that with reference-style links, your document\nsource is vastly more readable. Compare the above examples: using\nreference-style links, the paragraph itself is only 81 characters\nlong; with inline-style links, it&#39;s 176 characters; and as raw HTML,\nit&#39;s 234 characters. In the raw HTML, there&#39;s more markup than there\nis text.</p>\n\n<p>With Markdown&#39;s reference-style links, a source document much more\nclosely resembles the final output, as rendered in a browser. By\nallowing you to move the markup-related metadata out of the paragraph,\nyou can add links without interrupting the narrative flow of your\nprose.</p>\n\n<h3 id=\"em\">Emphasis</h3>\n\n<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of\nemphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an\nHTML <code>&lt;em&gt;</code> tag; double <code>*</code>&#39;s or <code>_</code>&#39;s will be wrapped with an HTML\n<code>&lt;strong&gt;</code> tag. E.g., this input:</p>\n\n<pre><code>*single asterisks*\n\n_single underscores_\n\n**double asterisks**\n\n__double underscores__\n</code></pre>\n\n<p>will produce:</p>\n\n<pre><code>&lt;em&gt;single asterisks&lt;/em&gt;\n\n&lt;em&gt;single underscores&lt;/em&gt;\n\n&lt;strong&gt;double asterisks&lt;/strong&gt;\n\n&lt;strong&gt;double underscores&lt;/strong&gt;\n</code></pre>\n\n<p>You can use whichever style you prefer; the lone restriction is that\nthe same character must be used to open and close an emphasis span.</p>\n\n<p>Emphasis can be used in the middle of a word:</p>\n\n<pre><code>un*fucking*believable\n</code></pre>\n\n<p>But if you surround an <code>*</code> or <code>_</code> with spaces, it&#39;ll be treated as a\nliteral asterisk or underscore.</p>\n\n<p>To produce a literal asterisk or underscore at a position where it\nwould otherwise be used as an emphasis delimiter, you can backslash\nescape it:</p>\n\n<pre><code>\\*this text is surrounded by literal asterisks\\*\n</code></pre>\n\n<h3 id=\"code\">Code</h3>\n\n<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>).\nUnlike a pre-formatted code block, a code span indicates code within a\nnormal paragraph. For example:</p>\n\n<pre><code>Use the `printf()` function.\n</code></pre>\n\n<p>will produce:</p>\n\n<pre><code>&lt;p&gt;Use the &lt;code&gt;printf()&lt;/code&gt; function.&lt;/p&gt;\n</code></pre>\n\n<p>To include a literal backtick character within a code span, you can use\nmultiple backticks as the opening and closing delimiters:</p>\n\n<pre><code>``There is a literal backtick (`) here.``\n</code></pre>\n\n<p>which will produce this:</p>\n\n<pre><code>&lt;p&gt;&lt;code&gt;There is a literal backtick (`) here.&lt;/code&gt;&lt;/p&gt;\n</code></pre>\n\n<p>The backtick delimiters surrounding a code span may include spaces --\none after the opening, one before the closing. This allows you to place\nliteral backtick characters at the beginning or end of a code span:</p>\n\n<pre><code>A single backtick in a code span: `` ` ``\n\nA backtick-delimited string in a code span: `` `foo` ``\n</code></pre>\n\n<p>will produce:</p>\n\n<pre><code>&lt;p&gt;A single backtick in a code span: &lt;code&gt;`&lt;/code&gt;&lt;/p&gt;\n\n&lt;p&gt;A backtick-delimited string in a code span: &lt;code&gt;`foo`&lt;/code&gt;&lt;/p&gt;\n</code></pre>\n\n<p>With a code span, ampersands and angle brackets are encoded as HTML\nentities automatically, which makes it easy to include example HTML\ntags. Markdown will turn this:</p>\n\n<pre><code>Please don&#39;t use any `&lt;blink&gt;` tags.\n</code></pre>\n\n<p>into:</p>\n\n<pre><code>&lt;p&gt;Please don&#39;t use any &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;\n</code></pre>\n\n<p>You can write this:</p>\n\n<pre><code>`&amp;#8212;` is the decimal-encoded equivalent of `&amp;mdash;`.\n</code></pre>\n\n<p>to produce:</p>\n\n<pre><code>&lt;p&gt;&lt;code&gt;&amp;amp;#8212;&lt;/code&gt; is the decimal-encoded\nequivalent of &lt;code&gt;&amp;amp;mdash;&lt;/code&gt;.&lt;/p&gt;\n</code></pre>\n\n<h3 id=\"img\">Images</h3>\n\n<p>Admittedly, it&#39;s fairly difficult to devise a &quot;natural&quot; syntax for\nplacing images into a plain text document format.</p>\n\n<p>Markdown uses an image syntax that is intended to resemble the syntax\nfor links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p>\n\n<p>Inline image syntax looks like this:</p>\n\n<pre><code>![Alt text](/path/to/img.jpg)\n\n![Alt text](/path/to/img.jpg &quot;Optional title&quot;)\n</code></pre>\n\n<p>That is:</p>\n\n<ul>\n<li>An exclamation mark: <code>!</code>;</li>\n<li>followed by a set of square brackets, containing the <code>alt</code>\nattribute text for the image;</li>\n<li>followed by a set of parentheses, containing the URL or path to\nthe image, and an optional <code>title</code> attribute enclosed in double\nor single quotes.</li>\n</ul>\n\n<p>Reference-style image syntax looks like this:</p>\n\n<pre><code>![Alt text][id]\n</code></pre>\n\n<p>Where &quot;id&quot; is the name of a defined image reference. Image references\nare defined using syntax identical to link references:</p>\n\n<pre><code>[id]: url/to/image  &quot;Optional title attribute&quot;\n</code></pre>\n\n<p>As of this writing, Markdown has no syntax for specifying the\ndimensions of an image; if this is important to you, you can simply\nuse regular HTML <code>&lt;img&gt;</code> tags.</p>\n\n<hr>\n\n<h2 id=\"misc\">Miscellaneous</h2>\n\n<h3 id=\"autolink\">Automatic Links</h3>\n\n<p>Markdown supports a shortcut style for creating &quot;automatic&quot; links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:</p>\n\n<pre><code>&lt;http://example.com/&gt;\n</code></pre>\n\n<p>Markdown will turn this into:</p>\n\n<pre><code>&lt;a href=&quot;http://example.com/&quot;&gt;http://example.com/&lt;/a&gt;\n</code></pre>\n\n<p>Automatic links for email addresses work similarly, except that\nMarkdown will also perform a bit of randomized decimal and hex\nentity-encoding to help obscure your address from address-harvesting\nspambots. For example, Markdown will turn this:</p>\n\n<pre><code>&lt;address@example.com&gt;\n</code></pre>\n\n<p>into something like this:</p>\n\n<pre><code>&lt;a href=&quot;&amp;#x6D;&amp;#x61;i&amp;#x6C;&amp;#x74;&amp;#x6F;:&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;\n&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;\n&amp;#109;&quot;&gt;&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;\n&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;&amp;#109;&lt;/a&gt;\n</code></pre>\n\n<p>which will render in a browser as a clickable link to &quot;address@example.com&quot;.</p>\n\n<p>(This sort of entity-encoding trick will indeed fool many, if not\nmost, address-harvesting bots, but it definitely won&#39;t fool all of\nthem. It&#39;s better than nothing, but an address published in this way\nwill probably eventually start receiving spam.)</p>\n\n<h3 id=\"backslash\">Backslash Escapes</h3>\n\n<p>Markdown allows you to use backslash escapes to generate literal\ncharacters which would otherwise have special meaning in Markdown&#39;s\nformatting syntax. For example, if you wanted to surround a word with\nliteral asterisks (instead of an HTML <code>&lt;em&gt;</code> tag), you can backslashes\nbefore the asterisks, like this:</p>\n\n<pre><code>\\*literal asterisks\\*\n</code></pre>\n\n<p>Markdown provides backslash escapes for the following characters:</p>\n\n<pre><code>\\   backslash\n`   backtick\n*   asterisk\n_   underscore\n{}  curly braces\n[]  square brackets\n()  parentheses\n#   hash mark\n+   plus sign\n-   minus sign (hyphen)\n.   dot\n!   exclamation mark\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/markdown_documentation_syntax.text",
    "content": "Markdown: Syntax\n================\n\n<ul id=\"ProjectSubmenu\">\n    <li><a href=\"/projects/markdown/\" title=\"Markdown Project Page\">Main</a></li>\n    <li><a href=\"/projects/markdown/basics\" title=\"Markdown Basics\">Basics</a></li>\n    <li><a class=\"selected\" title=\"Markdown Syntax Documentation\">Syntax</a></li>\n    <li><a href=\"/projects/markdown/license\" title=\"Pricing and License Information\">License</a></li>\n    <li><a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\">Dingus</a></li>\n</ul>\n\n\n*   [Overview](#overview)\n    *   [Philosophy](#philosophy)\n    *   [Inline HTML](#html)\n    *   [Automatic Escaping for Special Characters](#autoescape)\n*   [Block Elements](#block)\n    *   [Paragraphs and Line Breaks](#p)\n    *   [Headers](#header)\n    *   [Blockquotes](#blockquote)\n    *   [Lists](#list)\n    *   [Code Blocks](#precode)\n    *   [Horizontal Rules](#hr)\n*   [Span Elements](#span)\n    *   [Links](#link)\n    *   [Emphasis](#em)\n    *   [Code](#code)\n    *   [Images](#img)\n*   [Miscellaneous](#misc)\n    *   [Backslash Escapes](#backslash)\n    *   [Automatic Links](#autolink)\n\n\n**Note:** This document is itself written using Markdown; you\ncan [see the source for it by adding '.text' to the URL][src].\n\n  [src]: /projects/markdown/syntax.text\n\n* * *\n\n<h2 id=\"overview\">Overview</h2>\n\n<h3 id=\"philosophy\">Philosophy</h3>\n\nMarkdown is intended to be as easy-to-read and easy-to-write as is feasible.\n\nReadability, however, is emphasized above all else. A Markdown-formatted\ndocument should be publishable as-is, as plain text, without looking\nlike it's been marked up with tags or formatting instructions. While\nMarkdown's syntax has been influenced by several existing text-to-HTML\nfilters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4],\n[Grutatext] [5], and [EtText] [6] -- the single biggest source of\ninspiration for Markdown's syntax is the format of plain text email.\n\n  [1]: http://docutils.sourceforge.net/mirror/setext.html\n  [2]: http://www.aaronsw.com/2002/atx/\n  [3]: http://textism.com/tools/textile/\n  [4]: http://docutils.sourceforge.net/rst.html\n  [5]: http://www.triptico.com/software/grutatxt.html\n  [6]: http://ettext.taint.org/doc/\n\nTo this end, Markdown's syntax is comprised entirely of punctuation\ncharacters, which punctuation characters have been carefully chosen so\nas to look like what they mean. E.g., asterisks around a word actually\nlook like \\*emphasis\\*. Markdown lists look like, well, lists. Even\nblockquotes look like quoted passages of text, assuming you've ever\nused email.\n\n\n\n<h3 id=\"html\">Inline HTML</h3>\n\nMarkdown's syntax is intended for one purpose: to be used as a\nformat for *writing* for the web.\n\nMarkdown is not a replacement for HTML, or even close to it. Its\nsyntax is very small, corresponding only to a very small subset of\nHTML tags. The idea is *not* to create a syntax that makes it easier\nto insert HTML tags. In my opinion, HTML tags are already easy to\ninsert. The idea for Markdown is to make it easy to read, write, and\nedit prose. HTML is a *publishing* format; Markdown is a *writing*\nformat. Thus, Markdown's formatting syntax only addresses issues that\ncan be conveyed in plain text.\n\nFor any markup that is not covered by Markdown's syntax, you simply\nuse HTML itself. There's no need to preface it or delimit it to\nindicate that you're switching from Markdown to HTML; you just use\nthe tags.\n\nThe only restrictions are that block-level HTML elements -- e.g. `<div>`,\n`<table>`, `<pre>`, `<p>`, etc. -- must be separated from surrounding\ncontent by blank lines, and the start and end tags of the block should\nnot be indented with tabs or spaces. Markdown is smart enough not\nto add extra (unwanted) `<p>` tags around HTML block-level tags.\n\nFor example, to add an HTML table to a Markdown article:\n\n    This is a regular paragraph.\n\n    <table>\n        <tr>\n            <td>Foo</td>\n        </tr>\n    </table>\n\n    This is another regular paragraph.\n\nNote that Markdown formatting syntax is not processed within block-level\nHTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an\nHTML block.\n\nSpan-level HTML tags -- e.g. `<span>`, `<cite>`, or `<del>` -- can be\nused anywhere in a Markdown paragraph, list item, or header. If you\nwant, you can even use HTML tags instead of Markdown formatting; e.g. if\nyou'd prefer to use HTML `<a>` or `<img>` tags instead of Markdown's\nlink or image syntax, go right ahead.\n\nUnlike block-level HTML tags, Markdown syntax *is* processed within\nspan-level tags.\n\n\n<h3 id=\"autoescape\">Automatic Escaping for Special Characters</h3>\n\nIn HTML, there are two characters that demand special treatment: `<`\nand `&`. Left angle brackets are used to start tags; ampersands are\nused to denote HTML entities. If you want to use them as literal\ncharacters, you must escape them as entities, e.g. `&lt;`, and\n`&amp;`.\n\nAmpersands in particular are bedeviling for web writers. If you want to\nwrite about 'AT&T', you need to write '`AT&amp;T`'. You even need to\nescape ampersands within URLs. Thus, if you want to link to:\n\n    http://images.google.com/images?num=30&q=larry+bird\n\nyou need to encode the URL as:\n\n    http://images.google.com/images?num=30&amp;q=larry+bird\n\nin your anchor tag `href` attribute. Needless to say, this is easy to\nforget, and is probably the single most common source of HTML validation\nerrors in otherwise well-marked-up web sites.\n\nMarkdown allows you to use these characters naturally, taking care of\nall the necessary escaping for you. If you use an ampersand as part of\nan HTML entity, it remains unchanged; otherwise it will be translated\ninto `&amp;`.\n\nSo, if you want to include a copyright symbol in your article, you can write:\n\n    &copy;\n\nand Markdown will leave it alone. But if you write:\n\n    AT&T\n\nMarkdown will translate it to:\n\n    AT&amp;T\n\nSimilarly, because Markdown supports [inline HTML](#html), if you use\nangle brackets as delimiters for HTML tags, Markdown will treat them as\nsuch. But if you write:\n\n    4 < 5\n\nMarkdown will translate it to:\n\n    4 &lt; 5\n\nHowever, inside Markdown code spans and blocks, angle brackets and\nampersands are *always* encoded automatically. This makes it easy to use\nMarkdown to write about HTML code. (As opposed to raw HTML, which is a\nterrible format for writing about HTML syntax, because every single `<`\nand `&` in your example code needs to be escaped.)\n\n\n* * *\n\n\n<h2 id=\"block\">Block Elements</h2>\n\n\n<h3 id=\"p\">Paragraphs and Line Breaks</h3>\n\nA paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like a\nblank line -- a line containing nothing but spaces or tabs is considered\nblank.) Normal paragraphs should not be intended with spaces or tabs.\n\nThe implication of the \"one or more consecutive lines of text\" rule is\nthat Markdown supports \"hard-wrapped\" text paragraphs. This differs\nsignificantly from most other text-to-HTML formatters (including Movable\nType's \"Convert Line Breaks\" option) which translate every line break\ncharacter in a paragraph into a `<br />` tag.\n\nWhen you *do* want to insert a `<br />` break tag using Markdown, you\nend a line with two or more spaces, then type return.\n\nYes, this takes a tad more effort to create a `<br />`, but a simplistic\n\"every line break is a `<br />`\" rule wouldn't work for Markdown.\nMarkdown's email-style [blockquoting][bq] and multi-paragraph [list items][l]\nwork best -- and look better -- when you format them with hard breaks.\n\n  [bq]: #blockquote\n  [l]:  #list\n\n\n\n<h3 id=\"header\">Headers</h3>\n\nMarkdown supports two styles of headers, [Setext] [1] and [atx] [2].\n\nSetext-style headers are \"underlined\" using equal signs (for first-level\nheaders) and dashes (for second-level headers). For example:\n\n    This is an H1\n    =============\n\n    This is an H2\n    -------------\n\nAny number of underlining `=`'s or `-`'s will work.\n\nAtx-style headers use 1-6 hash characters at the start of the line,\ncorresponding to header levels 1-6. For example:\n\n    # This is an H1\n\n    ## This is an H2\n\n    ###### This is an H6\n\nOptionally, you may \"close\" atx-style headers. This is purely\ncosmetic -- you can use this if you think it looks better. The\nclosing hashes don't even need to match the number of hashes\nused to open the header. (The number of opening hashes\ndetermines the header level.) :\n\n    # This is an H1 #\n\n    ## This is an H2 ##\n\n    ### This is an H3 ######\n\n\n<h3 id=\"blockquote\">Blockquotes</h3>\n\nMarkdown uses email-style `>` characters for blockquoting. If you're\nfamiliar with quoting passages of text in an email message, then you\nknow how to create a blockquote in Markdown. It looks best if you hard\nwrap the text and put a `>` before every line:\n\n    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n    > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n    > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n    > \n    > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n    > id sem consectetuer libero luctus adipiscing.\n\nMarkdown allows you to be lazy and only put the `>` before the first\nline of a hard-wrapped paragraph:\n\n    > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n    consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n    Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n\n    > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n    id sem consectetuer libero luctus adipiscing.\n\nBlockquotes can be nested (i.e. a blockquote-in-a-blockquote) by\nadding additional levels of `>`:\n\n    > This is the first level of quoting.\n    >\n    > > This is nested blockquote.\n    >\n    > Back to the first level.\n\nBlockquotes can contain other Markdown elements, including headers, lists,\nand code blocks:\n\n\t> ## This is a header.\n\t> \n\t> 1.   This is the first list item.\n\t> 2.   This is the second list item.\n\t> \n\t> Here's some example code:\n\t> \n\t>     return shell_exec(\"echo $input | $markdown_script\");\n\nAny decent text editor should make email-style quoting easy. For\nexample, with BBEdit, you can make a selection and choose Increase\nQuote Level from the Text menu.\n\n\n<h3 id=\"list\">Lists</h3>\n\nMarkdown supports ordered (numbered) and unordered (bulleted) lists.\n\nUnordered lists use asterisks, pluses, and hyphens -- interchangably\n-- as list markers:\n\n    *   Red\n    *   Green\n    *   Blue\n\nis equivalent to:\n\n    +   Red\n    +   Green\n    +   Blue\n\nand:\n\n    -   Red\n    -   Green\n    -   Blue\n\nOrdered lists use numbers followed by periods:\n\n    1.  Bird\n    2.  McHale\n    3.  Parish\n\nIt's important to note that the actual numbers you use to mark the\nlist have no effect on the HTML output Markdown produces. The HTML\nMarkdown produces from the above list is:\n\n    <ol>\n    <li>Bird</li>\n    <li>McHale</li>\n    <li>Parish</li>\n    </ol>\n\nIf you instead wrote the list in Markdown like this:\n\n    1.  Bird\n    1.  McHale\n    1.  Parish\n\nor even:\n\n    3. Bird\n    1. McHale\n    8. Parish\n\nyou'd get the exact same HTML output. The point is, if you want to,\nyou can use ordinal numbers in your ordered Markdown lists, so that\nthe numbers in your source match the numbers in your published HTML.\nBut if you want to be lazy, you don't have to.\n\nIf you do use lazy list numbering, however, you should still start the\nlist with the number 1. At some point in the future, Markdown may support\nstarting ordered lists at an arbitrary number.\n\nList markers typically start at the left margin, but may be indented by\nup to three spaces. List markers must be followed by one or more spaces\nor a tab.\n\nTo make lists look nice, you can wrap items with hanging indents:\n\n    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n        Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n        viverra nec, fringilla in, laoreet vitae, risus.\n    *   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n        Suspendisse id sem consectetuer libero luctus adipiscing.\n\nBut if you want to be lazy, you don't have to:\n\n    *   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n    viverra nec, fringilla in, laoreet vitae, risus.\n    *   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n    Suspendisse id sem consectetuer libero luctus adipiscing.\n\nIf list items are separated by blank lines, Markdown will wrap the\nitems in `<p>` tags in the HTML output. For example, this input:\n\n    *   Bird\n    *   Magic\n\nwill turn into:\n\n    <ul>\n    <li>Bird</li>\n    <li>Magic</li>\n    </ul>\n\nBut this:\n\n    *   Bird\n\n    *   Magic\n\nwill turn into:\n\n    <ul>\n    <li><p>Bird</p></li>\n    <li><p>Magic</p></li>\n    </ul>\n\nList items may consist of multiple paragraphs. Each subsequent\nparagraph in a list item must be intended by either 4 spaces\nor one tab:\n\n    1.  This is a list item with two paragraphs. Lorem ipsum dolor\n        sit amet, consectetuer adipiscing elit. Aliquam hendrerit\n        mi posuere lectus.\n\n        Vestibulum enim wisi, viverra nec, fringilla in, laoreet\n        vitae, risus. Donec sit amet nisl. Aliquam semper ipsum\n        sit amet velit.\n\n    2.  Suspendisse id sem consectetuer libero luctus adipiscing.\n\nIt looks nice if you indent every line of the subsequent\nparagraphs, but here again, Markdown will allow you to be\nlazy:\n\n    *   This is a list item with two paragraphs.\n\n        This is the second paragraph in the list item. You're\n    only required to indent the first line. Lorem ipsum dolor\n    sit amet, consectetuer adipiscing elit.\n\n    *   Another item in the same list.\n\nTo put a blockquote within a list item, the blockquote's `>`\ndelimiters need to be indented:\n\n    *   A list item with a blockquote:\n\n        > This is a blockquote\n        > inside a list item.\n\nTo put a code block within a list item, the code block needs\nto be indented *twice* -- 8 spaces or two tabs:\n\n    *   A list item with a code block:\n\n            <code goes here>\n\n\nIt's worth noting that it's possible to trigger an ordered list by\naccident, by writing something like this:\n\n    1986. What a great season.\n\nIn other words, a *number-period-space* sequence at the beginning of a\nline. To avoid this, you can backslash-escape the period:\n\n    1986\\. What a great season.\n\n\n\n<h3 id=\"precode\">Code Blocks</h3>\n\nPre-formatted code blocks are used for writing about programming or\nmarkup source code. Rather than forming normal paragraphs, the lines\nof a code block are interpreted literally. Markdown wraps a code block\nin both `<pre>` and `<code>` tags.\n\nTo produce a code block in Markdown, simply indent every line of the\nblock by at least 4 spaces or 1 tab. For example, given this input:\n\n    This is a normal paragraph:\n\n        This is a code block.\n\nMarkdown will generate:\n\n    <p>This is a normal paragraph:</p>\n\n    <pre><code>This is a code block.\n    </code></pre>\n\nOne level of indentation -- 4 spaces or 1 tab -- is removed from each\nline of the code block. For example, this:\n\n    Here is an example of AppleScript:\n\n        tell application \"Foo\"\n            beep\n        end tell\n\nwill turn into:\n\n    <p>Here is an example of AppleScript:</p>\n\n    <pre><code>tell application \"Foo\"\n        beep\n    end tell\n    </code></pre>\n\nA code block continues until it reaches a line that is not indented\n(or the end of the article).\n\nWithin a code block, ampersands (`&`) and angle brackets (`<` and `>`)\nare automatically converted into HTML entities. This makes it very\neasy to include example HTML source code using Markdown -- just paste\nit and indent it, and Markdown will handle the hassle of encoding the\nampersands and angle brackets. For example, this:\n\n        <div class=\"footer\">\n            &copy; 2004 Foo Corporation\n        </div>\n\nwill turn into:\n\n    <pre><code>&lt;div class=\"footer\"&gt;\n        &amp;copy; 2004 Foo Corporation\n    &lt;/div&gt;\n    </code></pre>\n\nRegular Markdown syntax is not processed within code blocks. E.g.,\nasterisks are just literal asterisks within a code block. This means\nit's also easy to use Markdown to write about Markdown's own syntax.\n\n\n\n<h3 id=\"hr\">Horizontal Rules</h3>\n\nYou can produce a horizontal rule tag (`<hr>`) by placing three or\nmore hyphens, asterisks, or underscores on a line by themselves. If you\nwish, you may use spaces between the hyphens or asterisks. Each of the\nfollowing lines will produce a horizontal rule:\n\n    * * *\n\n    ***\n\n    *****\n\t\n    - - -\n\n    ---------------------------------------\n\n\t_ _ _\n\n\n* * *\n\n<h2 id=\"span\">Span Elements</h2>\n\n<h3 id=\"link\">Links</h3>\n\nMarkdown supports two style of links: *inline* and *reference*.\n\nIn both styles, the link text is delimited by [square brackets].\n\nTo create an inline link, use a set of regular parentheses immediately\nafter the link text's closing square bracket. Inside the parentheses,\nput the URL where you want the link to point, along with an *optional*\ntitle for the link, surrounded in quotes. For example:\n\n    This is [an example](http://example.com/ \"Title\") inline link.\n\n    [This link](http://example.net/) has no title attribute.\n\nWill produce:\n\n    <p>This is <a href=\"http://example.com/\" title=\"Title\">\n    an example</a> inline link.</p>\n\n    <p><a href=\"http://example.net/\">This link</a> has no\n    title attribute.</p>\n\nIf you're referring to a local resource on the same server, you can\nuse relative paths:\n\n    See my [About](/about/) page for details.\n\nReference-style links use a second set of square brackets, inside\nwhich you place a label of your choosing to identify the link:\n\n    This is [an example][id] reference-style link.\n\nYou can optionally use a space to separate the sets of brackets:\n\n    This is [an example] [id] reference-style link.\n\nThen, anywhere in the document, you define your link label like this,\non a line by itself:\n\n    [id]: http://example.com/  \"Optional Title Here\"\n\nThat is:\n\n*   Square brackets containing the link identifier (optionally\n    indented from the left margin using up to three spaces);\n*   followed by a colon;\n*   followed by one or more spaces (or tabs);\n*   followed by the URL for the link;\n*   optionally followed by a title attribute for the link, enclosed\n    in double or single quotes.\n\nThe link URL may, optionally, be surrounded by angle brackets:\n\n    [id]: <http://example.com/>  \"Optional Title Here\"\n\nYou can put the title attribute on the next line and use extra spaces\nor tabs for padding, which tends to look better with longer URLs:\n\n    [id]: http://example.com/longish/path/to/resource/here\n        \"Optional Title Here\"\n\nLink definitions are only used for creating links during Markdown\nprocessing, and are stripped from your document in the HTML output.\n\nLink definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links:\n\n\t[link text][a]\n\t[link text][A]\n\nare equivalent.\n\nThe *implicit link name* shortcut allows you to omit the name of the\nlink, in which case the link text itself is used as the name.\nJust use an empty set of square brackets -- e.g., to link the word\n\"Google\" to the google.com web site, you could simply write:\n\n\t[Google][]\n\nAnd then define the link:\n\n\t[Google]: http://google.com/\n\nBecause link names may contain spaces, this shortcut even works for\nmultiple words in the link text:\n\n\tVisit [Daring Fireball][] for more information.\n\nAnd then define the link:\n\t\n\t[Daring Fireball]: http://daringfireball.net/\n\nLink definitions can be placed anywhere in your Markdown document. I\ntend to put them immediately after each paragraph in which they're\nused, but if you want, you can put them all at the end of your\ndocument, sort of like footnotes.\n\nHere's an example of reference links in action:\n\n    I get 10 times more traffic from [Google] [1] than from\n    [Yahoo] [2] or [MSN] [3].\n\n      [1]: http://google.com/        \"Google\"\n      [2]: http://search.yahoo.com/  \"Yahoo Search\"\n      [3]: http://search.msn.com/    \"MSN Search\"\n\nUsing the implicit link name shortcut, you could instead write:\n\n    I get 10 times more traffic from [Google][] than from\n    [Yahoo][] or [MSN][].\n\n      [google]: http://google.com/        \"Google\"\n      [yahoo]:  http://search.yahoo.com/  \"Yahoo Search\"\n      [msn]:    http://search.msn.com/    \"MSN Search\"\n\nBoth of the above examples will produce the following HTML output:\n\n    <p>I get 10 times more traffic from <a href=\"http://google.com/\"\n    title=\"Google\">Google</a> than from\n    <a href=\"http://search.yahoo.com/\" title=\"Yahoo Search\">Yahoo</a>\n    or <a href=\"http://search.msn.com/\" title=\"MSN Search\">MSN</a>.</p>\n\nFor comparison, here is the same paragraph written using\nMarkdown's inline link style:\n\n    I get 10 times more traffic from [Google](http://google.com/ \"Google\")\n    than from [Yahoo](http://search.yahoo.com/ \"Yahoo Search\") or\n    [MSN](http://search.msn.com/ \"MSN Search\").\n\nThe point of reference-style links is not that they're easier to\nwrite. The point is that with reference-style links, your document\nsource is vastly more readable. Compare the above examples: using\nreference-style links, the paragraph itself is only 81 characters\nlong; with inline-style links, it's 176 characters; and as raw HTML,\nit's 234 characters. In the raw HTML, there's more markup than there\nis text.\n\nWith Markdown's reference-style links, a source document much more\nclosely resembles the final output, as rendered in a browser. By\nallowing you to move the markup-related metadata out of the paragraph,\nyou can add links without interrupting the narrative flow of your\nprose.\n\n\n<h3 id=\"em\">Emphasis</h3>\n\nMarkdown treats asterisks (`*`) and underscores (`_`) as indicators of\nemphasis. Text wrapped with one `*` or `_` will be wrapped with an\nHTML `<em>` tag; double `*`'s or `_`'s will be wrapped with an HTML\n`<strong>` tag. E.g., this input:\n\n    *single asterisks*\n\n    _single underscores_\n\n    **double asterisks**\n\n    __double underscores__\n\nwill produce:\n\n    <em>single asterisks</em>\n\n    <em>single underscores</em>\n\n    <strong>double asterisks</strong>\n\n    <strong>double underscores</strong>\n\nYou can use whichever style you prefer; the lone restriction is that\nthe same character must be used to open and close an emphasis span.\n\nEmphasis can be used in the middle of a word:\n\n    un*fucking*believable\n\nBut if you surround an `*` or `_` with spaces, it'll be treated as a\nliteral asterisk or underscore.\n\nTo produce a literal asterisk or underscore at a position where it\nwould otherwise be used as an emphasis delimiter, you can backslash\nescape it:\n\n    \\*this text is surrounded by literal asterisks\\*\n\n\n\n<h3 id=\"code\">Code</h3>\n\nTo indicate a span of code, wrap it with backtick quotes (`` ` ``).\nUnlike a pre-formatted code block, a code span indicates code within a\nnormal paragraph. For example:\n\n    Use the `printf()` function.\n\nwill produce:\n\n    <p>Use the <code>printf()</code> function.</p>\n\nTo include a literal backtick character within a code span, you can use\nmultiple backticks as the opening and closing delimiters:\n\n    ``There is a literal backtick (`) here.``\n\nwhich will produce this:\n\n    <p><code>There is a literal backtick (`) here.</code></p>\n\nThe backtick delimiters surrounding a code span may include spaces --\none after the opening, one before the closing. This allows you to place\nliteral backtick characters at the beginning or end of a code span:\n\n\tA single backtick in a code span: `` ` ``\n\t\n\tA backtick-delimited string in a code span: `` `foo` ``\n\nwill produce:\n\n\t<p>A single backtick in a code span: <code>`</code></p>\n\t\n\t<p>A backtick-delimited string in a code span: <code>`foo`</code></p>\n\nWith a code span, ampersands and angle brackets are encoded as HTML\nentities automatically, which makes it easy to include example HTML\ntags. Markdown will turn this:\n\n    Please don't use any `<blink>` tags.\n\ninto:\n\n    <p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>\n\nYou can write this:\n\n    `&#8212;` is the decimal-encoded equivalent of `&mdash;`.\n\nto produce:\n\n    <p><code>&amp;#8212;</code> is the decimal-encoded\n    equivalent of <code>&amp;mdash;</code>.</p>\n\n\n\n<h3 id=\"img\">Images</h3>\n\nAdmittedly, it's fairly difficult to devise a \"natural\" syntax for\nplacing images into a plain text document format.\n\nMarkdown uses an image syntax that is intended to resemble the syntax\nfor links, allowing for two styles: *inline* and *reference*.\n\nInline image syntax looks like this:\n\n    ![Alt text](/path/to/img.jpg)\n\n    ![Alt text](/path/to/img.jpg \"Optional title\")\n\nThat is:\n\n*   An exclamation mark: `!`;\n*   followed by a set of square brackets, containing the `alt`\n    attribute text for the image;\n*   followed by a set of parentheses, containing the URL or path to\n    the image, and an optional `title` attribute enclosed in double\n    or single quotes.\n\nReference-style image syntax looks like this:\n\n    ![Alt text][id]\n\nWhere \"id\" is the name of a defined image reference. Image references\nare defined using syntax identical to link references:\n\n    [id]: url/to/image  \"Optional title attribute\"\n\nAs of this writing, Markdown has no syntax for specifying the\ndimensions of an image; if this is important to you, you can simply\nuse regular HTML `<img>` tags.\n\n\n* * *\n\n\n<h2 id=\"misc\">Miscellaneous</h2>\n\n<h3 id=\"autolink\">Automatic Links</h3>\n\nMarkdown supports a shortcut style for creating \"automatic\" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:\n\n    <http://example.com/>\n    \nMarkdown will turn this into:\n\n    <a href=\"http://example.com/\">http://example.com/</a>\n\nAutomatic links for email addresses work similarly, except that\nMarkdown will also perform a bit of randomized decimal and hex\nentity-encoding to help obscure your address from address-harvesting\nspambots. For example, Markdown will turn this:\n\n    <address@example.com>\n\ninto something like this:\n\n    <a href=\"&#x6D;&#x61;i&#x6C;&#x74;&#x6F;:&#x61;&#x64;&#x64;&#x72;&#x65;\n    &#115;&#115;&#64;&#101;&#120;&#x61;&#109;&#x70;&#x6C;e&#x2E;&#99;&#111;\n    &#109;\">&#x61;&#x64;&#x64;&#x72;&#x65;&#115;&#115;&#64;&#101;&#120;&#x61;\n    &#109;&#x70;&#x6C;e&#x2E;&#99;&#111;&#109;</a>\n\nwhich will render in a browser as a clickable link to \"address@example.com\".\n\n(This sort of entity-encoding trick will indeed fool many, if not\nmost, address-harvesting bots, but it definitely won't fool all of\nthem. It's better than nothing, but an address published in this way\nwill probably eventually start receiving spam.)\n\n\n\n<h3 id=\"backslash\">Backslash Escapes</h3>\n\nMarkdown allows you to use backslash escapes to generate literal\ncharacters which would otherwise have special meaning in Markdown's\nformatting syntax. For example, if you wanted to surround a word with\nliteral asterisks (instead of an HTML `<em>` tag), you can backslashes\nbefore the asterisks, like this:\n\n    \\*literal asterisks\\*\n\nMarkdown provides backslash escapes for the following characters:\n\n    \\   backslash\n    `   backtick\n    *   asterisk\n    _   underscore\n    {}  curly braces\n    []  square brackets\n    ()  parentheses\n    #   hash mark\n\t+\tplus sign\n\t-\tminus sign (hyphen)\n    .   dot\n    !   exclamation mark\n\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_blockquotes.html",
    "content": "<blockquote>\n  <p>foo</p>\n  \n  <blockquote>\n    <p>bar</p>\n  </blockquote>\n  \n  <p>foo</p>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_blockquotes.text",
    "content": "> foo\n>\n> > bar\n>\n> foo\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_code.html",
    "content": "<p><code>hi ther `` ok ```</code></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_code.text",
    "content": "````` hi ther `` ok ``` `````\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_em.html",
    "content": "<p><em>test <strong>test</strong> test</em></p>\n\n<p><em>test <strong>test</strong> test</em></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_em.text",
    "content": "*test **test** test*\n\n_test __test__ test_\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_square_link.html",
    "content": "<p><a href=\"/url\">the <code>]</code> character</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/nested_square_link.text",
    "content": "[the `]` character](/url)\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/not_a_link.html",
    "content": "<p>[test](not a link)</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/not_a_link.text",
    "content": "\\[test](not a link)\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/ordered_and_unordered_lists.html",
    "content": "<h2 id=\"unordered\">Unordered</h2>\n\n<p>Asterisks tight:</p>\n\n<ul>\n<li>asterisk 1</li>\n<li>asterisk 2</li>\n<li>asterisk 3</li>\n</ul>\n\n<p>Asterisks loose:</p>\n\n<ul>\n<li><p>asterisk 1</p></li>\n<li><p>asterisk 2</p></li>\n<li><p>asterisk 3</p></li>\n</ul>\n\n<hr>\n\n<p>Pluses tight:</p>\n\n<ul>\n<li>Plus 1</li>\n<li>Plus 2</li>\n<li>Plus 3</li>\n</ul>\n\n<p>Pluses loose:</p>\n\n<ul>\n<li><p>Plus 1</p></li>\n<li><p>Plus 2</p></li>\n<li><p>Plus 3</p></li>\n</ul>\n\n<hr>\n\n<p>Minuses tight:</p>\n\n<ul>\n<li>Minus 1</li>\n<li>Minus 2</li>\n<li>Minus 3</li>\n</ul>\n\n<p>Minuses loose:</p>\n\n<ul>\n<li><p>Minus 1</p></li>\n<li><p>Minus 2</p></li>\n<li><p>Minus 3</p></li>\n</ul>\n\n<h2 id=\"ordered\">Ordered</h2>\n\n<p>Tight:</p>\n\n<ol>\n<li>First</li>\n<li>Second</li>\n<li>Third</li>\n</ol>\n\n<p>and:</p>\n\n<ol>\n<li>One</li>\n<li>Two</li>\n<li>Three</li>\n</ol>\n\n<p>Loose using tabs:</p>\n\n<ol>\n<li><p>First</p></li>\n<li><p>Second</p></li>\n<li><p>Third</p></li>\n</ol>\n\n<p>and using spaces:</p>\n\n<ol>\n<li><p>One</p></li>\n<li><p>Two</p></li>\n<li><p>Three</p></li>\n</ol>\n\n<p>Multiple paragraphs:</p>\n\n<ol>\n<li><p>Item 1, graf one.</p>\n\n<p>Item 2. graf two. The quick brown fox jumped over the lazy dog&#39;s\nback.</p></li>\n<li><p>Item 2.</p></li>\n<li><p>Item 3.</p></li>\n</ol>\n\n<h2 id=\"nested\">Nested</h2>\n\n<ul>\n<li>Tab\n<ul>\n<li>Tab\n<ul>\n<li>Tab</li>\n</ul></li>\n</ul></li>\n</ul>\n\n<p>Here&#39;s another:</p>\n\n<ol>\n<li>First</li>\n<li>Second:\n<ul>\n<li>Fee</li>\n<li>Fie</li>\n<li>Foe</li>\n</ul></li>\n<li>Third</li>\n</ol>\n\n<p>Same thing but with paragraphs:</p>\n\n<ol>\n<li><p>First</p></li>\n<li><p>Second:</p>\n\n<ul>\n<li>Fee</li>\n<li>Fie</li>\n<li>Foe</li>\n</ul></li>\n<li><p>Third</p></li>\n</ol>\n\n\n<p>This was an error in Markdown 1.0.1:</p>\n\n<ul>\n<li><p>this</p>\n\n<ul><li>sub</li></ul>\n\n<p>that</p></li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/ordered_and_unordered_lists.text",
    "content": "## Unordered\n\nAsterisks tight:\n\n*\tasterisk 1\n*\tasterisk 2\n*\tasterisk 3\n\n\nAsterisks loose:\n\n*\tasterisk 1\n\n*\tasterisk 2\n\n*\tasterisk 3\n\n* * *\n\nPluses tight:\n\n+\tPlus 1\n+\tPlus 2\n+\tPlus 3\n\n\nPluses loose:\n\n+\tPlus 1\n\n+\tPlus 2\n\n+\tPlus 3\n\n* * *\n\n\nMinuses tight:\n\n-\tMinus 1\n-\tMinus 2\n-\tMinus 3\n\n\nMinuses loose:\n\n-\tMinus 1\n\n-\tMinus 2\n\n-\tMinus 3\n\n\n## Ordered\n\nTight:\n\n1.\tFirst\n2.\tSecond\n3.\tThird\n\nand:\n\n1. One\n2. Two\n3. Three\n\n\nLoose using tabs:\n\n1.\tFirst\n\n2.\tSecond\n\n3.\tThird\n\nand using spaces:\n\n1. One\n\n2. Two\n\n3. Three\n\nMultiple paragraphs:\n\n1.\tItem 1, graf one.\n\n\tItem 2. graf two. The quick brown fox jumped over the lazy dog's\n\tback.\n\t\n2.\tItem 2.\n\n3.\tItem 3.\n\n\n\n## Nested\n\n*\tTab\n\t*\tTab\n\t\t*\tTab\n\nHere's another:\n\n1. First\n2. Second:\n\t* Fee\n\t* Fie\n\t* Foe\n3. Third\n\nSame thing but with paragraphs:\n\n1. First\n\n2. Second:\n\t* Fee\n\t* Fie\n\t* Foe\n\n3. Third\n\n\nThis was an error in Markdown 1.0.1:\n\n*\tthis\n\n\t*\tsub\n\n\tthat\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/ref_paren.html",
    "content": "<p><a href=\"/url\" title=\"there\">hi</a></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/ref_paren.text",
    "content": "[hi]\n\n[hi]: /url (there)\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/same_bullet.html",
    "content": "<ul>\n<li>test</li>\n<li>test</li>\n<li>test</li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/same_bullet.text",
    "content": "* test\n+ test\n- test\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/strong_and_em_together.html",
    "content": "<p><strong><em>This is strong and em.</em></strong></p>\n\n<p>So is <strong><em>this</em></strong> word.</p>\n\n<p><strong><em>This is strong and em.</em></strong></p>\n\n<p>So is <strong><em>this</em></strong> word.</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/strong_and_em_together.text",
    "content": "***This is strong and em.***\n\nSo is ***this*** word.\n\n___This is strong and em.___\n\nSo is ___this___ word.\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/tabs.html",
    "content": "<ul>\n<li><p>this is a list item\nindented with tabs</p></li>\n<li><p>this is a list item\nindented with spaces</p></li>\n</ul>\n\n<p>Code:</p>\n\n<pre><code>this code block is indented by one tab\n</code></pre>\n\n<p>And:</p>\n\n<pre><code>    this code block is indented by two tabs\n</code></pre>\n\n<p>And:</p>\n\n<pre><code>+   this is an example list item\n    indented with tabs\n\n+   this is an example list item\n    indented with spaces\n</code></pre>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/tabs.text",
    "content": "+\tthis is a list item\n\tindented with tabs\n\n+   this is a list item\n    indented with spaces\n\nCode:\n\n\tthis code block is indented by one tab\n\nAnd:\n\n\t\tthis code block is indented by two tabs\n\nAnd:\n\n\t+\tthis is an example list item\n\t\tindented with tabs\n\t\n\t+   this is an example list item\n\t    indented with spaces\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/text.smartypants.html",
    "content": "<p>Hello world ‘how’ “are” you — today…</p>\n\n<p>“It’s a more ‘challenging’ smartypants test…”</p>\n\n<p>‘And,’ as a bonus — “one\nmultiline” test!</p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/text.smartypants.text",
    "content": "Hello world 'how' \"are\" you -- today...\n\n\"It's a more 'challenging' smartypants test...\"\n\n'And,' as a bonus -- \"one\nmultiline\" test!\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/tidyness.html",
    "content": "<blockquote>\n<p>A list within a blockquote:</p>\n<ul>\n<li>asterisk 1</li>\n<li>asterisk 2</li>\n<li>asterisk 3</li>\n</ul>\n</blockquote>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/tidyness.text",
    "content": "> A list within a blockquote:\n> \n> *\tasterisk 1\n> *\tasterisk 2\n> *\tasterisk 3\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/toplevel_paragraphs.gfm.html",
    "content": "<p>hello world\n    how are you\n    how are you</p>\n\n<p>hello world</p>\n<pre><code>how are you</code></pre>\n\n<p>hello world</p>\n<hr>\n\n<p>hello world</p>\n<h1 id=\"how-are-you\">how are you</h1>\n\n<p>hello world</p>\n<h1 id=\"how-are-you\">how are you</h1>\n\n<p>hello world</p>\n<blockquote><p>how are you</p></blockquote>\n\n<p>hello world</p>\n<ul><li>how are you</li></ul>\n\n<p>hello world</p>\n<div>how are you</div>\n\n<p>hello world\n<span>how are you</span></p>\n\n<p>hello <a href=\"/are/you\">world</a>\n</p>\n\n<div>hello</div>\n\n<p><span>hello</span></p>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/toplevel_paragraphs.gfm.text",
    "content": "hello world\n    how are you\n    how are you\n\nhello world\n```\nhow are you\n```\n\nhello world\n* * *\n\nhello world\n# how are you\n\nhello world\nhow are you\n===========\n\nhello world\n> how are you\n\nhello world\n* how are you\n\nhello world\n<div>how are you</div>\n\nhello world\n<span>how are you</span>\n\nhello [world][how]\n[how]: /are/you\n\n<div>hello</div>\n\n<span>hello</span>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/tricky_list.html",
    "content": "<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>hello world</li>\n</ul>\n\n<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>hello world</li>\n</ul>\n\n<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>Hello world</li>\n</ul>\n\n<p><strong>hello</strong> <em>world</em></p>\n\n<ul>\n<li>hello world</li>\n</ul>\n"
  },
  {
    "path": "05-fks-master/fks_chart/bower_components/marked/test/tests/tricky_list.text",
    "content": "**hello** _world_\n\n* hello world\n\n**hello** _world_\n\n* hello world\n\n**hello** _world_\n\n* Hello world\n\n**hello** _world_\n\n* hello world\n"
  },
  {
    "path": "05-fks-master/fks_chart/css/style.css",
    "content": "/*Dendrogram*/\n.node circle {\n  fill: #fff;\n  stroke: steelblue;\n  stroke-width: 1.5px;\n}\n\n.node {\n  font: 20px sans-serif;\n  cursor: pointer;\n}\n\n.node text:hover {\n  fill: steelblue;\n}\n\n.link {\n  fill: none;\n  stroke: #ccc;\n  stroke-width: 1.5px;\n}\n\n/*tooltip*/\n#tooltip {\n  position: fixed;\n  min-width: 200px;\n  height: auto;\n  padding: 10px;\n  background-color: #444;\n  -webkit-border-radius: 10px;\n  -moz-border-radius: 10px;\n  border-radius: 10px;\n  -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  color: #fff;\n}\n\n#tooltip.hidden {\n  display: none;\n}\n\n#tooltip p {\n  margin: 0;\n  font-family: sans-serif;\n  font-size: 16px;\n  line-height: 20px;\n}\n\n.title { \n  width: 460px; \n  position: fixed;\n  top: 10px;\n  right: -40px;\n  height: auto;\n  padding: 10px;\n  margin: 15px;\n  background-color: #444;\n  -webkit-border-radius: 10px;\n  -moz-border-radius: 10px;\n  border-radius: 10px;\n  -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  color: #fff;\n}\n\na:hover {\n  text-decoration: none;\n}\n"
  },
  {
    "path": "05-fks-master/fks_chart/data/front-end.json",
    "content": "{\n  \"id\": \"0\",\n  \"name\": \"前端工程师\",\n  \"children\": [\n    {\n      \"id\": \"1\",\n      \"name\": \"浏览器\",\n      \"children\": [\n        {\n          \"id\": \"2\",\n          \"name\": \"IE6/[7](http://www.microsoft.com/en-US/download/details.aspx?id=2)/[8](http://windows.microsoft.com/en-US/internet-explorer/downloads/ie-8)/[9](http://windows.microsoft.com/en-US/internet-explorer/downloads/ie-9/worldwide-languages)/[10](http://windows.microsoft.com/en-US/internet-explorer/ie-10-worldwide-languages)/[11](http://windows.microsoft.com/en-US/internet-explorer/ie-11-worldwide-languages) (Trident)\"\n        },\n        {\n          \"id\": \"3\",\n          \"name\": \"[Firefox](http://www.mozilla.org/en-US/) (Gecko)\"\n        },\n        {\n          \"id\": \"4\",\n          \"name\": \"[Chrome](http://www.google.com/chrome)/[Chromium](http://www.chromium.org/) (Blink)\"\n        },\n        {\n          \"id\": \"5\",\n          \"name\": \"[Safari](http://www.apple.com/safari/) (WebKit)\"\n        },\n        {\n          \"id\": \"6\",\n          \"name\": \"[Opera](http://www.opera.com/) (Blink)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"7\",\n      \"name\": \"编程语言\",\n      \"children\": [\n        {\n          \"id\": \"8\",\n          \"name\": \"[JavaScript](https://developer.mozilla.org/en-US/docs/JavaScript)/[Node.js](http://nodejs.org/)\"\n        },\n        {\n          \"id\": \"9\",\n          \"name\": \"[CoffeeScript](http://coffeescript.org/)\"\n        },\n        {\n          \"id\": \"10\",\n          \"name\": \"[TypeScript](http://www.typescriptlang.org/)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"11\",\n      \"name\": \"切页面\",\n      \"children\": [\n        {\n          \"id\": \"12\",\n          \"name\": \"[HTML](http://www.w3.org/html/)/[HTML5](http://www.w3.org/TR/html5/)\"\n        },\n        {\n          \"id\": \"13\",\n          \"name\": \"[CSS/CSS3](http://www.w3.org/Style/CSS/)\"\n        },\n        {\n          \"id\": \"14\",\n          \"name\": \"[Sass](http://sass-lang.com/)/[LESS](http://lesscss.org/)/[Stylus](http://learnboost.github.io/stylus/)\"\n        },\n        {\n          \"id\": \"15\",\n          \"name\": \"[PhotoShop](http://www.photoshop.com/products/photoshop)/[Paint.net](http://www.getpaint.net/)/[Fireworks](http://www.adobe.com/cn/products/fireworks.html)/[GIMP](http://www.gimp.org/)/[Sketch](http://bohemiancoding.com/sketch/)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"16\",\n      \"name\": \"开发工具\",\n      \"children\": [\n        {\n          \"id\": \"17\",\n          \"name\": \"编辑器和IDE\",\n          \"children\": [\n            {\n              \"id\": \"18\",\n              \"name\": \"[VIM](http://www.vim.org/)/[Sublime Text2](http://www.sublimetext.com/)\"\n            },\n            {\n              \"id\": \"19\",\n              \"name\": \"[Notepad++](http://notepad-plus-plus.org/)/[EditPlus](http://www.editplus.com/)\"\n            },\n            {\n              \"id\": \"20\",\n              \"name\": \"[WebStorm](http://www.jetbrains.com/webstorm/)\"\n            },\n            {\n              \"id\": \"21\",\n              \"name\": \"[Emacs](http://www.gnu.org/software/emacs/)  [EmacsWiki](http://emacswiki.org)\"\n            },\n            {\n              \"id\": \"22\",\n              \"name\": \"[Brackets](http://brackets.io)\"\n            },\n            {\n              \"id\": \"23\",\n              \"name\": \"[Atom](https://atom.io/)\"\n            },\n            {\n              \"id\": \"24\",\n              \"name\": \"[Lime Text](http://limetext.org/)\"\n            },\n            {\n              \"id\": \"25\",\n              \"name\": \"[Light Table](http://lighttable.com/)\"\n            },\n            {\n              \"id\": \"26\",\n              \"name\": \"[Codebox](https://www.codebox.io/)\"\n            },\n            {\n              \"id\": \"27\",\n              \"name\": \"[TextMate](http://macromates.com/)\"\n            },\n            {\n              \"id\": \"28\",\n              \"name\": \"[Neovim](http://neovim.org/)\"\n            },\n            {\n              \"id\": \"29\",\n              \"name\": \"[Komodo IDE / Edit](http://www.activestate.com/komodo-edit)\"\n            },\n            {\n              \"id\": \"30\",\n              \"name\": \"[Eclipse](http://www.eclipse.org/)\"\n            },\n            {\n              \"id\": \"31\",\n              \"name\": \"[Visual Studio](http://www.visualstudio.com/)\"\n            },\n            {\n              \"id\": \"32\",\n              \"name\": \"[NetBeans](https://netbeans.org/)\"\n            },\n            {\n              \"id\": \"33\",\n              \"name\": \"[Cloud9 IDE](http://c9.io/)\"\n            },\n            {\n              \"id\": \"34\",\n              \"name\": \"[HBuilder](http://www.dcloud.io/)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"35\",\n          \"name\": \"调试工具\",\n          \"children\": [\n            {\n              \"id\": \"36\",\n              \"name\": \"[Firebug](http://getfirebug.com/)/[Firecookie](https://addons.mozilla.org/en-US/firefox/addon/firecookie/)\"\n            },\n            {\n              \"id\": \"37\",\n              \"name\": \"[YSlow](http://developer.yahoo.com/yslow/)\"\n            },\n            {\n              \"id\": \"38\",\n              \"name\": \"[IEDeveloperToolbar](http://www.microsoft.com/en-us/download/details.aspx?id=18359)/[IETester](http://www.my-debugbar.com/wiki/IETester/HomePage)\"\n            },\n            {\n              \"id\": \"39\",\n              \"name\": \"[Fiddler](http://www.fiddler2.com/fiddler2/)\"\n            },\n            {\n              \"id\": \"40\",\n              \"name\": \"[Chrome Dev Tools](https://developers.google.com/chrome-developer-tools/)\"\n            },\n            {\n              \"id\": \"41\",\n              \"name\": \"[Dragonfly](http://www.opera.com/dragonfly/)\"\n            },\n            {\n              \"id\": \"42\",\n              \"name\": \"[DebugBar](http://www.debugbar.com/)\"\n            },\n            {\n              \"id\": \"43\",\n              \"name\": \"[Venkman](https://developer.mozilla.org/en-US/docs/Venkman)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"44\",\n          \"name\": \"版本管理\",\n          \"children\": [\n            {\n              \"id\": \"45\",\n              \"name\": \"[Git](git-scm.com/)/[SVN](http://subversion.apache.org/)/[Mercurial](http://mercurial.selenic.com/)\"\n            },\n            {\n              \"id\": \"46\",\n              \"name\": \"[Github](https://github.com/)/[GitLab](https://about.gitlab.com/)/[Bitbucket](https://bitbucket.org/)/[Google Code](http://code.google.com/hosting/)/[Gitorious](https://gitorious.org/)/[GNU Savannah](http://savannah.gnu.org/)/[Launchpad](https://launchpad.net/)/[SourceForge](http://sourceforge.net/)/[TeamForge](http://www.collab.net/products/teamforge)\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"id\": \"47\",\n      \"name\": \"代码质量\",\n      \"children\": [\n        {\n          \"id\": \"48\",\n          \"name\": \"Coding style\",\n          \"children\": [\n            {\n              \"id\": \"49\",\n              \"name\": \"[JSLint](http://www.jslint.com/)/[JSHint](http://www.jshint.com/)/[jscs](https://github.com/mdevils/node-jscs)\"\n            },\n            {\n              \"id\": \"50\",\n              \"name\": \"[CSSLint](http://csslint.net/)\"\n            },\n            {\n              \"id\": \"51\",\n              \"name\": \"[Markup Validation Service](http://validator.w3.org/)\"\n            },\n            {\n              \"id\": \"52\",\n              \"name\": \"[HTML Validators](https://validator.whatwg.org/)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"53\",\n          \"name\": \"单元测试\",\n          \"children\": [\n            {\n              \"id\": \"54\",\n              \"name\": \"[QUnit](http://qunitjs.com/)/[Jasmine](http://pivotal.github.com/jasmine/)\"\n            },\n            {\n              \"id\": \"55\",\n              \"name\": \"[Mocha](http://visionmedia.github.com/mocha/)/[Should](https://github.com/visionmedia/should.js/)/[Chai](http://chaijs.com/)/[Expect](https://github.com/LearnBoost/expect.js/)\"\n            },\n            {\n              \"id\": \"56\",\n              \"name\": \"[Unit JS](http://unitjs.com/)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"57\",\n          \"name\": \"自动化测试\",\n          \"children\": [\n            {\n              \"id\": \"58\",\n              \"name\": \"[WebDriver](http://docs.seleniumhq.org/docs/03_webdriver.jsp)/[Protractor](https://github.com/angular/protractor)/[Karma Runner](https://github.com/karma-runner/karma)/[Sahi](http://sahi.co.in/)\"\n            },\n            {\n              \"id\": \"59\",\n              \"name\": \"[phantomjs](http://phantomjs.org/)\"\n            },\n            {\n              \"id\": \"60\",\n              \"name\": \"[SourceLabs](https://saucelabs.com/)/[BrowserStack](http://www.browserstack.com/)\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"id\": \"61\",\n      \"name\": \"前端库/框架\",\n      \"children\": [\n        {\n          \"id\": \"62\",\n          \"name\": \"[jQuery](http://jquery.com/)/[Underscore](http://underscorejs.org/)/[Mootools](http://mootools.net/)/[Prototype.js](http://www.prototypejs.org/)\"\n        },\n        {\n          \"id\": \"63\",\n          \"name\": \"[YUI3](http://yuilibrary.com/projects/yui3/)/[Dojo](http://dojotoolkit.org/)/[ExtJS](http://www.sencha.com/products/extjs)/[KISSY](http://docs.kissyui.com/)\"\n        },\n        {\n          \"id\": \"64\",\n          \"name\": \"[Backbone](http://backbonejs.org/)/[KnockoutJS](http://knockoutjs.com/)/[Emberjs](http://emberjs.com/)\"\n        },\n        {\n          \"id\": \"65\",\n          \"name\": \"[AngularJS](http://angularjs.org/)\",\n          \"children\": [\n            {\n              \"id\": \"66\",\n              \"name\": \"[Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"67\",\n          \"name\": \"[Bootstrap](http://getbootstrap.com/)\"\n        },\n        {\n          \"id\": \"68\",\n          \"name\": \"[Semantic UI](http://www.semantic-ui.com/)\"\n        },\n        {\n          \"id\": \"69\",\n          \"name\": \"[Juice UI](http://juiceui.com/)\"\n        },\n        {\n          \"id\": \"70\",\n          \"name\": \"[Web Atoms](http://webatomsjs.neurospeech.com/)\"\n        },\n        {\n          \"id\": \"71\",\n          \"name\": \"[Polymer](http://docs.polymerchina.org/)\"\n        },\n        {\n          \"id\": \"72\",\n          \"name\": \"[Dhtmlx](http://dhtmlx.com/)\"\n        },\n        {\n          \"id\": \"73\",\n          \"name\": \"[qooxdoo](http://qooxdoo.org/)\"\n        },\n        {\n          \"id\": \"74\",\n          \"name\": \"[React](http://facebook.github.io/react/)\"\n        },\n        {\n          \"id\": \"75\",\n          \"name\": \"[Brick](http://mozbrick.github.io/)\"\n        },\n        {\n          \"id\": \"76\",\n          \"name\": \"[Knockout](http://knockoutjs.com/)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"77\",\n      \"name\": \"前端标准/规范\",\n      \"children\": [\n        {\n          \"id\": \"78\",\n          \"name\": \"HTTP/1.1: RFCs 7230-7235\"\n        },\n        {\n          \"id\": \"79\",\n          \"name\": \"[HTTP/2](https://http2.github.io/)\"\n        },\n        {\n          \"id\": \"80\",\n          \"name\": \"[ECMAScript3/5](http://www.ecma-international.org/publications/standards/Ecma-262.htm)\"\n        },\n        {\n          \"id\": \"81\",\n          \"name\": \"[W3C: DOM/BOM/XHTML/XML/JSON/JSONP/...](http://www.w3.org/TR/)\"\n        },\n        {\n          \"id\": \"82\",\n          \"name\": \"[CommonJS Modules](http://wiki.commonjs.org/wiki/Modules/1.0)/[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)\"\n        },\n        {\n          \"id\": \"83\",\n          \"name\": \"[HTML5](http://www.w3.org/html/wg/drafts/html/master/)/[CSS3](http://www.w3.org/Style/CSS/specs.en.html)\"\n        },\n        {\n          \"id\": \"84\",\n          \"name\": \"[Semantic Web](http://semanticweb.org/)\",\n          \"children\": [\n            {\n              \"id\": \"85\",\n              \"name\": \"[MicroData](http://schema.org)\"\n            },\n            {\n              \"id\": \"86\",\n              \"name\": \"[RDFa](http://www.w3.org/TR/rdfa-core/)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"87\",\n          \"name\": \"[Web Accessibility](http://www.w3.org/WAI/)\",\n          \"children\": [\n            {\n              \"id\": \"88\",\n              \"name\": \"[WCAG](http://www.w3.org/TR/WAI-WEBCONTENT/)\"\n            },\n            {\n              \"id\": \"89\",\n              \"name\": \"[Role Attribute](http://www.w3.org/TR/role-attribute/)\"\n            },\n            {\n              \"id\": \"90\",\n              \"name\": \"[WAI-ARIA](http://www.w3.org/TR/wai-aria/)\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"id\": \"91\",\n      \"name\": \"性能\",\n      \"children\": [\n        {\n          \"id\": \"92\",\n          \"name\": \"[JSPerf](http://jsperf.com/)\"\n        },\n        {\n          \"id\": \"93\",\n          \"name\": \"[YSlow 35 rules](http://developer.yahoo.com/performance/rules.html)\"\n        },\n        {\n          \"id\": \"94\",\n          \"name\": \"[PageSpeed](https://developers.google.com/speed/pagespeed/)\"\n        },\n        {\n          \"id\": \"95\",\n          \"name\": \"[HTTPWatch](http://www.httpwatch.com/)\"\n        },\n        {\n          \"id\": \"96\",\n          \"name\": \"[DynaTrace's Ajax](http://www.compuware.com/application-performance-management/dynatrace-ajax-download.html)\"\n        },\n        {\n          \"id\": \"97\",\n          \"name\": \"[高性能JavaScript](http://book.douban.com/subject/5362856/)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"98\",\n      \"name\": \"SEO\"\n    },\n    {\n      \"id\": \"99\",\n      \"name\": \"编程知识储备\",\n      \"children\": [\n        {\n          \"id\": \"100\",\n          \"name\": \"[数据结构](http://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84)\"\n        },\n        {\n          \"id\": \"101\",\n          \"name\": \"OOP/AOP\"\n        },\n        {\n          \"id\": \"102\",\n          \"name\": \"[原型链](http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/)/作用域链\"\n        },\n        {\n          \"id\": \"103\",\n          \"name\": \"[闭包](http://www.jibbering.com/faq/notes/closures/)\"\n        },\n        {\n          \"id\": \"104\",\n          \"name\": \"[编程范型](http://zh.wikipedia.org/wiki/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%9E%8B)\"\n        },\n        {\n          \"id\": \"105\",\n          \"name\": \"[设计模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/)\"\n        },\n        {\n          \"id\": \"106\",\n          \"name\": \"[Javascript Tips](http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"107\",\n      \"name\": \"部署流程\",\n      \"children\": [\n        {\n          \"id\": \"108\",\n          \"name\": \"压缩合并\",\n          \"children\": [\n            {\n              \"id\": \"109\",\n              \"name\": \"[YUI Compressor](http://developer.yahoo.com/yui/compressor/)\"\n            },\n            {\n              \"id\": \"110\",\n              \"name\": \"[Google Clousure Complier](https://developers.google.com/closure/compiler/)\"\n            },\n            {\n              \"id\": \"111\",\n              \"name\": \"[UglifyJS](https://github.com/mishoo/UglifyJS)\"\n            },\n            {\n              \"id\": \"112\",\n              \"name\": \"[CleanCSS](https://github.com/GoalSmashers/clean-css)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"113\",\n          \"name\": \"文档输出\",\n          \"children\": [\n            {\n              \"id\": \"114\",\n              \"name\": \"[JSDoc](https://github.com/jsdoc3/jsdoc)\"\n            },\n            {\n              \"id\": \"115\",\n              \"name\": \"[Dox](https://github.com/visionmedia/dox)/[Doxmate](https://github.com/JacksonTian/doxmate)/[Grunt-Doxmate](https://github.com/luozhihua/grunt-doxmate)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"116\",\n          \"name\": \"项目构建工具\",\n          \"children\": [\n            {\n              \"id\": \"117\",\n              \"name\": \"[make](http://www.gnu.org/software/make/)/[Ant](http://ant.apache.org/)\"\n            },\n            {\n              \"id\": \"118\",\n              \"name\": \"[GYP](http://code.google.com/p/gyp/)\"\n            },\n            {\n              \"id\": \"119\",\n              \"name\": \"[Grunt](http://gruntjs.com/)\"\n            },\n            {\n              \"id\": \"120\",\n              \"name\": \"[Gulp](http://gulpjs.com/)\"\n            },\n            {\n              \"id\": \"121\",\n              \"name\": \"[Yeoman](http://yeoman.io/)\"\n            },\n            {\n              \"id\": \"122\",\n              \"name\": \"[FIS](http://fis.baidu.com/)\"\n            },\n            {\n              \"id\": \"123\",\n              \"name\": \"[Mod](https://github.com/modulejs/modjs)\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"id\": \"124\",\n      \"name\": \"代码组织\",\n      \"children\": [\n        {\n          \"id\": \"125\",\n          \"name\": \"类库模块化\",\n          \"children\": [\n            {\n              \"id\": \"126\",\n              \"name\": \"[CommonJS](http://www.commonjs.org/)/AMD\"\n            },\n            {\n              \"id\": \"127\",\n              \"name\": \"[YUI3模块](http://yuilibrary.com/projects/yui3/)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"128\",\n          \"name\": \"业务逻辑模块化\",\n          \"children\": [\n            {\n              \"id\": \"129\",\n              \"name\": \"[bower](https://github.com/twitter/bower)/[component](https://github.com/component/component)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"130\",\n          \"name\": \"文件加载\",\n          \"children\": [\n            {\n              \"id\": \"131\",\n              \"name\": \"[LABjs](http://labjs.com/)\"\n            },\n            {\n              \"id\": \"132\",\n              \"name\": \"[SeaJS](http://seajs.org/)/[Require.js](http://requirejs.org/)\"\n            }\n          ]\n        },\n        {\n          \"id\": \"133\",\n          \"name\": \"模块化预处理器\",\n          \"children\": [\n            {\n              \"id\": \"134\",\n              \"name\": \"[Browserify](https://github.com/substack/node-browserify)\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"id\": \"135\",\n      \"name\": \"安全\",\n      \"children\": [\n        {\n          \"id\": \"136\",\n          \"name\": \"[CSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)/[XSS](http://en.wikipedia.org/wiki/Cross-site_scripting)\"\n        },\n        {\n          \"id\": \"137\",\n          \"name\": \"[CSP](http://www.w3.org/TR/CSP/)\"\n        },\n        {\n          \"id\": \"138\",\n          \"name\": \"[Same-origin policy](https://developer.mozilla.org/docs/Web/Security/Same-origin_policy)\"\n        },\n        {\n          \"id\": \"139\",\n          \"name\": \"ADsafe/Caja/Sandbox\"\n        }\n      ]\n    },\n    {\n      \"id\": \"140\",\n      \"name\": \"移动Web\",\n      \"children\": [\n        {\n          \"id\": \"141\",\n          \"name\": \"HTML5/CSS3\"\n        },\n        {\n          \"id\": \"142\",\n          \"name\": \"[响应式网页设计](http://zh.wikipedia.org/wiki/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1)\"\n        },\n        {\n          \"id\": \"143\",\n          \"name\": \"[Zeptojs](http://zeptojs.com/)/[iScroll](http://cubiq.org/iscroll)\"\n        },\n        {\n          \"id\": \"144\",\n          \"name\": \"V5/[Sencha Touch](http://www.sencha.com/products/touch)\"\n        },\n        {\n          \"id\": \"145\",\n          \"name\": \"[PhoneGap](http://phonegap.com/)\"\n        },\n        {\n          \"id\": \"146\",\n          \"name\": \"[jQuery Mobile](http://jquerymobile.com/)\"\n        },\n        {\n          \"id\": \"147\",\n          \"name\": \"[W3C Mobile Web Initiative](http://www.w3.org/Mobile/)\"\n        },\n        {\n          \"id\": \"148\",\n          \"name\": \"[W3C mobileOK Checker](http://validator.w3.org/mobile/)\"\n        },\n        {\n          \"id\": \"149\",\n          \"name\": \"[Open Mobile Alliance](http://openmobilealliance.org/)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"150\",\n      \"name\": \"前沿技术社区/会议\",\n      \"children\": [\n        {\n          \"id\": \"151\",\n          \"name\": \"[D2](http://d2forum.org)/[WebRebuild](http://www.webrebuild.org/)\"\n        },\n        {\n          \"id\": \"152\",\n          \"name\": \"NodeParty/[W3CTech](http://w3ctech.com)/[HTML5梦工厂](http://www.html5dw.com)\"\n        },\n        {\n          \"id\": \"153\",\n          \"name\": \"[JSConf](http://jsconf.com/)/[沪JS(JSConf.cn)](http://jsconf.cn)\"\n        },\n        {\n          \"id\": \"154\",\n          \"name\": \"QCon/Velocity/SDCC\"\n        },\n        {\n          \"id\": \"155\",\n          \"name\": \"[JSConf](http://jsconf.com/)/[NodeConf](http://www.nodeconf.com/)\"\n        },\n        {\n          \"id\": \"156\",\n          \"name\": \"[CSSConf](http://cssconf.com/)\"\n        },\n        {\n          \"id\": \"157\",\n          \"name\": \"YDN/YUIConf\"\n        },\n        {\n          \"id\": \"158\",\n          \"name\": \"HybridApp\"\n        },\n        {\n          \"id\": \"159\",\n          \"name\": \"[WHATWG](http://whatwg.org/)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"160\",\n      \"name\": \"计算机知识储备\",\n      \"children\": [\n        {\n          \"id\": \"161\",\n          \"name\": \"编译原理\"\n        },\n        {\n          \"id\": \"162\",\n          \"name\": \"[计算机网络](http://zh.wikipedia.org/wiki/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C)\"\n        },\n        {\n          \"id\": \"163\",\n          \"name\": \"[操作系统](http://zh.wikipedia.org/wiki/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F)\"\n        },\n        {\n          \"id\": \"164\",\n          \"name\": \"算法原理\"\n        },\n        {\n          \"id\": \"165\",\n          \"name\": \"软件工程/软件测试原理\"\n        },\n        {\n          \"id\": \"166\",\n          \"name\": \"[Unicode](http://www.unicode.org/)\"\n        }\n      ]\n    },\n    {\n      \"id\": \"167\",\n      \"name\": \"软技能\",\n      \"children\": [\n        {\n          \"id\": \"168\",\n          \"name\": \"知识管理/总结分享\"\n        },\n        {\n          \"id\": \"169\",\n          \"name\": \"沟通技巧/团队协作\"\n        },\n        {\n          \"id\": \"170\",\n          \"name\": \"需求管理/PM\"\n        },\n        {\n          \"id\": \"171\",\n          \"name\": \"交互设计/可用性/可访问性知识\"\n        }\n      ]\n    },\n    {\n      \"id\": \"172\",\n      \"name\": \"可视化\",\n      \"children\": [\n        {\n          \"id\": \"173\",\n          \"name\": \"SVG/Canvas/VML\"\n        },\n        {\n          \"id\": \"174\",\n          \"name\": \"SVG: [D3](http://d3js.org/)/[Raphaël](http://raphaeljs.com/)/[Snap.svg](http://snapsvg.io/)/[DataV](http://datavlab.org/datavjs/)\"\n        },\n        {\n          \"id\": \"175\",\n          \"name\": \"Canvas: [CreateJS](http://www.createjs.com/)/[KineticJS](http://kineticjs.com/)\"\n        },\n        {\n          \"id\": \"176\",\n          \"name\": \"[WebGL](http://en.wikipedia.org/wiki/WebGL)/[Three.JS](http://threejs.org/)\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "05-fks-master/fks_chart/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\">\n    <script src=\"bower_components/jquery/dist/jquery.min.js\"></script>\n    <script src=\"bower_components/angular/angular.min.js\"></script>\n    <script src=\"bower_components/marked/lib/marked.js\"></script>\n    <script src=\"bower_components/angular-marked/angular-marked.min.js\"></script>\n    <script src=\"bower_components/d3/d3.min.js\"></script>\n    <script src=\"js/app.js\"></script>\n  </head>\n  <body ng-app=\"frontEnd\" ng-controller=\"frontEndCtrl\">\n     <div id=\"tooltip\" class=\"hidden\">\n        <p><strong id=\"name\"></strong></p>\n        <p><span id=\"desc\"></span></p>\n     </div>\n     <h3 class=\"title\">\n        <a href=\"https://github.com/JacksonTian/fks\" target=\"_blank\">Frontend Knowledge Structure</a> Chart\n        <p class=\"lead\" style=\"padding-left:150px;\"> <a href=\"https://github.com/hjzheng\">Follow me on Github</a></p>\n     </h3>\n     <front-end-chart></front-end-chart>\n  </body>\n</html>\n"
  },
  {
    "path": "05-fks-master/fks_chart/js/app.js",
    "content": "angular.module('frontEnd', [\"hc.marked\"])\n  .factory('data', ['$http', function($http) {\n    return {\n      getFrontEndData: function() {\n        var url = 'data/front-end.json';\n        return $http.get(url);\n      }\n    };\n  }])\n  .controller('frontEndCtrl', ['$scope', '$window', 'data',\n    function($scope, $window, data) {\n      $scope.type = 'Dendrogram';\n      $scope.frontEndData = '';\n\n      $window.addEventListener('resize', function() {\n        $scope.$broadcast('windowResize');\n      });\n\n      data.getFrontEndData()\n        .success(function(res) {\n          if (res.error) {\n            throw new Error(res.message);\n          } else {\n            $scope.frontEndData = res\n          }\n        });\n    }\n  ]).directive('frontEndChart', ['data','$window', \"marked\", function(data, $window, marked) {\n\n    var link = function($scope, $el, $attrs) {\n\n      var radius = 1200 / 2;\n\n      var cluster = d3.layout.cluster()\n        .size([360, radius - 120]);\n\n      var diagonal = d3.svg.diagonal.radial()\n        .projection(function(d) {\n          return [d.y, d.x / 180 * Math.PI];\n        });\n\n      var svg = d3.select($el[0]).append(\"svg\")\n        .attr(\"width\", document.documentElement.clientWidth)\n        .attr(\"height\", document.documentElement.clientHeight - 5)\n        .call(\n          d3.behavior.zoom().scaleExtent([0.6, 3]).on(\"zoom\", zoom)\n        );\n\n      var g = svg.append(\"g\")\n        .attr(\"transform\", \"translate(\" + radius + \",\" + radius + \")\");\n\n      function zoom () {\n        g.attr(\"transform\", \"translate(\" + d3.event.translate + \")scale(\" + d3.event.scale + \")\" );\n      }\n\n      var update = function() {\n        if ($scope.frontEndData === '') return;\n\n        var data = $scope.frontEndData;\n\n        var nodes = cluster.nodes(data);\n\n        var link = g.selectAll(\"path.link\")\n          .data(cluster.links(nodes))\n          .enter().append(\"path\")\n          .attr(\"class\", \"link\")\n          .attr(\"d\", diagonal);\n\n        var node = g.selectAll(\"g.node\")\n          .data(nodes)\n          .enter().append(\"g\")\n          .attr(\"class\", \"node\")\n          .attr(\"transform\", function(d) {\n            return \"rotate(\" + (d.x - 90) + \")translate(\" + d.y + \")\";\n          });\n\n        node.append(\"circle\")\n          .attr(\"r\", 4.5);\n\n        node.append(\"text\")\n          .attr(\"dy\", \".31em\")\n          .attr(\"text-anchor\", function(d) {\n            return d.x < 180 ? \"start\" : \"end\";\n          })\n          .attr(\"transform\", function(d) {\n            return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\";\n          })\n          .text(function(d) {\n            return $(marked(d.name)).text();\n          })\n          .attr(\"fill\", \"#000\")\n          .on(\"click\", function(d) {\n\n              //Update the tooltip position and value\n              d3.select(\"#tooltip\")\n                .style(\"left\", 10 + \"px\")\n                .style(\"top\", 10 + \"px\")    \n                \n              $(\"#name\").html(marked(d.name));\n \n              //Show the tooltip\n              d3.select(\"#tooltip\").classed(\"hidden\", false);\n           });\n      };\n\n      $scope.$watch('frontEndData', update);\n\n    };\n    return {\n      template: '<div></div>',\n      replace: true,\n      link: link,\n      restrict: 'E'\n    };\n  }\n]);"
  },
  {
    "path": "05-fks-master/package.json",
    "content": "{\n  \"name\": \"FKS\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Frontend Knowledge Structure\",\n  \"main\": \"index.js\",\n  \"directories\": {\n    \"doc\": \"doc\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/JacksonTian/fks.git\"\n  },\n  \"keywords\": [\n    \"Frontend\"\n  ],\n  \"author\": \"Jackson Tian\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "06-WebFrontEndStack-master/.gitignore",
    "content": "~$*\nv1.1/WebFrontEndStackv1.1.zip\nnode_modules\nnpm-debug.log"
  },
  {
    "path": "06-WebFrontEndStack-master/LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "06-WebFrontEndStack-master/README.es-es.md",
    "content": "# Overflow Stack\nThe overflow stack family (Web Front End Stack, Database Stack, .NET Stack etc.):\nhttp://overflowstack.github.io\n\n# Localization\nEnglish:\nhttps://github.com/unruledboy/WebFrontEndStack/\n\n中文:\nhttps://github.com/unruledboy/WebFrontEndStack/blob/master/README.zh-cn.md\n\nEspañol:\nhttps://github.com/unruledboy/WebFrontEndStack/blob/master/README.es-es.md\n\n\n# WebFrontEndStack\nWeb front-end stack: navegadores, plataformas, librerías, frameworks, herramientas etc.\n\n![Image of Web Front End Stack](Web Front End Stack.png)\n\n# Genera la imagen\n\n## Prepara el entorno\nTienes que tener instalado el Visual Studio 2010+ en Windows.\n\n1. Instalar [nodejs](https://nodejs.org).\n\n2. Instalar [Phantomjs](http://phantomjs.org).\n\n3. Instalar [Python 2.7](https://www.python.org/).\n\n4. ``npm install``\n\nSi aparece algún error, comprueba las dependencias de [phantomjs-node](https://github.com/sgentle/phantomjs-node/wiki), [node-gyp](https://github.com/TooTallNate/node-gyp#installation).\n\n## Ejecución de comandos\n``npm start`` para lanzar un servidor done ver el html.\n\n``npm run build`` para generar la imagen.\n\n\n## Opciones\n### Uso\n\tnode index task1 \\[task2\\] \\[task3\\] .. \\[--option=value\\] \\[--option=value\\] ...\n#### Tareas\n##### phantomjs\n\tGenera la imagen\n##### readme\n\tReconstruye los README.\n##### updatestargazers\n\tActualiza los contadores de estrellas de los proyectos github.\n#### Opciones\n#### port\n\tDefault: 3000\n#### update_existed_stargazers\n\tDefault: false\n\n# ¿Por qué realizar esta tabla?\nAlguna vez te has preguntado:\n* ¿Cuantas tecnologías se incluyen en el desarrollo Front end?\n* ¿Cuantas conozco?\n\n\nNo pude encontrar un diagrama muy completo que mostrase la pila de tecnologías involucradas en el desarrollo web front end, así realicé mi propia versión.\n\nPuede que haya errores, en categorías, enlaces o en nombres de\nlibrerías, o puede que falte alguna que consideres importante, pero\nbonito es que puedes modificarlo y arreglarlo como quieras.\n\nPuedes encontrar una vista previa del gráfico aquí (usa el ratón para\nmoverte / hacer zoom):\n\nhttps://rawgit.com/unruledboy/WebFrontEndStack/master/ux/WebFrontEndStack.htm\n\n\n# The Web Front End Stack\n<!--BUILD_START-->\n\n- Web Front End\n\t- Navegadores\n\t\t- [Internet Explorer](http://windows.microsoft.com/en-us/internet-explorer/download-ie)\n\t\t- [Chrome](http://www.google.com/chrome/)\n\t\t- [Firefox](https://www.mozilla.org/)\n\t\t- [Safari](http://www.apple.com/safari/)\n\t\t- [Opera](http://www.opera.com/)\n\t\t- [Edge](https://www.microsoft.com/en-us/windows/microsoft-edge)\n\t\t- [Netscape ;-)](https://en.wikipedia.org/wiki/Netscape)\n\t- Protocolos\n\t\t- [HTTP/1.1](https://www.ietf.org/rfc/rfc2616.txt)\n\t\t\t- URI\n\t\t\t- Sesión\n\t\t\t- Autenticación\n\t\t\t- Petición\n\t\t\t- Respuesta\n\t\t- [HTTP/2](https://en.wikipedia.org/wiki/HTTP/2)\n\t\t\t- Compresión\n\t\t\t- Minificación\n\t\t\t- Server Push\n\t\t- WebSocket\n\t- The 3 Pillars\n\t\t- HTML (HyperText Markup Language)\n\t\t- CSS (Cascading Style Sheets)\n\t\t- JavaScript\n\t- Estándares\n\t\t- W3C\n\t\t\t- HTML\n\t\t\t- CSS\n\t\t\t- XHTML\n\t\t\t- XML\n\t- Conceptons principales\n\t\t- HTML\n\t\t\t- [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)\n\t\t\t- [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)\n\t\t\t- Attribute\n\t\t- JavaScript\n\t\t\t- [Prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype)\n\t\t\t- [Scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope)\n\t\t\t- [Closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)\n\t\t\t- [JSON (JavaSript Object Notation)](https://developer.mozilla.org/en-US/docs/Glossary/JSON)\n\t\t\t- [AJAX (Asynchronous JavaScript and XML)](https://developer.mozilla.org/en-US/docs/AJAX)\n\t\t- CSS\n\t\t\t- Selector\n\t\t\t- Priority\n\t\t\t- Specificity\n\t\t\t- Box Model\n\t- Motores de renderizado\n\t\t- [Trident (IE)](https://en.wikipedia.org/wiki/Trident_(layout_engine))\n\t\t- [Blink / prev. WebKit (Chrome)](http://www.chromium.org/blink)\n\t\t- [Gecko (Firefox)](https://developer.mozilla.org/en-us/docs/Mozilla/Gecko)\n\t\t- [WebKit (Safari)](http://www.webkit.org/)\n\t\t- [Blink / prev. Presto (Opera)](http://www.chromium.org/blink)\n\t\t- [EdgeHTML (Edge)](https://en.wikipedia.org/wiki/EdgeHTML)\n\t- Motores JavaScript\n\t\t- [JScript (IE8- / ASP)](https://en.wikipedia.org/wiki/JScript)\n\t\t- [Chakra (IE9+ / Edge)](https://en.wikipedia.org/wiki/Chakra_(JScript_engine))\n\t\t- [V8 (Chrome / Opera / Nodejs / MongoDB)](https://developers.google.com/v8/?hl=zh-CN) [[GitHub]](https://github.com/v8/v8/)\n\t\t- [SpiderMonkey (Firefox)]( https://developer.mozilla.org/en-us/docs/Mozilla/Projects/SpiderMonkey)\n\t\t- [Nitro (Safari)](https://en.wikipedia.org/wiki/WebKit#JavaScriptCore)\n\t- Tiempo de ejecución\n\t\t- Cookie\n\t\t- Local Cache\n\t\t- Session Storage\n\t\t- Local Storage\n\t\t- Componentes\n\t\t\t- Extensiones\n\t\t\t- Plugins\n\t\t- Resources\n\t\t\t- Images\n\t\t\t- Icons\n\t\t\t- Fonts\n\t\t\t- Audios\n\t\t\t- Videos\n\t- Editores de texto\n\t\t- [Sublime Text](http://www.sublimetext.com/)\n\t\t- [WebStorm](https://www.jetbrains.com/webstorm/)\n\t\t- [Atom](https://atom.io/) [[GitHub]](https://github.com/atom/atom/)\n\t\t- [Vim](http://www.vim.org/)\n\t\t- [Emacs](https://www.gnu.org/software/emacs/)\n\t\t- [Brackets](http://brackets.io/) [[GitHub]](https://github.com/adobe/brackets/)\n\t\t- [Light Table](http://lighttable.com/) [[GitHub]](https://github.com/LightTable/LightTable/)\n\t\t- [Visual Studio](https://www.visualstudio.com/)\n\t\t- [Visual Studio Code](https://code.visualstudio.com/) [[GitHub]](https://github.com/Microsoft/vscode)\n\t\t- Dreamweaver ;-)\n\t\t- FrontPage / SharePoint Designer ;-)\n\t- Build Tasks\n\t\t- Minificación\n\t\t- Compilación\n\t\t- Concatenación\n\t\t- Uglification\n\t\t- Optimización de imágenes\n\t\t- Tests unitarios\n\t- Herramientas de tareas\n\t\t- [Grunt](http://www.gruntjs.com/) [[GitHub]](https://github.com/cowboy/jquery-tiny-pubsub/)\n\t\t- [Gulp](http://gulpjs.com/) [[GitHub]](https://github.com/gulpjs/gulp/)\n\t\t- [Brunch](http://brunch.io/) [[GitHub]](https://github.com/brunch/brunch/)\n\t\t- [Yeoman](http://yeoman.io/)\n\t\t- Broccoli [[GitHub]](https://github.com/broccolijs/broccoli/)\n\t- Depuración\n\t\t- [Developer Tools](https://developer.chrome.com/devtools)\n\t\t- [Firebug](http://getfirebug.com/) [[GitHub]](https://github.com/firebug/firebug/)\n\t- Herramientas base\n\t\t- [Node.js](https://nodejs.org/) [[GitHub]](https://github.com/joyent/node/)\n\t\t- [Phantom.js](http://phantomjs.org/) [[GitHub]](https://github.com/ariya/phantomjs/)\n\t\t- [SpiderMonkey](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey)\n\t- Calidad\n\t\t- [JSLint](http://www.jslint.com/) [[GitHub]](https://github.com/douglascrockford/JSLint/)\n\t\t- [JSHint](http://jshint.com/) [[GitHub]](https://github.com/jshint/jshint/)\n\t\t- [jscs](http://jscs.info/) [[GitHub]](https://github.com/jscs-dev/node-jscs)\n\t\t- [Closure Linter](https://developers.google.com/closure/utilities/)\n\t- Gestores de paquetes\n\t\t- [npm](https://www.npmjs.com/) [[GitHub]](https://github.com/npm/npm/)\n\t\t- [Bower](http://bower.io/) [[GitHub]](https://github.com/bower/bower/)\n\t- Test\n\t\t- Herramientas\n\t\t\t- [QUnit](https://qunitjs.com/) [[GitHub]](https://github.com/jquery/qunit/)\n\t\t\t- [Jasmine](http://jasmine.github.io/) [[GitHub]](https://github.com/jasmine/jasmine/)\n\t\t\t- [Mocha](https://mochajs.org/) [[GitHub]](https://github.com/mochajs/mocha/)\n\t\t\t- [Selenium](http://www.seleniumhq.org/) [[GitHub]](https://github.com/SeleniumHQ/selenium/)\n\t\t\t- [WebDriverIO](http://webdriver.io/) [[GitHub]](https://github.com/webdriverio/webdriverio/)\n\t\t\t- [Protractor](http://www.protractortest.org/)\n\t\t\t- [Chai](http://chaijs.com/) [[GitHub]](https://github.com/jfirebaugh/konacha/)\n\t\t\t- [Sinon.JS](http://sinonjs.org/) [[GitHub]](https://github.com/cjohansen/Sinon.JS/)\n\t\t\t- [Karma](http://karma-runner.github.io/) [[GitHub]](https://github.com/karma-runner/karma/)\n\t\t\t- nodeunit [[GitHub]](https://github.com/caolan/nodeunit/)\n\t\t\t- tape [[GitHub]](http://github.com/substack/tape)\n\t\t\t- [nightmare](http://nightmarejs.org/) [[GitHub]](https://github.com/segmentio/nightmare)\n\t\t- Composite\n\t\t\t- [Sauce Labs](https://saucelabs.com/)\n\t\t\t- [Browser Stack](https://www.browserstack.com/)\n\t\t\t- [Browser Shots](http://browsershots.org/)\n\t\t\t- [Browserling](https://www.browserling.com/)\n\t\t\t- [Browser Sandbox](https://spoon.net/browsers/)\n\t\t\t- [Cross Browser Testing](https://crossbrowsertesting.com/)\n\t\t\t- [Browsera](http://www.browsera.com/)\n\t\t\t- [SortSite](http://www.powermapper.com/products/sortsite/checks/browser-compatibility/)\n\t- Librerías y frameworks\n\t\t- JavaScript base library\n\t\t\t- [jQuery](https://jquery.com/) [[GitHub]](https://github.com/jquery/jquery/)\n\t\t\t- [Prototype](http://prototypejs.org/) [[GitHub]](https://github.com/sstephenson/prototype/)\n\t\t\t- [Zepto](http://zeptojs.com/) [[GitHub]](https://github.com/madrobby/zepto/)\n\t\t\t- [MooTool](http://mootools.net/) [[GitHub]](https://github.com/mootools/mootools-core/)\n\t\t- Módulos\n\t\t\t- ES6 Module\n\t\t\t- CommonJS\n\t\t\t\t- [webpack](http://webpack.github.io/) [[GitHub]](https://github.com/webpack/webpack/)\n\t\t\t\t- [browserify](http://browserify.org/) [[GitHub]](https://github.com/substack/node-browserify/)\n\t\t\t- AMD\n\t\t\t\t- [RequireJS](http://requirejs.org/) [[GitHub]](https://github.com/jrburke/requirejs/)\n\t\t\t- UMD\n\t\t\t\t- umd [[GitHub]](https://github.com/umdjs/umd/)\n\t\t- JavaScript Framework\n\t\t\t- [AngularJS](https://angularjs.org/) [[GitHub]](https://github.com/angular/angular.js/)\n\t\t\t- [Backbone](http://backbonejs.org/) [[GitHub]](https://github.com/jashkenas/backbone/)\n\t\t\t- [Knockout](http://knockoutjs.com/) [[GitHub]](https://github.com/SteveSanderson/knockout/)\n\t\t\t- [Ember](http://emberjs.com/) [[GitHub]](https://github.com/emberjs/ember.js/)\n\t\t\t- [React](http://facebook.github.io/react/) [[GitHub]](https://github.com/facebook/react/)\n\t\t\t- [polymer](https://www.polymer-project.org/) [[GitHub]](https://github.com/polymer/polymer/)\n\t\t\t- [Deft.js](http://deftjs.org/) [[GitHub]](https://github.com/deftjs/DeftJS/)\n\t\t\t- [Vue](http://vuejs.org/) [[GitHub]](https://github.com/yyx990803/vue/)\n\t\t\t- [Riot](http://riotjs.com/) [[GitHub]](https://github.com/riot/riot)\n\t\t- UI framework\n\t\t\t- [Bootstrap](http://getbootstrap.com/) [[GitHub]](https://github.com/twbs/bootstrap/)\n\t\t\t- [Semantic UI](http://semantic-ui.com/) [[GitHub]](https://github.com/Semantic-Org/Semantic-UI/)\n\t\t\t- [Foundation](http://foundation.zurb.com/) [[GitHub]](https://github.com/zurb/foundation/)\n\t\t\t- [Material UI](http://material-ui.com/) [[GitHub]](https://github.com/callemall/material-ui/)\n\t\t\t- [WinJS](https://dev.windows.com/en-us/develop/winjs) [[GitHub]](https://github.com/winjs/winjs)\n\t\t\t- [Pure](http://purecss.io/) [[GitHub]](https://github.com/yahoo/pure/)\n\t\t\t- [Amaze UI](http://amazeui.org/) [[GitHub]](https://github.com/allmobilize/amazeui)\n\t\t- WebSocket\n\t\t\t- [Socket.io](http://socket.io/) [[GitHub]](https://github.com/Automattic/socket.io/)\n\t\t\t- web-socket-js [[GitHub]](https://github.com/gimite/web-socket-js/)\n\t\t- Visualización de datos\n\t\t\t- [D3](http://d3js.org/) [[GitHub]](https://github.com/mbostock/d3/wiki/Gallery/)\n\t\t\t- [Echarts](http://echarts.baidu.com) [[GitHub]](https://github.com/ecomfe/esl/)\n\t\t\t- [HighCharts](http://www.highcharts.com/) [[GitHub]](https://github.com/highslide-software/highcharts.com/)\n\t\t\t- [Vis.js](http://visjs.org/) [[GitHub]](https://github.com/almende/vis/)\n\t\t\t- [Flot](http://www.flotcharts.org/) [[GitHub]](https://github.com/flot/flot/)\n\t\t- WebGL\n\t\t\t- [Three.js](http://threejs.org/) [[GitHub]](https://github.com/mrdoob/three.js/)\n\t\t\t- [Babylon.js](http://www.babylonjs.com/) [[GitHub]](https://github.com/BabylonJS/Babylon.js/)\n\t\t\t- [Pixi.js](http://www.pixijs.com/) [[GitHub]](https://github.com/GoodBoyDigital/pixi.js/)\n\t\t- CSS3 Animation\n\t\t\t- [Animate.css](https://daneden.github.io/animate.css/) [[GitHub]](https://github.com/daneden/animate.css/)\n\t\t\t- [bounce.js](http://bouncejs.com/) [[GitHub]](https://github.com/tictail/bounce.js/)\n\t\t\t- [Effeckt.css](https://h5bp.github.io/Effeckt.css/) [[GitHub]](https://github.com/h5bp/Effeckt.css/)\n\t\t\t- [move.js](https://visionmedia.github.io/move.js/) [[GitHub]](https://github.com/visionmedia/move.js/)\n\t\t- Control de flujo\n\t\t\t- ES6\n\t\t\t\t- Promise\n\t\t\t\t- Generator\n\t\t\t- ES7\n\t\t\t\t- yield\n\t\t\t\t- await\n\t\t\t- async [[GitHub]](https://github.com/caolan/async/)\n\t\t\t- co [[GitHub]](https://github.com/tj/co/)\n\t\t\t- Promise\n\t\t\t\t- Bluebird [[GitHub]](https://github.com/petkaantonov/bluebird/)\n\t\t\t\t- q [[GitHub]](https://github.com/kriskowal/q/)\n\t\t\t\t- when.js [[GitHub]](https://github.com/cujojs/when/)\n\t\t- Funcional\n\t\t\t- [bacon.js](http://baconjs.github.io/) [[GitHub]](https://github.com/baconjs/bacon.js/)\n\t\t\t- [immutable.js](https://facebook.github.io/immutable-js/) [[GitHub]](https://github.com/facebook/immutable-js/)\n\t\t\t- [ramda](http://ramdajs.com/) [[GitHub]](http://github.com/ramda/ramda)\n\t\t\t- [underscore.js](http://underscorejs.org/) [[GitHub]](https://github.com/jashkenas/underscore)\n\t\t\t- [lodash](https://lodash.com/) [[GitHub]](https://github.com/lodash/lodash)\n\t\t\t- [ReactiveX](http://reactivex.io/) [[GitHub]](https://github.com/Reactive-Extensions/RxJS)\n\t\t- Mobile UI\n\t\t\t- [jQuery Mobile](https://jquerymobile.com/) [[GitHub]](https://github.com/jquery/jquery-mobile/)\n\t\t\t- [Jo](http://joapp.com/) [[GitHub]](https://github.com/davebalmer/jo/)\n\t\t\t- [Dojo Mobile](https://dojotoolkit.org/reference-guide/1.10/dojox/mobile.html)\n\t\t\t- [Lungo](http://lungo.tapquo.com/) [[GitHub]](https://github.com/tapquo/Lungo.js/)\n\t- Pre-procesadores CSS\n\t\t- LESS\n\t\t\t- [LESS](http://lesscss.org/) [[GitHub]](https://github.com/less/less.js/)\n\t\t\t- [Hat](http://lesshat.madebysource.com/) [[GitHub]](https://github.com/csshat/lesshat/)\n\t\t- Sass(SCSS)\n\t\t\t- [Compass](http://compass-style.org/) [[GitHub]](https://github.com/chriseppstein/compass/)\n\t\t\t- [Bourbon](http://bourbon.io/) [[GitHub]](https://github.com/thoughtbot/bourbon/)\n\t\t\t- [Gumby](http://www.gumbyframework.com/) [[GitHub]](https://github.com/GumbyFramework/Gumby/)\n\t\t- Stylus\n\t\t\t- nib [[GitHub]](https://github.com/tj/nib/)\n\t- Future Standards\n\t\t- [babel](https://babeljs.io/) [[GitHub]](https://github.com/babel/babel)\n\t- Plantillas\n\t\t- [Handlebars](http://handlebarsjs.com/) [[GitHub]](https://github.com/wycats/handlebars.js/)\n\t\t- [Haml](http://haml.info/) [[GitHub]](https://github.com/haml/haml/)\n\t\t- [Slim](http://slim-lang.com/) [[GitHub]](https://github.com/slim-template/slim/)\n\t\t- [Jade](http://jade-lang.com/) [[GitHub]](https://github.com/jadejs/jade/)\n\t\t- [Ejs](http://www.embeddedjs.com/)\n\t\t- [Spacebars](http://meteorcapture.com/spacebars/)\n\t\t- [mustache](http://mustache.github.io/) [[GitHub]](https://github.com/janl/mustache.js/)\n\t- Modernisation\n\t\t- [Normalize](http://necolas.github.io/normalize.css/) [[GitHub]](https://github.com/necolas/normalize.css/)\n\t\t- Reset\n\t- Buenas prácticas\n\t\t- [SEO](https://en.wikipedia.org/wiki/Search_engine_optimization)\n\t\t- Responsiveness\n\t\t- [CDN](https://en.wikipedia.org/wiki/Content_delivery_network)\n\t- Seguridad\n\t\t- Sandbox\n\t\t- [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting)\n\t\t- [CORS](http://www.w3.org/TR/cors/)\n\t- Lenguajes intermedios\n\t\t- [CoffeeScript](http://coffeescript.org/) [[GitHub]](https://github.com/jashkenas/coffeescript/)\n\t\t- [TypeScript](http://www.typescriptlang.org/) [[GitHub]](https://github.com/Microsoft/TypeScript/)\n\t\t- ClojureScript [[GitHub]](https://github.com/clojure/clojurescript/)\n\t\t- [JSX (Facebook)](http://facebook.github.io/react/docs/jsx-in-depth.html)\n\t- Empaquetadores de Apps para móvil\n\t\t- [PhoneGap / Cordova](https://cordova.apache.org/) [[GitHub]](https://github.com/apache/cordova-android/)\n\t\t- [MUI](http://dev.dcloud.net.cn/mui/) [[GitHub]](https://github.com/dcloudio/mui/)\n\t\t- [React Native](https://facebook.github.io/react-native/) [[GitHub]](https://github.com/facebook/react-native/)\n\t\t- [Ionic](http://ionicframework.com/) [[GitHub]](https://github.com/driftyco/ionic/)\n\t- Desktop Application Development\n\t\t- [Electron](http://electron.atom.io/) [[GitHub]](https://github.com/atom/electron)\n\t\t- [NW.js](http://nwjs.io/) [[GitHub]](https://github.com/nwjs/nw.js)\n\n<!--BUILD_END-->\n"
  },
  {
    "path": "06-WebFrontEndStack-master/README.md",
    "content": "# Overflow Stack\nThe overflow stack family (Web Front End Stack, Database Stack, .NET Stack etc.):\nhttp://overflowstack.github.io\n\n# Localization\n中文: \nhttps://github.com/unruledboy/WebFrontEndStack/blob/master/README.zh-cn.md\n\nEspañol: \nhttps://github.com/unruledboy/WebFrontEndStack/blob/master/README.es-es.md\n\n\n# WebFrontEndStack\nWeb front-end stack: browsers, platforms, libraries, frameworks, tools etc.\n\n![Image of Web Front End Stack](Web Front End Stack.png)\n\n# Generate image yourself\n\n## Prepare for environment\nYou should have Visual Studio 2010+ installed in Windows. \n\n1. Install [nodejs](https://nodejs.org). (Shoule be >= iojs 1.8.0)\n\n2. Install [Phantomjs](http://phantomjs.org).\n\n3. Install [Python 2.7](https://www.python.org/).\n\n4. ``npm install``\n\nIf the error occurs, you can check the dependence of [phantomjs-node](https://github.com/sgentle/phantomjs-node/wiki), [node-gyp](https://github.com/TooTallNate/node-gyp#installation).\n\n## Run commands\n``npm start`` for start a server to open the html directly.\n\n``npm run build`` for generate the image.\n\n\n## Options\n```bash\n\n  -h, --help                           Display help message.\n  -p, --port number                    (Default: 3000) Set the port what express listening.\n  -ues, --update_existed_stargazers    (Default: false) Update project's stargazers including existed.\n  --phantomjs                          The task to generate the image.\n  --readme                             The task to update readme.\n  --updatestargazers                   The task to update the count of the stargazers.\n\n```\n\n\n# What and why?\nHave you ever wondered:\n* what technologies web front end really includes? \n* how many do I possess?\n\n\nI could not find a really comprehensive diagram that shows the web front end technology stack, so I come up with my own version.\n\nThere might be issues here and there, like the category, the individual ones, but the beauty is you can modify it as you want.\n\nYou can have a graphical preview here (use mouse to move / zoom): \n\nhttps://rawgit.com/unruledboy/WebFrontEndStack/master/ux/WebFrontEndStack.htm \n\n\n# The Web Front End Stack\n<!--BUILD_START-->\n\n- Web Front End\n\t- Browser\n\t\t- [Internet Explorer](http://windows.microsoft.com/en-us/internet-explorer/download-ie)\n\t\t- [Chrome](http://www.google.com/chrome/)\n\t\t- [Firefox](https://www.mozilla.org/)\n\t\t- [Safari](http://www.apple.com/safari/)\n\t\t- [Opera](http://www.opera.com/)\n\t\t- [Edge](https://www.microsoft.com/en-us/windows/microsoft-edge)\n\t\t- [Netscape ;-)](https://en.wikipedia.org/wiki/Netscape)\n\t- Protocol\n\t\t- [HTTP/1.1](https://www.ietf.org/rfc/rfc2616.txt)\n\t\t\t- URI\n\t\t\t- Session\n\t\t\t- Authentication\n\t\t\t- Request\n\t\t\t- Response\n\t\t- [HTTP/2](https://en.wikipedia.org/wiki/HTTP/2)\n\t\t\t- Compression\n\t\t\t- Minification\n\t\t\t- Server Push\n\t\t- WebSocket\n\t- The 3 Pillars\n\t\t- HTML (HyperText Markup Language)\n\t\t- CSS (Cascading Style Sheets)\n\t\t- JavaScript\n\t- Standards\n\t\t- W3C\n\t\t\t- HTML\n\t\t\t- CSS\n\t\t\t- XHTML\n\t\t\t- XML\n\t- Core Concepts\n\t\t- HTML\n\t\t\t- [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)\n\t\t\t- [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)\n\t\t\t- Attribute\n\t\t- JavaScript\n\t\t\t- [Prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype)\n\t\t\t- [Scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope)\n\t\t\t- [Closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)\n\t\t\t- [JSON (JavaSript Object Notation)](https://developer.mozilla.org/en-US/docs/Glossary/JSON)\n\t\t\t- [AJAX (Asynchronous JavaScript and XML)](https://developer.mozilla.org/en-US/docs/AJAX)\n\t\t- CSS\n\t\t\t- Selector\n\t\t\t- Priority\n\t\t\t- Specificity\n\t\t\t- Box Model\n\t- Rendering Engine\n\t\t- [Trident (IE)](https://en.wikipedia.org/wiki/Trident_(layout_engine))\n\t\t- [Blink / prev. WebKit (Chrome)](http://www.chromium.org/blink)\n\t\t- [Gecko (Firefox)](https://developer.mozilla.org/en-us/docs/Mozilla/Gecko)\n\t\t- [WebKit (Safari)](http://www.webkit.org/)\n\t\t- [Blink / prev. Presto (Opera)](http://www.chromium.org/blink)\n\t\t- [EdgeHTML (Edge)](https://en.wikipedia.org/wiki/EdgeHTML)\n\t- JavaScript Engine\n\t\t- [JScript (IE8- / ASP)](https://en.wikipedia.org/wiki/JScript)\n\t\t- [Chakra (IE9+ / Edge)](https://en.wikipedia.org/wiki/Chakra_(JScript_engine))\n\t\t- [V8 (Chrome / Opera / Nodejs / MongoDB)](https://developers.google.com/v8/?hl=zh-CN) [[GitHub]](https://github.com/v8/v8/)\n\t\t- [SpiderMonkey (Firefox)]( https://developer.mozilla.org/en-us/docs/Mozilla/Projects/SpiderMonkey)\n\t\t- [Nitro (Safari)](https://en.wikipedia.org/wiki/WebKit#JavaScriptCore)\n\t- Runtime\n\t\t- Cookie\n\t\t- Local Cache\n\t\t- Session Storage\n\t\t- Local Storage\n\t\t- Components\n\t\t\t- Extensions\n\t\t\t- Plugins\n\t\t- Resources\n\t\t\t- Images\n\t\t\t- Icons\n\t\t\t- Fonts\n\t\t\t- Audios\n\t\t\t- Videos\n\t- Editors\n\t\t- [Sublime Text](http://www.sublimetext.com/)\n\t\t- [WebStorm](https://www.jetbrains.com/webstorm/)\n\t\t- [Atom](https://atom.io/) [[GitHub]](https://github.com/atom/atom/)\n\t\t- [Vim](http://www.vim.org/)\n\t\t- [Emacs](https://www.gnu.org/software/emacs/)\n\t\t- [Brackets](http://brackets.io/) [[GitHub]](https://github.com/adobe/brackets/)\n\t\t- [Light Table](http://lighttable.com/) [[GitHub]](https://github.com/LightTable/LightTable/)\n\t\t- [Visual Studio](https://www.visualstudio.com/)\n\t\t- [Visual Studio Code](https://code.visualstudio.com/) [[GitHub]](https://github.com/Microsoft/vscode)\n\t\t- Dreamweaver ;-)\n\t\t- FrontPage / SharePoint Designer ;-)\n\t- Build Tasks\n\t\t- Minification\n\t\t- Compilation\n\t\t- Concatenation\n\t\t- Uglification\n\t\t- Image Optimization\n\t\t- Unit Testing\n\t- Build Tools\n\t\t- [Grunt](http://www.gruntjs.com/) [[GitHub]](https://github.com/cowboy/jquery-tiny-pubsub/)\n\t\t- [Gulp](http://gulpjs.com/) [[GitHub]](https://github.com/gulpjs/gulp/)\n\t\t- [Brunch](http://brunch.io/) [[GitHub]](https://github.com/brunch/brunch/)\n\t\t- [Yeoman](http://yeoman.io/)\n\t\t- Broccoli [[GitHub]](https://github.com/broccolijs/broccoli/)\n\t- Debug\n\t\t- [Developer Tools](https://developer.chrome.com/devtools)\n\t\t- [Firebug](http://getfirebug.com/) [[GitHub]](https://github.com/firebug/firebug/)\n\t- Base Tools\n\t\t- [Node.js](https://nodejs.org/) [[GitHub]](https://github.com/joyent/node/)\n\t\t- [Phantom.js](http://phantomjs.org/) [[GitHub]](https://github.com/ariya/phantomjs/)\n\t\t- [SpiderMonkey](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey)\n\t- Quality\n\t\t- [JSLint](http://www.jslint.com/) [[GitHub]](https://github.com/douglascrockford/JSLint/)\n\t\t- [JSHint](http://jshint.com/) [[GitHub]](https://github.com/jshint/jshint/)\n\t\t- [jscs](http://jscs.info/) [[GitHub]](https://github.com/jscs-dev/node-jscs)\n\t\t- [Closure Linter](https://developers.google.com/closure/utilities/)\n\t- Package\n\t\t- [npm](https://www.npmjs.com/) [[GitHub]](https://github.com/npm/npm/)\n\t\t- [Bower](http://bower.io/) [[GitHub]](https://github.com/bower/bower/)\n\t- Test\n\t\t- Tools\n\t\t\t- [QUnit](https://qunitjs.com/) [[GitHub]](https://github.com/jquery/qunit/)\n\t\t\t- [Jasmine](http://jasmine.github.io/) [[GitHub]](https://github.com/jasmine/jasmine/)\n\t\t\t- [Mocha](https://mochajs.org/) [[GitHub]](https://github.com/mochajs/mocha/)\n\t\t\t- [Selenium](http://www.seleniumhq.org/) [[GitHub]](https://github.com/SeleniumHQ/selenium/)\n\t\t\t- [WebDriverIO](http://webdriver.io/) [[GitHub]](https://github.com/webdriverio/webdriverio/)\n\t\t\t- [Protractor](http://www.protractortest.org/)\n\t\t\t- [Chai](http://chaijs.com/) [[GitHub]](https://github.com/jfirebaugh/konacha/)\n\t\t\t- [Sinon.JS](http://sinonjs.org/) [[GitHub]](https://github.com/cjohansen/Sinon.JS/)\n\t\t\t- [Karma](http://karma-runner.github.io/) [[GitHub]](https://github.com/karma-runner/karma/)\n\t\t\t- nodeunit [[GitHub]](https://github.com/caolan/nodeunit/)\n\t\t\t- tape [[GitHub]](http://github.com/substack/tape)\n\t\t\t- [nightmare](http://nightmarejs.org/) [[GitHub]](https://github.com/segmentio/nightmare)\n\t\t- Composite\n\t\t\t- [Sauce Labs](https://saucelabs.com/)\n\t\t\t- [Browser Stack](https://www.browserstack.com/)\n\t\t\t- [Browser Shots](http://browsershots.org/)\n\t\t\t- [Browserling](https://www.browserling.com/)\n\t\t\t- [Browser Sandbox](https://spoon.net/browsers/)\n\t\t\t- [Cross Browser Testing](https://crossbrowsertesting.com/)\n\t\t\t- [Browsera](http://www.browsera.com/)\n\t\t\t- [SortSite](http://www.powermapper.com/products/sortsite/checks/browser-compatibility/)\n\t- Frameworks / Libraries\n\t\t- JavaScript base library\n\t\t\t- [jQuery](https://jquery.com/) [[GitHub]](https://github.com/jquery/jquery/)\n\t\t\t- [Prototype](http://prototypejs.org/) [[GitHub]](https://github.com/sstephenson/prototype/)\n\t\t\t- [Zepto](http://zeptojs.com/) [[GitHub]](https://github.com/madrobby/zepto/)\n\t\t\t- [MooTool](http://mootools.net/) [[GitHub]](https://github.com/mootools/mootools-core/)\n\t\t- Modular\n\t\t\t- ES6 Module\n\t\t\t- CommonJS\n\t\t\t\t- [webpack](http://webpack.github.io/) [[GitHub]](https://github.com/webpack/webpack/)\n\t\t\t\t- [browserify](http://browserify.org/) [[GitHub]](https://github.com/substack/node-browserify/)\n\t\t\t- AMD\n\t\t\t\t- [RequireJS](http://requirejs.org/) [[GitHub]](https://github.com/jrburke/requirejs/)\n\t\t\t- UMD\n\t\t\t\t- umd [[GitHub]](https://github.com/umdjs/umd/)\n\t\t- JavaScript Framework\n\t\t\t- [AngularJS](https://angularjs.org/) [[GitHub]](https://github.com/angular/angular.js/)\n\t\t\t- [Backbone](http://backbonejs.org/) [[GitHub]](https://github.com/jashkenas/backbone/)\n\t\t\t- [Knockout](http://knockoutjs.com/) [[GitHub]](https://github.com/SteveSanderson/knockout/)\n\t\t\t- [Ember](http://emberjs.com/) [[GitHub]](https://github.com/emberjs/ember.js/)\n\t\t\t- [React](http://facebook.github.io/react/) [[GitHub]](https://github.com/facebook/react/)\n\t\t\t- [polymer](https://www.polymer-project.org/) [[GitHub]](https://github.com/polymer/polymer/)\n\t\t\t- [Deft.js](http://deftjs.org/) [[GitHub]](https://github.com/deftjs/DeftJS/)\n\t\t\t- [Vue](http://vuejs.org/) [[GitHub]](https://github.com/yyx990803/vue/)\n\t\t\t- [Riot](http://riotjs.com/) [[GitHub]](https://github.com/riot/riot)\n\t\t- UI framework\n\t\t\t- [Bootstrap](http://getbootstrap.com/) [[GitHub]](https://github.com/twbs/bootstrap/)\n\t\t\t- [Semantic UI](http://semantic-ui.com/) [[GitHub]](https://github.com/Semantic-Org/Semantic-UI/)\n\t\t\t- [Foundation](http://foundation.zurb.com/) [[GitHub]](https://github.com/zurb/foundation/)\n\t\t\t- [Material UI](http://material-ui.com/) [[GitHub]](https://github.com/callemall/material-ui/)\n\t\t\t- [WinJS](https://dev.windows.com/en-us/develop/winjs) [[GitHub]](https://github.com/winjs/winjs)\n\t\t\t- [Pure](http://purecss.io/) [[GitHub]](https://github.com/yahoo/pure/)\n\t\t\t- [Amaze UI](http://amazeui.org/) [[GitHub]](https://github.com/allmobilize/amazeui)\n\t\t- WebSocket\n\t\t\t- [Socket.io](http://socket.io/) [[GitHub]](https://github.com/Automattic/socket.io/)\n\t\t\t- web-socket-js [[GitHub]](https://github.com/gimite/web-socket-js/)\n\t\t- Data Visualization\n\t\t\t- [D3](http://d3js.org/) [[GitHub]](https://github.com/mbostock/d3/wiki/Gallery/)\n\t\t\t- [Echarts](http://echarts.baidu.com) [[GitHub]](https://github.com/ecomfe/esl/)\n\t\t\t- [HighCharts](http://www.highcharts.com/) [[GitHub]](https://github.com/highslide-software/highcharts.com/)\n\t\t\t- [Vis.js](http://visjs.org/) [[GitHub]](https://github.com/almende/vis/)\n\t\t\t- [Flot](http://www.flotcharts.org/) [[GitHub]](https://github.com/flot/flot/)\n\t\t- WebGL\n\t\t\t- [Three.js](http://threejs.org/) [[GitHub]](https://github.com/mrdoob/three.js/)\n\t\t\t- [Babylon.js](http://www.babylonjs.com/) [[GitHub]](https://github.com/BabylonJS/Babylon.js/)\n\t\t\t- [Pixi.js](http://www.pixijs.com/) [[GitHub]](https://github.com/GoodBoyDigital/pixi.js/)\n\t\t- CSS3 Animation\n\t\t\t- [Animate.css](https://daneden.github.io/animate.css/) [[GitHub]](https://github.com/daneden/animate.css/)\n\t\t\t- [bounce.js](http://bouncejs.com/) [[GitHub]](https://github.com/tictail/bounce.js/)\n\t\t\t- [Effeckt.css](https://h5bp.github.io/Effeckt.css/) [[GitHub]](https://github.com/h5bp/Effeckt.css/)\n\t\t\t- [move.js](https://visionmedia.github.io/move.js/) [[GitHub]](https://github.com/visionmedia/move.js/)\n\t\t- Flow Controller\n\t\t\t- ES6\n\t\t\t\t- Promise\n\t\t\t\t- Generator\n\t\t\t- ES7\n\t\t\t\t- yield\n\t\t\t\t- await\n\t\t\t- async [[GitHub]](https://github.com/caolan/async/)\n\t\t\t- co [[GitHub]](https://github.com/tj/co/)\n\t\t\t- Promise\n\t\t\t\t- Bluebird [[GitHub]](https://github.com/petkaantonov/bluebird/)\n\t\t\t\t- q [[GitHub]](https://github.com/kriskowal/q/)\n\t\t\t\t- when.js [[GitHub]](https://github.com/cujojs/when/)\n\t\t- Functional\n\t\t\t- [bacon.js](http://baconjs.github.io/) [[GitHub]](https://github.com/baconjs/bacon.js/)\n\t\t\t- [immutable.js](https://facebook.github.io/immutable-js/) [[GitHub]](https://github.com/facebook/immutable-js/)\n\t\t\t- [ramda](http://ramdajs.com/) [[GitHub]](http://github.com/ramda/ramda)\n\t\t\t- [underscore.js](http://underscorejs.org/) [[GitHub]](https://github.com/jashkenas/underscore)\n\t\t\t- [lodash](https://lodash.com/) [[GitHub]](https://github.com/lodash/lodash)\n\t\t\t- [ReactiveX](http://reactivex.io/) [[GitHub]](https://github.com/Reactive-Extensions/RxJS)\n\t\t- Mobile UI\n\t\t\t- [jQuery Mobile](https://jquerymobile.com/) [[GitHub]](https://github.com/jquery/jquery-mobile/)\n\t\t\t- [Jo](http://joapp.com/) [[GitHub]](https://github.com/davebalmer/jo/)\n\t\t\t- [Dojo Mobile](https://dojotoolkit.org/reference-guide/1.10/dojox/mobile.html)\n\t\t\t- [Lungo](http://lungo.tapquo.com/) [[GitHub]](https://github.com/tapquo/Lungo.js/)\n\t- CSS Pre-processors\n\t\t- LESS\n\t\t\t- [LESS](http://lesscss.org/) [[GitHub]](https://github.com/less/less.js/)\n\t\t\t- [Hat](http://lesshat.madebysource.com/) [[GitHub]](https://github.com/csshat/lesshat/)\n\t\t- Sass(SCSS)\n\t\t\t- [Compass](http://compass-style.org/) [[GitHub]](https://github.com/chriseppstein/compass/)\n\t\t\t- [Bourbon](http://bourbon.io/) [[GitHub]](https://github.com/thoughtbot/bourbon/)\n\t\t\t- [Gumby](http://www.gumbyframework.com/) [[GitHub]](https://github.com/GumbyFramework/Gumby/)\n\t\t- Stylus\n\t\t\t- nib [[GitHub]](https://github.com/tj/nib/)\n\t- Future Standards\n\t\t- [babel](https://babeljs.io/) [[GitHub]](https://github.com/babel/babel)\n\t- Template\n\t\t- [Handlebars](http://handlebarsjs.com/) [[GitHub]](https://github.com/wycats/handlebars.js/)\n\t\t- [Haml](http://haml.info/) [[GitHub]](https://github.com/haml/haml/)\n\t\t- [Slim](http://slim-lang.com/) [[GitHub]](https://github.com/slim-template/slim/)\n\t\t- [Jade](http://jade-lang.com/) [[GitHub]](https://github.com/jadejs/jade/)\n\t\t- [Ejs](http://www.embeddedjs.com/)\n\t\t- [Spacebars](http://meteorcapture.com/spacebars/)\n\t\t- [mustache](http://mustache.github.io/) [[GitHub]](https://github.com/janl/mustache.js/)\n\t- Modernisation\n\t\t- [Normalize](http://necolas.github.io/normalize.css/) [[GitHub]](https://github.com/necolas/normalize.css/)\n\t\t- Reset\n\t- Best Practices\n\t\t- [SEO](https://en.wikipedia.org/wiki/Search_engine_optimization)\n\t\t- Responsiveness\n\t\t- [CDN](https://en.wikipedia.org/wiki/Content_delivery_network)\n\t- Security\n\t\t- Sandbox\n\t\t- [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting)\n\t\t- [CORS](http://www.w3.org/TR/cors/)\n\t- Intermediate Languages\n\t\t- [CoffeeScript](http://coffeescript.org/) [[GitHub]](https://github.com/jashkenas/coffeescript/)\n\t\t- [TypeScript](http://www.typescriptlang.org/) [[GitHub]](https://github.com/Microsoft/TypeScript/)\n\t\t- ClojureScript [[GitHub]](https://github.com/clojure/clojurescript/)\n\t\t- [JSX (Facebook)](http://facebook.github.io/react/docs/jsx-in-depth.html)\n\t- Mobile Application Development\n\t\t- [PhoneGap / Cordova](https://cordova.apache.org/) [[GitHub]](https://github.com/apache/cordova-android/)\n\t\t- [MUI](http://dev.dcloud.net.cn/mui/) [[GitHub]](https://github.com/dcloudio/mui/)\n\t\t- [React Native](https://facebook.github.io/react-native/) [[GitHub]](https://github.com/facebook/react-native/)\n\t\t- [Ionic](http://ionicframework.com/) [[GitHub]](https://github.com/driftyco/ionic/)\n\t- Desktop Application Development\n\t\t- [Electron](http://electron.atom.io/) [[GitHub]](https://github.com/atom/electron)\n\t\t- [NW.js](http://nwjs.io/) [[GitHub]](https://github.com/nwjs/nw.js)\n\n<!--BUILD_END-->\n"
  },
  {
    "path": "06-WebFrontEndStack-master/README.zh-cn.md",
    "content": "# 爆栈\n系统开发技术栈、Web前端开发技术栈、数据库技术栈、.NET技术栈！\nhttp://overflowstack.github.io\n\n# 本地化\nEnglish:\nhttps://github.com/unruledboy/WebFrontEndStack/\n\n中文博客:\nhttp://www.cnblogs.com/unruledboy/p/WebFrontEndStack.html\n\nEspañol:\nhttps://github.com/unruledboy/WebFrontEndStack/blob/master/README.es-es.md\n\n\n# Web前端技术栈\n比较全面的浏览器、平台、类库、框架、工具等。\n\n![Image of Web Front End Stack](Web Front End Stack.zh-cn.png)\n\n# 自行生成预览图\n\n## 准备环境\n您应该安装Visual Studio 2010+。\n\n1. 安装 [nodejs](https://nodejs.org).\n\n2. 安装 [Phantomjs](http://phantomjs.org).\n\n3. 安装 [Python 2.7](https://www.python.org/).\n\n4. ``npm install``\n\n如果出现错误，您可以检查 [phantomjs-node] 的依赖(https://github.com/sgentle/phantomjs-node/wiki), [node-gyp](https://github.com/TooTallNate/node-gyp#installation).\n\n## 运行命令\n``npm start`` 运行服务并直接打开主html文件。\n\n``npm run build`` 生成预览图。\n\n\n## 选项\n```\n\n  -h, --help                           Display this message.\n  -p, --port number                    (Default: 3000) Set the port what express listening.\n  -ues, --update_existed_stargazers    (Default: false) Update project's stargazers including existed.\n  --phantomjs                          The task to generate the image.\n  --readme                             The task to update readme.\n  --updatestargazers                   The task to update the count of the stargazers.\n\n```\n\n# 为什么？\n大家是否想过：\n* Web前端开发究竟包含哪些技术呢？\n* 我所掌握的技术这个子集，在Web前端技术大系这个超集里面占的比例是多少呢？\n* 我究竟还没有掌握多少Web前端技术呢？\n* 面试的时候会考哪些技术呢？\n\n\n那么，Web前端开发是否也应该有这样的技术栈概览图呢？搜索了很久，没有找到一个符合我要求的“较为全面”地表述Web前端技术大系的图表。所以我们自行设计了这个Web前端技术栈。\n\n这个图表里的分类未必准确，相关技术也难免会有遗漏，欢迎大家指点以便不断改进。\n\nWeb前端技术实在太繁多限于篇幅，，这里没有罗列一些技术。\n\n您可以点击下面链接查看交互式预览图(用鼠标移动/缩放/点击节点打开相关网站)：\n\nhttps://rawgit.com/unruledboy/WebFrontEndStack/master/ux/WebFrontEndStack.htm?locale=zh-cn \n\n\n# Web前端技术栈\n<!--BUILD_START-->\n\n- Web前端开发技术栈\n\t- 浏览器\n\t\t- [Internet Explorer](http://windows.microsoft.com/en-us/internet-explorer/download-ie)\n\t\t- [Chrome](http://www.google.com/chrome/)\n\t\t- [Firefox](https://www.mozilla.org/)\n\t\t- [Safari](http://www.apple.com/safari/)\n\t\t- [Opera](http://www.opera.com/)\n\t\t- [Edge](https://www.microsoft.com/en-us/windows/microsoft-edge)\n\t\t- [Netscape ;-)](https://en.wikipedia.org/wiki/Netscape)\n\t- 协议\n\t\t- [HTTP/1.1](https://www.ietf.org/rfc/rfc2616.txt)\n\t\t\t- 链接\n\t\t\t- 会话\n\t\t\t- 授权\n\t\t\t- 请求\n\t\t\t- 响应\n\t\t- [HTTP/2](https://en.wikipedia.org/wiki/HTTP/2)\n\t\t\t- 压缩\n\t\t\t- 打包\n\t\t\t- 服务器端推送\n\t\t- WebSocket\n\t- Web三剑客\n\t\t- HTML (HyperText Markup Language)\n\t\t- CSS (Cascading Style Sheets)\n\t\t- JavaScript\n\t- 标准\n\t\t- W3C\n\t\t\t- HTML\n\t\t\t- CSS\n\t\t\t- XHTML\n\t\t\t- XML\n\t- 核心概念\n\t\t- HTML\n\t\t\t- [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)\n\t\t\t- [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element)\n\t\t\t- Attribute\n\t\t- JavaScript\n\t\t\t- [Prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype)\n\t\t\t- [Scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope)\n\t\t\t- [Closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)\n\t\t\t- [JSON (JavaSript Object Notation)](https://developer.mozilla.org/en-US/docs/Glossary/JSON)\n\t\t\t- [AJAX (Asynchronous JavaScript and XML)](https://developer.mozilla.org/en-US/docs/AJAX)\n\t\t- CSS\n\t\t\t- Selector\n\t\t\t- Priority\n\t\t\t- Specificity\n\t\t\t- Box Model\n\t- 渲染引擎\n\t\t- [Trident (IE)](https://en.wikipedia.org/wiki/Trident_(layout_engine))\n\t\t- [Blink / prev. WebKit (Chrome)](http://www.chromium.org/blink)\n\t\t- [Gecko (Firefox)](https://developer.mozilla.org/en-us/docs/Mozilla/Gecko)\n\t\t- [WebKit (Safari)](http://www.webkit.org/)\n\t\t- [Blink / prev. Presto (Opera)](http://www.chromium.org/blink)\n\t\t- [EdgeHTML (Edge)](https://en.wikipedia.org/wiki/EdgeHTML)\n\t- 脚本引擎\n\t\t- [JScript (IE8- / ASP)](https://en.wikipedia.org/wiki/JScript)\n\t\t- [Chakra (IE9+ / Edge)](https://en.wikipedia.org/wiki/Chakra_(JScript_engine))\n\t\t- [V8 (Chrome / Opera / Nodejs / MongoDB)](https://developers.google.com/v8/?hl=zh-CN) [[GitHub]](https://github.com/v8/v8/)\n\t\t- [SpiderMonkey (Firefox)]( https://developer.mozilla.org/en-us/docs/Mozilla/Projects/SpiderMonkey)\n\t\t- [Nitro (Safari)](https://en.wikipedia.org/wiki/WebKit#JavaScriptCore)\n\t- 运行时\n\t\t- Cookie\n\t\t- Local Cache\n\t\t- Session Storage\n\t\t- Local Storage\n\t\t- Components\n\t\t\t- Extensions\n\t\t\t- Plugins\n\t\t- Resources\n\t\t\t- Images\n\t\t\t- Icons\n\t\t\t- Fonts\n\t\t\t- Audios\n\t\t\t- Videos\n\t- 编辑器\n\t\t- [Sublime Text](http://www.sublimetext.com/)\n\t\t- [WebStorm](https://www.jetbrains.com/webstorm/)\n\t\t- [Atom](https://atom.io/) [[GitHub]](https://github.com/atom/atom/)\n\t\t- [Vim](http://www.vim.org/)\n\t\t- [Emacs](https://www.gnu.org/software/emacs/)\n\t\t- [Brackets](http://brackets.io/) [[GitHub]](https://github.com/adobe/brackets/)\n\t\t- [Light Table](http://lighttable.com/) [[GitHub]](https://github.com/LightTable/LightTable/)\n\t\t- [Visual Studio](https://www.visualstudio.com/)\n\t\t- [Visual Studio Code](https://code.visualstudio.com/) [[GitHub]](https://github.com/Microsoft/vscode)\n\t\t- Dreamweaver ;-)\n\t\t- FrontPage / SharePoint Designer ;-)\n\t- 编译任务\n\t\t- 精简\n\t\t- 编译\n\t\t- 合并\n\t\t- 混淆\n\t\t- 图像优化\n\t\t- 单元测试\n\t- 编译工具\n\t\t- [Grunt](http://www.gruntjs.com/) [[GitHub]](https://github.com/cowboy/jquery-tiny-pubsub/)\n\t\t- [Gulp](http://gulpjs.com/) [[GitHub]](https://github.com/gulpjs/gulp/)\n\t\t- [Brunch](http://brunch.io/) [[GitHub]](https://github.com/brunch/brunch/)\n\t\t- [Yeoman](http://yeoman.io/)\n\t\t- Broccoli [[GitHub]](https://github.com/broccolijs/broccoli/)\n\t- 调试\n\t\t- [Developer Tools](https://developer.chrome.com/devtools)\n\t\t- [Firebug](http://getfirebug.com/) [[GitHub]](https://github.com/firebug/firebug/)\n\t- 基础工具\n\t\t- [Node.js](https://nodejs.org/) [[GitHub]](https://github.com/joyent/node/)\n\t\t- [Phantom.js](http://phantomjs.org/) [[GitHub]](https://github.com/ariya/phantomjs/)\n\t\t- [SpiderMonkey](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey)\n\t- 质量控制\n\t\t- [JSLint](http://www.jslint.com/) [[GitHub]](https://github.com/douglascrockford/JSLint/)\n\t\t- [JSHint](http://jshint.com/) [[GitHub]](https://github.com/jshint/jshint/)\n\t\t- [jscs](http://jscs.info/) [[GitHub]](https://github.com/jscs-dev/node-jscs)\n\t\t- [Closure Linter](https://developers.google.com/closure/utilities/)\n\t- 包管理\n\t\t- [npm](https://www.npmjs.com/) [[GitHub]](https://github.com/npm/npm/)\n\t\t- [Bower](http://bower.io/) [[GitHub]](https://github.com/bower/bower/)\n\t- 测试\n\t\t- 工具\n\t\t\t- [QUnit](https://qunitjs.com/) [[GitHub]](https://github.com/jquery/qunit/)\n\t\t\t- [Jasmine](http://jasmine.github.io/) [[GitHub]](https://github.com/jasmine/jasmine/)\n\t\t\t- [Mocha](https://mochajs.org/) [[GitHub]](https://github.com/mochajs/mocha/)\n\t\t\t- [Selenium](http://www.seleniumhq.org/) [[GitHub]](https://github.com/SeleniumHQ/selenium/)\n\t\t\t- [WebDriverIO](http://webdriver.io/) [[GitHub]](https://github.com/webdriverio/webdriverio/)\n\t\t\t- [Protractor](http://www.protractortest.org/)\n\t\t\t- [Chai](http://chaijs.com/) [[GitHub]](https://github.com/jfirebaugh/konacha/)\n\t\t\t- [Sinon.JS](http://sinonjs.org/) [[GitHub]](https://github.com/cjohansen/Sinon.JS/)\n\t\t\t- [Karma](http://karma-runner.github.io/) [[GitHub]](https://github.com/karma-runner/karma/)\n\t\t\t- nodeunit [[GitHub]](https://github.com/caolan/nodeunit/)\n\t\t\t- tape [[GitHub]](http://github.com/substack/tape)\n\t\t\t- [nightmare](http://nightmarejs.org/) [[GitHub]](https://github.com/segmentio/nightmare)\n\t\t- 在线工具\n\t\t\t- [Sauce Labs](https://saucelabs.com/)\n\t\t\t- [Browser Stack](https://www.browserstack.com/)\n\t\t\t- [Browser Shots](http://browsershots.org/)\n\t\t\t- [Browserling](https://www.browserling.com/)\n\t\t\t- [Browser Sandbox](https://spoon.net/browsers/)\n\t\t\t- [Cross Browser Testing](https://crossbrowsertesting.com/)\n\t\t\t- [Browsera](http://www.browsera.com/)\n\t\t\t- [SortSite](http://www.powermapper.com/products/sortsite/checks/browser-compatibility/)\n\t- 库 / 框架\n\t\t- 基础库\n\t\t\t- [jQuery](https://jquery.com/) [[GitHub]](https://github.com/jquery/jquery/)\n\t\t\t- [Prototype](http://prototypejs.org/) [[GitHub]](https://github.com/sstephenson/prototype/)\n\t\t\t- [Zepto](http://zeptojs.com/) [[GitHub]](https://github.com/madrobby/zepto/)\n\t\t\t- [MooTool](http://mootools.net/) [[GitHub]](https://github.com/mootools/mootools-core/)\n\t\t- 模块化\n\t\t\t- ES6 Module\n\t\t\t- CommonJS\n\t\t\t\t- [webpack](http://webpack.github.io/) [[GitHub]](https://github.com/webpack/webpack/)\n\t\t\t\t- [browserify](http://browserify.org/) [[GitHub]](https://github.com/substack/node-browserify/)\n\t\t\t- AMD\n\t\t\t\t- [RequireJS](http://requirejs.org/) [[GitHub]](https://github.com/jrburke/requirejs/)\n\t\t\t- UMD\n\t\t\t\t- umd [[GitHub]](https://github.com/umdjs/umd/)\n\t\t- 框架\n\t\t\t- [AngularJS](https://angularjs.org/) [[GitHub]](https://github.com/angular/angular.js/)\n\t\t\t- [Backbone](http://backbonejs.org/) [[GitHub]](https://github.com/jashkenas/backbone/)\n\t\t\t- [Knockout](http://knockoutjs.com/) [[GitHub]](https://github.com/SteveSanderson/knockout/)\n\t\t\t- [Ember](http://emberjs.com/) [[GitHub]](https://github.com/emberjs/ember.js/)\n\t\t\t- [React](http://facebook.github.io/react/) [[GitHub]](https://github.com/facebook/react/)\n\t\t\t- [polymer](https://www.polymer-project.org/) [[GitHub]](https://github.com/polymer/polymer/)\n\t\t\t- [Deft.js](http://deftjs.org/) [[GitHub]](https://github.com/deftjs/DeftJS/)\n\t\t\t- [Vue](http://vuejs.org/) [[GitHub]](https://github.com/yyx990803/vue/)\n\t\t\t- [Riot](http://riotjs.com/) [[GitHub]](https://github.com/riot/riot)\n\t\t- UI框架\n\t\t\t- [Bootstrap](http://getbootstrap.com/) [[GitHub]](https://github.com/twbs/bootstrap/)\n\t\t\t- [Semantic UI](http://semantic-ui.com/) [[GitHub]](https://github.com/Semantic-Org/Semantic-UI/)\n\t\t\t- [Foundation](http://foundation.zurb.com/) [[GitHub]](https://github.com/zurb/foundation/)\n\t\t\t- [Material UI](http://material-ui.com/) [[GitHub]](https://github.com/callemall/material-ui/)\n\t\t\t- [WinJS](https://dev.windows.com/en-us/develop/winjs) [[GitHub]](https://github.com/winjs/winjs)\n\t\t\t- [Pure](http://purecss.io/) [[GitHub]](https://github.com/yahoo/pure/)\n\t\t\t- [Amaze UI](http://amazeui.org/) [[GitHub]](https://github.com/allmobilize/amazeui)\n\t\t- WebSocket\n\t\t\t- [Socket.io](http://socket.io/) [[GitHub]](https://github.com/Automattic/socket.io/)\n\t\t\t- web-socket-js [[GitHub]](https://github.com/gimite/web-socket-js/)\n\t\t- 数据可视化\n\t\t\t- [D3](http://d3js.org/) [[GitHub]](https://github.com/mbostock/d3/wiki/Gallery/)\n\t\t\t- [Echarts](http://echarts.baidu.com) [[GitHub]](https://github.com/ecomfe/esl/)\n\t\t\t- [HighCharts](http://www.highcharts.com/) [[GitHub]](https://github.com/highslide-software/highcharts.com/)\n\t\t\t- [Vis.js](http://visjs.org/) [[GitHub]](https://github.com/almende/vis/)\n\t\t\t- [Flot](http://www.flotcharts.org/) [[GitHub]](https://github.com/flot/flot/)\n\t\t- WebGL\n\t\t\t- [Three.js](http://threejs.org/) [[GitHub]](https://github.com/mrdoob/three.js/)\n\t\t\t- [Babylon.js](http://www.babylonjs.com/) [[GitHub]](https://github.com/BabylonJS/Babylon.js/)\n\t\t\t- [Pixi.js](http://www.pixijs.com/) [[GitHub]](https://github.com/GoodBoyDigital/pixi.js/)\n\t\t- CSS3 动画\n\t\t\t- [Animate.css](https://daneden.github.io/animate.css/) [[GitHub]](https://github.com/daneden/animate.css/)\n\t\t\t- [bounce.js](http://bouncejs.com/) [[GitHub]](https://github.com/tictail/bounce.js/)\n\t\t\t- [Effeckt.css](https://h5bp.github.io/Effeckt.css/) [[GitHub]](https://github.com/h5bp/Effeckt.css/)\n\t\t\t- [move.js](https://visionmedia.github.io/move.js/) [[GitHub]](https://github.com/visionmedia/move.js/)\n\t\t- 流程控制\n\t\t\t- ES6\n\t\t\t\t- Promise\n\t\t\t\t- Generator\n\t\t\t- ES7\n\t\t\t\t- yield\n\t\t\t\t- await\n\t\t\t- async [[GitHub]](https://github.com/caolan/async/)\n\t\t\t- co [[GitHub]](https://github.com/tj/co/)\n\t\t\t- Promise\n\t\t\t\t- Bluebird [[GitHub]](https://github.com/petkaantonov/bluebird/)\n\t\t\t\t- q [[GitHub]](https://github.com/kriskowal/q/)\n\t\t\t\t- when.js [[GitHub]](https://github.com/cujojs/when/)\n\t\t- 函数式编程\n\t\t\t- [bacon.js](http://baconjs.github.io/) [[GitHub]](https://github.com/baconjs/bacon.js/)\n\t\t\t- [immutable.js](https://facebook.github.io/immutable-js/) [[GitHub]](https://github.com/facebook/immutable-js/)\n\t\t\t- [ramda](http://ramdajs.com/) [[GitHub]](http://github.com/ramda/ramda)\n\t\t\t- [underscore.js](http://underscorejs.org/) [[GitHub]](https://github.com/jashkenas/underscore)\n\t\t\t- [lodash](https://lodash.com/) [[GitHub]](https://github.com/lodash/lodash)\n\t\t\t- [ReactiveX](http://reactivex.io/) [[GitHub]](https://github.com/Reactive-Extensions/RxJS)\n\t\t- 手机 UI 框架\n\t\t\t- [jQuery Mobile](https://jquerymobile.com/) [[GitHub]](https://github.com/jquery/jquery-mobile/)\n\t\t\t- [Jo](http://joapp.com/) [[GitHub]](https://github.com/davebalmer/jo/)\n\t\t\t- [Dojo Mobile](https://dojotoolkit.org/reference-guide/1.10/dojox/mobile.html)\n\t\t\t- [Lungo](http://lungo.tapquo.com/) [[GitHub]](https://github.com/tapquo/Lungo.js/)\n\t- CSS 预处理器\n\t\t- LESS\n\t\t\t- [LESS](http://lesscss.org/) [[GitHub]](https://github.com/less/less.js/)\n\t\t\t- [Hat](http://lesshat.madebysource.com/) [[GitHub]](https://github.com/csshat/lesshat/)\n\t\t- Sass(SCSS)\n\t\t\t- [Compass](http://compass-style.org/) [[GitHub]](https://github.com/chriseppstein/compass/)\n\t\t\t- [Bourbon](http://bourbon.io/) [[GitHub]](https://github.com/thoughtbot/bourbon/)\n\t\t\t- [Gumby](http://www.gumbyframework.com/) [[GitHub]](https://github.com/GumbyFramework/Gumby/)\n\t\t- Stylus\n\t\t\t- nib [[GitHub]](https://github.com/tj/nib/)\n\t- 未来标准\n\t\t- [babel](https://babeljs.io/) [[GitHub]](https://github.com/babel/babel)\n\t- 模板引擎\n\t\t- [Handlebars](http://handlebarsjs.com/) [[GitHub]](https://github.com/wycats/handlebars.js/)\n\t\t- [Haml](http://haml.info/) [[GitHub]](https://github.com/haml/haml/)\n\t\t- [Slim](http://slim-lang.com/) [[GitHub]](https://github.com/slim-template/slim/)\n\t\t- [Jade](http://jade-lang.com/) [[GitHub]](https://github.com/jadejs/jade/)\n\t\t- [Ejs](http://www.embeddedjs.com/)\n\t\t- [Spacebars](http://meteorcapture.com/spacebars/)\n\t\t- [mustache](http://mustache.github.io/) [[GitHub]](https://github.com/janl/mustache.js/)\n\t- 统一化\n\t\t- [Normalize](http://necolas.github.io/normalize.css/) [[GitHub]](https://github.com/necolas/normalize.css/)\n\t\t- Reset\n\t- 最佳实践\n\t\t- [SEO](https://en.wikipedia.org/wiki/Search_engine_optimization)\n\t\t- Responsiveness\n\t\t- [CDN](https://en.wikipedia.org/wiki/Content_delivery_network)\n\t- 安全\n\t\t- Sandbox\n\t\t- [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting)\n\t\t- [CORS](http://www.w3.org/TR/cors/)\n\t- 中间语言\n\t\t- [CoffeeScript](http://coffeescript.org/) [[GitHub]](https://github.com/jashkenas/coffeescript/)\n\t\t- [TypeScript](http://www.typescriptlang.org/) [[GitHub]](https://github.com/Microsoft/TypeScript/)\n\t\t- ClojureScript [[GitHub]](https://github.com/clojure/clojurescript/)\n\t\t- [JSX (Facebook)](http://facebook.github.io/react/docs/jsx-in-depth.html)\n\t- 移动应用开发\n\t\t- [PhoneGap / Cordova](https://cordova.apache.org/) [[GitHub]](https://github.com/apache/cordova-android/)\n\t\t- [MUI](http://dev.dcloud.net.cn/mui/) [[GitHub]](https://github.com/dcloudio/mui/)\n\t\t- [React Native](https://facebook.github.io/react-native/) [[GitHub]](https://github.com/facebook/react-native/)\n\t\t- [Ionic](http://ionicframework.com/) [[GitHub]](https://github.com/driftyco/ionic/)\n\t- 桌面应用开发\n\t\t- [Electron](http://electron.atom.io/) [[GitHub]](https://github.com/atom/electron)\n\t\t- [NW.js](http://nwjs.io/) [[GitHub]](https://github.com/nwjs/nw.js)\n\n<!--BUILD_END-->\n"
  },
  {
    "path": "06-WebFrontEndStack-master/index.js",
    "content": "/* global require, setTimeout, console, __dirname, process*/\n/**\n * Builder\n * @author zsx<zsx@zsxsoft.com>\n */\n(function () {\n\t\"use strict\";\n\n\tconst pageWidth = 2000; // Magic number!\n\tconst pageHeight = 3800;\n\n\tlet Express = require('express');\n\tlet path = require('path');\n\tlet phantom = require(\"phantomjs-promise\");\n\tlet request = require(\"request\");\n\tlet async = require(\"async\");\n\tlet fs = require('fs');\n\tlet commandLineArgs = require(\"command-line-args\");\n\n\tlet app = new Express();\n\n\tlet cli = commandLineArgs([{\n\t\tname: \"help\",\n\t\talias: \"h\",\n\t\ttype: Boolean,\n\t\tdefaultOption: true,\n\t\tdescription: \"Display this message.\"\n\t}, {\n\t\tname: \"port\",\n\t\talias: \"p\",\n\t\ttype: Number,\n\t\tdefaultValue: 3000,\n\t\tdescription: \"(Default: 3000) Set the port what express listening.\"\n\t}, {\n\t\tname: \"update_existed_stargazers\",\n\t\talias: \"ues\",\n\t\ttype: Boolean,\n\t\tdefaultValue: false,\n\t\tdescription: \"(Default: false) Update project's stargazers including existed.\"\n\t}, {\n\t\tname: \"phantomjs\",\n\t\ttype: Boolean,\n\t\tdefaultValue: false,\n\t\tdescription: \"The task to generate the image.\"\n\t}, {\n\t\tname: \"readme\",\n\t\ttype: Boolean,\n\t\tdefaultValue: false,\n\t\tdescription: \"The task to update readme.\"\n\t}, {\n\t\tname: \"updatestargazers\",\n\t\ttype: Boolean,\n\t\tdefaultValue: false,\n\t\tdescription: \"The task to update the count of the stargazers.\"\n\t}]);\n\tlet options = cli.parse();\n\tlet httpServer = \"http://127.0.0.1:\" + options.port + \"/\";\n\n\tlet languages = [];\n\tlet jsonData = JSON.parse(fs.readFileSync('./ux/WebFrontEndStack.json', \"utf-8\")); // Require will lock the file.\n\n\t/**\n\t * Tiemout\n\t * @param int ms\n\t * @return Promise<any>\t \n\t */\n\tfunction timeout(ms) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tsetTimeout(resolve, ms, 'done');\n\t\t});\n\t}\n\t/**\n\t * Recursion to generate readme\n\t * @param object object\n\t * @param string language\n\t * @param int deep\n\t * @return string\t \n\t */\n\tfunction buildReadme(object, language, deep) {\n\t\tlet deeper = deep + 1;\n\t\tlet deepString = new Array(deeper).join(\"\\t\") + \"- \";\n\t\tlet ret = [];\n\t\tlet lang = \"\";\n\t\tif (object.languages) {\n\t\t\tlang = object.languages[language];\n\t\t}\n\t\tlang = lang || object.name;\n\n\t\tret.push((function (deepString, name, url, github) {\n\t\t\tlet haveUrl = !!url;\n\t\t\tlet haveGitHub = !!github;\n\t\t\tlet ret = [];\n\t\t\tret.push(deepString);\n\t\t\tret.push((haveUrl ? \"[\" : \"\") + name + (haveUrl ? \"](\" + url + \")\" : \"\"));\n\t\t\tret.push((haveGitHub ? \" [\\[GitHub\\]](\" + github + \")\" : \"\"));\n\t\t\treturn ret.join(\"\");\n\t\t})(deepString, lang, object.url, object.github));\n\n\t\tif (object.children) {\n\t\t\tobject.children.map((value, index) => {\n\t\t\t\tret.push(buildReadme(value, language, deeper));\n\t\t\t});\n\t\t}\n\t\treturn ret.join(\"\\n\");\n\t}\n\n\t/**\n\t * Update the stargazers of the GitHub repo\n\t * Be careful! There have the rate limit!\n\t * @see  https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications\n\t * @return Promise<any>\n\t */\n\tfunction updatestargazers() {\n\t\treturn new Promise((resolve, reject) => {\n\n\t\t\tfunction getGitHubApi(github) {\n\t\t\t\tlet githubArray = github.split(\"/\");\n\t\t\t\t// I want a sprintf T_T\n\t\t\t\treturn \"https://api.github.com/repos/\" + githubArray[3] + \"/\" + githubArray[4];\n\t\t\t}\n\n\n\t\t\tlet q = async.queue(function (object, callback) {\n\t\t\t\tif (!object.github || (!options.update_existed_stargazers && object.stargazers)) {\n\t\t\t\t\tcallback(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet githubUrl = getGitHubApi(object.github);\n\t\t\t\tconsole.log(\"Getting \" + githubUrl);\n\t\t\t\trequest({\n\t\t\t\t\turl: githubUrl,\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": \"https://github.com/unruledboy/WebFrontEndStack\" // GitHub required user-agent\n\t\t\t\t\t}\n\t\t\t\t}, (err, res, body) => {\n\t\t\t\t\tif (!err && res.statusCode == 200) {\n\t\t\t\t\t\tlet json = JSON.parse(body);\n\t\t\t\t\t\tif (json === null) {\n\t\t\t\t\t\t\tcallback(false);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tobject.stargazers = json.stargazers_count;\n\t\t\t\t\t\tcallback(true);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (res.statusCode == 403) { // Out of API limit!\n\t\t\t\t\t\t\tconsole.error(\"Out of GitHub API limit!\");\n\t\t\t\t\t\t\tconsole.error(\"The limit will be reset when \" + new Date(res.headers['x-ratelimit-reset'] * 1000));\n\t\t\t\t\t\t\tq.kill();\n\t\t\t\t\t\t\treject(\"Out of GitHub API limit!\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallback(false);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t}, 5);\n\t\t\tq.drain = function () {\n\t\t\t\tfs.writeFileSync('./ux/WebFrontEndStack.json', JSON.stringify(jsonData), \"utf-8\");\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tfunction addQueue(object) {\n\t\t\t\tq.push(object, (noErr) => {\n\t\t\t\t\tif (noErr) console.log(object.name + \" = \" + object.stargazers);\n\t\t\t\t});\n\t\t\t\tif (object.children) {\n\t\t\t\t\tobject.children.forEach((val) => {\n\t\t\t\t\t\taddQueue(val);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\taddQueue(jsonData);\n\n\t\t\treturn q;\n\t\t});\n\t}\n\t/**\n\t * For running phantomjs to take a screenshot for the webpage\n\t * @return Promise<any>\n\t */\n\tfunction phantomjs(language) {\n\t\tlet displayLanguage = language === \"\" ? \"en\" : language;\n\t\tlet promise = new Promise((resolve, reject) => {\n\t\t\treturn phantom.createAsync().then((phantom) => {\n\t\t\t\treturn phantom.createPageAsync();\n\t\t\t}).then((objects) => {\n\t\t\t\tconsole.log(\"Setting viewportSize..\");\n\t\t\t\treturn objects.page.setAsync('viewportSize', {\n\t\t\t\t\twidth: pageWidth,\n\t\t\t\t\theight: pageHeight\n\t\t\t\t});\n\t\t\t}).then((objects) => {\n\t\t\t\tconsole.log(\"Opening \" + httpServer + \"?locale=\" + language + \" for \" + displayLanguage);\n\t\t\t\treturn objects.page.openAsync(httpServer + \"?locale=\" + language);\n\t\t\t}).then((objects) => {\n\t\t\t\tconsole.log(\"Rendered HTML, the image will be saved after 2 seconds.\");\n\t\t\t\tif (objects.ret[0] != \"success\") {\n\t\t\t\t\tthrow objects.ret[0];\n\t\t\t\t}\n\t\t\t\treturn timeout(2000).then(() => {\n\t\t\t\t\treturn objects.page.renderAsync(path.join(__dirname, 'Web Front End Stack' + (language === \"\" ? \"\" : \".\") + language + '.png'));\n\t\t\t\t});\n\t\t\t}).then((objects) => {\n\t\t\t\tconsole.log(\"The image(\" + displayLanguage + \") saved successfully!\");\n\t\t\t\tobjects.page.close();\n\t\t\t\tobjects.phantom.exit();\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t\treturn promise;\n\n\t}\n\n\n\t/**\n\t * To rebuild the README.md\n\t * @return Promise<any>\n\t */\n\tfunction readme(language) {\n\t\tlet extension = (language === \"\" ? \"\" : \".\") + language;\n\t\tlet promise = new Promise((resolve, reject) => {\n\t\t\tfs.readFile('./README' + extension + '.md', \"utf-8\", (err, content) => {\n\t\t\t\tif (err) return reject(err);\n\t\t\t\tresolve(content);\n\t\t\t});\n\t\t});\n\t\treturn promise.then((fileContent) => {\n\t\t\tlet ret = buildReadme(jsonData, language, 0);\n\t\t\tfileContent = fileContent.replace(/<\\!--BUILD_START-->[\\d\\D]+?<\\!--BUILD_END-->/, \"{%BuildStart%}\");\n\t\t\tfs.writeFileSync('./README' + extension + '.md', fileContent.replace(\"{%BuildStart%}\", \"<!--BUILD_START-->\\n\\n\" + ret + \"\\n\\n<!--BUILD_END-->\", \"utf-8\"));\n\t\t\tconsole.log('Readme (' + language + ') built successfully!');\n\t\t});\n\t}\n\n\n\t/**\n\t * To start an express server\n\t * @return Promise<any>\n\t */\n\tfunction server() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\treturn app\n\t\t\t\t.set('port', options.port)\n\t\t\t\t.set('view engine', 'html')\n\t\t\t\t.use(Express.static(path.join(__dirname, '/ux')))\n\t\t\t\t.use('/', function (req, res) {\n\t\t\t\t\tres.redirect('/WebFrontEndStack.htm?locale=' + req.query.locale);\n\t\t\t\t})\n\t\t\t\t.listen(options.port, function () {\n\t\t\t\t\tconsole.info('Express started on: http://127.0.0.1:' + options.port);\n\t\t\t\t\tresolve(app);\n\t\t\t\t});\n\t\t});\n\t}\n\n\tif (options.help) {\n\t\tlet usage = cli.getUsage({\n\t\t\ttitle: \"Generator\"\n\t\t});\n\t\tconsole.log(usage);\n\t\treturn;\n\t}\n\n\tlet queue = [];\n\tqueue.push(server());\n\n\t// Firstly, check languages.\n\n\tlanguages.push(\"\");\n\tfor (let item in jsonData.languages) {\n\t\tlanguages.push(item);\n\t}\n\n\tlanguages.map((val) => {\n\t\tif (options.phantomjs) {\n\t\t\tqueue.push(phantomjs(val));\n\t\t}\n\t\tif (options.readme) {\n\t\t\tqueue.push(readme(val));\n\t\t}\n\t});\n\n\tif (options.updatestargazers) {\n\t\tqueue.push(updatestargazers());\n\t}\n\n\tlet promise = Promise.all(queue);\n\n\tif (queue.length > 1) { // for somebody who only want to start the server.\n\t\tconsole.log(\"You can press Ctrl+C to exit if tasks finished.\");\n\t\tpromise.then(() => {\n\t\t\tconsole.log(\"OK!\");\n\t\t\tprocess.exit(0);\n\t\t});\n\t}\n})();\n"
  },
  {
    "path": "06-WebFrontEndStack-master/package.json",
    "content": "{\n  \"name\": \"WebFrontEndStack\",\n  \"version\": \"2.0.0\",\n  \"description\": \"Generate a image for web front-end stack.\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"build\": \"node index --phantomjs --readme\",\n    \"start\": \"node index\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/unruledboy/WebFrontEndStack.git\"\n  },\n  \"keywords\": [\n    \"Web\",\n    \"FrontEnd\",\n    \"Stack\"\n  ],\n  \"author\": [\n    \"unruledboy <unruledboy@gmail.com>\",\n    \"zsx <zsx@zsxsoft.com>\"\n  ],\n  \"license\": \"ISC\",\n  \"bugs\": {\n    \"url\": \"https://github.com/unruledboy/WebFrontEndStack/issues\"\n  },\n  \"homepage\": \"https://github.com/unruledboy/WebFrontEndStack\",\n  \"dependencies\": {\n    \"async\": \"^1.4.2\",\n    \"command-line-args\": \"^1.0.1\",\n    \"express\": \"^4.13.3\",\n    \"phantomjs-promise\": \"0.0.1\",\n    \"request\": \"^2.61.0\"\n  }, \n  \"devDependencies\": {\n    \"phantomjs\": \"^1.9.18\",\n    \"weak\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "06-WebFrontEndStack-master/ux/WebFrontEndStack.htm",
    "content": "﻿<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>Web Front End Stack</title>\n\t<meta name=\"keywords\" content=\"web,front end, frontend,HTML,CSS,XML,JavaScript,stack,full stack,web front end stack,WebFontEndStack\">\n    <style type=\"text/css\">\n    .node {\n        cursor: pointer;\n    }\n    \n    .overlay {\n        background-color: #EEE;\n    }\n    \n    .node circle {\n        fill: #fff;\n        stroke: steelblue;\n        stroke-width: 1.5px;\n    }\n    \n    .node text {\n        font-size: 10px;\n    }\n    \n    .link {\n        fill: none;\n        stroke: #ccc;\n        stroke-width: 1.5px;\n    }\n    \n    .templink {\n        fill: none;\n        stroke: red;\n        stroke-width: 3px;\n    }\n    \n    .ghostCircle.show {\n        display: block;\n    }\n    \n    .ghostCircle,\n    .activeDrag .ghostCircle {\n        display: none;\n    }\n    \n    html,\n    body {\n        background-color: #EEE;\n        margin: 0px;\n        height: 100%;\n    }\n    \n    body {\n        float: left;\n        font-family: 'PT Sans', '微软雅黑 Light', '方正兰亭纤黑', '微软雅黑', '新宋体', sans-serif;\n    }\n    \n    .container {\n        margin: 0 0 0 8px;\n        height: 100%;\n        position: fixed;\n    }\n    \n    .left {\n        float: left;\n    }\n    \n    .right {\n        float: right;\n        right: 5px;\n        position: fixed;\n    }\n    \n    header {}\n    \n    #tree-container {\n        height: 100%;\n        float: left;\n    }\n    \n    a {\n        text-decoration: none;\n        color: currentColor;\n    }\n    </style>\n    <link href='//fonts.googleapis.com/css?family=PT+Sans' rel='stylesheet' type='text/css'>\n    <script src=\"//cdnjscn.b0.upaiyun.com/libs/jquery/2.1.1/jquery.min.js\"></script>\n    <script src=\"//cdnjscn.b0.upaiyun.com/libs/d3/3.4.11/d3.min.js\"></script>\n    <script src=\"dndTree.js\"></script>\n</head>\n\n<body>\n    <div class=\"container\">\n        <header>\n            <div class=\"left\">\n                <h1><a href=\"https://github.com/unruledboy/WebFrontEndStack\" target=\"_blank\">Web Front-end Stack v2.5</a></h1>\n            </div>\n            <div class=\"right\">\n                <p><a href=\"http://github.com/unruledboy\">Wilson Chen (twitter@unruleboy) - unruledboy@gmail.com</a></p>\n                <p><a href=\"http://github.com/zsxsoft\">zsx (GitHub@zsxsoft) - zsx@zsxsoft.com</a></p>\n            </div>\n        </header>\n        <section id=\"tree-container\"></section>\n    </div>\n</body>\n\n</html>\n"
  },
  {
    "path": "06-WebFrontEndStack-master/ux/WebFrontEndStack.json",
    "content": "{\n\t\"name\": \"Web Front End\",\n\t\"languages\": {\n\t\t\"zh-cn\": \"Web前端开发技术栈\",\n\t\t\"es-es\": \"Web Front End\"\n\t},\n\t\"children\": [{\n\t\t\"name\": \"Browser\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"浏览器\",\n\t\t\t\"es-es\": \"Navegadores\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Internet Explorer\",\n\t\t\t\"url\": \"http://windows.microsoft.com/en-us/internet-explorer/download-ie\"\n\t\t}, {\n\t\t\t\"name\": \"Chrome\",\n\t\t\t\"url\": \"http://www.google.com/chrome/\"\n\t\t}, {\n\t\t\t\"name\": \"Firefox\",\n\t\t\t\"url\": \"https://www.mozilla.org/\"\n\t\t}, {\n\t\t\t\"name\": \"Safari\",\n\t\t\t\"url\": \"http://www.apple.com/safari/\"\n\t\t}, {\n\t\t\t\"name\": \"Opera\",\n\t\t\t\"url\": \"http://www.opera.com/\"\n\t\t}, {\n\t\t\t\"name\": \"Edge\",\n\t\t\t\"url\": \"https://www.microsoft.com/en-us/windows/microsoft-edge\"\n\t\t}, {\n\t\t\t\"name\": \"Netscape ;-)\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/Netscape\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Protocol\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"协议\",\n\t\t\t\"es-es\": \"Protocolos\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"HTTP/1.1\",\n\t\t\t\"url\": \"https://www.ietf.org/rfc/rfc2616.txt\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"URI\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"链接\"\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\t\"name\": \"Session\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"会话\",\n\t\t\t\t\t\"es-es\": \"Sesión\"\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\t\"name\": \"Authentication\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"授权\",\n\t\t\t\t\t\"es-es\": \"Autenticación\"\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\t\"name\": \"Request\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"请求\",\n\t\t\t\t\t\"es-es\": \"Petición\"\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\t\"name\": \"Response\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"响应\",\n\t\t\t\t\t\"es-es\": \"Respuesta\"\n\t\t\t\t}\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"HTTP/2\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/HTTP/2\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Compression\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"压缩\",\n\t\t\t\t\t\"es-es\": \"Compresión\"\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\t\"name\": \"Minification\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"打包\",\n\t\t\t\t\t\"es-es\": \"Minificación\"\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\t\"name\": \"Server Push\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"zh-cn\": \"服务器端推送\"\n\t\t\t\t}\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"WebSocket\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"The 3 Pillars\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"Web三剑客\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"HTML (HyperText Markup Language)\"\n\t\t}, {\n\t\t\t\"name\": \"CSS (Cascading Style Sheets)\"\n\t\t}, {\n\t\t\t\"name\": \"JavaScript\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Standards\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"标准\",\n\t\t\t\"es-es\": \"Estándares\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"W3C\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"HTML\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"CSS\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"XHTML\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"XML\"\n\t\t\t}]\n\t\t}]\n\t}, {\n\t\t\"name\": \"Core Concepts\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"核心概念\",\n\t\t\t\"es-es\": \"Conceptons principales\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"HTML\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"DOM\",\n\t\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Element\",\n\t\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/Web/API/Element\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Attribute\"\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"JavaScript\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Prototype\",\n\t\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Scope\",\n\t\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/Glossary/Scope\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Closure\",\n\t\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"JSON (JavaSript Object Notation)\",\n\t\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/Glossary/JSON\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"AJAX (Asynchronous JavaScript and XML)\",\n\t\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/AJAX\"\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"CSS\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Selector\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Priority\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Specificity\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Box Model\"\n\t\t\t}]\n\t\t}]\n\t}, {\n\t\t\"name\": \"Rendering Engine\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"渲染引擎\",\n\t\t\t\"es-es\": \"Motores de renderizado\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Trident (IE)\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/Trident_(layout_engine)\"\n\t\t}, {\n\t\t\t\"name\": \"Blink / prev. WebKit (Chrome)\",\n\t\t\t\"url\": \"http://www.chromium.org/blink\",\n\t\t\t\"github\": \"\"\n\t\t}, {\n\t\t\t\"name\": \"Gecko (Firefox)\",\n\t\t\t\"url\": \"https://developer.mozilla.org/en-us/docs/Mozilla/Gecko\"\n\t\t}, {\n\t\t\t\"name\": \"WebKit (Safari)\",\n\t\t\t\"url\": \"http://www.webkit.org/\"\n\t\t}, {\n\t\t\t\"name\": \"Blink / prev. Presto (Opera)\",\n\t\t\t\"url\": \"http://www.chromium.org/blink\",\n\t\t\t\"github\": \"\"\n\t\t}, {\n\t\t\t\"name\": \"EdgeHTML (Edge)\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/EdgeHTML\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"JavaScript Engine\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"脚本引擎\",\n\t\t\t\"es-es\": \"Motores JavaScript\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"JScript (IE8- / ASP)\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/JScript\"\n\t\t}, {\n\t\t\t\"name\": \"Chakra (IE9+ / Edge)\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/Chakra_(JScript_engine)\"\n\t\t}, {\n\t\t\t\"name\": \"V8 (Chrome / Opera / Nodejs / MongoDB)\",\n\t\t\t\"url\": \"https://developers.google.com/v8/?hl=zh-CN\",\n\t\t\t\"github\": \"https://github.com/v8/v8/\",\n\t\t\t\"stargazers\": 2577\n\t\t}, {\n\t\t\t\"name\": \"SpiderMonkey (Firefox)\",\n\t\t\t\"url\": \" https://developer.mozilla.org/en-us/docs/Mozilla/Projects/SpiderMonkey\"\n\t\t}, {\n\t\t\t\"name\": \"JavaScriptCore (Safari)\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/WebKit#JavaScriptCore\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Runtime\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"运行时\",\n\t\t\t\"es-es\": \"Tiempo de ejecución\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Cookie\"\n\t\t}, {\n\t\t\t\"name\": \"Local Cache\"\n\t\t}, {\n\t\t\t\"name\": \"Session Storage\"\n\t\t}, {\n\t\t\t\"name\": \"Local Storage\"\n\t\t}, {\n\t\t\t\"name\": \"Components\",\n\t\t\t\"languages\": {\n\t\t\t\t\"es-es\": \"Componentes\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Extensions\",\n\t\t\t\t\"languages\": {\n\t\t\t\t\t\"es-es\": \"Extensiones\"\n\t\t\t\t}\n\t\t\t}, {\n\t\t\t\t\"name\": \"Plugins\"\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Resources\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Images\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Icons\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Fonts\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Audios\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Videos\"\n\t\t\t}]\n\t\t}]\n\t}, {\n\t\t\"name\": \"Editors\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"编辑器\",\n\t\t\t\"es-es\": \"Editores de texto\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Sublime Text\",\n\t\t\t\"url\": \"http://www.sublimetext.com/\"\n\t\t}, {\n\t\t\t\"name\": \"WebStorm\",\n\t\t\t\"url\": \"https://www.jetbrains.com/webstorm/\"\n\t\t}, {\n\t\t\t\"name\": \"Atom\",\n\t\t\t\"url\": \"https://atom.io/\",\n\t\t\t\"github\": \"https://github.com/atom/atom/\",\n\t\t\t\"stargazers\": 19510\n\t\t}, {\n\t\t\t\"name\": \"Vim\",\n\t\t\t\"url\": \"http://www.vim.org/\"\n\t\t}, {\n\t\t\t\"name\": \"Emacs\",\n\t\t\t\"url\": \"https://www.gnu.org/software/emacs/\"\n\t\t}, {\n\t\t\t\"name\": \"Brackets\",\n\t\t\t\"url\": \"http://brackets.io/\",\n\t\t\t\"github\": \"https://github.com/adobe/brackets/\",\n\t\t\t\"stargazers\": 23091\n\t\t}, {\n\t\t\t\"name\": \"Light Table\",\n\t\t\t\"url\": \"http://lighttable.com/\",\n\t\t\t\"github\": \"https://github.com/LightTable/LightTable/\",\n\t\t\t\"stargazers\": 7926\n\t\t}, {\n\t\t\t\"name\": \"Visual Studio\",\n\t\t\t\"url\": \"https://www.visualstudio.com/\"\n\t\t}, {\n\t\t\t\"name\": \"Visual Studio Code\",\n\t\t\t\"url\": \"https://code.visualstudio.com/\",\n\t\t\t\"github\": \"https://github.com/Microsoft/vscode\",\n\t\t\t\"stargazers\": 6652\n\t\t}, {\n\t\t\t\"name\": \"Dreamweaver ;-)\"\n\t\t}, {\n\t\t\t\"name\": \"FrontPage / SharePoint Designer ;-)\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Build Tasks\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"编译任务\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Minification\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"精简\",\n\t\t\t\t\"es-es\": \"Minificación\"\n\t\t\t}\n\t\t}, {\n\t\t\t\"name\": \"Compilation\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"编译\",\n\t\t\t\t\"es-es\": \"Compilación\"\n\t\t\t}\n\t\t}, {\n\t\t\t\"name\": \"Concatenation\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"合并\",\n\t\t\t\t\"es-es\": \"Concatenación\"\n\t\t\t}\n\t\t}, {\n\t\t\t\"name\": \"Uglification\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"混淆\"\n\t\t\t}\n\t\t}, {\n\t\t\t\"name\": \"Image Optimization\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"图像优化\",\n\t\t\t\t\"es-es\": \"Optimización de imágenes\"\n\t\t\t}\n\t\t}, {\n\t\t\t\"name\": \"Unit Testing\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"单元测试\",\n\t\t\t\t\"es-es\": \"Tests unitarios\"\n\t\t\t}\n\t\t}]\n\t}, {\n\t\t\"name\": \"Build Tools\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"编译工具\",\n\t\t\t\"es-es\": \"Herramientas de tareas\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Grunt\",\n\t\t\t\"url\": \"http://www.gruntjs.com/\",\n\t\t\t\"github\": \"https://github.com/cowboy/jquery-tiny-pubsub/\",\n\t\t\t\"stargazers\": 662\n\t\t}, {\n\t\t\t\"name\": \"Gulp\",\n\t\t\t\"url\": \"http://gulpjs.com/\",\n\t\t\t\"github\": \"https://github.com/gulpjs/gulp/\",\n\t\t\t\"stargazers\": 15661\n\t\t}, {\n\t\t\t\"name\": \"Brunch\",\n\t\t\t\"url\": \"http://brunch.io/\",\n\t\t\t\"github\": \"https://github.com/brunch/brunch/\",\n\t\t\t\"stargazers\": 4472\n\t\t}, {\n\t\t\t\"name\": \"Yeoman\",\n\t\t\t\"url\": \"http://yeoman.io/\"\n\t\t}, {\n\t\t\t\"name\": \"Broccoli\",\n\t\t\t\"github\": \"https://github.com/broccolijs/broccoli/\",\n\t\t\t\"stargazers\": 2391\n\t\t}]\n\t}, {\n\t\t\"name\": \"Debug\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"调试\",\n\t\t\t\"es-es\": \"Depuración\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Developer Tools\",\n\t\t\t\"url\": \"https://developer.chrome.com/devtools\"\n\t\t}, {\n\t\t\t\"name\": \"Firebug\",\n\t\t\t\"url\": \"http://getfirebug.com/\",\n\t\t\t\"github\": \"https://github.com/firebug/firebug/\",\n\t\t\t\"stargazers\": 924\n\t\t}]\n\t}, {\n\t\t\"name\": \"Base Tools\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"基础工具\",\n\t\t\t\"es-es\": \"Herramientas base\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Node.js\",\n\t\t\t\"url\": \"https://nodejs.org/\",\n\t\t\t\"github\": \"https://github.com/joyent/node/\",\n\t\t\t\"stargazers\": 37851\n\t\t}, {\n\t\t\t\"name\": \"Phantom.js\",\n\t\t\t\"url\": \"http://phantomjs.org/\",\n\t\t\t\"github\": \"https://github.com/ariya/phantomjs/\",\n\t\t\t\"stargazers\": 14950\n\t\t}, {\n\t\t\t\"name\": \"SpiderMonkey\",\n\t\t\t\"url\": \"https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Quality\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"质量控制\",\n\t\t\t\"es-es\": \"Calidad\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"JSLint\",\n\t\t\t\"url\": \"http://www.jslint.com/\",\n\t\t\t\"github\": \"https://github.com/douglascrockford/JSLint/\",\n\t\t\t\"stargazers\": 2382\n\t\t}, {\n\t\t\t\"name\": \"JSHint\",\n\t\t\t\"url\": \"http://jshint.com/\",\n\t\t\t\"github\": \"https://github.com/jshint/jshint/\",\n\t\t\t\"stargazers\": 5384\n\t\t}, {\n\t\t\t\"name\": \"jscs\",\n\t\t\t\"url\": \"http://jscs.info/\",\n\t\t\t\"github\": \"https://github.com/jscs-dev/node-jscs\",\n\t\t\t\"stargazers\": 3982\n\t\t}, {\n\t\t\t\"name\": \"Closure Linter\",\n\t\t\t\"url\": \"https://developers.google.com/closure/utilities/\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Package\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"包管理\",\n\t\t\t\"es-es\": \"Gestores de paquetes\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"npm\",\n\t\t\t\"url\": \"https://www.npmjs.com/\",\n\t\t\t\"github\": \"https://github.com/npm/npm/\",\n\t\t\t\"stargazers\": 6816\n\t\t}, {\n\t\t\t\"name\": \"Bower\",\n\t\t\t\"url\": \"http://bower.io/\",\n\t\t\t\"github\": \"https://github.com/bower/bower/\",\n\t\t\t\"stargazers\": 12747\n\t\t}]\n\t}, {\n\t\t\"name\": \"Test\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"测试\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Tools\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"工具\",\n\t\t\t\t\"es-es\": \"Herramientas\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"QUnit\",\n\t\t\t\t\"url\": \"https://qunitjs.com/\",\n\t\t\t\t\"github\": \"https://github.com/jquery/qunit/\",\n\t\t\t\t\"stargazers\": 3228\n\t\t\t}, {\n\t\t\t\t\"name\": \"Jasmine\",\n\t\t\t\t\"url\": \"http://jasmine.github.io/\",\n\t\t\t\t\"github\": \"https://github.com/jasmine/jasmine/\",\n\t\t\t\t\"stargazers\": 9303\n\t\t\t}, {\n\t\t\t\t\"name\": \"Mocha\",\n\t\t\t\t\"url\": \"https://mochajs.org/\",\n\t\t\t\t\"github\": \"https://github.com/mochajs/mocha/\",\n\t\t\t\t\"stargazers\": 7226\n\t\t\t}, {\n\t\t\t\t\"name\": \"Selenium\",\n\t\t\t\t\"url\": \"http://www.seleniumhq.org/\",\n\t\t\t\t\"github\": \"https://github.com/SeleniumHQ/selenium/\",\n\t\t\t\t\"stargazers\": 1563\n\t\t\t}, {\n\t\t\t\t\"name\": \"WebDriverIO\",\n\t\t\t\t\"url\": \"http://webdriver.io/\",\n\t\t\t\t\"github\": \"https://github.com/webdriverio/webdriverio/\",\n\t\t\t\t\"stargazers\": 1073\n\t\t\t}, {\n\t\t\t\t\"name\": \"Protractor\",\n\t\t\t\t\"url\": \"http://www.protractortest.org/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Chai\",\n\t\t\t\t\"url\": \"http://chaijs.com/\",\n\t\t\t\t\"github\": \"https://github.com/jfirebaugh/konacha/\",\n\t\t\t\t\"stargazers\": 977\n\t\t\t}, {\n\t\t\t\t\"name\": \"Sinon.JS\",\n\t\t\t\t\"url\": \"http://sinonjs.org/\",\n\t\t\t\t\"github\": \"https://github.com/cjohansen/Sinon.JS/\",\n\t\t\t\t\"stargazers\": 2230\n\t\t\t}, {\n\t\t\t\t\"name\": \"Karma\",\n\t\t\t\t\"url\": \"http://karma-runner.github.io/\",\n\t\t\t\t\"github\": \"https://github.com/karma-runner/karma/\",\n\t\t\t\t\"stargazers\": 5550\n\t\t\t}, {\n\t\t\t\t\"name\": \"nodeunit\",\n\t\t\t\t\"github\": \"https://github.com/caolan/nodeunit/\",\n\t\t\t\t\"stargazers\": 1608\n\t\t\t}, {\n\t\t\t\t\"name\": \"tape\",\n\t\t\t\t\"github\": \"http://github.com/substack/tape\",\n\t\t\t\t\"stargazers\": 1264\n\t\t\t}, {\n\t\t\t\t\"name\": \"nightmare\",\n\t\t\t\t\"url\": \"http://nightmarejs.org/\",\n\t\t\t\t\"github\": \"https://github.com/segmentio/nightmare\",\n\t\t\t\t\"stargazers\": 6110\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Composite\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"在线工具\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Sauce Labs\",\n\t\t\t\t\"url\": \"https://saucelabs.com/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Browser Stack\",\n\t\t\t\t\"url\": \"https://www.browserstack.com/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Browser Shots\",\n\t\t\t\t\"url\": \"http://browsershots.org/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Browserling\",\n\t\t\t\t\"url\": \"https://www.browserling.com/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Browser Sandbox\",\n\t\t\t\t\"url\": \"https://spoon.net/browsers/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Cross Browser Testing\",\n\t\t\t\t\"url\": \"https://crossbrowsertesting.com/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Browsera\",\n\t\t\t\t\"url\": \"http://www.browsera.com/\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"SortSite\",\n\t\t\t\t\"url\": \"http://www.powermapper.com/products/sortsite/checks/browser-compatibility/\"\n\t\t\t}]\n\t\t}]\n\t}, {\n\t\t\"name\": \"Frameworks / Libraries\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"库 / 框架\",\n\t\t\t\"es-es\": \"Librerías y frameworks\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"JavaScript base library\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"基础库\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"jQuery\",\n\t\t\t\t\"url\": \"https://jquery.com/\",\n\t\t\t\t\"github\": \"https://github.com/jquery/jquery/\",\n\t\t\t\t\"stargazers\": 35652\n\t\t\t}, {\n\t\t\t\t\"name\": \"Prototype\",\n\t\t\t\t\"url\": \"http://prototypejs.org/\",\n\t\t\t\t\"github\": \"https://github.com/sstephenson/prototype/\",\n\t\t\t\t\"stargazers\": 3022\n\t\t\t}, {\n\t\t\t\t\"name\": \"Zepto\",\n\t\t\t\t\"url\": \"http://zeptojs.com/\",\n\t\t\t\t\"github\": \"https://github.com/madrobby/zepto/\",\n\t\t\t\t\"stargazers\": 9109\n\t\t\t}, {\n\t\t\t\t\"name\": \"MooTool\",\n\t\t\t\t\"url\": \"http://mootools.net/\",\n\t\t\t\t\"github\": \"https://github.com/mootools/mootools-core/\",\n\t\t\t\t\"stargazers\": 2168\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Modular\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"模块化\",\n\t\t\t\t\"es-es\": \"Módulos\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"ES6 Module\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"CommonJS\",\n\t\t\t\t\"children\": [{\n\t\t\t\t\t\"name\": \"webpack\",\n\t\t\t\t\t\"url\": \"http://webpack.github.io/\",\n\t\t\t\t\t\"github\": \"https://github.com/webpack/webpack/\",\n\t\t\t\t\t\"stargazers\": 7271\n\t\t\t\t}, {\n\t\t\t\t\t\"name\": \"browserify\",\n\t\t\t\t\t\"url\": \"http://browserify.org/\",\n\t\t\t\t\t\"github\": \"https://github.com/substack/node-browserify/\",\n\t\t\t\t\t\"stargazers\": 8004\n\t\t\t\t}]\n\t\t\t}, {\n\t\t\t\t\"name\": \"AMD\",\n\t\t\t\t\"children\": [{\n\t\t\t\t\t\"name\": \"RequireJS\",\n\t\t\t\t\t\"url\": \"http://requirejs.org/\",\n\t\t\t\t\t\"github\": \"https://github.com/jrburke/requirejs/\",\n\t\t\t\t\t\"stargazers\": 8002\n\t\t\t\t}]\n\t\t\t}, {\n\t\t\t\t\"name\": \"UMD\",\n\t\t\t\t\"children\": [{\n\t\t\t\t\t\"name\": \"umd\",\n\t\t\t\t\t\"github\": \"https://github.com/umdjs/umd/\",\n\t\t\t\t\t\"stargazers\": 2764\n\t\t\t\t}]\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"JavaScript Framework\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"框架\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"AngularJS\",\n\t\t\t\t\"url\": \"https://angularjs.org/\",\n\t\t\t\t\"github\": \"https://github.com/angular/angular.js/\",\n\t\t\t\t\"stargazers\": 41780\n\t\t\t}, {\n\t\t\t\t\"name\": \"Backbone\",\n\t\t\t\t\"url\": \"http://backbonejs.org/\",\n\t\t\t\t\"github\": \"https://github.com/jashkenas/backbone/\",\n\t\t\t\t\"stargazers\": 22720\n\t\t\t}, {\n\t\t\t\t\"name\": \"Knockout\",\n\t\t\t\t\"url\": \"http://knockoutjs.com/\",\n\t\t\t\t\"github\": \"https://github.com/SteveSanderson/knockout/\",\n\t\t\t\t\"stargazers\": 6660\n\t\t\t}, {\n\t\t\t\t\"name\": \"Ember\",\n\t\t\t\t\"url\": \"http://emberjs.com/\",\n\t\t\t\t\"github\": \"https://github.com/emberjs/ember.js/\",\n\t\t\t\t\"stargazers\": 14555\n\t\t\t}, {\n\t\t\t\t\"name\": \"React\",\n\t\t\t\t\"url\": \"http://facebook.github.io/react/\",\n\t\t\t\t\"github\": \"https://github.com/facebook/react/\",\n\t\t\t\t\"stargazers\": 26617\n\t\t\t}, {\n\t\t\t\t\"name\": \"polymer\",\n\t\t\t\t\"url\": \"https://www.polymer-project.org/\",\n\t\t\t\t\"github\": \"https://github.com/polymer/polymer/\",\n\t\t\t\t\"stargazers\": 12217\n\t\t\t}, {\n\t\t\t\t\"name\": \"Deft.js\",\n\t\t\t\t\"url\": \"http://deftjs.org/\",\n\t\t\t\t\"github\": \"https://github.com/deftjs/DeftJS/\",\n\t\t\t\t\"stargazers\": 308\n\t\t\t}, {\n\t\t\t\t\"name\": \"Vue\",\n\t\t\t\t\"url\": \"http://vuejs.org/\",\n\t\t\t\t\"github\": \"https://github.com/yyx990803/vue/\",\n\t\t\t\t\"stargazers\": 6261\n\t\t\t}, {\n\t\t\t\t\"name\": \"Riot\",\n\t\t\t\t\"url\": \"http://riotjs.com/\",\n\t\t\t\t\"github\": \"https://github.com/riot/riot\",\n\t\t\t\t\"stargazers\": 7875\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"UI framework\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"UI框架\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Bootstrap\",\n\t\t\t\t\"url\": \"http://getbootstrap.com/\",\n\t\t\t\t\"github\": \"https://github.com/twbs/bootstrap/\",\n\t\t\t\t\"stargazers\": 84763\n\t\t\t}, {\n\t\t\t\t\"name\": \"Semantic UI\",\n\t\t\t\t\"url\": \"http://semantic-ui.com/\",\n\t\t\t\t\"github\": \"https://github.com/Semantic-Org/Semantic-UI/\",\n\t\t\t\t\"stargazers\": 19552\n\t\t\t}, {\n\t\t\t\t\"name\": \"Foundation\",\n\t\t\t\t\"url\": \"http://foundation.zurb.com/\",\n\t\t\t\t\"github\": \"https://github.com/zurb/foundation/\",\n\t\t\t\t\"stargazers\": 20711\n\t\t\t}, {\n\t\t\t\t\"name\": \"Material UI\",\n\t\t\t\t\"url\": \"http://material-ui.com/\",\n\t\t\t\t\"github\": \"https://github.com/callemall/material-ui/\",\n\t\t\t\t\"stargazers\": 10048\n\t\t\t}, {\n\t\t\t\t\"name\": \"WinJS\",\n\t\t\t\t\"url\": \"https://dev.windows.com/en-us/develop/winjs\",\n\t\t\t\t\"github\": \"https://github.com/winjs/winjs\",\n\t\t\t\t\"stargazers\": 3621\n\t\t\t}, {\n\t\t\t\t\"name\": \"Pure\",\n\t\t\t\t\"url\": \"http://purecss.io/\",\n\t\t\t\t\"github\": \"https://github.com/yahoo/pure/\",\n\t\t\t\t\"stargazers\": 12367\n\t\t\t}, {\n\t\t\t\t\"name\": \"Amaze UI\",\n\t\t\t\t\"url\": \"http://amazeui.org/\",\n\t\t\t\t\"github\": \"https://github.com/allmobilize/amazeui\",\n\t\t\t\t\"stargazers\": 5965\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"WebSocket\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Socket.io\",\n\t\t\t\t\"url\": \"http://socket.io/\",\n\t\t\t\t\"github\": \"https://github.com/Automattic/socket.io/\",\n\t\t\t\t\"stargazers\": 19169\n\t\t\t}, {\n\t\t\t\t\"name\": \"web-socket-js\",\n\t\t\t\t\"github\": \"https://github.com/gimite/web-socket-js/\",\n\t\t\t\t\"stargazers\": 2115\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Data Visualization\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"数据可视化\",\n\t\t\t\t\"es-es\": \"Visualización de datos\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"D3\",\n\t\t\t\t\"url\": \"http://d3js.org/\",\n\t\t\t\t\"github\": \"https://github.com/mbostock/d3/wiki/Gallery/\",\n\t\t\t\t\"stargazers\": 40794\n\t\t\t}, {\n\t\t\t\t\"name\": \"Echarts\",\n\t\t\t\t\"url\": \"http://echarts.baidu.com\",\n\t\t\t\t\"github\": \"https://github.com/ecomfe/esl/\",\n\t\t\t\t\"stargazers\": 396\n\t\t\t}, {\n\t\t\t\t\"name\": \"HighCharts\",\n\t\t\t\t\"url\": \"http://www.highcharts.com/\",\n\t\t\t\t\"github\": \"https://github.com/highslide-software/highcharts.com/\",\n\t\t\t\t\"stargazers\": 4041\n\t\t\t}, {\n\t\t\t\t\"name\": \"Vis.js\",\n\t\t\t\t\"url\": \"http://visjs.org/\",\n\t\t\t\t\"github\": \"https://github.com/almende/vis/\",\n\t\t\t\t\"stargazers\": 2993\n\t\t\t}, {\n\t\t\t\t\"name\": \"Flot\",\n\t\t\t\t\"url\": \"http://www.flotcharts.org/\",\n\t\t\t\t\"github\": \"https://github.com/flot/flot/\",\n\t\t\t\t\"stargazers\": 4531\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"WebGL\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Three.js\",\n\t\t\t\t\"url\": \"http://threejs.org/\",\n\t\t\t\t\"github\": \"https://github.com/mrdoob/three.js/\",\n\t\t\t\t\"stargazers\": 20758\n\t\t\t}, {\n\t\t\t\t\"name\": \"Babylon.js\",\n\t\t\t\t\"url\": \"http://www.babylonjs.com/\",\n\t\t\t\t\"github\": \"https://github.com/BabylonJS/Babylon.js/\",\n\t\t\t\t\"stargazers\": 2349\n\t\t\t}, {\n\t\t\t\t\"name\": \"Pixi.js\",\n\t\t\t\t\"url\": \"http://www.pixijs.com/\",\n\t\t\t\t\"github\": \"https://github.com/GoodBoyDigital/pixi.js/\",\n\t\t\t\t\"stargazers\": 8361\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"CSS3 Animation\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"CSS3 动画\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Animate.css\",\n\t\t\t\t\"url\": \"https://daneden.github.io/animate.css/\",\n\t\t\t\t\"github\": \"https://github.com/daneden/animate.css/\",\n\t\t\t\t\"stargazers\": 24549\n\t\t\t}, {\n\t\t\t\t\"name\": \"bounce.js\",\n\t\t\t\t\"url\": \"http://bouncejs.com/\",\n\t\t\t\t\"github\": \"https://github.com/tictail/bounce.js/\",\n\t\t\t\t\"stargazers\": 3727\n\t\t\t}, {\n\t\t\t\t\"name\": \"Effeckt.css\",\n\t\t\t\t\"url\": \"https://h5bp.github.io/Effeckt.css/\",\n\t\t\t\t\"github\": \"https://github.com/h5bp/Effeckt.css/\",\n\t\t\t\t\"stargazers\": 9777\n\t\t\t}, {\n\t\t\t\t\"name\": \"move.js\",\n\t\t\t\t\"url\": \"https://visionmedia.github.io/move.js/\",\n\t\t\t\t\"github\": \"https://github.com/visionmedia/move.js/\",\n\t\t\t\t\"stargazers\": 2830\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Flow Controller\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"流程控制\",\n\t\t\t\t\"es-es\": \"Control de flujo\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"ES6\",\n\t\t\t\t\"children\": [{\n\t\t\t\t\t\"name\": \"Promise\"\n\t\t\t\t}, {\n\t\t\t\t\t\"name\": \"Generator\"\n\t\t\t\t}]\n\t\t\t}, {\n\t\t\t\t\"name\": \"ES7\",\n\t\t\t\t\"children\": [{\n\t\t\t\t\t\"name\": \"yield\"\n\t\t\t\t}, {\n\t\t\t\t\t\"name\": \"await\"\n\t\t\t\t}]\n\t\t\t}, {\n\t\t\t\t\"name\": \"async\",\n\t\t\t\t\"github\": \"https://github.com/caolan/async/\",\n\t\t\t\t\"stargazers\": 14156\n\t\t\t}, {\n\t\t\t\t\"name\": \"co\",\n\t\t\t\t\"github\": \"https://github.com/tj/co/\",\n\t\t\t\t\"stargazers\": 3502\n\t\t\t}, {\n\t\t\t\t\"name\": \"Promise\",\n\t\t\t\t\"children\": [{\n\t\t\t\t\t\"name\": \"Bluebird\",\n\t\t\t\t\t\"github\": \"https://github.com/petkaantonov/bluebird/\",\n\t\t\t\t\t\"stargazers\": 7530\n\t\t\t\t}, {\n\t\t\t\t\t\"name\": \"q\",\n\t\t\t\t\t\"github\": \"https://github.com/kriskowal/q/\",\n\t\t\t\t\t\"stargazers\": 9460\n\t\t\t\t}, {\n\t\t\t\t\t\"name\": \"when.js\",\n\t\t\t\t\t\"github\": \"https://github.com/cujojs/when/\",\n\t\t\t\t\t\"stargazers\": 2579\n\t\t\t\t}]\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Functional\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"函数式编程\",\n\t\t\t\t\"es-es\": \"Funcional\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"bacon.js\",\n\t\t\t\t\"url\": \"http://baconjs.github.io/\",\n\t\t\t\t\"github\": \"https://github.com/baconjs/bacon.js/\",\n\t\t\t\t\"stargazers\": 4498\n\t\t\t}, {\n\t\t\t\t\"name\": \"immutable.js\",\n\t\t\t\t\"url\": \"https://facebook.github.io/immutable-js/\",\n\t\t\t\t\"github\": \"https://github.com/facebook/immutable-js/\",\n\t\t\t\t\"stargazers\": 7999\n\t\t\t}, {\n\t\t\t\t\"name\": \"ramda\",\n\t\t\t\t\"url\": \"http://ramdajs.com/\",\n\t\t\t\t\"github\": \"http://github.com/ramda/ramda\",\n\t\t\t\t\"stargazers\": 2792\n\t\t\t}, {\n\t\t\t\t\"name\": \"underscore.js\",\n\t\t\t\t\"url\": \"http://underscorejs.org/\",\n\t\t\t\t\"github\": \"https://github.com/jashkenas/underscore\",\n\t\t\t\t\"stargazers\": 15823\n\t\t\t}, {\n\t\t\t\t\"name\": \"lodash\",\n\t\t\t\t\"url\": \"https://lodash.com/\",\n\t\t\t\t\"github\": \"https://github.com/lodash/lodash\",\n\t\t\t\t\"stargazers\": 11071\n\t\t\t}, {\n\t\t\t\t\"name\": \"ReactiveX\",\n\t\t\t\t\"url\": \"http://reactivex.io/\",\n\t\t\t\t\"github\": \"https://github.com/Reactive-Extensions/RxJS\",\n\t\t\t\t\"stargazers\": 6720\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Mobile UI\",\n\t\t\t\"languages\": {\n\t\t\t\t\"zh-cn\": \"手机 UI 框架\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"jQuery Mobile\",\n\t\t\t\t\"url\": \"https://jquerymobile.com/\",\n\t\t\t\t\"github\": \"https://github.com/jquery/jquery-mobile/\",\n\t\t\t\t\"stargazers\": 9654\n\t\t\t}, {\n\t\t\t\t\"name\": \"Jo\",\n\t\t\t\t\"url\": \"http://joapp.com/\",\n\t\t\t\t\"github\": \"https://github.com/davebalmer/jo/\",\n\t\t\t\t\"stargazers\": 1227\n\t\t\t}, {\n\t\t\t\t\"name\": \"Dojo Mobile\",\n\t\t\t\t\"url\": \"https://dojotoolkit.org/reference-guide/1.10/dojox/mobile.html\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"Lungo\",\n\t\t\t\t\"url\": \"http://lungo.tapquo.com/\",\n\t\t\t\t\"github\": \"https://github.com/tapquo/Lungo.js/\",\n\t\t\t\t\"stargazers\": 2457\n\t\t\t}]\n\t\t}]\n\t}, {\n\t\t\"name\": \"CSS Pre-processors\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"CSS 预处理器\",\n\t\t\t\"es-es\": \"Pre-procesadores CSS\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"LESS\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"LESS\",\n\t\t\t\t\"url\": \"http://lesscss.org/\",\n\t\t\t\t\"github\": \"https://github.com/less/less.js/\",\n\t\t\t\t\"stargazers\": 12679\n\t\t\t}, {\n\t\t\t\t\"name\": \"Hat\",\n\t\t\t\t\"url\": \"http://lesshat.madebysource.com/\",\n\t\t\t\t\"github\": \"https://github.com/csshat/lesshat/\",\n\t\t\t\t\"stargazers\": 2057\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Sass(SCSS)\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"Compass\",\n\t\t\t\t\"url\": \"http://compass-style.org/\",\n\t\t\t\t\"github\": \"https://github.com/chriseppstein/compass/\",\n\t\t\t\t\"stargazers\": 6406\n\t\t\t}, {\n\t\t\t\t\"name\": \"Bourbon\",\n\t\t\t\t\"url\": \"http://bourbon.io/\",\n\t\t\t\t\"github\": \"https://github.com/thoughtbot/bourbon/\",\n\t\t\t\t\"stargazers\": 6178\n\t\t\t}, {\n\t\t\t\t\"name\": \"Gumby\",\n\t\t\t\t\"url\": \"http://www.gumbyframework.com/\",\n\t\t\t\t\"github\": \"https://github.com/GumbyFramework/Gumby/\",\n\t\t\t\t\"stargazers\": 2920\n\t\t\t}]\n\t\t}, {\n\t\t\t\"name\": \"Stylus\",\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"nib\",\n\t\t\t\t\"github\": \"https://github.com/tj/nib/\",\n\t\t\t\t\"stargazers\": 1520\n\t\t\t}]\n\t\t}]\n\t}, {\n\t\t\"name\": \"Future Standards\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"未来标准\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"babel\",\n\t\t\t\"github\": \"https://github.com/babel/babel\",\n\t\t\t\"url\": \"https://babeljs.io/\",\n\t\t\t\"stargazers\": 9712\n\t\t}]\n\t}, {\n\t\t\"name\": \"Template\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"模板引擎\",\n\t\t\t\"es-es\": \"Plantillas\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Handlebars\",\n\t\t\t\"url\": \"http://handlebarsjs.com/\",\n\t\t\t\"github\": \"https://github.com/wycats/handlebars.js/\",\n\t\t\t\"stargazers\": 8808\n\t\t}, {\n\t\t\t\"name\": \"Haml\",\n\t\t\t\"url\": \"http://haml.info/\",\n\t\t\t\"github\": \"https://github.com/haml/haml/\",\n\t\t\t\"stargazers\": 2778\n\t\t}, {\n\t\t\t\"name\": \"Slim\",\n\t\t\t\"url\": \"http://slim-lang.com/\",\n\t\t\t\"github\": \"https://github.com/slim-template/slim/\",\n\t\t\t\"stargazers\": 3480\n\t\t}, {\n\t\t\t\"name\": \"Jade\",\n\t\t\t\"url\": \"http://jade-lang.com/\",\n\t\t\t\"github\": \"https://github.com/jadejs/jade/\",\n\t\t\t\"stargazers\": 8958\n\t\t}, {\n\t\t\t\"name\": \"Ejs\",\n\t\t\t\"url\": \"http://www.embeddedjs.com/\"\n\t\t}, {\n\t\t\t\"name\": \"Spacebars\",\n\t\t\t\"url\": \"http://meteorcapture.com/spacebars/\"\n\t\t}, {\n\t\t\t\"name\": \"mustache\",\n\t\t\t\"url\": \"http://mustache.github.io/\",\n\t\t\t\"github\": \"https://github.com/janl/mustache.js/\",\n\t\t\t\"stargazers\": 8139\n\t\t}]\n\t}, {\n\t\t\"name\": \"Modernisation\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"统一化\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Normalize\",\n\t\t\t\"url\": \"http://necolas.github.io/normalize.css/\",\n\t\t\t\"github\": \"https://github.com/necolas/normalize.css/\",\n\t\t\t\"stargazers\": 17966\n\t\t}, {\n\t\t\t\"name\": \"Reset\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Best Practices\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"最佳实践\",\n\t\t\t\"es-es\": \"Buenas prácticas\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"SEO\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/Search_engine_optimization\"\n\t\t}, {\n\t\t\t\"name\": \"Responsiveness\"\n\t\t}, {\n\t\t\t\"name\": \"CDN\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/Content_delivery_network\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Security\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"安全\",\n\t\t\t\"es-es\": \"Seguridad\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Sandbox\"\n\t\t}, {\n\t\t\t\"name\": \"XSS\",\n\t\t\t\"url\": \"https://en.wikipedia.org/wiki/Cross-site_scripting\"\n\t\t}, {\n\t\t\t\"name\": \"CORS\",\n\t\t\t\"url\": \"http://www.w3.org/TR/cors/\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Intermediate Languages\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"中间语言\",\n\t\t\t\"es-es\": \"Lenguajes intermedios\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"CoffeeScript\",\n\t\t\t\"url\": \"http://coffeescript.org/\",\n\t\t\t\"github\": \"https://github.com/jashkenas/coffeescript/\",\n\t\t\t\"stargazers\": 11755\n\t\t}, {\n\t\t\t\"name\": \"TypeScript\",\n\t\t\t\"url\": \"http://www.typescriptlang.org/\",\n\t\t\t\"github\": \"https://github.com/Microsoft/TypeScript/\",\n\t\t\t\"stargazers\": 6379\n\t\t}, {\n\t\t\t\"name\": \"ClojureScript\",\n\t\t\t\"github\": \"https://github.com/clojure/clojurescript/\",\n\t\t\t\"stargazers\": 4876\n\t\t}, {\n\t\t\t\"name\": \"JSX (Facebook)\",\n\t\t\t\"url\": \"http://facebook.github.io/react/docs/jsx-in-depth.html\"\n\t\t}]\n\t}, {\n\t\t\"name\": \"Mobile Application Development\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"移动应用开发\",\n\t\t\t\"es-es\": \"Empaquetadores de Apps para móvil\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"PhoneGap / Cordova\",\n\t\t\t\"url\": \"https://cordova.apache.org/\",\n\t\t\t\"github\": \"https://github.com/apache/cordova-android/\",\n\t\t\t\"stargazers\": 1166\n\t\t}, {\n\t\t\t\"name\": \"MUI\",\n\t\t\t\"url\": \"http://dev.dcloud.net.cn/mui/\",\n\t\t\t\"github\": \"https://github.com/dcloudio/mui/\",\n\t\t\t\"stargazers\": 1476\n\t\t}, {\n\t\t\t\"name\": \"React Native\",\n\t\t\t\"url\": \"https://facebook.github.io/react-native/\",\n\t\t\t\"github\": \"https://github.com/facebook/react-native/\",\n\t\t\t\"stargazers\": 19802\n\t\t}, {\n\t\t\t\"name\": \"Ionic\",\n\t\t\t\"url\": \"http://ionicframework.com/\",\n\t\t\t\"github\": \"https://github.com/driftyco/ionic/\",\n\t\t\t\"stargazers\": 19472\n\t\t}]\n\t}, {\n\t\t\"name\": \"Desktop Application Development\",\n\t\t\"languages\": {\n\t\t\t\"zh-cn\": \"桌面应用开发\"\n\t\t},\n\t\t\"children\": [{\n\t\t\t\"name\": \"Electron\",\n\t\t\t\"url\": \"http://electron.atom.io/\",\n\t\t\t\"github\": \"https://github.com/atom/electron\",\n\t\t\t\"stargazers\": 16896\n\t\t}, {\n\t\t\t\"name\": \"NW.js\",\n\t\t\t\"url\": \"http://nwjs.io/\",\n\t\t\t\"github\": \"https://github.com/nwjs/nw.js\",\n\t\t\t\"stargazers\": 24680\n\t\t}]\n\t}]\n}\n"
  },
  {
    "path": "06-WebFrontEndStack-master/ux/dndTree.js",
    "content": "﻿\n(function() {\n    var isPhantom = /PhantomJS/ig.test(navigator.userAgent);\n\tvar locale = location.search.split(\"locale=\").pop().split(\"&\").shift();\n\n    var parseName = function(object) {\n        if (!object.languages) return object.name;\n        return object.languages[locale] || object.name;\n    }\n\n    // Get JSON data\n    var treeJSON = d3.json('WebFrontEndStack.json', function(error, treeData) {\n\n        // Calculate total nodes, max label length\n        var totalNodes = 0;\n        var maxLabelLength = [];\n        // variables for drag/drop\n        var selectedNode = null;\n        var draggingNode = null;\n        // panning variables\n        var panSpeed = 200;\n        var panBoundary = 20; // Within 20px from edges will pan when dragging.\n        // Misc. variables\n        var i = 0;\n        var duration = 750;\n        var root;\n\n        // size of the diagram\n        var viewerWidth = $(document).width();\n        var viewerHeight = $(document).height();\n\n        var tree = d3.layout.tree()\n            .size([viewerHeight, viewerWidth]);\n\n        // define a d3 diagonal projection for use by the node paths later on.\n        var diagonal = d3.svg.diagonal()\n            .projection(function(d) {\n                return [d.y, d.x];\n            });\n\n        // A recursive helper function for performing some setup by walking through all nodes\n\n        function visit(parent, visitFn, childrenFn, depth) {\n            if (!parent) return;\n\n            visitFn(parent, depth);\n\n            var children = childrenFn(parent);\n            if (children) {\n                var count = children.length;\n\t\t\t\tvar d = depth + 1;\n                for (var i = 0; i < count; i++) {\n                    visit(children[i], visitFn, childrenFn, d);\n                }\n            }\n        }\n\n        // Call visit function to establish maxLabelLength\n        visit(treeData, function(d, depth) {\n            totalNodes++;\n            if (maxLabelLength[depth] == undefined)\n                maxLabelLength[depth] = 0;\n            maxLabelLength[depth] = Math.max(parseName(d).length, maxLabelLength[depth]);\n        }, function(d) {\n            return d.children && d.children.length > 0 ? d.children : null;\n        }, 0);\n\n\n        // sort the tree according to the node names\n\n        function sortTree() {\n            tree.sort(function(a, b) {\n                return parseName(b).toLowerCase() < parseName(a).toLowerCase() ? 1 : -1;\n            });\n        }\n        // Sort the tree initially incase the JSON isn't in a sorted order.\n        //sortTree();\n\n        // TODO: Pan function, can be better implemented.\n\n        function pan(domNode, direction) {\n            var speed = panSpeed;\n            if (panTimer) {\n                clearTimeout(panTimer);\n                translateCoords = d3.transform(svgGroup.attr(\"transform\"));\n                if (direction == 'left' || direction == 'right') {\n                    translateX = direction == 'left' ? translateCoords.translate[0] + speed : translateCoords.translate[0] - speed;\n                    translateY = translateCoords.translate[1];\n                } else if (direction == 'up' || direction == 'down') {\n                    translateX = translateCoords.translate[0];\n                    translateY = direction == 'up' ? translateCoords.translate[1] + speed : translateCoords.translate[1] - speed;\n                }\n                scaleX = translateCoords.scale[0];\n                scaleY = translateCoords.scale[1];\n                scale = zoomListener.scale();\n                svgGroup.transition().attr(\"transform\", \"translate(\" + translateX + \",\" + translateY + \")scale(\" + scale + \")\");\n                d3.select(domNode).select('g.node').attr(\"transform\", \"translate(\" + translateX + \",\" + translateY + \")\");\n                zoomListener.scale(zoomListener.scale());\n                zoomListener.translate([translateX, translateY]);\n                panTimer = setTimeout(function() {\n                    pan(domNode, speed, direction);\n                }, 50);\n            }\n        }\n\n        // Define the zoom function for the zoomable tree\n\n        function zoom() {\n            svgGroup.attr(\"transform\", \"translate(\" + d3.event.translate + \")scale(\" + d3.event.scale + \")\");\n        }\n\n\n        // define the zoomListener which calls the zoom function on the \"zoom\" event constrained within the scaleExtents\n        var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on(\"zoom\", zoom);\n\n        function initiateDrag(d, domNode) {\n            draggingNode = d;\n            d3.select(domNode).select('.ghostCircle').attr('pointer-events', 'none');\n            d3.selectAll('.ghostCircle').attr('class', 'ghostCircle show');\n            d3.select(domNode).attr('class', 'node activeDrag');\n\n            svgGroup.selectAll(\"g.node\").sort(function(a, b) { // select the parent and sort the path's\n                if (a.id != draggingNode.id) return 1; // a is not the hovered element, send \"a\" to the back\n                else return -1; // a is the hovered element, bring \"a\" to the front\n            });\n            // if nodes has children, remove the links and nodes\n            if (nodes.length > 1) {\n                // remove link paths\n                links = tree.links(nodes);\n                nodePaths = svgGroup.selectAll(\"path.link\")\n                    .data(links, function(d) {\n                        return d.target.id;\n                    }).remove();\n                // remove child nodes\n                nodesExit = svgGroup.selectAll(\"g.node\")\n                    .data(nodes, function(d) {\n                        return d.id;\n                    }).filter(function(d, i) {\n                        if (d.id == draggingNode.id) {\n                            return false;\n                        }\n                        return true;\n                    }).remove();\n            }\n\n            // remove parent link\n            parentLink = tree.links(tree.nodes(draggingNode.parent));\n            svgGroup.selectAll('path.link').filter(function(d, i) {\n                if (d.target.id == draggingNode.id) {\n                    return true;\n                }\n                return false;\n            }).remove();\n\n            dragStarted = null;\n        }\n\n        // define the baseSvg, attaching a class for styling and the zoomListener\n        var baseSvg = d3.select(\"#tree-container\").append(\"svg:svg\")\n            .attr(\"width\", viewerWidth)\n            .attr(\"height\", viewerHeight)\n            .attr(\"class\", \"overlay\")\n            .call(zoomListener)\n\n\n        // Define the drag listeners for drag/drop behaviour of nodes.\n        dragListener = d3.behavior.drag()\n            .on(\"dragstart\", function(d) {\n                if (d == root) {\n                    return;\n                }\n                dragStarted = true;\n                nodes = tree.nodes(d);\n                d3.event.sourceEvent.stopPropagation();\n                // it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it d3.select(this).attr('pointer-events', 'none');\n            })\n            .on(\"drag\", function(d) {\n                if (d == root) {\n                    return;\n                }\n                if (dragStarted) {\n                    domNode = this;\n                    initiateDrag(d, domNode);\n                }\n\n                // get coords of mouseEvent relative to svg container to allow for panning\n                relCoords = d3.mouse($('svg').get(0));\n                if (relCoords[0] < panBoundary) {\n                    panTimer = true;\n                    pan(this, 'left');\n                } else if (relCoords[0] > ($('svg').width() - panBoundary)) {\n\n                    panTimer = true;\n                    pan(this, 'right');\n                } else if (relCoords[1] < panBoundary) {\n                    panTimer = true;\n                    pan(this, 'up');\n                } else if (relCoords[1] > ($('svg').height() - panBoundary)) {\n                    panTimer = true;\n                    pan(this, 'down');\n                } else {\n                    try {\n                        clearTimeout(panTimer);\n                    } catch (e) {\n\n                    }\n                }\n\n                d.x0 += d3.event.dy;\n                d.y0 += d3.event.dx;\n                var node = d3.select(this);\n                node.attr(\"transform\", \"translate(\" + d.y0 + \",\" + d.x0 + \")\");\n                updateTempConnector();\n            }).on(\"dragend\", function(d) {\n                if (d == root) {\n                    return;\n                }\n                domNode = this;\n                if (selectedNode) {\n                    // now remove the element from the parent, and insert it into the new elements children\n                    var index = draggingNode.parent.children.indexOf(draggingNode);\n                    if (index > -1) {\n                        draggingNode.parent.children.splice(index, 1);\n                    }\n                    if (typeof selectedNode.children !== 'undefined' || typeof selectedNode._children !== 'undefined') {\n                        if (typeof selectedNode.children !== 'undefined') {\n                            selectedNode.children.push(draggingNode);\n                        } else {\n                            selectedNode._children.push(draggingNode);\n                        }\n                    } else {\n                        selectedNode.children = [];\n                        selectedNode.children.push(draggingNode);\n                    }\n                    // Make sure that the node being added to is expanded so user can see added node is correctly moved\n                    expand(selectedNode);\n                    sortTree();\n                    endDrag();\n                } else {\n                    endDrag();\n                }\n            });\n\n        function endDrag() {\n            selectedNode = null;\n            d3.selectAll('.ghostCircle').attr('class', 'ghostCircle');\n            d3.select(domNode).attr('class', 'node');\n            // now restore the mouseover event or we won't be able to drag a 2nd time\n            d3.select(domNode).select('.ghostCircle').attr('pointer-events', '');\n            updateTempConnector();\n            if (draggingNode !== null) {\n                update(root);\n                centerNode(draggingNode);\n                draggingNode = null;\n            }\n        }\n\n        // Helper functions for collapsing and expanding nodes.\n\n        function collapse(d) {\n            if (d.children) {\n                d._children = d.children;\n                d._children.forEach(collapse);\n                d.children = null;\n            }\n        }\n\n        function expand(d) {\n            if (d._children) {\n                d.children = d._children;\n                d.children.forEach(expand);\n                d._children = null;\n            }\n        }\n\n        var overCircle = function(d) {\n            selectedNode = d;\n            updateTempConnector();\n        };\n        var outCircle = function(d) {\n            selectedNode = null;\n            updateTempConnector();\n        };\n\n        // Function to update the temporary connector indicating dragging affiliation\n        var updateTempConnector = function() {\n            var data = [];\n            if (draggingNode !== null && selectedNode !== null) {\n                // have to flip the source coordinates since we did this for the existing connectors on the original tree\n                data = [{\n                    source: {\n                        x: selectedNode.y0,\n                        y: selectedNode.x0\n                    },\n                    target: {\n                        x: draggingNode.y0,\n                        y: draggingNode.x0\n                    }\n                }];\n            }\n            var link = svgGroup.selectAll(\".templink\").data(data);\n\n            link.enter().append(\"path\")\n                .attr(\"class\", \"templink\")\n                .attr(\"d\", d3.svg.diagonal())\n                .attr('pointer-events', 'none');\n\n            link.attr(\"d\", d3.svg.diagonal());\n\n            link.exit().remove();\n        };\n\n        // Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children.\n\n        function centerNode(source) {\n            scale = zoomListener.scale();\n\n            x = -source.y0;\n            y = -source.x0;\n            x = x * scale + viewerWidth / 2;\n            y = y * scale + viewerHeight / 2;\n            d3.select('g').transition()\n                .duration(duration)\n                .attr(\"transform\", \"translate(\" + x + \",\" + y + \")scale(\" + scale + \")\");\n            zoomListener.scale(scale);\n            zoomListener.translate([x, y]);\n        }\n\n        function leftNode(source) {\n            scale = zoomListener.scale();\n\n            x = 100 * scale;\n            y = source.y0 * scale;\n            console.log(x);\n\n            d3.select('g').transition()\n                .duration(duration)\n                .attr(\"transform\", \"translate(\" + x + \",\" + y + \")scale(\" + scale + \")\");\n            zoomListener.scale(scale);\n            zoomListener.translate([x, y]);\n        }\n\n        // Toggle children function\n\n        function toggleChildren(d) {\n            if (d.children) {\n                d._children = d.children;\n                d.children = null;\n            } else if (d._children) {\n                d.children = d._children;\n                d._children = null;\n            }\n            return d;\n        }\n\n        // Toggle children on click.\n\n        function click(d) {\n            if (d3.event.defaultPrevented) return; // click suppressed\n            d = toggleChildren(d);\n            update(d);\n            centerNode(d);\n        }\n\n        function update(source) {\n            // Compute the new height, function counts total children of root node and sets tree height accordingly.\n            // This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed\n            // This makes the layout more consistent.\n            var levelWidth = [1];\n            var childCount = function(level, n) {\n\n                if (n.children && n.children.length > 0) {\n                    if (levelWidth.length <= level + 1) levelWidth.push(0);\n\n                    levelWidth[level + 1] += n.children.length;\n                    n.children.forEach(function(d) {\n                        childCount(level + 1, d);\n                    });\n                }\n            };\n            childCount(0, root);\n            var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line  \n            tree = tree.size([newHeight, viewerWidth]);\n\n            // Compute the new tree layout.\n            var nodes = tree.nodes(root).reverse(),\n                links = tree.links(nodes);\n\n            // Set widths between levels based on maxLabelLength.\n            nodes.forEach(function(d) {\n                var labelLength = 0;\n                for (var j = 0; j <= d.depth; j++) {\n                    labelLength += maxLabelLength[j];\n                }\n                d.y = labelLength * 10; //maxLabelLength * 10px\n                // alternatively to keep a fixed scale one can set a fixed depth per level\n                // Normalize for fixed-depth by commenting out below line\n                // d.y = (d.depth * 500); //500px per level.\n            });\n\n            // Update the nodes…\n            node = svgGroup.selectAll(\"g.node\")\n                .data(nodes, function(d) {\n                    return d.id || (d.id = ++i);\n                });\n\n            // Enter any new nodes at the parent's previous position.\n            var nodeEnter = node.enter().append(\"g\")\n                .call(dragListener)\n                .attr(\"class\", \"node\")\n                .attr(\"transform\", function(d) {\n                    return \"translate(\" + source.y0 + \",\" + source.x0 + \")\";\n                })\n                .on('click', click)\n                .append(\"a\")\n                .attr(\"xlink:href\", function(d) {\n                    return d.url || d.github; \n                })\n                .attr(\"target\", \"_blank\");\n\n            nodeEnter.append(\"circle\")\n                .attr('class', 'nodeCircle')\n                .attr(\"r\", 0)\n                .style(\"fill\", function(d) {\n                    return d._children ? \"lightsteelblue\" : \"#fff\";\n                });\n\n            nodeEnter.append(\"text\")\n                .attr(\"x\", function(d) {\n                    return d.children || d._children ? -10 : 10;\n                })\n                .attr(\"dy\", \".35em\")\n                .attr('class', 'nodeText')\n                .attr(\"text-anchor\", function(d) {\n                    return d.children || d._children ? \"end\" : \"start\";\n                })\n                .text(function(d) {\n                    return parseName(d);\n                })\n                .style(\"fill-opacity\", 0);\n\n            // phantom node to give us mouseover in a radius around it\n            nodeEnter.append(\"circle\")\n                .attr('class', 'ghostCircle')\n                .attr(\"r\", 30)\n                .attr(\"opacity\", 0.2) // change this to zero to hide the target area\n                .style(\"fill\", \"red\")\n                .attr('pointer-events', 'mouseover')\n                .on(\"mouseover\", function(node) {\n                    overCircle(node);\n                })\n                .on(\"mouseout\", function(node) {\n                    outCircle(node);\n                });\n\n            // Update the text to reflect whether node has children or not.\n            node.select('text')\n                .attr(\"x\", function(d) {\n                    return d.children || d._children ? -10 : 10;\n                })\n                .attr(\"text-anchor\", function(d) {\n                    return d.children || d._children ? \"end\" : \"start\";\n                })\n                .text(function(d) {\n                    return parseName(d);\n                });\n\n            // Change the circle fill depending on whether it has children and is collapsed\n            node.select(\"circle.nodeCircle\")\n                .attr(\"r\", 4.5)\n                .style(\"fill\", function(d) {\n                    return d._children ? \"lightsteelblue\" : \"#fff\";\n                });\n\n            // Transition nodes to their new position.\n            var nodeUpdate = node.transition()\n                .duration(duration)\n                .attr(\"transform\", function(d) {\n                    return \"translate(\" + d.y + \",\" + d.x + \")\";\n                });\n\n            // Fade the text in\n            nodeUpdate.select(\"text\")\n                .style(\"fill-opacity\", 1);\n\n            // Transition exiting nodes to the parent's new position.\n            var nodeExit = node.exit().transition()\n                .duration(duration)\n                .attr(\"transform\", function(d) {\n                    return \"translate(\" + source.y + \",\" + source.x + \")\";\n                })\n                .remove();\n\n            nodeExit.select(\"circle\")\n                .attr(\"r\", 0);\n\n            nodeExit.select(\"text\")\n                .style(\"fill-opacity\", 0);\n\n            // Update the links…\n            var link = svgGroup.selectAll(\"path.link\")\n                .data(links, function(d) {\n                    return d.target.id;\n                });\n\n            // Enter any new links at the parent's previous position.\n            link.enter().insert(\"path\", \"g\")\n                .attr(\"class\", \"link\")\n                .attr(\"d\", function(d) {\n                    var o = {\n                        x: source.x0,\n                        y: source.y0\n                    };\n                    return diagonal({\n                        source: o,\n                        target: o\n                    });\n                });\n\n            // Transition links to their new position.\n            link.transition()\n                .duration(duration)\n                .attr(\"d\", diagonal);\n\n            // Transition exiting nodes to the parent's new position.\n            link.exit().transition()\n                .duration(duration)\n                .attr(\"d\", function(d) {\n                    var o = {\n                        x: source.x,\n                        y: source.y\n                    };\n                    return diagonal({\n                        source: o,\n                        target: o\n                    });\n                })\n                .remove();\n\n            // Stash the old positions for transition.\n            nodes.forEach(function(d) {\n                d.x0 = d.x;\n                d.y0 = d.y;\n            });\n        }\n\n        // Append a group which holds all nodes and which the zoom Listener can act upon.\n        var svgGroup = baseSvg.append(\"g\");\n\n        // Define the root\n        root = treeData;\n        root.x0 = viewerHeight / 2;\n        root.y0 = 0;\n        update(root);\n\n        // Layout the tree initially and center on the root node.\n        if (isPhantom) {\n            zoomListener.scale(1.25);\n            leftNode(root);\n        } else {\n            zoomListener.scale(0.25);\n            centerNode(root);\n        }\n\n        //\n    });\n\n})();\n"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/2015letter.md",
    "content": "##致 Front-End Developers（2015）\n\n摘录至百度百科\n\n> Web前端开发工程师是一个很新的职业，在国内乃至国际上真正开始受到重视的时间不超过7年。Web前端开发是从网页制作演变而来的，名称上有很明显的时代特征。在互联网的演化进程中，网页制作是Web 1.0时代的产物，那时网站的主要内容都是静态的，用户使用网站的行为也以浏览为主。\n\n\n2005年以后，互联网进入Web 2.0时代，各种类似桌面软件的Web应用大量涌现，网站的前端由此发生了翻天覆地的变化。网页不再只是承载单一的文字和图片，各种丰富媒体让网页的内容更加生动，网页上软件化的交互形式为用户提供了更好的使用体验，这些都是基于前端技术实现的。\n\n近二十年的发展之后，到目前的形势来看，“前端”这个行业的热火程度，应该可以用“爆发式”来描述，不管是PC端的原始开发技术，移动端这几年膨胀的“框架”，手机App混合开发的ionic以及react native，链接硬件的cylonjs和osbean，服务端的Nodejs，都预示着“前端”应该说是JavaScript这门语言的可应用程度，超出了很多人的预期，那么我需要问自己，“学的完吗？”\n\n显而易见，学不完。\n\n###该如何起航\n\n如果是一个初学者，我想很可能会被这“玩意”吓着了，平心而论，我们应该学会适应它，以及有一份很好的指南对资源去进行筛选。\n\n一些借鉴该如何起航：\n\n就初学来看HTML，CSS，JavaScript是你唯一的入门方式，如果反过来，我真心的推荐Apple的Swift做为你的入门语言，为什么？因为你需要了解程序的实质是什么，Swift可以很好的让你了解什么是类型系统，什么是面向对象，什么是编译器。\n\n了解“程序”是你起航的开始。\n\n====\n\n###前端可能是这样的\n\n分类   | 技术代表  | 评价\n----- | ----- | ------\nPC |原始生产HTML，CSS，JavaScript，最有代表的技术是[jQuery](https://jquery.com/) | 相信是大多数人的入门，适合传统页面的编程。 \nPC |开始考虑模块以及代码结构，最有代表的技术是[RequireJS](http://requirejs.org/)和[Backbone.js](http://backbonejs.org/)，这一阶段也会使用了一些工具函数库，开始流行自动构建工具，比如[Underscore.js](http://underscorejs.org/)和[Grunt](http://gruntjs.com/)| 相信大家到了这个阶段，也是Ajax使用最多的时候，无刷新页面，客户端模板也开始应用。\nPC |从[Angular](https://angularjs.org/)开始，整个业界开始风靡双向绑定，依赖注入，自动化测试，Nodejs越来越多的应用在“前端”领域中，国内比较有代表的是司徒正美老师的[avalon](https://github.com/RubyLouvre/avalon)和尤小右老师的[vue](https://github.com/yyx990803/vue)|WebApp兴起，以及硬件设备越来越给力的计算能力和内存利用率，意味着“前端”开始更加的追求体验，细致，的问题\nPC |[reactjs](https://facebook.github.io/react/)的出现，又开启了一次新的尝试，Nodejs也开启了从分裂成iojs，又合并成为了Nodejs的进程|Nodejs开始对于前端的工程化越来越重要，想想你使用的工具，多多少少都构建在Nodejs之上。\nPC |未来个人感觉web components，编译型的JavaScript会成为很多团队的首选选择，比如[Flow](https://code.facebook.com/posts/1505962329687926/flow-a-new-static-type-checker-for-javascript/)，[TypeScript](http://www.typescriptlang.org/) | 编译可以减少在运行时的错误，可以检查代码有利于维护。\nMobile|基于HTML5，CSS3编写的页面，比如营销广告，最有代表性的技术是[Zepto](http://zeptojs.com/)，基于它的效果插件非常多| 也许大家开始适应了没有960px像素的时候\nMobile|HTML5单页应用的出现|大多数人会选择把PC端WebApp实现的技术移到这里来，相应的HTML5，CSS3技术开始大量的使用\nMobile|HTML5游戏的出现，《神经猫》在微信中的疯传，最有代表性的技术是[COCOS2D-JS](http://www.cocos2d-x.org/wiki/Cocos2d-JS)| 游戏是你复习数学几何知识最好的基友\nMobile|[PhoneGap](http://phonegap.com/)的出现，让使用HTML CSS JavaScript开发App成为了可能|探索与摸索\nMobile|[ionic](http://ionicframework.com/)让Angular与[Apache Cordova](https://cordova.apache.org/)结合开启了高级HTML5混合移动应用开发框架的进程，它最有代表性。|利用HTML5 CSS3 JavaScript编写的大量应用开始在市场上可以被找到。\nMobile|[React Native](https://facebook.github.io/react-native/)让开发移动App有了一个新选择，虽然它实现的逻辑，已经有很多人在从前就实现了，但是愿意尝试使用这个技术的人还是蛮多的|通过中间语言JavaScript转换成Native语言实现，虽然只有UI\nMobile|未来个人感觉HTML5 CSS3 JavaScript会成为很多团队开发App首选选择，抛开一些（游戏）等需要高性能，复杂动画的领域，为什么？|快速，简单，周期短，试错的机会增加\nServer|[Node.js](https://nodejs.org/)我相信这应该是最有代表性的，而且未来也会越来越重要|使用JavaScript的用户数量巨大，服务器知识的普及，会让学习成本低\nDatabase|[MongoDB](https://www.mongodb.org/)应该是在这个领域比较有代表性|数据库的出现，让存储的解决方案成为了可能\nDocker|也许你应该要了解一下什么是[Docker](https://github.com/DeanXu/Docker-introduce/blob/master/README.md)|你的开发效率会进一步提升\n硬件领域|听说有人使用[cylonjs](http://cylonjs.com/)开发机器人|国内也有一家公司推出了[智能机器控制器与快速开发框架](http://www.osbean.com/)，嗨，JavaScript已经入侵硬件领域了\n自动化|最有代表的应该是[Grunt](http://gruntjs.com/)| 但是你依然有很多选择，[gulp](http://gulpjs.com/)是其中之一\ncss编译|最有代表的应该是[sass](http://sass-lang.com/)| 编译的出现让你组织代码，管理更容易了\n2015年|通过了ES2015，也许你目前还不清楚这是什么，那么我告诉你，这就是ECMA6，随着今年（2015）Apple WWDC和Google I/O的落幕，一大波的硬件，软件即将更新，数不尽的各种服务类SDK，以及HTML5 Device Api| 少年，未来的你面对无尽的学习，以及从PC切换到移动的思维逻辑，可能还有可穿戴设备喔\n\n###展望\n\n随着W3C发布的的公告“耗时8年 HTML5标准终于完工了”，可以看出来以后HTNL5和CSS3应该会被重点使用，而且现在更多的方向是朝着移动端迁移。\n\n有理由相信，这是迎接变革的开始，未来这是一个全新的战场。\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/Articles.md",
    "content": "###说明：文章从《码农周刊》，《奇舞周刊》，以及个人平时阅读收集而来\n\n[JavaScript 与有限状态机](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ruanyifeng.com%2Fblog%2F2013%2F09%2Ffinite-state_machine_for_javascript.html&aid=5&nid=1)  \n[网站实时协作功能 Javascript 库 TogetherJS](http://weekly.manong.io/bounce?url=https%3A%2F%2Ftogetherjs.com%2F&aid=28&nid=2)  \n[[译] 学用 JavaScript 设计模式（开源中国）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.oschina.net%2Ftranslate%2Flearning-javascript-design-patterns&aid=64&nid=5)  \n[大量 D3.js 示例（biovisualize）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fchristopheviau.com%2Fd3list%2F&aid=70&nid=5)  \n[Snap.svg - JavaScript SVG 库](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsnapsvg.io%2F&aid=115&nid=7)  \n[JavaScript 编码风格指南（Airbnb）](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fairbnb%2Fjavascript&aid=138&nid=8)  \n[Riot.js — 1kb 的客户端 MVP 框架](http://weekly.manong.io/bounce?url=https%3A%2F%2Fmoot.it%2Fblog%2Ftechnology%2Friotjs-the-1kb-mvp-framework.html&aid=148&nid=8)  \n[经常被误解的一些 JavaScript 概念（Michael Bolin）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbolinfest.com%2Fjavascript%2Fmisunderstood.html&aid=158&nid=9)  \n[dsjslib - 一个 JavaScript 实现的数据结构和工具集](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fmonmohan%2Fdsjslib&aid=163&nid=9)  \n[D3plus - 一个 D3.js 的扩展库](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Falexandersimoes%2Fd3plus&aid=222&nid=11)  \n[mindb - 一个帮助你进行复杂数据操作的 JS 库](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fiwillwen%2Fmindb&aid=284&nid=13)  \n[OpenUI5 - SAP 开源的 JavaScript 框架](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsap.github.io%2Fopenui5%2F&aid=320&nid=14)  \n[系列文章：JavaScript 高级程序设计（blinkstar824）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.csdn.net%2Fblinkstar824%2Farticle%2Fcategory%2F1085574&aid=338&nid=17)  \n[JavaScript 模式集合（@shichuan石川）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fshichuan.github.io%2Fjavascript-patterns%2F&aid=347&nid=17)  \n[math.js - 一个 JavaScript & Node.js Math 扩展库](http://weekly.manong.io/bounce?url=http%3A%2F%2Fmathjs.org%2F&aid=376&nid=17)  \n[JavaScript 异步编程原理（@BarretLee）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fhustskyking%2Fp%2Fjavascript-asynchronous-programming.html&aid=399&nid=18)  \n[ConvNetJS - 在浏览器里训练深度学习模型的 JS 库](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcs.stanford.edu%2Fpeople%2Fkarpathy%2Fconvnetjs%2F&aid=451&nid=19)  \n[37 道 JavaScript 选择题](http://weekly.manong.io/bounce?url=http%3A%2F%2Fjavascript-puzzlers.herokuapp.com%2F&aid=471&nid=20)  \n[JavaScript 之道](http://weekly.manong.io/bounce?url=http%3A%2F%2Fjstherightway.org%2F&aid=472&nid=20)  \n[JavaScript 高级教程 (John Resig)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fejohn.org%2Fapps%2Flearn%2F&aid=509&nid=21)  \n[Mousetrap - 一个用于处理键盘快捷键的 JS 库](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fccampbell%2Fmousetrap&aid=523&nid=21)  \n[Eloquent JavaScript（第二版）](http://weekly.manong.io/bounce?url=http%3A%2F%2Feloquentjavascript.net%2F2nd_edition%2Fpreview%2F&aid=656&nid=23)  \n[免费 JavaScript 电子书《Speaking JavaScript》 (Dr. Axel Rauschmayer)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fspeakingjs.com%2Fes5%2Findex.html&aid=766&nid=24)  \n[jQuery 编码规范与最佳实践 (Abhinay Rathore)](http://weekly.manong.io/bounce?url=http%3A%2F%2Flab.abhinayrathore.com%2Fjquery-standards%2F&aid=777&nid=24)  \n[[译] MEAN 简介（@ShuPengfei）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fstormslowly.github.io%2Fstack%2F2014%2F03%2F10%2FIntroduction-to-the-MEAN-Stack.html&aid=778&nid=24)  \n[JavaScript 内存优化 (Life Map)](http://weekly.manong.io/bounce?url=http%3A%2F%2Flifemap.in%2Fjavascript-memory-optimize%2F&aid=833&nid=25)  \n[免费 JavaScript 电子书《Learning JavaScript Design Patterns》 (Addy Osmani)](http://weekly.manong.io/bounce?url=http%3A%2F%2Faddyosmani.com%2Fresources%2Fessentialjsdesignpatterns%2Fbook%2F&aid=834&nid=25)  \n[JavaScript 必备工具清单 (Code Fellows)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fwww.codefellows.org%2Fblogs%2Fcomplete-list-of-javascript-tools&aid=877&nid=26)  \n[ECMAScript 6 工具集锦](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Faddyosmani%2Fes6-tools&aid=885&nid=26)  \n[[译] jQuery API 中文文档最新版（@愚人码头）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.css88.com%2Fjqapi-1.9%2F&aid=887&nid=26)  \n[ECharts - 一个基于 Canvas 的纯 Javascript 图表库](http://weekly.manong.io/bounce?url=http%3A%2F%2Fecharts.baidu.com%2Findex.html&aid=895&nid=26)  \n[系列文章：RequireJS 源码学习（叶小钗）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fyexiaochai%2Fp%2F3632580.html&aid=903&nid=27)  \n[Superhero.js - 一站式的 JavaScript 知识库](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsuperherojs.com%2F&aid=924&nid=27)  \n[slick - 一个超棒的 JS 轮播插件](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fkenwheeler%2Fslick&aid=957&nid=28)  \n[大量 Meteor.js 学习资源 (yauh)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyauh.de%2Farticles%2F376%2Fbest-learning-resources-for-meteorjs&aid=958&nid=28)  \n[系列文章：MVVM 框架大比拼（@侯振宇hzy）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fsskyy%2Fp%2F3709740.html&aid=1006&nid=30)  \n[JavaScript 高性能动画与页面渲染（李光毅）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.infoq.com%2Fcn%2Farticles%2Fjavascript-high-performance-animation-and-page-rendering&aid=1012&nid=30)  \n[ECMAScript 6 入门 (@ruanyf)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fes6.ruanyifeng.com%2F&aid=1027&nid=30)  \n[[译] 我希望自己尽早知道的 7 个 JavaScript 怪癖 (Coding Serf)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.codingserf.com%2Findex.php%2F2014%2F05%2Fjsquirks%2F&aid=1051&nid=31)  \n[fibjs - 一个基于 Coroutine 实现的服务器开发框架（@孢子响马）](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fxicilion%2Ffibjs&aid=1065&nid=31)  \n[[PDF] 大型 JavaScript 应用实战经验分享 (Matt)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fspeakerdeck.com%2Fmseeley%2Flife-on-the-grid&aid=1193&nid=35)  \n[Ember.js 教程 (Vic Ramon)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fember.vicramon.com%2F&aid=1196&nid=35)  \n[MT - 腾讯出品的专注于移动端的 JS 模块管理框架](http://weekly.manong.io/bounce?url=http%3A%2F%2Fmt.tencent.com%2F&aid=1199&nid=35)  \n[系列文章：重构 JavaScript 应用的七种模式 (Michael Phillips)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fjournal.crushlovely.com%2Fpost%2F88286828068%2F7-patterns-to-refactor-javascript-applications-value&aid=1217&nid=37)  \n[JavaScript 在线交互教程](http://weekly.manong.io/bounce?url=http%3A%2F%2Fjsrobot.tk%2F&aid=1249&nid=38)  \n[理解 JS 闭包 (fcoral)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.w3cfuns.com%2Fblog-5435393-5399202.html&aid=1280&nid=39)  \n[免费电子书《Eloquent JavaScript（第二版）》 (Marijn Haverbeke)](http://weekly.manong.io/bounce?url=http%3A%2F%2Feloquentjavascript.net%2F&aid=1319&nid=40)  \n[最牛叉的 JS 游戏框架](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Ffinscn%2FThe-Best-JS-Game-Framework&aid=1346&nid=41)  \n[[PDF] JavaScript 内存管理 (Addy Osmani)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fspeakerdeck.com%2Faddyosmani%2Fjavascript-memory-management-masterclass&aid=1403&nid=43)  \n[JavaScript 高级对象 (Bjorn Tipling)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbjorn.tipling.com%2Fadvanced-objects-in-javascript&aid=1428&nid=44)  \n[新的 JavaScript 模块系统 (LYing)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzhuanlan.zhihu.com%2FFrontendMagazine%2F19850058&aid=1452&nid=45)  \n[用 JavaScript 编写 OS X 应用 (Tyler Gaw)](http://weekly.manong.io/bounce?url=http%3A%2F%2Ftylergaw.com%2Farticles%2Fbuilding-osx-apps-with-js&aid=1482&nid=46)  \n[wechat.js - 微信相关的 js 操作：分享、网络、菜单 (@sofish)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fsofish%2Fwechat.js&aid=1493&nid=46)  \n[细嗅 Promise（@Barret李靖）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fhustskyking%2Fp%2Fpromise.html&aid=1506&nid=47)  \n[SweetAlert - 一个 JavaScript alert() 方法的替代品 (Tristan Edwards)](http://weekly.manong.io/bounce?url=http%3A%2F%2Ftristanedwards.me%2Fsweetalert&aid=1520&nid=47)  \n[Gifshot - 一个从流媒体、视频或者图片中生成 Gif 动画的 JS 库](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyahoo.github.io%2Fgifshot%2F&aid=1521&nid=47)  \n[抽象语法树在 JavaScript 中的应用 (xcatliu)](http://weekly.manong.io/bounce?url=http%3A%2F%2Ftech.meituan.com%2Fabstract-syntax-tree.html&aid=1532&nid=48)  \n[[视频] JavaScript 的诞生与死亡](http://weekly.manong.io/bounce?url=http%3A%2F%2Fv.youku.com%2Fv_show%2Fid_XODAzOTY1MTM2.html&aid=1533&nid=48)  \n[fibjs 介绍 (@孢子响马)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbaoz.cn%2F498326&aid=1562&nid=49)  \n[JavaScript 应用程序架构 (Addy Osmani)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fmedium.com%2F%40addyosmani%2Fjavascript-application-architecture-on-the-road-to-2015-d8125811101b&aid=1736&nid=55)  \n[玩转 AMD（Loader 篇） (@errorrik)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fefe.baidu.com%2Fblog%2Fdissecting-amd-how%2F&aid=1747&nid=55)  \n[颠覆式前端 UI 开发框架：React (王沛)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.infoq.com%2Fcn%2Farticles%2Fsubversion-front-end-ui-development-framework-react&aid=1754&nid=55)  \n[fibjs 关于异步的设计逻辑 (@孢子响马)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbaoz.cn%2F547734&aid=1770&nid=57)  \n[[译] JavaScript 奇技淫巧 45 招 (Sid)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fchensd.com%2F2015-01%2F45-useful-javascript-tips-tricks-and-best-practices.html&aid=1808&nid=58)  \n[Draggabilly - 一个专注于拖拽功能的 JS 库 (David DeSandro)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fdesandro%2Fdraggabilly&aid=1847&nid=59)  \n[[译] 详解 this (@刘哇勇)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2FWayou%2Fp%2Fall-this.html&aid=1870&nid=60)  \n[JavaScript Promise 迷你书（中文版） (liubin & kaku & honnkyou)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fliubin.github.io%2Fpromises-book%2F&aid=1871&nid=60)  \n[[译] JavaScript 简易教程 (颜海镜)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyanhaijing.com%2Fbasejs%2Findex.html&aid=1903&nid=61)  \n[React 入门学习实例 (Kejun)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.w3ctech.com%2Ftopic%2F758&aid=1947&nid=62)  \n[ECMAScript 6 Features 中文版 (@lenville)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Flenville%2Fes6features%2Fblob%2Fmaster%2FREADME.md&aid=1953&nid=62)  \n[实战 JS 正则表达式 (@大额大额哼歌等日落)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fskylar%2Fp%2F4265490.html&aid=1985&nid=63)  \n[fullPage.js - 一个 jQuery 全屏滚动插件 (Álvaro)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Falvarotrigo%2FfullPage.js&aid=1994&nid=63)  \n[KVM.js - 一个轻量级模块管理器 (王智力)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2FjanryWang%2Fkvm&aid=1995&nid=63)  \n[Slideout.js - 一个用于移动 Web 应用的触摸滑出式导航菜单 (Mango)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2FMango%2Fslideout&aid=2032&nid=64)  \n[必须了解的 ECMAScript 6 新特性 (@MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.oyanglul.us%2Fjavascript%2Fessential-ecmascript6.html&aid=2060&nid=65)  \n[[译] 深入浅出 React Native：使用 JavaScript 构建原生应用 (寸志 等)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzhuanlan.zhihu.com%2FFrontendMagazine%2F19996445&aid=2096&nid=66)  \n[React Native 学习指南 (@玩儿音乐的程序猿)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fele828%2Freact-native-guide&aid=2104&nid=66)  \n[[译] 2015 前端 JS 工程师必知必会 (@_像阳光一样)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzhuanlan.zhihu.com%2FFrontendMagazine%2F20002850&aid=2135&nid=67)  \n[React Native 之布局篇 (@sysu_学家)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Ftmallfe%2Ftmallfe.github.io%2Fissues%2F19&aid=2146&nid=67)  \n[Dragula - 一个让拖放操作变简单的 JS 库 (Nicolas Bevacqua)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fbevacqua%2Fdragula&aid=2156&nid=67)  \n[Layzr.js - 一个小巧快速的图片懒加载库 (Michael Cavalea)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fcallmecavs%2Flayzr.js&aid=2154&nid=67)  \n[T3 - 一个用于搭建大型 Web 应用的客户端 JS 框架 (Box)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fbox%2Ft3js%2F&aid=2153&nid=67)  \n[Facebook React Native 中文教程 (@极客学院_jikexueyuan)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwiki.jikexueyuan.com%2Fproject%2Freact-native%2F&aid=2186&nid=68)  \n[BooJS：在命令行中执行 JavaScript (Seo Townsend)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fsotownsend%2FBooJS&aid=2196&nid=68)  \n[Sprint.js - 一个高性能、小体积的 DOM 操作库 (Benjamin De Cock)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fbendc%2Fsprint&aid=2197&nid=68)  \n[elevator.js - 一个模拟电梯运行“返回顶部”的 JS 插件 (Tim Holman)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Ftholman%2Felevator.js&aid=2198&nid=68)  \n[react-native-swiper - 一个用于 React Native 的最佳轮播类组件 (斯人)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fleecade%2Freact-native-swiper&aid=2234&nid=69)  \n[Clusterize.js - 一个轻松显示大数据集的 JS 插件 (NeXTs)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2FNeXTs%2FClusterize.js&aid=2235&nid=69)  \n[Picturefill - 一个响应式图片 JS 插件 (Scott Jehl)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fscottjehl%2Fpicturefill&aid=2236&nid=69)  \n[重新介绍 JavaScript](http://weekly.manong.io/bounce?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FJavaScript%2FA_re-introduction_to_JavaScript&aid=2265&nid=70)  \n[Clojure 风格的 JavaScript 并发编程 (@MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.oyanglul.us%2Fjavascript%2Fclojure-core.async-essence-in-native-javascript.html&aid=2266&nid=70)  \n[PyPy.js：将 PyPy 代码编译成 JavaScript 代码 (rfk)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Frfk%2Fpypyjs&aid=2279&nid=70)  \n[observe.js - 一个用于观察任意对象的任意变化的类库 (kmdjs)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fkmdjs%2Fobservejs&aid=2286&nid=70)  \n[zoom.js - 一个 jQuery 图片放大插件 (fat)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Ffat%2Fzoom.js&aid=2288&nid=70)  \n[[英] JavaScript 闭包工作原理 (@jiacai2050)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fstackoverflow.com%2Fquestions%2F111102%2Fhow-do-javascript-closures-work&aid=2325&nid=71)  \n[ReactJS 入门教程 (雲霏霏)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fyunfeifei%2Fp%2F4486125.html&aid=2327&nid=71)  \n[watermark.js - 一个在浏览器中添加图片水印的 JS 库（ES6） (brianium)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fbrianium%2Fwatermarkjs&aid=2347&nid=71)  \n[[译] 去除 JavaScript 代码的怪味 (@涂鸦码龙)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fjinlong.github.io%2F2015%2F05%2F21%2Feliminate-javascript-code-smells%2F&aid=2377&nid=72)  \n[JavaScript 玩转 Clojure 大法之 Transducer (@MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.oyanglul.us%2Fjavascript%2Fclojure-essence-in-javascript-transducer.html&aid=2378&nid=72)  \n[[英] JS 之父谈 JavaScript（幻灯片） (Brendan Eich)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbrendaneich.github.io%2FModernWeb.tw-2015%2F&aid=2379&nid=72)  \n[iconate.js：将 icons 增加动画效果的 JS 库 (bitshadow)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fbitshadow%2Ficonate&aid=2405&nid=72)  \n[zepto.fullpage：专注于移动端的 fullPage.js (@颜海镜)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fyanhaijing%2Fzepto.fullpage&aid=2407&nid=72)  \n[MetaHandler.js：移动端适配各种屏幕无痛工具脚本 (@听奏)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Funbug%2Fgenerator-webappstarter%2Fblob%2Fmaster%2Fapp%2Ftemplates%2Fapp%2Fsrc%2Futil%2FMetaHandler.js&aid=2410&nid=72)  \n[JavaScript 玩转 Clojure 大法之 Trampoline (MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.oyanglul.us%2Fjavascript%2Fclojure-essence-in-javascript-trampoline.html&aid=2449&nid=73)  \n[[译] 理解并掌握 JavaScript 中 this 的用法 (MForever78)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcode.mforever78.com%2Ftranslation%2F2015%2F05%2F19%2Funderstand-javascripts-this-with-clarity-and-master-it%2F&aid=2450&nid=73)  \n[我是怎么从顾虑到热爱 ReactJS 的？](http://weekly.manong.io/bounce?url=http%3A%2F%2Fourjs.com%2Fdetail%2F5567c046d11a73aa4d000003&aid=2451&nid=73)  \n[JSPatch 实现原理详解 (bang)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.cnbang.net%2Ftech%2F2808%2F&aid=2460&nid=73)  \n[一个 JavaScript 实现的 GBA 模拟器 (jsemu)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fjsemu%2Fgba&aid=2462&nid=73)  \n[fstorm：超快速和安全的进行文件“写入”（JavaScript） (拴萝卜的棍子)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fleeluolee%2Ffstorm&aid=2468&nid=73)  \n[jsblocks：更好的 JavaScript MV-ish 框架 (astoilkov)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fastoilkov%2Fjsblocks&aid=2469&nid=73)  \n[编写高质量 JavaScript 代码 (北鼻鱼博客)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.lovebabyyu.com%2F2015%2F05%2Fgzjjavscript.html&aid=2554&nid=75)  \n[JavaScript 玩转 Clojure 大法之 Macro（一） (MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.oyanglul.us%2Fjavascript%2Fclojure-essence-in-javascript-macro.html&aid=2555&nid=75)  \n[ECMAScript 6 新特性介绍 (久艾分享)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ido321.com%2F1596.html&aid=2628&nid=76)  \n[入 lang：移植 Clojure macro 到 JavaScript (MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fru-lang.org%2F&aid=2644&nid=76)  \n[Airbnb JavaScript Style Guide（中文版） (jigsawye)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fjigsawye%2Fjavascript&aid=2658&nid=76)  \n[从零开始构建实现一个 JavaScript 模块化加载器 (@晓风well)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwwsun.me%2Fposts%2Fcreating-javascript-modules-loader.html&aid=2744&nid=77)  \n[JavaScript 全栈教程 (@廖雪峰)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.liaoxuefeng.com%2Fwiki%2F001434446689867b27157e896e74d51a89c25cc8b43bdb3000&aid=2780&nid=78)  \n[[译] 真实世界的 JavaScript MVC 框架 (范洪春)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzhuanlan.zhihu.com%2FFrontendMagazine%2F20087355&aid=2781&nid=78)  \n[[译] 深入浅出 ES6（五）：不定参数和默认参数 (@Lenville)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.infoq.com%2Fcn%2Farticles%2Fes6-in-depth-rest-parameters-and-defaults&aid=2795&nid=78)  \n[MDN JavaScript 教程](http://weekly.manong.io/bounce?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FJavaScript&aid=2797&nid=78)  \n[一张图学习 JavaScript (coodict)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fcoodict%2Fjavascript-in-one-pic%2Fblob%2Fmaster%2FREADME-zh.md&aid=2805&nid=78)  \n[io.js API 中文文档（需梯子） (DavidCai1993)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fdavidcai1993.gitbooks.io%2Fiojs-api-doc-in-chinese%2Fcontent%2F&aid=2806&nid=78)  \n[JSPatch 实现原理详解（二） (@bang)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.cnbang.net%2Ftech%2F2855%2F&aid=2815&nid=78)  \n[Intro.js - 一个创建引导式网站介绍功能的 JS 库 (usablica)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fusablica%2Fintro.js&aid=2824&nid=78)  \n[ES6 的功能侦测库 ES-Checker (@ruanyf)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ruanyifeng.com%2Fblog%2F2015%2F06%2Fes-checker.html&aid=2831&nid=78)  \n[理解 JavaScript 的原型链和继承 (MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.oyanglul.us%2Fjavascript%2Funderstand-prototype.html&aid=2861&nid=79)  \n[JavaScript 的语法解析与抽象语法树 (@晓风well)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwwsun.me%2Fposts%2Fjavascript-ast-tutorial.html&aid=2862&nid=79)  \n[Airbnb JavaScript 编码规范（简体中文版） (Che Yu)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fyuche%2Fjavascript&aid=2884&nid=79)  \n[Node Profiler - 一个 JavaScript 性能调优工具 (阿里云V8/Node团队)](http://weekly.manong.io/bounce?url=http%3A%2F%2Falinode.aliyun.com%2F&aid=2898&nid=79)  \n[《React 和 Webpack 小书》 (@fakefish_wjy)](http://weekly.manong.io/bounce?url=https%3A%2F%2Ffakefish.github.io%2Freact-webpack-cookbook%2F&aid=2879&nid=79)  \n[图解 JavaScript 原型链 (i小雨生)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.rainy.im%2F2015%2F07%2F20%2Fprototype-chain-in-js%2F&aid=2934&nid=80)  \n[ReactEurope Conf 参会感想 (@郭达峰)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fdfguo%2Fblog%2Fissues%2F1&aid=2942&nid=80)  \n[anypack：适用于组件化的打包工具（JavaScript） (SKing7)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2FSKing7%2Fanypack&aid=2972&nid=80)  \n[JavaScript 单例模式的理解 (涂根华)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Ftugenhua0707%2Fp%2F4660236.html&aid=3008&nid=81)  \n[[译] React Mixin 的使用 (@微博里的毛毛虫)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsegmentfault.com%2Fa%2F1190000003016446&aid=3010&nid=81)  \n[ES6 In Depth (Mozilla Hacks)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fhacks.mozilla.org%2Fcategory%2Fes6-in-depth%2F&aid=3022&nid=81)  \n[TSD：提升 IDE 对 JavaScript 智能感知的能力 (静听梵音-破狼)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fwhitewolf%2Fp%2Ftsd-javascript-Intelli-sense.html&aid=3067&nid=81)  \n[impressjs 插件开发 (yalishizhude)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyalishizhude.github.io%2F2015%2F07%2F06%2Fapis4impressjs%2F&aid=3048&nid=81)  \n[一个“三端”开发者眼中的 React Native (@小芋头君)](http://weekly.manong.io/bounce?url=http%3A%2F%2Ff2e.souche.com%2Fblog%2F-ge-san-duan-kai-fa-zhe-yan-zhong-de-react-native%2F&aid=3107&nid=82)  \n[Decorators in ES7 (llh911001)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fhackll.com%2F2015%2F07%2F24%2Fdecorators-in-es7%2F&aid=3108&nid=82)  \n[高性能 JavaScript 加载和执行 (韩子迟)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fzichi%2Fp%2F4684102.html&aid=3110&nid=82)  \n[Vue.js 源码学习笔记 (@勾三股四)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fjiongks.name%2Fblog%2Fvue-code-review%2F&aid=3128&nid=82)  \n[优雅的 underscore (亚里士朱德)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyalishizhude.github.io%2F2015%2F08%2F02%2Fbeatiful-underscore%2F&aid=3131&nid=82)  \n[Handlebars.js 初探 (久艾分享)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ido321.com%2F1629.html&aid=3141&nid=82)  \n[jdists：强大的代码块预处理工具（JS） (@王集鹄)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fzswang%2Fjdists&aid=3234&nid=83)  \n[谈谈 React.js 的核心入门知识 (晓风well)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwwsun.me%2Fposts%2Freact-getting-started.html&aid=3258&nid=84)  \n[理解 JavaScript 中的策略模式 (涂根华)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Ftugenhua0707%2Fp%2F4722696.html&aid=3259&nid=84)  \n[Vue.js：轻量高效的前端组件化方案 (尤雨溪)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.csdn.net%2Farticle%2F2015-08-11%2F2825439-vue&aid=3326&nid=84)  \n[入语言第二试：readtable 与 core.async (MilhouseVanHouten)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.oyanglul.us%2Fjavascript%2Fru-lang-second-attampt.html&aid=3279&nid=84)  \n[Babel.js 插件开发（二）：开始编写 (booooom)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.codefrom.com%2Fc%2F170&aid=3285&nid=84)  \n[[译] web workers 到底有多快？ (TAT.joey)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.alloyteam.com%2F2015%2F08%2Fweb-worker%2F&aid=3298&nid=84)  \n[CSS 指南 (Harry Roberts)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcssguidelin.es%2F&aid=1366&nid=42)  \n[CSS 置中完全指南 (Chris Coyier)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcss-tricks.com%2Fcentering-css-complete-guide%2F&aid=1435&nid=44)  \n[从 HTML Components 的衰落看 Web Components 的危机（@民工精髓V）](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fxufei%2Fblog%2Fissues%2F3&aid=1518&nid=47)  \n[前端代码异常监控 (@raphealguo)](http://weekly.manong.io/bounce?url=http%3A%2F%2Frapheal.sinaapp.com%2F2014%2F11%2F06%2Fjavascript-error-monitor%2F&aid=1601&nid=50)  \n[[译] 前端代码规范及最佳实践 (@老码农的自留地)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcoderlmn.github.io%2Fcode-standards%2F&aid=1603&nid=50)  \n[CSS 动画入门 (Rachel Cope)](http://weekly.manong.io/bounce?url=http%3A%2F%2Frobots.thoughtbot.com%2Fcss-animation-for-beginners&aid=1780&nid=57)  \n[2014 年 CSS 报告 (Alex McPherson)](http://weekly.manong.io/bounce?url=http%3A%2F%2Freports.quickleft.com%2Fcss&aid=1809&nid=58)  \n[2014 年 Web 高手都在做什么 (李亚飞)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyafeilee.me%2Fblogs%2F54995f3a6c69342f6d100000&aid=1811&nid=58)  \n[纯 CSS 实现打地鼠游戏 (Zihua Li)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzihua.li%2F2015%2F01%2Fimplement-pure-css-game%2F&aid=1837&nid=59)  \n[2015 前端框架何去何从？ (@侯振宇hzy)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fsskyy%2Fp%2F4264371.html&aid=1875&nid=60)  \n[前端组件库 (@Mr憬忟)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2FJingwenTian%2Fawesome-frontend&aid=1913&nid=61)  \n[创新高性能移动 UI 框架：Canvas UI 框架 (rank)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzA5NDY0ODkxNA%3D%3D%26mid%3D202786512%26idx%3D1%26sn%3Dc3b470b68a6d73953d38c309ea2f5f4b&aid=1952&nid=62)  \n[[译] CSS 的简写属性](http://weekly.manong.io/bounce?url=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FCSS%2FShorthand_properties&aid=1986&nid=63)  \n[CSS 参考手册 v4.1.7 (@doyoe)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcss.doyoe.com%2F&aid=2016&nid=64)  \n[2015 前端组件化框架之路 (@民工精髓V)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fxufei%2Fblog%2Fissues%2F19&aid=2018&nid=64)  \n[[译] 提升 Sketch 使用效率的 6 个实用技巧 (@C7210)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbeforweb.com%2Fnode%2F679&aid=2025&nid=64)  \n[[译] 30 个你必须记住的 CSS 选择符 (@颜海镜)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyanhaijing.com%2Fcss%2F2014%2F01%2F04%2Fthe-30-css-selectors-you-must-memorize%2F&aid=2136&nid=67)  \n[[译] 提升设计效率的 15 个免费 Sketch 插件 (@陈子木)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.uisdc.com%2F15-free-efficiency-plugins-sketch&aid=2144&nid=67)  \n[[译] 函数式 CSS (@颜海镜)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyanhaijing.com%2Fcss%2F2013%2F09%2F02%2Ffunctional-css-fcss%2F&aid=2182&nid=68)  \n[Amaze UI - 一个移动优先的跨屏前端框架 (AllMobilize)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fallmobilize%2Famazeui&aid=2199&nid=68)  \n[Materialize - 一个基于 Material Design 的 CSS 框架 (Alvin Wang)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2FDogfalo%2Fmaterialize&aid=2200&nid=68)  \n[前端性能优化最佳实践 (@前端开发博客)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcaibaojian.com%2Fwebfront-practice.html&aid=2258&nid=70)  \n[前端完美展现显示数学公式探讨 (@Aurthur-LK)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.gitos.cn%2F2015%2F05%2F10%2FThe-mathematical-formula-perfect-show.html&aid=2326&nid=71)  \n[Sass Guidelines（中文版）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsass-guidelin.es%2Fzh%2F&aid=2339&nid=71)  \n[深入理解 CSS3 弹性盒布局模型（2014） (成富)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ibm.com%2Fdeveloperworks%2Fcn%2Fweb%2F1409_chengfu_css3flexbox%2F&aid=2381&nid=72)  \n[[译] 为网页设计而生的 15 个优质 Sketch 插件 (@陈子木)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.uisdc.com%2F15-best-sketch-plugins-for-developers&aid=2415&nid=72)  \n[CSS Animation 初探 (@alexhilton)](http://weekly.manong.io/bounce?url=http%3A%2F%2Ftoughcoder.net%2Fblog%2F2015%2F05%2F04%2Fintroduction-to-css-animation%2F&aid=2452&nid=73)  \n[GitHub 上值得关注的前端项目 (@trigkit4)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsegmentfault.com%2Fa%2F1190000002804472&aid=2457&nid=73)  \n[前端架构介绍 (SaitoWu)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsaito.im%2Fnote%2FThe-Architecture-of-F2E%2F&aid=2503&nid=74)  \n[[译] 网页动画的十二原则 (@刘英滕)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.jianshu.com%2Fp%2F1858a8733ba3&aid=2510&nid=74)  \n[Canvas 处理头像上传 (lxjwlt)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.lxjwlt.com%2Ffront-end%2F2015%2F05%2F22%2Fcanvas-deal-width-avatar.html&aid=2519&nid=74)  \n[[译] CSS 布局模块 (@公子锦衣夜行)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.w3cplus.com%2Fcss3%2Fcss3-layout-modules.html&aid=2566&nid=75)  \n[浏览器 CSS Hack 收集 (@微博里的毛毛虫)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fsegmentfault.com%2Fa%2F1190000002890541&aid=2567&nid=75)  \n[用 Grunt 搭建自动化 Web 前端开发环境 (王福朋)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Fwangfupeng1988%2Fp%2F4561993.html&aid=2570&nid=75)  \n[IE7 浏览器下 CSS 属性选择器二三事 (@张鑫旭)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.zhangxinxu.com%2Fwordpress%2F2015%2F06%2Fie7-attribute-css-selector%2F&aid=2632&nid=76)  \n[[译] HTML 和 CSS 代码规范 (ZoomZhao)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzoomzhao.github.io%2Fcode-guide%2F&aid=2633&nid=76)  \n[[译] 网页动画终极指南 (@十萬個為什麽)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcolachan.com%2Fpost%2F3444&aid=2666&nid=76)  \n[仿造 iOS 风格的 UIPickerView 插件 (wen)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Flcepy%2FloseYourself&aid=2720&nid=77)  \n[Sketch 秒杀 PS CC 2015 新功能的 7 个地方 (@JingDesign)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.uisdc.com%2Fsketch-ps-cc2015-advantages&aid=2713&nid=77)  \n[前端技能训练：重构一 (@Phodal)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.phodal.com%2Fblog%2Ffrontend-improve-refactor-javascript-code%2F&aid=2710&nid=77)  \n[Web Components 初探 (大眼夹的鸟巢)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fblog.dayanjia.com%2F2014%2F06%2Fweb-components-introduction%2F&aid=2705&nid=77)  \n[HTML 中的 attribute 和 property (@寒冬winter)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fweibo.com%2Fp%2F1001603859879528949427&aid=2782&nid=78)  \n[《CSS 设计指南》学习笔记（二） (@大板栗Clear)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cleardesign.me%2Fstylin-with-css-note-2&aid=2783&nid=78)  \n[前端自动化测试探索 (@设计无极限的地盘)](http://weekly.manong.io/bounce?url=http%3A%2F%2Ffex.baidu.com%2Fblog%2F2015%2F07%2Ffront-end-test%2F&aid=2791&nid=78)  \n[Flexbox：更加优雅的 Web 布局 (卢小健)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fluxiaojian.me%2F2015%2F03%2F22%2Fflexboxgeng-jia-you-ya-de-webbu-ju%2F&aid=2802&nid=78)  \n[[译] Google 官方出品的 Material Design Web 框架 (cnBeta)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnbeta.com%2Farticles%2F408705.htm&aid=2816&nid=78)  \n[前端代码优化带来搜索引擎高效地识别移动页面 (@an7)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.an7.me%2F1561&aid=2892&nid=79)  \n[FIS3 发布了！ (fex-team)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Ffex-team%2Ffis3&aid=2902&nid=79)  \n[解读 CSS 布局之水平垂直居中 (@大地Dudy)](http://weekly.manong.io/bounce?url=http%3A%2F%2Ff2e.souche.com%2Fblog%2Fjie-du-cssbu-ju-zhi-shui-ping-chui-zhi-ju-zhong%2F&aid=2938&nid=80)  \n[移动端高清、多屏适配方案 (Lovesueee)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.html-js.com%2Farticle%2F3041&aid=2945&nid=80)  \n[最全前端开发面试问题及答案整理 (@trigkit4)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fhawx1993%2FFront-end-Interview-questions&aid=2948&nid=80)  \n[AEditor - 一个 H5 动画交互页开发工具 (AlloyTeam)](http://weekly.manong.io/bounce?url=http%3A%2F%2Faeditor.alloyteam.com%2F&aid=2978&nid=80)  \n[七牛前端测试实践 (@七牛云存储)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fweibo.com%2Fp%2F1001603864951990185052&aid=2964&nid=80)  \n[Flex 布局教程：实例篇 (@ruanyf)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ruanyifeng.com%2Fblog%2F2015%2F07%2Fflex-examples.html&aid=2970&nid=80)  \n[自定义标签在 IE6-8 的困境 (@司徒正美)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Frubylouvre%2Fp%2F4659431.html&aid=3025&nid=81)  \n[前端的基础修养：Microdata (@lepture)](http://weekly.manong.io/bounce?url=https%3A%2F%2Flepture.com%2Fzh%2F2015%2Ffe-microdata&aid=3027&nid=81)  \n[Web 中的图标 (@w3cplus)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Famfe%2Farticle%2Fissues%2F2&aid=3030&nid=81)  \n[[译] Web 设计师不可错过的 25+ CSS 工具 (shirleywong 等)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.oschina.net%2Ftranslate%2Fbest-css-tools-web-design&aid=3137&nid=82)  \n[利用 SVG 制作素描动画 (playniuniu)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.playniuniu.com%2Fposts%2Fli-yong-svg-zhi-zuo-su-miao-dong-hua.html&aid=3145&nid=82)  \n[Web App 变革之 rem (云平-Owen)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fisux.tencent.com%2Fweb-app-rem.html&aid=3201&nid=83)  \n[[Slide] 重拾 CSS 的乐趣（上） (@CSS魔法)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fcssmagic%2Fblog%2Fissues%2F52&aid=3260&nid=84)  \n[Web 前端开发大系概览 (@灵感之源)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.cnblogs.com%2Funruledboy%2Fp%2FWebFrontEndStack.html&aid=3276&nid=84)  \n[移动时代的前端加密 (@王集鹄)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fdiv.io%2Ftopic%2F1220&aid=3265&nid=84)  \n[[译] 42 个移动端启动页面优化 Tips](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.oschina.net%2Ftranslate%2F42-mobile-landing-page-optimization-tips&aid=3283&nid=84)  \n[[英] 如何实现基于物理的 UI 动效 (desandro)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fdesandro%2Fpractical-ui-physics&aid=3286&nid=84)  \n[写给前端面试者 (@w3cplus)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Famfe%2Farticle%2Fissues%2F5&aid=3293&nid=84)  \n[SVG 图标在移动端的应用 (ljian)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fued.ctrip.com%2Fblog%2F%3Fp%3D3893&aid=3299&nid=84)  \n[[译] 如何成为一名卓越的前端工程师 (@勾三股四)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fjiongks.name%2Fblog%2Fhow-to-become-a-great-front-end-engineer%2F&aid=3303&nid=84)\n[前端工程与性能优化（张云龙）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.infoq.com%2Fcn%2Farticles%2Ffront-end-engineering-and-performance-optimization-part1&aid=38&nid=3)  \n[15个响应式设计前端框架](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbeforweb.com%2Fnode%2F331&aid=113&nid=7)  \n[Font Awesome 4 发布](http://weekly.manong.io/bounce?url=http%3A%2F%2Ffontawesome.io%2F&aid=116&nid=7)  \n[12个超棒的 CSS3 功能（Martin Angelov）](http://weekly.manong.io/bounce?url=http%3A%2F%2Ftutorialzine.com%2F2013%2F10%2F12-awesome-css3-features-you-can-finally-use%2F&aid=139&nid=8)  \n[如何打造一个完美的 WebApp 全屏体验？（Paul Kinlan）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.html5rocks.com%2Fen%2Fmobile%2Ffullscreen%2F&aid=147&nid=8)  \n[学习 CSS 布局](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzh.learnlayout.com%2F&aid=164&nid=9)  \n[128款 Icon 免费下载](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.smashingmagazine.com%2F2013%2F11%2F03%2Ffreebie-nice-things-icon-set-png-ai-source%2F&aid=165&nid=9)  \n[[译] 交互体验优化：4步让移动网站看起来像本地应用（@sheran_兰）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fdjt.qq.com%2Farticle%2Fview%2F927&aid=189&nid=10)  \n[前端技能汇总（@朴灵）](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2FJacksonTian%2Ffks&aid=193&nid=10)  \n[Iconfont - 阿里巴巴矢量图标库](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.iconfont.cn%2F&aid=194&nid=10)  \n[DOM 事件介绍（Wilson Page）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fcoding.smashingmagazine.com%2F2013%2F11%2F12%2Fan-introduction-to-dom-events%2F&aid=213&nid=11)  \n[前端编程安全最佳实践](http://weekly.manong.io/bounce?url=http%3A%2F%2Fnet.tutsplus.com%2Ftutorials%2Fclient-side-security-best-practices%2F&aid=220&nid=11)  \n[前端 CSS 框架比较](http://weekly.manong.io/bounce?url=http%3A%2F%2Fusablica.github.io%2Ffront-end-frameworks%2Fcompare.html&aid=221&nid=11)  \n[[PDF] 前端自动化工作流（Addy Osmani）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fvdisk.weibo.com%2Fs%2FG-kaugh72r52&aid=240&nid=12)  \n[最佳设计工具集](http://weekly.manong.io/bounce?url=https%3A%2F%2Fhackdesign.org%2Ftoolkit&aid=251&nid=12)  \n[前端开发资源汇总（foru17）](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fforu17%2Ffront-end-collect&aid=278&nid=13)  \n[前端开发技术文档汇总](http://weekly.manong.io/bounce?url=http%3A%2F%2Fdevdocs.io%2F&aid=279&nid=13)  \n[HTML 标准](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.whatwg.org%2Fspecs%2Fweb-apps%2Fcurrent-work%2F&aid=317&nid=14)  \n[2014年最受关注的前端开发框架](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.sitepoint.com%2Fbest-web-designing-frameworks-2014%2F&aid=360&nid=17)  \n[Web Uploader - 一个简单的现代文件上传组件](http://weekly.manong.io/bounce?url=http%3A%2F%2Fgmuteam.github.io%2Fwebuploader%2F&aid=374&nid=17)  \n[[译] CSS3 transition 规范的实际使用经验（magie）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fisux.tencent.com%2Fcss3-transition.html&aid=403&nid=18)  \n[CSS3 悬停特效合集 Hover.css](http://weekly.manong.io/bounce?url=http%3A%2F%2Fianlunn.github.io%2FHover%2F&aid=410&nid=18)  \n[CSS 动画简介（@ruanyf）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ruanyifeng.com%2Fblog%2F2014%2F02%2Fcss_transition_and_animation.html&aid=513&nid=21)  \n[一些有用的 Web 设计师学习资源 (The Smashing Editorial)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.smashingmagazine.com%2F2014%2F02%2F14%2Flearning-resources-roundup%2F&aid=515&nid=21)  \n[响应式设计简明指南 (Adam Kaplan)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.adamkaplan.me%2Fgrid%2F&aid=659&nid=23)  \n[JX.Animate - 腾讯出品的轻量级 CSS3 动画库](http://weekly.manong.io/bounce?url=http%3A%2F%2Falloyteam.github.io%2FJXAnimate%2F&aid=668&nid=23)  \n[响应式 Web 图形篇——icon fonts 的探析及应用 (@beenhero)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fbeenhero.com%2Ficons-fonts-as-your-responsive-strategy%2F&aid=929&nid=27)  \n[CSS 魔法书 (Adam Schwartz)](http://weekly.manong.io/bounce?url=http%3A%2F%2Fadamschwartz.co%2Fmagic-of-css%2F&aid=950&nid=28)  \n[[译] 12 个很少被人知道的 CSS 事实（大圆）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.w3cplus.com%2Fcss%2F12-little-known-css-facts.html&aid=980&nid=29)  \n[海量前端开发资源 (dypsilon)](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fdypsilon%2Ffrontend-dev-bookmarks&aid=985&nid=29)  \n[前端开发框架对比（王芳侠）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.ibm.com%2Fdeveloperworks%2Fcn%2Fweb%2F1404_wangfx_jsframeworks%2F&aid=1055&nid=31)  \n[响应式 CSS 框架比较表](http://weekly.manong.io/bounce?url=http%3A%2F%2Fresponsive.vermilion.com%2Fcompare.php&aid=1056&nid=31)  \n[[译] 深入浅出 CSS Shape（@寸志）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fzhuanlan.zhihu.com%2Fthefrontendperiodicals%2F19774074&aid=1163&nid=34)  \n[Web Starter Kit - Google 出品的多设备 Web 开发入门套件](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fgoogle%2Fweb-starter-kit&aid=1198&nid=35)  \n[CSS 词汇表（@一丝yisi）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fyisibl.github.io%2Fcss-vocabulary%2F&aid=1225&nid=37)  \n[一些值得前端开发者订阅的 RSS 源](http://weekly.manong.io/bounce?url=https%3A%2F%2Fgithub.com%2Fimpressivewebs%2Ffrontend-feeds&aid=1284&nid=39)  \n[让我们再聊聊浏览器资源加载优化（李光毅）](http://weekly.manong.io/bounce?url=http%3A%2F%2Fwww.infoq.com%2Fcn%2Farticles%2Fbrowser-resource-loading-optimization&aid=1313&nid=40)  \n[[PDF] UC 前端工程实践](http://weekly.manong.io/bounce?url=http%3A%2F%2Fpan.baidu.com%2Fs%2F1o67Hlk2&aid=1338&nid=41)  "
  },
  {
    "path": "07-Front-End-Develop-Guide-master/Featured-Articles.md",
    "content": "## Front-End Develop 文章精选\n\n> 站在个人的角度，针对收录过的文章做了一个甄别、筛选。目的是摒弃杂音，更利于提高学习效率。\n\n由[@icepy](http://weibo.com/2455876310)负责整理\n\n### 教程类\n\n零基础的同学非常适合在学JavaScript之前阅读它：[重新介绍 JavaScript（JS 教程）](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript)，然后接着阅读[消除一些经常被误解的概念](http://bolinfest.com/javascript/misunderstood.html)。\n\n* [译：理解并掌握 JavaScript 中 this 的用法](http://code.mforever78.com/translation/2015/05/19/understand-javascripts-this-with-clarity-and-master-it/)\n* [理解JavaScript的原型链和继承](http://blog.oyanglul.us/javascript/understand-prototype.html)\n* [理解js闭包](http://www.w3cfuns.com/blog-5435393-5399202.html)\n* [细嗅Promise](http://www.cnblogs.com/hustskyking/p/promise.html)\n* [实战JS正则表达式](http://www.cnblogs.com/skylar/p/4265490.html)\n\n37个JavaScript题目，看看你能做正确多少个：[JavaScript Puzzlers](http://javascript-puzzlers.herokuapp.com/)\n\n编程风格指南推荐：[Airbnb JavaScript Style Guide](https://github.com/yuche/javascript)\n\n### ES6 前瞻\n\n个人认为是时候开始学习了，可以先了解一下有哪些特性，[Essential EcmaScript 6](http://blog.oyanglul.us/javascript/essential-ecmascript6.html)\n\n* [ECMAScript 6入门](http://es6.ruanyifeng.com/)\n* [ECMAScript 6 Features 中文版](https://github.com/ES-CN/es6features/blob/master/README.md)\n* [ECMAScript 6 Tools](https://github.com/addyosmani/es6-tools)\n\n### 深入浅出ES6系列\n\n从[InfoQ中文站](http://www.infoq.com/cn/minibooks/ES6-in-Depth)收集而来\n\n* [深入浅出ES6（一）：ES6是什么](http://www.infoq.com/cn/articles/es6-in-depth-an-introduction)\n* [深入浅出ES6（二）：迭代器和for-of循环](http://www.infoq.com/cn/articles/es6-in-depth-iterators-and-the-for-of-loop)\n* [深入浅出ES6（三）：生成器 Generators](http://www.infoq.com/cn/articles/es6-in-depth-generators)\n* [深入浅出ES6（四）：模板字符串](http://www.infoq.com/cn/articles/es6-in-depth-template-string)\n* [深入浅出ES6（五）：不定参数和默认参数](http://www.infoq.com/cn/articles/es6-in-depth-rest-parameters-and-defaults)\n* [深入浅出ES6（六）：解构 Destructuring](http://www.infoq.com/cn/articles/es6-in-depth-destructuring)\n* [深入浅出ES6（七）：箭头函数 Arrow Functions](http://www.infoq.com/cn/articles/es6-in-depth-arrow-functions)\n* [深入浅出ES6（八）：Symbols](http://www.infoq.com/cn/articles/es6-in-depth-symbols)\n* [学习Babel和Broccoli，马上就用ES6](http://www.infoq.com/cn/articles/es6-in-depth-babel-and-broccoli)\n* [深入浅出ES6（十）：集合](http://www.infoq.com/cn/articles/es6-in-depth-collections?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=articles_link&utm_content=link_text)\n* [深入浅出ES6（十一）：生成器 Generators，续篇](http://www.infoq.com/cn/articles/es6-in-depth-generators-continued)\n* [深入浅出ES6（十二）：代理 Proxies](http://www.infoq.com/cn/articles/es6-in-depth-proxies-and-reflect)\n* [深入浅出ES6（十三）：类 Class](http://www.infoq.com/cn/articles/es6-in-depth-classes)\n* [深入浅出ES6（十四）：let和const](http://www.infoq.com/cn/articles/es6-in-depth-let-and-const)\n* [深入浅出ES6（十五）：子类 Subclassing](http://www.infoq.com/cn/articles/es6-in-depth-subclassing)\n* [深入浅出ES6（十六）：模块 Modules](http://www.infoq.com/cn/articles/es6-in-depth-modules)\n* [深入浅出ES6（十七）：展望未来](http://www.infoq.com/cn/articles/es6-in-depth-the-future)\n\n### 深入浅出Node.js\n\n* [深入浅出Node.Js  在InfoQ上的内容](http://www.infoq.com/cn/master-nodejs/)"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/Featured.md",
    "content": "## Front-End Develop 项目精选\n\n> 站在个人的角度，针对开源项目做了一个甄别、筛选以及介绍。\n\n由[@icepy](http://weibo.com/2455876310)负责整理\n\n说明：顺序不分排名先后。\n\n## 目录\n\n* [框架](#framework)\n* [模板引擎](#template)\n* [模块化](#module)\n* [图表](#charts)\n* [界面](#ui)\n* [网络](#network)\n* [异步编程](#async)\n* [数据库操作](#db)\n* [应用环境类工具](#product-tools)\n* [开发环境类工具](#dev-tools)\n* [react 生态圈](#react)\n* [angular 生态圈](#angular)\n\n### <a id=\"framework\"></a> 框架\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[vue](https://github.com/yyx990803/vue) | [yyx990803](https://github.com/yyx990803) | 用于构建Web界面的MVVM JavaScript框架；\n[ionic](https://github.com/driftyco/ionic) | [Ionic](https://github.com/driftyco)| Ionic是一个强大的HTML5 原生应用（native app） 开发框架，帮助你用HTMLL，css和javascript构建具有原生味道的移动应用（mobile apps）；\n[koa](https://github.com/koajs/koa) | [koajs](https://github.com/koajs) | 下一代Node.js Web开发框架\n[angular.js](https://github.com/angular/angular.js) | [Angular](https://github.com/angular) | AngularJS是为了克服HTML在构建应用上的不足而设计的，通过为开发者呈现一个更高层次的抽象来简化应用的开发。如同其他的抽象技术一样，这也会损失一部分灵活性。换句话说，并不是所有的应用都适合用AngularJS来做。AngularJS主要考虑的是构建CRUD应用。幸运的是，至少90%的WEB应用都是CRUD应用。但是要了解什么适合用AngularJS构建，就得了解什么不适合用AngularJS构建。\n[avalon](https://github.com/RubyLouvre/avalon) | [RubyLouvre](https://github.com/RubyLouvre) | 用于构建Web界面的MVVM JavaScript框架；\n[express](https://github.com/strongloop/express) | [StrongLoop, Inc.](https://github.com/strongloop) | 它用于构建Web网站，非常快速；\n[riot](https://github.com/riot/riot) | [riot](https://github.com/riot/) | 一个小巧的UI和代码结构的框架；\n[wx](https://github.com/baoshan/wx) | [baoshan](https://github.com/baoshan)| wx是极简设计的微信（公共平台）应用参考级框架，而并非微信接口在node.js下的幂等映射；\n\n### <a id=\"template\"></a> 模板引擎\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[ejs](https://github.com/tj/ejs) | [tj](https://github.com/tj) | JavaScript模板引擎；\n[artTemplate](https://github.com/aui/artTemplate) | [aui](https://github.com/aui) | JavaScript模板引擎；\n\n### <a id=\"module\"></a> 模块化\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[requirejs](https://github.com/jrburke/requirejs)| [jrburke](https://github.com/jrburke) | JavaScript模块化的开山鼻祖，代表着AMD规范。\n[seajs](https://github.com/seajs/seajs)| [seajs](https://github.com/seajs) |JavaScript模块化库，代表着CMD规范。\n\n### <a id=\"charts\"></a> 图表\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[three.js](https://github.com/mrdoob/three.js) | [mrdoob](https://github.com/mrdoob/) |three.js是JavaScript编写的WebGL第三方库。提供了非常多的3D显示功能。Three.js 是一款运行在浏览器中的 3D 引擎，你可以用它创建各种三维场景，包括了摄影机、光影、材质等各种对象；\n[echarts](https://github.com/ecomfe/echarts) | [Baidu EFE team](https://github.com/ecomfe) | 基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据可视化图表；\n[d3](https://github.com/mbostock/d3) | [mbostock](https://github.com/mbostock)|基于JavaScript编写的一个图表库，非常强大；\n\n### <a id=\"ui\"></a> 界面\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[amazeui](https://github.com/amazeui/amazeui) | [amazeui](https://github.com/amazeui) | 国人出品的HTML5框架\n[fullPage.js](https://github.com/alvarotrigo/fullPage.js) | [alvarotrigo](https://github.com/alvarotrigo)| fullPage.js 是一个基于 jQuery 的插件，它能够很方便、很轻松的制作出全屏网站；\n[jQuery](https://github.com/jquery/jquery) | [jQuery Foundation](https://github.com/jquery) | jQuery 是一个高效、精简并且功能丰富的JavaScript 工具库；\n[Zepto](https://github.com/madrobby/zepto/) | [madrobby](https://github.com/madrobby) | Zepto是一个轻量级的针对现代高级浏览器的JavaScript库， 它与jquery有着类似的api。 如果你会用jquery，那么你也会用zepto；\n[FastClick](https://github.com/ftlabs/fastclick) | [FT Labs](https://github.com/ftlabs) | FastClick是一个简单的、易于使用的库，消除在移动浏览器上触发click事件与一个物理Tap(敲击)之间的300延迟；\n[backbone](https://github.com/jashkenas/backbone) | [jashkenas](https://github.com/jashkenas) | Backbone.js为复杂WEB应用程序提供模型(models)、集合(collections)、视图(views)的结构。其中模型用于绑定键值数据和自定义事件；集合附有可枚举函数的丰富API； 视图可以声明事件处理函数，并通过RESRful JSON接口连接到应用程序；\n[cheerio](https://github.com/cheeriojs/cheerio) | [cheeriojs](https://github.com/cheeriojs/) | 它可以从一坨html的片断中构建DOM结构，然后提供像jquery一样的css选择器查询；\n[hammer.js](https://github.com/hammerjs/hammer.js) | [hammerjs](https://github.com/hammerjs)| 处理触摸事件，以及手势的JavaScript库；\n\n### <a id=\"network\"></a> 网络\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[socket.io](https://github.com/socketio/socket.io) | [Socket.IO](https://github.com/socketio) | Socket.io是使用得非常普遍的前端调用Websocket的库；\n[superagent](https://github.com/visionmedia/superagent) | [visionmedia](https://github.com/visionmedia) |superagent 是nodejs里一个非常方便的客户端请求代理模块；\n\n### <a id=\"async\"></a> 异步编程\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[async](https://github.com/caolan/async) | [caolan](https://github.com/caolan/) |JS实现的一个方便快捷异步编程的库；\n[persistencejs](https://github.com/coresmart/persistencejs) | [coresmart](https://github.com/coresmart)| 是一个异步的Javascript库的对象关系映射框架；\n\n### <a id=\"db\"></a> 数据库操作\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[node-mongodb-native](https://github.com/mongodb/node-mongodb-native) | [mongodb](https://github.com/mongodb)| nodejs用于操作mongodb；\n\n### <a id=\"product-tools\"></a> 应用环境类工具\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[underscore](https://github.com/jashkenas/underscore) | [jashkenas](https://github.com/jashkenas)| JavaScript函数工具库；\n[lo_dash](https://lodash.com/)| [Lodash Utilities](https://github.com/lodash) | JavaScript函数工具库； \n[sugar.js](http://sugarjs.com/) | [andrewplummer](https://github.com/andrewplummer) | 它扩展了现有的JS对象的方法，让你可以用更少的代码做更多的事情；\n[JavaScript-MD5](https://github.com/blueimp/JavaScript-MD5) | [blueimp](https://github.com/blueimp/) | JS版的MD5;\n[resumable.js](https://github.com/23/resumable.js) | [23](https://github.com/23)| 这是用于HMLT5 File Api封装可以方便操作文件的一个库；\n[node-memwatch](https://github.com/lloyd/node-memwatch) | [lloyd](https://github.com/lloyd) | 用于检测Node服务内存\n[node-heapdump](https://github.com/bnoordhuis/node-heapdump) | [bnoordhuis](https://github.com/bnoordhuis) | Node内存调试\n\n### <a id=\"dev-tools\"></a> 开发环境类工具\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[browserify](https://github.com/substack/node-browserify) | [substack](https://github.com/substack)| browserify是一个node.js模块，主要用于改写现有的CommonJS模块，使得浏览器端也可以使用这些模块；\n[TSD](https://github.com/DefinitelyTyped/tsd) | [DefinitelyTyped](https://github.com/DefinitelyTyped)| 在TypeScript中替换第三方库所使用的引用文件;\n[TypeScript](https://github.com/Microsoft/TypeScript) | [Microsoft](https://github.com/Microsoft)| JavaScript的超集，扩展了类型，类，接口等语法，兼容ES6；\n[Commander.js](https://github.com/tj/commander.js) | [tj](https://github.com/tj)| 可以帮助快速开发Nodejs命令行工具的一个包\n[marked](https://github.com/chjj/marked) | [chjj](https://github.com/chjj) | markdown解析器；\n[node-inspector](https://github.com/node-inspector/node-inspector) | [node-inspector](https://github.com/node-inspector) |nodejs的调试工具；\n[node-supervisor](https://github.com/petruisfan/node-supervisor) | [petruisfan](https://github.com/petruisfan) |nodejs用于无需重启的工具\n[candy](https://github.com/guo-yu/candy) | [guo-yu](https://github.com/guo-yu)| 基于多说社交评论的社会化论坛系统，采用 Node.js/Mongodb 构建；\n\n### <a id=\"react\"></a> react 生态圈\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[React](https://github.com/facebook/react) | [Facebook](https://github.com/facebook)| 这是该公司用于构建反应式图形界面的JavaScript库;\n[react-redux](https://github.com/rackt/react-redux) | [rackt](https://github.com/rackt) | Flux架构实现\n[react-router](https://github.com/rackt/react-router) | [rackt](https://github.com/rackt) | React路由系统\n[Flow](https://github.com/facebook/flow) | [Facebook](https://github.com/facebook)| 该公司出品的一个JavaScript静态编译器\n[React Native](https://github.com/facebook/react-native) | [Facebook](https://github.com/facebook) | 该公司出品的一个可以使用JavaScript来构建Native UI的库；\n[classnames](https://github.com/JedWatson/classnames) | [JedWatson](https://github.com/JedWatson/)| 一个简单的工具有条件性的添加class类名\n[react-bootstrap](https://github.com/react-bootstrap/react-bootstrap) | [react-bootstrap](https://github.com/react-bootstrap/)| bootstrap react版\n\n### <a id=\"angular\"></a> angular生态圈\n\n项目 |开发者&组织 | 备注\n---- | ---- | ----\n[angular-ui-router](https://github.com/angular-ui/ui-router) | [AngularUI](https://github.com/angular-ui) | angular-ui-router是AngularJS的路由框架，和默认的$route不同，它将所有路由包装成可划分层级的状态机状态,路由路径在ui-router中不是必须的。由于ui-router的路由状态机是分层级的，所以使用ui-router可以非常方便地创建包含多个嵌入的子模板；"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/HelloWorld.swift",
    "content": "print(\"Hello world\")\n"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/README.md",
    "content": "##Front-End-Develop-Guide 前端开发指南\n\n创建此项目灵感从[SwiftGuide](https://github.com/ipader/SwiftGuide)而来，这份指南汇集了前端开发所使用语言的主流学习资源，并以开发者的视角进行整理编排而成。\n\nGitHub：[mulgore/Front-End-Develop-Guide](https://github.com/mulgore/Front-End-Develop-Guide) ｜欢迎开发者一起[维护](https://github.com/mulgore/Front-End-Develop-Guide/pulls)，或[反馈/投稿](https://github.com/mulgore/Front-End-Develop-Guide/issues/new)_\n\n> 想了解关于该指南及 前端开发 更多信息的同学，可以阅读短文《[致 Front-End Developers](https://github.com/mulgore/Front-End-Develop-Guide/blob/master/2015letter.md)》。 想查看优秀的开源项目，可以访问[《Front-End Develop 项目精选》](https://github.com/mulgore/Front-End-Develop-Guide/blob/master/Featured.md)。希望查看精选文章，可以访问[《Front-End Develop 文章精选》](https://github.com/mulgore/Front-End-Develop-Guide/blob/master/Featured-Articles.md)。也欢迎企业招聘人才提供工作岗位(請附上薪資)，可以提交到[工作岗位](https://github.com/mulgore/Front-End-Develop-Guide/issues/3)。\n\n由[@icepy](http://weibo.com/2455876310)负责整理，欢迎大家加入《前端Talk读者交流群》添加 **icepy_1988** 为好友后会邀请你加入。\n\n**由于个人精力有限，不足之处还望大家多多包容与提供建议。**\n\n<span style=\"color:lightgray;font-size:12px\"></span>\n\n##目录\n\n* [Front-End Develop 文档](#fed_doc)\n\t* [Welcome to Front-End Develop](#fed_we)\n\t* [Front-End Develop Language](#fed_language)\n\t\t* [HTML&HTML5 文档](#html_doc)\n\t\t* [CSS&CSS3 文档](#css_doc)\n\t\t\t* [CSS Style Guide](#css_style_guide)\n\t\t\t* [CSS Language](#css_language)\n\t\t\t* [Sass Guide](#sass_guide)\n\t\t\t* [PostCss](#postcss_guide)\n\t\t* [JavaScript 文档](#javascript_doc)\n\t\t\t* [JavaScript Style Guide](#javascript_style_guide)\n\t\t\t* [JavaScript Language](#javascript_language)\n\t* [Front-End Develop Fly](#fed_fly)\n\t\t* [常用库与框架的使用文档](#fed_library)\n\t\t* [JavaScript 日志](#fed_log)\n\t\t* [开放网络标准](#fed_openAPI)\n\t\t* [HTTP 文档](#fed_http)\n\t\t* [缓存策略](#fed_cache)\n\t\t* [前端自动化工具](#fed_automate_kit)\n\t\t* [React&React Native生态-探索学习](#fed_point_recommend)\n\t\t* [移动前端技术](#fed_mobile_jishu)\n\t\t* [移动web UI框架](#fed_mobile_lib)\n\t\t* [动画](#fed_animation)\n\t\t* [性能调优](#fed_xingneng_tiaoyou)\n\t* [Front-End Develop 项目与工具](#fed_project_kit)\n\t\t* [相关工具](#fed_kit)\n\t\t* [Front-End Develop 开源项目](#fed_opensource)\n\t* [Front-End Questions](#fed_questions)\n\t* [Front-End 需要了解的数据结构与算法](#fed_datastructure)\n* [延伸可扩展的方向](#fed_scalable)\n\t* [Node.js](#fed_nodejs)\n\t* [Mongodb](#fed_mongodb)\n\t* [WebGL](#fed_webGL)\n\t* [Chrome扩展开发](#fed_chrome)\n\t* [桌面应用程序开发](#fed_PCAPP)\n\t* [移动应用程序开发](#fed_mobile)\n\t* [V8 引擎文献](#fed_v8)\n* [社区](#fed_community)\n* [码农周刊JavaScript和前端部分优秀文章集合](#fed_article)\n\n# <a id=\"fed_doc\"></a> Front-End Develop 文档\n\n初略读懂Front-End Develop要做些什么\n\n[Web Front-End Stack](https://github.com/unruledboy/WebFrontEndStack/blob/master/README.md)：这张图非常详细。\n\n## <a id=\"fed_we\"></a> Welcom to Front-End Develop\n\nW3C组织提供了官网的地址：[w3.org](http://www.w3.org/)，可以去查询最近实现的标准以及将来可能实现的讨论。\n\n## <a id=\"fed_language\"></a> Front-End Develop Language\n\nweb前端开发可能包括HTML,CSS,JavaScript,Web API,SVG,WebGL,MathML等，语言是编程的基础，火狐的MDN出了一份比较通略的文档，可以快速查看[Web 技术文档](https://developer.mozilla.org/zh-CN/docs/Web)。\n\n### <a id=\"html_doc\"></a> HTML&HTML5 文档\n===\n\n* [无处不在的html](https://www.phodal.com/blog/be-a-geek-chapter-1-anywhere-html/)：HTML是Web的核心语言，也是最基础的语言；\n* [XHTML2 Working Group Home Page](http://www.w3.org/MarkUp/)\n* [HTML5 API Search](http://html5index.org/)：可以快速的查询某个HTML5的API；\n* [HTML5 Rocks](http://www.html5rocks.com/zh/tutorials/?page=1)：通过这个网站可以搜索到很多关于HTML5的教程；\n\n书籍：\n\n* [图灵程序设计丛书:HTML5权威指南](http://www.amazon.cn/%E5%9B%BE%E7%81%B5%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E2%80%A69B%BC/dp/B00H706BIG/ref=sr_1_4?ie=UTF8&qid=1424220765&sr=8-4&keywords=html)\n\n### <a id=\"css_doc\"></a> CSS&CSS3 文档\n===\n\n#### <a id=\"css_style_guide\"></a> CSS Style Guide\n\n* [编码规范 by @mdo](http://zoomzhao.github.io/code-guide/)：开发灵活，稳定，可持续 HTML 和 CSS 代码的规范，每一项都有很详细的解释；\n* [css guide lines](http://cssguidelin.es/)\n* [通用 CSS 笔记、建议与指导](https://github.com/chadluo/CSS-Guidelines/blob/master/README.md)：本文档第一部分将探讨语法、格式以及分析 CSS 结构；第二部分将围绕方法论、思维框架以及编写与规划 CSS 的看法；\n\n#### <a id=\"css_language\"></a> CSS Language\n\n* [学习CSS布局](http://zh.learnlayout.com/)：教授的是现在广泛使用于网站布局领域的CSS基础；\n* [CSS3 Tutorial 《CSS3 教程》](https://github.com/waylau/css3-tutorial)：CSS3 Tutorial 是一本关于 CSS3 的开源书，作者利用业余时间写了本书，图文并茂，用大量实例带你一步一步走进 CSS3 的世界；\n* [Magic of CSS](http://adamschwartz.co/magic-of-css/)\n* [CSS词汇表](http://yisibl.github.io/css-vocabulary/)：查询CSS的词汇；\n* [CSS参考](http://css.doyoe.com/)\n\n#### <a id=\"sass_guide\"></a> Sass Guide\n\n* [Sass基础知识](http://sass-lang.com/guide)：Sass官网，讲述Sass/SCSS应用的基础知识，变量、函数、条件、循环、宏等等；\n* [Sass中文网](http://www.sasschina.com/)：中文大，给E文不好的小朋友们；\n* [Sass Guidelines](http://sass-guidelin.es/zh/)：这是由Sass专家[Hugo Giraudel](http://hugogiraudel.com/)撰写的一份“编写稳健、可维护和可扩展的Sass”的指南，这份指南已被翻译成中文；\n* [Sass meister](http://www.sassmeister.com/)：在线Sass/SCSS调试器；\n\n#### <a id=\"postcss_guide\"></a> PostCss\n\n* [Post Css](https://github.com/postcss/postcss)\n\n### <a id=\"javascript_doc\"></a> JavaScript 文档\n===\n\n注明：JavaScript文档将引用[justjavac/free-programming-books-zh_CN#JavaScript](https://github.com/justjavac/free-programming-books-zh_CN#javascript)所整理的免费图书以及自己所收集的资料；\n\n#### <a id=\"javascript_style_guide\"></a> JavaScript Style Guide\n\n* [Google JavaScript 代码风格指南](http://bq69.com/blog/articles/script/868/google-javascript-style-guide.html)：Google风格指南不但指出每条规范，还解释了为什么这样写的原因，同时给出了对与错的实例；\n* [Airbnb JavaScript 规范](https://github.com/adamlu/javascript-style-guide)：A mostly reasonable approach to JavaScript，跟Google规范类似；\n* [Google JSON 风格指南](https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md)：该风格指南是对在Google创建JSON APIs而提供的指导性准则和建议。总体来讲，JSON APIs应遵循JSON.org上的规范。这份风格指南澄清和标准化了特定情况，从而使Google的JSON APIs有一种标准的外观和感觉。这些指南适用于基于RPC和基于REST风格的API的JSON请求和响应；\n* [Javascript编程指南](http://pij.robinqu.me/) ([源码](https://github.com/RobinQu/Programing-In-Javascript))\n\n#### <a id=\"javascript_language\"></a> JavaScript Language\n\n* [重新介绍 JavaScript（JS 教程）](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript)：是火狐推出的一系列的JS教程，为什么会有这一篇“重新介绍”呢？因为 JavaScript 堪称世界上被人误解最深的编程语言。虽然常被视作“玩具语言”，但它看似简洁外衣下，还隐藏着强大的语言特性。 JavaScript 目前广泛应用于一大批知名应用中，对于网页和移动开发者来说，深入理解 JavaScript 就尤有必要；\n* [JavaScript 标准参考教程（alpha）](http://javascript.ruanyifeng.com/)\n* [javascript 的 12 个怪癖](https://github.com/justjavac/12-javascript-quirks)\n* [JavaScript 秘密花园](http://bonsaiden.github.io/JavaScript-Garden/zh/)\n* [JavaScript核心概念及实践](http://icodeit.org/jsccp/)：(PDF) (此书已由人民邮电出版社出版发行，但作者依然免费提供PDF版本，希望开发者们去购买，支持作者)；\n* [《JavaScript 模式》](https://github.com/jayli/javascript-patterns)：“JavaScript patterns”中译本；\n* [命名函数表达式探秘](http://justjavac.com/named-function-expressions-demystified.html) ：(注:原文由[为之漫笔](http://www.cn-cuckoo.com)翻译，原始地址无法打开，所以此处地址为我博客上的备份)；\n* [学用 JavaScript 设计模式](http://www.oschina.net/translate/learning-javascript-design-patterns) ：(开源中国)\n* [深入理解JavaScript系列](http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html)：汤姆大叔2011年翻译的一系列的文章，很值得一读；\n* [ECMAScript 6 入门](http://es6.ruanyifeng.com/)：(作者：阮一峰)\n* [JavaScript Promise迷你书](http://liubin.github.io/promises-book/)：讲述Promise实现；\n* [You-Dont-Know-JS](https://github.com/getify/You-Dont-Know-JS)：(深入JavaScript语言核心机制的系列图书)；\n\n## <a id=\"fed_fly\"></a> Front-End Develop Fly\n\n如果你想飞起来，这正是好去处。\n\n### <a id=\"fed_library\"></a>了解常用库与框架的使用文档\n\n* jQuery\n\t* [简单易懂的JQuery魔法](http://www.nowamagic.net/librarys/books/contents/jquery)\n\t* [How to write jQuery plugin](http://i5ting.github.io/How-to-write-jQuery-plugin/build/jquery.plugin.html)\n* underscore.js\n    * [Underscore.js中文文档](http://learningcn.com/underscore/)\n* backbone.js\n    * [backbone.js入门教程](http://www.the5fire.com/backbone-js-tutorials-pdf-download.html) (PDF)\n    * [Backbone.js入门教程第二版](https://github.com/the5fire/backbonejs-learning-note)\n    * [Developing Backbone.js Applications(中文版)](http://feliving.github.io/developing-backbone-applications)\n* AngularJS\n    * [AngularJS最佳实践和风格指南](https://github.com/mgechev/angularjs-style-guide/blob/master/README-zh-cn.md)\n    * [AngularJS中译本](https://github.com/peiransun/angularjs-cn)\n    * [AngularJS入门教程](https://github.com/zensh/AngularjsTutorial_cn)\n    * [构建自己的AngularJS](https://github.com/xufei/Make-Your-Own-AngularJS/blob/master/01.md)\n    * [在Windows环境下用Yeoman构建AngularJS项目](http://www.waylau.com/build-angularjs-app-with-yeoman-in-windows/)\n    * [大型应用下的 AngularJS 性能](http://web.jobbole.com/82060/)\n    * [Angular Modules](http://ngmodules.org/)  可以搜索Angular.JS可用的各种插件，模块等等。\n    * [AngularJS性能优化心得](https://github.com/atian25/blog/issues/5)\n* Zepto.js\n    * [Zepto.js](http://zeptojs.com/)\n* JSLite\n    * [JSLite.io](http://JSLite.io/)\n* Sea.js\n    * [Hello Sea.js](http://island205.github.io/HelloSea.js/)\n* impress.js\n    * [impress.js的中文教程](https://github.com/kokdemo/impress.js-tutorial-in-Chinese)\n* CoffeeScript\n    * [CoffeeScript Cookbook](http://island205.github.io/coffeescript-cookbook.github.com/)\n    * [The Little Book on CoffeeScript中文版](http://island205.github.io/tlboc/)\n    * [CoffeeScript 编码风格指南](https://github.com/geekplux/coffeescript-style-guide)\n* ExtJS\n    * [Ext4.1.0 中文文档](http://extjs-doc-cn.github.io/ext4api/)\n* Meteor\n    * [Discover Meteor](http://zh.discovermeteor.com/)\n* TypeScript\n\t* [TypeScript 指南](https://github.com/vilic/typescript-guide)\n\t* [TypeScript手册翻译系列](http://my.oschina.net/1pei/blog/515680?fromerr=O3Jow9bO)\n* requirejs\n\t* [RequireJS 中文网](http://requirejs.cn/)\n* vue.js\n\t* [vue 官方网站](http://cn.vuejs.org/)\n\n\n### <a id=\"javascript_log\"></a> JavaScript 日志\n\n[前端代码异常日志与监控](http://www.cnblogs.com/hustskyking/p/fe-monitor.html)\n\n### <a id=\"fed_openAPI\"></a> 开放网络标准\n\n[理解OAuth 2.0](http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html)\n\n### <a id=\"fed_http\"></a> HTTP 文档\n\n下面两篇文章不会对 HTTP 的细节进行深究，而是从够高和更结构化的角度将 HTTP 协议的元素进行分类讲解，可以先阅读[HTTP 协议漫谈](http://blog.jobbole.com/88199/)和[图解Http协议](http://www.bysocket.com/?p=282)来对HTTP有一个大概的了解。\n\n* [HTTP协议](http://www.cnblogs.com/TankXiao/category/415412.html)\n* [HTTP/2协议的背景、内容、实现和未来](https://ye11ow.gitbooks.io/http2-explained/content/)\n* [HTTP 下午茶](http://happypeter.github.io/tealeaf-http/#chinese)\n* [HTTP接口设计指南](https://github.com/bolasblack/http-api-guide)\n* [白话 HTTPS & SSL/TSL](http://www.jianshu.com/p/992bad24412e)：你肯定能阅读明白。\n\n深入全面了解，可阅读[HTTP权威指南](http://book.douban.com/subject/10746113/)。\n\n### <a id=\"fed_cache\"></a> 缓存策略\n\ncache是提高应用性能重要的一个环节，必需要有所了解。\n\n[Web缓存机制系列](http://www.alloyteam.com/2012/03/web-cache-1-web-cache-overview/)\n\n### <a id=\"fed_automate_kit\"></a> 前端自动化工具\n\n现在的前端自动化工具主要如下三个流派，目测涵盖90%以上经常使用。\n\n* [Grunt JavaScript世界的构建工具](http://www.gruntjs.net/)\n* [Gulp 用自动化构建工具增强你的工作流](http://www.gulpjs.com.cn/)\n* [Webpack](https://github.com/webpack/webpack)\n\n### <a id=\"fed_point_recommend\"></a> React&React Native生态-探索学习\n\n* [React&React Native生态-探索学习](https://github.com/mulgore/Front-End-Develop-Guide/blob/master/react/React.md)\n\n### <a id=\"fed_mobile_jishu\"></a> 移动前端技术\n\n* [移动端尺寸基础知识](http://colachan.com/post/3435)\n* [移动端高清、多屏适配方案](http://www.html-js.com/article/Mobile-terminal-H5-mobile-terminal-HD-multi-screen-adaptation-scheme%203041)\n* [移动端开发小记 - Flexbox](http://taobaofed.org/blog/2015/11/11/flexbox-in-mobile-web/)\n\n### <a id=\"fed_mobile_lib\"></a> 移动web UI框架\n* [微信的We UI](https://github.com/weui/weui)\n* [淘宝的SUI](http://m.sui.taobao.org/)\n* [百度的GMU](http://gmu.baidu.com/)\n* [豆瓣的CardKit](https://github.com/dexteryy/CardKit)\n\n### <a id=\"fed_animation\"></a> 动画\n\n* [搞定这些疑难杂症，向css3动画说yes](http://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=400429327&idx=1&sn=e535eac5d3c74e2fb1633d3e8cc0e0ed&scene=4#wechat_redirect)\n\n### <a id=\"fed_xingneng_tiaoyou\"></a> 性能调优\n\n* [web移动端性能调优及16ms优化](http://www.ghugo.com/gone-in-60-frames-per-second/)\n* [无线性能优化：域名收敛](http://taobaofed.org/blog/2015/12/16/h5-performance-optimization-and-domain-convergence/)\n* [缓存机制浅析 移动端 Web 加载性能优化](http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=402077566&idx=1&sn=def3337205c3aec5e0fde2476ee03397&scene=0&key=ac89cba618d2d976159e30761eefe9953dc2030a7d72c1872c445a8caaa0f1d3cc4eb416a1c7cfb82651db48d11f3f90&ascene=0&uin=MjAyNzY1NTU%3D)\n* [移动端网络优化－同样适用于HTML5页面](http://www.trinea.cn/android/mobile-performance-optimization/)\n* [移动H5前端性能优化指南](http://isux.tencent.com/h5-performance.html)\n* [权威的前端性能指南](https://browserdiet.com/zh/)\n\n## <a id=\"fed_project_kit\"></a> Front-End Develop 项目与工具\n\n工欲善其事，必先利其器。开源项目与工具的使用，将极大的提高前端开发之效率。\n\n### <a id=\"fed_kit\"></a> 相关工具\n\n####1. 开发工具\n\n* [Sublime Text](http://www.sublimetext.com/)：前端开发好用到爆；\n* [Atom](https://atom.io/)：Github出品的一个类似Sublime Text编辑器，长的蛮像的，快捷键也非常类似；\n* [Vundle.vim](https://github.com/VundleVim/Vundle.vim)：使用vim开发前端的利剑，包括其他语言；\n\nSublime Text常用的插件：\n\n* [Emmet](https://github.com/sergeche/emmet-sublime)：zen coding的升级版，对于前端来说，可是必备插件;\n* [sublimelint](https://github.com/lunixbochs/sublimelint)：用于代码的校验，支持 HTML、CSS、JS、PHP、Java、C++ 等16种语言;\n* [JsFormat](https://packagecontrol.io/packages/JsFormat)：用于JavaScript格式化;\n* [jQuery](https://packagecontrol.io/packages/jQuery)：jQuery语法提示;\n* [Underscore](https://packagecontrol.io/packages/Underscore.js%20Snippets)：Underscore语法提示;\n* [DocBlockr](https://packagecontrol.io/packages/DocBlockr)：快速编写注释;\n* [SublimeCodeIntel](https://packagecontrol.io/packages/SublimeCodeIntel)：智能语法分析提示;\n* [ColorPicker](https://packagecontrol.io/packages/ColorPicker)：快速选取颜色\n* [HTML-CSS-JS Prettify](https://packagecontrol.io/packages/HTML-CSS-JS%20Prettify)：html/css/js 格式化\n* [Alignment](https://packagecontrol.io/packages/Alignment)：用于代码对齐;\n* [WakaTime](https://packagecontrol.io/packages/WakaTime)：用于记录编程时间；\n* [Seti_UI](https://packagecontrol.io/packages/Seti_UI)：好看的主题，包括文件icon；\n* [OmniMarkupPreviewer](https://packagecontrol.io/packages/OmniMarkupPreviewer)：将MD文件渲染成网页，可以在浏览器中查看；\n* [Babel](https://packagecontrol.io/packages/Babel)：ES6语法高亮；\n\nAtom常用的插件：\n\n* [TypeScript](https://github.com/TypeStrong/atom-typescript)：支持TypeScript编译；\n* [run-in-browser](https://atom.io/packages/run-in-browser)：支持运行网页；\n* [Emmet](https://atom.io/packages/emmet)：快速编写HTML；\n* [minimap](https://atom.io/packages/minimap)：右侧小地图；\n* [color-picker](https://atom.io/packages/color-picker)：CSS颜色取色器；\n* [autoprefixer](https://atom.io/packages/autoprefixer)：自动补全CSS前缀；\n* [autocomplete-paths](https://atom.io/packages/autocomplete-paths)：对路径选择进行增强；\n* [autocomplete-python](https://atom.io/packages/autocomplete-python)：对Python提示进行增强；\n* [docblockr](https://atom.io/packages/docblockr)：编写注释好帮手；\n* [file-icons](https://atom.io/packages/file-icons)：美化编辑器图标；\n* [linter-jshint](https://atom.io/packages/linter-jshint)：JavaScript语法检查；\n\nvim常用的插件：\n\n\tBundle 'christoomey/vim-run-interactive'\n\tBundle 'Valloric/YouCompleteMe'\n\tBundle 'croaky/vim-colors-github'\n\tBundle 'danro/rename.vim'\n\tBundle 'majutsushi/tagbar'\n\tBundle 'kien/ctrlp.vim'\n\tBundle 'pbrisbin/vim-mkdir'\n\tBundle 'scrooloose/syntastic'\n\tBundle 'slim-template/vim-slim'\n\tBundle 'thoughtbot/vim-rspec'\n\tBundle 'tpope/vim-bundler'\n\tBundle 'tpope/vim-endwise'\n\tBundle 'tpope/vim-fugitive'\n\tBundle 'tpope/vim-rails'\n\tBundle 'tpope/vim-surround'\n\tBundle 'vim-scripts/ctags.vim'\n\tBundle 'vim-scripts/tComment'\n\tBundle \"mattn/emmet-vim\"\n\tBundle \"scrooloose/nerdtree\"\n\tBundle \"Lokaltog/vim-powerline\"\n\tBundle \"godlygeek/tabular\"\n\tBundle \"msanders/snipmate.vim\"\n\tBundle \"jelera/vim-javascript-syntax\"\n\tBundle \"altercation/vim-colors-solarized\"\n\tBundle \"othree/html5.vim\"\n\tBundle \"xsbeats/vim-blade\"\n\tBundle \"Raimondi/delimitMate\"\n\tBundle \"groenewege/vim-less\"\n\tBundle \"evanmiller/nginx-vim-syntax\"\n\tBundle \"Lokaltog/vim-easymotion\"\n\tBundle \"tomasr/molokai\"\n\tBundle \"klen/python-mode\"\n\tBundle \"leafgarland/typescript-vim\"\n\tBundle \"scrooloose/nerdcommenter\"\n\n* [HTML5 Please](http://html5please.com/)：HTML5与CSS3技术评估\n* [Mobile HTML5](http://mobilehtml5.org/)：HTML5兼容性速查表\n* [HTML5 Cross Browser Polyfills](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills)\n\n####2. 源代码管理工具\n\n* [Github](https://github.com)：声望日盛-全球最大的“同性”网站；\n* [Github For Mac](https://desktop.github.com/)：设计的非常美观的git管理客户端，它能取代命令行所获得的功能；\n* [Gitcafe](https://gitcafe.com/)：国内的Github，相比之下拥有速度优势；\n* [Git@OSC](https://git.oschina.net/)：也是类似的项目，在国内，可以免费建立1000+私有项目；\n\n####3. Mac工具\n\n关于Mac平台的使用，推荐大家阅读[入门精选](http://wsgzao.github.io/post/mac/)\n\n* [HomeBrew](http://brew.sh/index_zh-cn.html)：OS X上非常优秀的包管理工具；\n* [HomeBrew-Cask](http://ksmx.me/homebrew-cask-cli-workflow-to-install-mac-applications/)：简洁优雅的Mac OS X软件安装体验；\n* [iTerm 2](http://www.iterm2.com/index.html)：OS X上一个增强版的shell终端；\n* [oh-my-zsh](http://ohmyz.sh/)：OS X上用来增强shell命令行的工具；\n* [Dash](https://kapeli.com/dash)：Dash is an API Documentation Browser and Code Snippet Manager. Dash stores snippets of code and instantly searches offline documentation sets for 150+ APIs (for a full list, see below). You can even generate your own docsets or request docsets to be included；\n* [tmux](https://aquaregia.gitbooks.io/tmux-productive-mouse-free-development_zh/content/index.html)：终端复用神器，帮助在Mac或者Linux上做开发的程序员在使用终端时更加得心应手；\n* [MacVim](https://github.com/b4winckler/macvim)：Mac下GUI vim编辑器；\n* [Xcode](https://developer.apple.com/xcode/downloads/)：也许你用不上，安装Xcode主要是为了Xcode command line tools工具包，你也可以选择不安装Xcode，使用xcode-select --install跳过Xcode的安装；\n* [Postman](http://chromecj.com/web-development/2014-09/60.html) Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。\n\n####4. VPN\n\n* [云梯VPN](https://www.cloudtizi.com/)\n\n####5. ES6编译\n\n* [babel](https://github.com/babel/babel)\n\n####6. gulp工具\n\n* [gulp-clean](https://www.npmjs.com/package/gulp-clean)：用于清理;\n* [gulp-notify](https://www.npmjs.com/package/gulp-notify)：用于打印消息文本;\n* [gulp-rename](https://www.npmjs.com/package/gulp-rename)：用于修改名字;\n* [gulp-concat](https://www.npmjs.com/package/gulp-concat)：用于合并文件;\n* [gulp-zip](https://www.npmjs.com/package/gulp-zip)：用于生成一个zip压缩包;\n* [gulp-minify-css](https://www.npmjs.com/package/gulp-minify-css)：用于压缩css;\n* [gulp-autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer)：用于给css添加前缀;\n* [gulp-imagemin](https://www.npmjs.com/package/gulp-imagemin)：用于给图片进行优化;\n* [gulp-uglify](https://www.npmjs.com/package/gulp-uglify)：用于压缩js;\n* [amd-optimize](https://www.npmjs.com/package/amd-optimize)：用于AMD模块引用编译；\n* [gulp-import-css](https://www.npmjs.com/package/gulp-import-css)：如果css文件是通过import导入的可以使用此插件进行合并优化;\n* [gulp-rev-replace](https://www.npmjs.com/package/gulp-rev-replace)：用于替换;\n* [gulp-useref](https://www.npmjs.com/package/gulp-useref)：引入使用build标记，进行替换;\n* [gulp-rev](https://www.npmjs.com/package/gulp-rev)：生成md5文件名;\n* [gulp-filter](https://www.npmjs.com/package/gulp-filter)：对文件进行过滤;\n* [gulp-header](https://www.npmjs.com/package/gulp-header/)：压缩之后将注释写入到文件的头部\n* [gulp-if](https://www.npmjs.com/package/gulp-if)：进行逻辑判断\n* [gulp-size](https://www.npmjs.com/package/gulp-size)：获取文件大小\n* [gulp-less](https://www.npmjs.com/package/gulp-less)：编译less文件\n* [gulp-sass](https://www.npmjs.com/package/gulp-sass)：编译sass文件\n* [gulp-file-include](https://www.npmjs.com/package/gulp-file-include)：对文件进行引入\n* [gulp-sourcemaps](https://www.npmjs.com/package/gulp-sourcemaps)：生成map文件\n* [gulp-livereload](https://www.npmjs.com/package/gulp-livereload)：自动刷新\n\n####7.webpack\n\n* [raw-loader](https://www.npmjs.com/package/raw-loader)：将文件require进来；\n* [url-loader](https://www.npmjs.com/package/url-loader)：可以将图片require进来；\n* [css-loader](https://www.npmjs.com/package/css-loader)：require css文件；\n* [eslint-loader](https://www.npmjs.com/package/eslint-loader)：语法检查；\n* [less-loader](https://www.npmjs.com/package/less-loader)：less loader；\n* [extract text plugin for webpack](https://www.npmjs.com/package/extract-text-webpack-plugin)：CSS文件提取；\n\n####8.服务\n\n* [Travis-CI](https://travis-ci.org/)\n* [Coveralls](https://coveralls.io/)\n* [Slack](https://slack.com/)\n* [js bin](http://jsbin.com/?html,output)\n* [zenHub](https://github.com/ZenHubIO)\n* [trello](https://trello.com/)\n\n\n### <a id=\"fed_opensource\"></a> Front-End Develop 开源项目\n\n想查看优秀的开源项目，可以访问[《Front-End Develop 项目精选》](https://github.com/mulgore/Front-End-Develop-Guide/blob/master/Featured.md)。\n\n####1. 有趣味的开源项目\n\n* [Web Developer技能树](https://github.com/phodal/skilltree)：类似《魔兽世界》中的天赋树；\n* [octotree](https://github.com/buunguyen/octotree)：浏览器扩展(Chrome,Firefox,Safari和Opera)显示GitHub树格式的代码；\n* [passport-bnet](https://github.com/Blizzard/passport-bnet)：暴雪提供的Nodejs版SDK\n* [hexo](https://github.com/hexojs/hexo)：编写博客使用的工具\n* [traceur-compiler](https://github.com/google/traceur-compiler)：可以运行未来的JavaScript的JavaScript；\n* [EpicEditor](https://github.com/OscarGodson/EpicEditor)：可以嵌入网页的Markdown编辑器；\n* [gitbook](https://github.com/GitbookIO/gitbook)：用于生成在线书籍的工具；\n* [kityminder](https://github.com/fex-team/kityminder)：作为一款在线的脑图编辑工具，它有着不亚于 native 脑图工具的交互体验；\n* [api-wow-docs](https://github.com/Blizzard/api-wow-docs)：暴雪提供的魔兽世界API文\n\n其他工具：[http://123.jser.us/](http://123.jser.us/)\n\n## <a id=\"fed_questions\"></a>Front-End Questions\n\n* [Front-end-Developer-Interview-Questions](https://github.com/h5bp/Front-end-Developer-Interview-Questions)：面试题集合；\n* [中文前端开发面试题](https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions) 中文前端开发面试题\n* [Mars - mobile needs a hero](https://github.com/AlloyTeam/Mars)：腾讯出品的移动端实践；\n* [mobileTech](https://github.com/jtyjty99999/mobileTech)：收集了移动端出现的问题以及解决思路与技巧；\n* [移动web资源整理](http://www.cnblogs.com/PeunZhang/p/3407453.html)：移动web资源整理；\n\n## <a id=\"fed_datastructure\"></a> Front-End 需要了解的数据结构与算法\n\n* [数据结构与算法（JS 版） (@进击的Luke)](https://github.com/LukeLin/data-structure-with-js)\n* [What are the 10 algorithms one must know in order to solve most algorithm problems](http://www.quora.com/What-are-the-10-algorithms-one-must-know-in-order-to-solve-most-algorithm-problems)\n* [基础算法](https://www.coursera.org/course/spalgo)\n* [那些少人所知而又有用的数据结构（StackOverflow）](http://stackoverflow.com/questions/500607/what-are-the-lesser-known-but-useful-data-structures)\n* [高级数据结构大全](http://isa.unomaha.edu/wp-content/uploads/2012/08/Advanced-Data-structures.pdf)\n\n## <a id=\"fed_scalable\"></a> 延伸可扩展的方向（全栈）\n\n延伸可扩展的方向是指，脱离了浏览器环境的编程。\n\n关于编译，强烈建议阅读[工程中的编译原理--Jison入门篇](http://icodeit.org/2015/09/write-a-parser/)\n\n如果你想发展为全栈，强烈建议阅读[Growth: 全栈增长工程师指南](https://github.com/phodal/growth-ebook)\n\n#### <a id=\"fed_nodejs\"></a> Node.js\n\n**入门**\n\n* [Node入门](http://www.nodebeginner.org/index-zh-cn.html)\n* [七天学会NodeJS](http://nqdeng.github.io/7-days-nodejs/)\n* [Nodejs Wiki Book](https://github.com/nodejs-tw/nodejs-wiki-book)\n* [Node.js 包教不包会](https://github.com/alsotang/node-lessons)\n\n**文档**\n\n* [nodejs中文文档](https://www.gitbook.com/book/0532/nodejs/details)\n* [express.js 中文文档](http://expressjs.jser.us/)\n* [koa 中文文档](https://github.com/guo-yu/koa-guide)\n* [express框架](http://javascript.ruanyifeng.com/nodejs/express.html)\n\n**阅读**\n\n* [使用 Express + MongoDB 搭建多人博客](https://github.com/nswbmw/N-blog)\n* [Learn You The Node.js For Much Win! (中文版)](https://www.npmjs.com/package/learnyounode-zh-cn)\n* [Node debug 三法三例](http://i5ting.github.io/node-debug-tutorial/)\n* [深入浅出Nodejs读书笔记](http://tw93.github.io/2015-03-01/shen-ru-qian-chu-nodejs-reading-mind-map.html)\n* [NodeJS的代码调试和性能调优](http://www.barretlee.com/blog/2015/10/07/debug-nodejs-in-command-line/)\n* [在 Node.js 应用中集成 Redis](http://www.ibm.com/developerworks/cn/opensource/os-cn-nodejs-redis/index.html)\n* [Node.js 应用程序的 5 条性能建议](http://zhuanlan.zhihu.com/FrontendMagazine/20432208)\n* [国内Nodejs 2015汇总](https://cnodejs.org/topic/5696e43e6272216e51bff67e)\n\n#### <a id=\"fed_mongodb\"></a>Mongodb\n\n* [the-little-mongodb-book-cn](https://github.com/justinyhuang/the-little-mongodb-book-cn/blob/master/mongodb.md)\n\n#### <a id=\"fed_chrome\"></a>Chrome扩展开发\n\n* [Chrome扩展及应用开发](http://www.ituring.com.cn/minibook/950)\n\n#### <a id=\"fed_PCAPP\"></a>桌面应用程序开发\n\n* [使用node-webkit构建桌面应用程序（一）](http://www.infoq.com/cn/articles/using-node-webkit-to-build-desktop-applications-part1)\n* [使用node-webkit构建桌面应用程序（二）](http://www.infoq.com/cn/articles/using-node-webkit-to-build-desktop-applications-part2)\n* [youdao出品的HEX](http://hex.youdao.com/zh-cn/tutorial/index.html)\n* [electron](http://electron.atom.io/)\n\n#### <a id=\"fed_mobile\"></a>移动应用程序开发\n\n* [ionic中文指南](https://github.com/ychow/ionic-guide)\n* [React Native 中文版](http://wiki.jikexueyuan.com/project/react-native/)\n\n#### <a id=\"fed_webGL\"></a> WebGL\n\n* [WebGL 中文版](http://wiki.jikexueyuan.com/project/webgl/)\n\n#### <a id=\"fed_v8\"></a>v8 引擎文献\n\n可以先通过阅读[V8引擎简介](http://impd.tencent.com/?p=35)来了解JavaScript现在最好的引擎是怎样的，然后访问[Chrome V8](https://developers.google.com/v8/)来获取最新的资料，API文档可以访问[v8-docs](http://izs.me/v8-docs/)。\n\n* [V8 Javascript 引擎设计理念](http://blog.pluskid.org/?p=186)\n* [JavaScript引擎的性能优化](http://velocity.oreilly.com.cn/2015//2013/index.php?func=session&id=27)\n* [V8引擎中的hidden class](https://github.com/BE-FE/Blog/blob/master/blogs/V8%E5%BC%95%E6%93%8E%E4%B8%AD%E7%9A%84hidden%20class.md)\n* [JavaScript V8 性能小贴士](http://justjavac.com/javascript/2015/12/14/performance-tips-for-javascript-in-v8.html)\n\n## <a id=\"fed_community\"></a> 社区\n\n访问：[社区列表](https://github.com/icepy/Front-End-Develop-Guide/blob/master/community.md)\n\n## <a id=\"fed_article\"></a> 码农周刊JavaScript和前端部分优秀文章集合\n\n访问：[码农周刊JavaScript和前端部分优秀文章集合](https://github.com/icepy/Front-End-Develop-Guide/blob/master/Articles.md)\n"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/community.md",
    "content": "## 社区\n\n* [Front-End Developer Blog](#fed_blog)\n* [通用Developer 社区](#fed_community)\n* [技术分享会议](#fed_jishu_share)\n\n## <a id=\"fed_blog\"></a> Front-End Developer Blog\n\n中文 Front-End 开发博客列表，本博客列表会长期维护，如果有推荐的博客，请到此处[提交博客信息](https://github.com/icepy/Front-End-Develop-Guide/issues/1)\n\n博客地址 | RSS地址\n----- | -----\n[Phodal ](https://www.phodal.com/) | <https://www.phodal.com/>\n[Plane Art](http://www.planeart.cn) | <http://www.planeart.cn/?feed=rss2>\n[王玮的博客](http://imvirgo.com) | <http://imvirgo.com/feed/>\n[UED TEAM](http://www.ued163.com) | <http://www.ued163.com/?feed=rss2>\n[随网之舞](http://dancewithnet.com) | <http://feeds.feedburner.com/dancewithnet>\n[不名一格](http://www.microidc.com) | <http://www.microidc.com/feed/>\n[Hugo Web前端开发](http://www.ghugo.com) | <http://www.ghugo.com/feed/>\n[阿里巴巴（中文站）用户体验设计部博客](http://www.aliued.cn) | <http://www.aliued.cn/feed>\n[何畏](http://www.lzlu.com/blog) | <http://www.lzlu.com/blog/?feed=rss2>\n[PlanABC - 怿飞’s Blog](http://www.planabc.net) | <http://feed.planabc.net/>\n[Designsor](http://www.designsor.com) | <http://www.designsor.com/feed>\n[Time Machine](http://rlog.cn) | <http://rlog.cn/?feed=rss2>\n[为之漫笔](http://blog.cn-cuckoo.com) | <http://www.cn-cuckoo.com/feed>\n[博客园_风流涕淌](http://www.cnblogs.com/Philoo) | <http://www.cnblogs.com/Philoo/rss>\n[彬Go](http://blog.bingo929.com) | <http://blog.bingo929.com/feed>\n[Gracecode.com](http://www.gracecode.com/) | <http://feeds.gracecode.com/gracecode/>\n[Koubei UED](http://ued.koubei.com) | <http://ued.koubei.com/?feed=rss2>\n[Alibaba.com UED](http://www.aliued.com) | <http://www.aliued.com/feed/>\n[Taobao UED Team](http://ued.taobao.org/blog/) | <http://ued.taobao.com/blog/feed/>\n[博客园-振之博文](http://www.cnblogs.com/zhenn/rss) | <http://www.cnblogs.com/zhenn/>\n[Kejun's Blog](http://hikejun.com/blog/) | <http://hikejun.com/blog/feed/>\n[博客园_纸头折飞机](http://www.cnblogs.com/xueduanyang/) | <http://www.cnblogs.com/xueduanyang/rss>\n[最前端的生活](http://www.bq69.com/) | <http://www.bq69.com/feed>\n[腾讯CDC](http://cdc.tencent.com) | <http://cdc.tencent.com/?feed=rss2>\n[博客园_叶小钗](http://www.cnblogs.com/yexiaochai/) | <http://www.cnblogs.com/yexiaochai/rss>\n[Hua's View](http://huaview.com) | <http://huaview.com/feed>\n[RainBlog-烟雨空间](http://rain520.net/) | <http://rain520.net/Feed/rss.xml>\n[web前端开发工程师的随记--黑妞haha](http://www.heiniuhaha.cn/blog) | <http://www.heiniuhaha.cn/blog/?feed=rss2>\n[蓝色理想](http://www.blueidea.com) | <http://www.blueidea.com/common/rss.asp>\n[博客园_Ruby's Louvre](http://www.cnblogs.com/rubylouvre/) | <http://www.cnblogs.com/rubylouvre/rss>\n[hax的技术部落格](http://hax.iteye.com)|<http://hax.javaeye.com/rss>\n[CssRain-前端技术](http://www.cssrain.cn/) | <http://www.cssrain.cn/?feed=rss2>\n[MED](http://mux.alimama.com/) | <http://mux.alimama.com/feed/>\n[W3CPLUS](http://www.w3cplus.com) | <http://feed.feedsky.com/W3CPlus>\n[博客园_winter-cn](http://www.cnblogs.com/winter-cn/rss) | <http://www.cnblogs.com/winter-cn/>\n[走走停停看看](http://shawphy.com) | <http://shawphy.com/feed>\n[Hi, I'm Adam Lu.](http://adamlu.com) | <http://adamlu.com/?feed=rss2>\n[WEB前端开发](http://www.css88.com) | <http://www.css88.com/feed>\n[岁月如歌](https://lifesinger.wordpress.com) | <https://lifesinger.wordpress.com/feed/>\n[Web开发中需要了解的东西](http://coolshell.cn) | <http://coolshell.cn/feed>\n[样式之美](http://www.aoao.org.cn) | <http://feeds2.feedburner.com/aoao>\n[時計坂一刻館三号室](https://quchao.com/) | <http://feed.quchao.com/>\n[CSS森林(CSS Forest)](http://www.cssforest.org/blog/) | <http://www.cssforest.org/blog/index.php?atom=1>\n[Ross Wan's World!](https://mrwlwan.wordpress.com) | <https://mrwlwan.wordpress.com/feed/>\n[博客园_汤姆大叔的博客](http://www.cnblogs.com/TomXu/) | <http://www.cnblogs.com/TomXu/rss>\n[前端观察](https://www.qianduan.net/) | <https://www.qianduan.net/rss/>\n[张云龙个人博客](https://github.com/fouber/blog) | <https://github.com/fouber/blog>\n\n## <a id=\"fed_community\"></a> 通用Developer 社区\n\n在Github上找到一个社区网站收集的项目-- [front-end-collect](https://github.com/foru17/front-end-collect)\n\n中文 Developer 社区列表，本社区列表会长期维护，如果有推荐的社区，请到此处[提交社区信息](https://github.com/icepy/Front-End-Develop-Guide/issues/2)\n\n中文 Developer 社区列表 | 地址\n----- | -----\n[领略前端技术 阅读奇舞周刊](http://www.75team.com/weekly/)|<http://www.75team.com/weekly/>\n[div.io](http://div.io/#/welcome) | <http://div.io/#/welcome>\n[稀土掘金](http://gold.xitu.io) | <http://gold.xitu.io>\n[开发者头条](http://toutiao.io/) | <http://toutiao.io/>\n[码农周刊](http://weekly.manong.io/) | <http://weekly.manong.io/>\n[InfoQ](http://www.infoq.com/cn/) | <http://www.infoq.com/cn/>\n[Segmentfault](http://segmentfault.com/) | <http://segmentfault.com/>\n[Get社区](http://get.ftqq.com/) | <http://get.jobdeer.com/>\n[极客头条](http://geek.csdn.net/hotest) | <http://geek.csdn.net/hotest>\n[极客头条－前端](http://geek.csdn.net/forum/47) | <http://geek.csdn.net/forum/47>\n[推酷](http://www.tuicool.com/) | <http://www.tuicool.com/>\n[编程狂人周刊](http://www.tuicool.com/mags) | <http://www.tuicool.com/mags>\n[react-china](http://react-china.org/) | <http://react-china.org/>\n[atom](https://atom-china.org/) | <https://atom-china.org/>\n[rockq](http://www.rockq.org/) | <http://www.rockq.org/>\n\n## <a id=\"fed_jishu_share\"></a> 技术分享会议\n\n说明：技术分享会议引用了[ufologist](https://github.com/ufologist)项目中的收集，与自己收集的资源整理而成。\n\n会议组织列表 | 地址\n---- | ----\n[D2前端技术论坛](http://www.d2forum.org/) | <http://www.d2forum.org/>\n[WebReBuild](http://webrebuild.org) | <http://webrebuild.org>\n[Velocity](http://velocity.oreilly.com.cn) | <http://velocity.oreilly.com.cn>\n[JSCONF.CN](http://jsconf.cn/) | <http://jsconf.cn/>\n[阿里技术嘉年华](http://adc.taobao.com) | <http://adc.taobao.com>\n[中国CSS开发者大会](http://css.w3ctech.com/) | <http://css.w3ctech.com/>\n[w3ctech](http://www.w3ctech.com/event) | <http://www.w3ctech.com/event>\n[HTML5梦工厂](http://www.html5dw.com/) | <http://www.html5dw.com/>\n[前端圈](http://www.fequan.com/) | <http://www.fequan.com/>\n[QCon北京](http://qconbeijing.com/) | <http://qconbeijing.com/>\n[QCon上海](http://qconshanghai.com/) | <http://qconshanghai.com/>\n[QCon@InfoQ](http://www.infoq.com/cn/qcon) | <http://www.infoq.com/cn/qcon>\n[ArchSummit](http://www.archsummit.com/) | <http://www.archsummit.com/>\n[阿里技术沙龙](http://club.alibabatech.org)| <http://club.alibabatech.org>\n[Apple WWDC](https://developer.apple.com/wwdc/) | <https://developer.apple.com/wwdc/>\n[Google I/O](https://events.google.com/io2015/)|<https://events.google.com/io2015/>\n"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/feedly.opml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<opml version=\"1.0\">\n    <head>\n        <title>文文 subscriptions in feedly Cloud</title>\n    </head>\n    <body>\n        <outline text=\"前端开发\" title=\"前端开发\">\n            <outline type=\"rss\" text=\"Plane Art\" title=\"Plane Art\" xmlUrl=\"http://www.planeart.cn/?feed=rss2\" htmlUrl=\"http://www.planeart.cn\"/>\n            <outline type=\"rss\" text=\"王玮的博客\" title=\"王玮的博客\" xmlUrl=\"http://imvirgo.com/feed/\" htmlUrl=\"http://imvirgo.com\"/>\n            <outline type=\"rss\" text=\"UED TEAM\" title=\"UED TEAM\" xmlUrl=\"http://www.ued163.com/?feed=rss2\"/>\n            <outline type=\"rss\" text=\"随网之舞\" title=\"随网之舞\" xmlUrl=\"http://feeds.feedburner.com/dancewithnet\" htmlUrl=\"http://dancewithnet.com\"/>\n            <outline type=\"rss\" text=\"不名一格\" title=\"不名一格\" xmlUrl=\"http://www.microidc.com/feed/\"/>\n            <outline type=\"rss\" text=\"Hugo Web前端开发\" title=\"Hugo Web前端开发\" xmlUrl=\"http://www.ghugo.com/feed/\" htmlUrl=\"http://www.ghugo.com\"/>\n            <outline type=\"rss\" text=\"阿里巴巴（中文站）用户体验设计部博客\" title=\"阿里巴巴（中文站）用户体验设计部博客\" xmlUrl=\"http://www.aliued.cn/feed\" htmlUrl=\"http://www.aliued.cn\"/>\n            <outline type=\"rss\" text=\"何畏\" title=\"何畏\" xmlUrl=\"http://www.lzlu.com/blog/?feed=rss2\" htmlUrl=\"http://www.lzlu.com/blog\"/>\n            <outline type=\"rss\" text=\"PlanABC - 怿飞’s Blog\" title=\"PlanABC - 怿飞’s Blog\" xmlUrl=\"http://feed.planabc.net/\" htmlUrl=\"http://www.planabc.net\"/>\n            <outline type=\"rss\" text=\"Designsor\" title=\"Designsor\" xmlUrl=\"http://www.designsor.com/feed\"/>\n            <outline type=\"rss\" text=\"Time Machine\" title=\"Time Machine\" xmlUrl=\"http://rlog.cn/?feed=rss2\" htmlUrl=\"http://rlog.cn\"/>\n            <outline type=\"rss\" text=\"为之漫笔\" title=\"为之漫笔\" xmlUrl=\"http://www.cn-cuckoo.com/feed\" htmlUrl=\"http://blog.cn-cuckoo.com\"/>\n            <outline type=\"rss\" text=\"博客园_风流涕淌\" title=\"博客园_风流涕淌\" xmlUrl=\"http://www.cnblogs.com/Philoo/rss\"/>\n            <outline type=\"rss\" text=\"彬Go\" title=\"彬Go\" xmlUrl=\"http://blog.bingo929.com/feed\" htmlUrl=\"http://blog.bingo929.com\"/>\n            <outline type=\"rss\" text=\"Gracecode.com\" title=\"Gracecode.com\" xmlUrl=\"http://feeds.gracecode.com/gracecode/\" htmlUrl=\"http://www.gracecode.com/\"/>\n            <outline type=\"rss\" text=\"Koubei UED\" title=\"Koubei UED\" xmlUrl=\"http://ued.koubei.com/?feed=rss2\"/>\n            <outline type=\"rss\" text=\"Alibaba.com UED\" title=\"Alibaba.com UED\" xmlUrl=\"http://www.aliued.com/feed/\" htmlUrl=\"http://www.aliued.com\"/>\n            <outline type=\"rss\" text=\"Taobao UED Team\" title=\"Taobao UED Team\" xmlUrl=\"http://ued.taobao.com/blog/feed/\" htmlUrl=\"http://ued.taobao.org/blog\"/>\n            <outline type=\"rss\" text=\"博客园-振之博文\" title=\"博客园-振之博文\" xmlUrl=\"http://www.cnblogs.com/zhenn/rss\" htmlUrl=\"http://www.cnblogs.com/zhenn/\"/>\n            <outline type=\"rss\" text=\"Kejun's Blog\" title=\"Kejun's Blog\" xmlUrl=\"http://hikejun.com/blog/?feed=rss2\" htmlUrl=\"http://hikejun.com/blog\"/>\n            <outline type=\"rss\" text=\"博客园_纸头折飞机\" title=\"博客园_纸头折飞机\" xmlUrl=\"http://www.cnblogs.com/xueduanyang/rss\" htmlUrl=\"http://www.cnblogs.com/xueduanyang/\"/>\n            <outline type=\"rss\" text=\"最前端的生活\" title=\"最前端的生活\" xmlUrl=\"http://www.bq69.com/feed\"/>\n            <outline type=\"rss\" text=\"腾讯CDC\" title=\"腾讯CDC\" xmlUrl=\"http://cdc.tencent.com/?feed=rss2\" htmlUrl=\"http://cdc.tencent.com\"/>\n            <outline type=\"rss\" text=\"博客园_叶小钗\" title=\"博客园_叶小钗\" xmlUrl=\"http://www.cnblogs.com/yexiaochai/rss\" htmlUrl=\"http://www.cnblogs.com/yexiaochai/\"/>\n            <outline type=\"rss\" text=\"Hua's View\" title=\"Hua's View\" xmlUrl=\"http://huaview.com/feed\"/>\n            <outline type=\"rss\" text=\"RainBlog-烟雨空间\" title=\"RainBlog-烟雨空间\" xmlUrl=\"http://rain520.net/Feed/rss.xml\" htmlUrl=\"http://rain520.net/\"/>\n            <outline type=\"rss\" text=\"web前端开发工程师的随记--黑妞haha\" title=\"web前端开发工程师的随记--黑妞haha\" xmlUrl=\"http://www.heiniuhaha.cn/blog/?feed=rss2\"/>\n            <outline type=\"rss\" text=\"蓝色理想\" title=\"蓝色理想\" xmlUrl=\"http://www.blueidea.com/common/rss.asp\" htmlUrl=\"http://www.blueidea.com\"/>\n            <outline type=\"rss\" text=\"博客园_Ruby's Louvre\" title=\"博客园_Ruby's Louvre\" xmlUrl=\"http://www.cnblogs.com/rubylouvre/rss\" htmlUrl=\"http://www.cnblogs.com/rubylouvre/\"/>\n            <outline type=\"rss\" text=\"hax的技术部落格\" title=\"hax的技术部落格\" xmlUrl=\"http://hax.javaeye.com/rss\" htmlUrl=\"http://hax.iteye.com\"/>\n            <outline type=\"rss\" text=\"CssRain-前端技术\" title=\"CssRain-前端技术\" xmlUrl=\"http://www.cssrain.cn/?feed=rss2\"/>\n            <outline type=\"rss\" text=\"MED\" title=\"MED\" xmlUrl=\"http://ued.alimama.com/feed/\"/>\n            <outline type=\"rss\" text=\"W3CPLUS | DEMOS\" title=\"W3CPLUS | DEMOS\" xmlUrl=\"http://feed.feedsky.com/W3CPlus\" htmlUrl=\"http://www.w3cplus.com\"/>\n            <outline type=\"rss\" text=\"博客园_winter-cn\" title=\"博客园_winter-cn\" xmlUrl=\"http://www.cnblogs.com/winter-cn/rss\" htmlUrl=\"http://www.cnblogs.com/winter-cn/\"/>\n            <outline type=\"rss\" text=\"走走停停看看\" title=\"走走停停看看\" xmlUrl=\"http://shawphy.com/feed\" htmlUrl=\"http://shawphy.com\"/>\n            <outline type=\"rss\" text=\"Hi, I'm Adam Lu.\" title=\"Hi, I'm Adam Lu.\" xmlUrl=\"http://adamlu.com/?feed=rss2\" htmlUrl=\"http://adamlu.com\"/>\n            <outline type=\"rss\" text=\"WEB前端开发\" title=\"WEB前端开发\" xmlUrl=\"http://www.css88.com/feed\" htmlUrl=\"http://www.css88.com\"/>\n            <outline type=\"rss\" text=\"岁月如歌 » SeaJS v0.9.1\" title=\"岁月如歌 » SeaJS v0.9.1\" xmlUrl=\"http://lifesinger.wordpress.com/feed/\" htmlUrl=\"https://lifesinger.wordpress.com\"/>\n            <outline type=\"rss\" text=\"Web开发中需要了解的东西| 酷壳- CoolShell.cn\" title=\"Web开发中需要了解的东西| 酷壳- CoolShell.cn\" xmlUrl=\"http://coolshell.cn/feed\" htmlUrl=\"http://coolshell.cn\"/>\n            <outline type=\"rss\" text=\"样式之美\" title=\"样式之美\" xmlUrl=\"http://feeds2.feedburner.com/aoao\" htmlUrl=\"http://www.aoao.org.cn\"/>\n            <outline type=\"rss\" text=\"時計坂一刻館三号室\" title=\"時計坂一刻館三号室\" xmlUrl=\"http://feed.quchao.com/\" htmlUrl=\"http://www.quchao.com/\"/>\n            <outline type=\"rss\" text=\"CSS森林(CSS Forest)\" title=\"CSS森林(CSS Forest)\" xmlUrl=\"http://www.cssforest.org/blog/index.php?atom=1\" htmlUrl=\"http://www.cssforest.org/blog/\"/>\n            <outline type=\"rss\" text=\"Ross Wan's World!\" title=\"Ross Wan's World!\" xmlUrl=\"http://mrwlwan.wordpress.com/feed/\" htmlUrl=\"https://mrwlwan.wordpress.com\"/>\n            <outline type=\"rss\" text=\"博客园_汤姆大叔的博客\" title=\"博客园_汤姆大叔的博客\" xmlUrl=\"http://www.cnblogs.com/TomXu/rss\" htmlUrl=\"http://www.cnblogs.com/TomXu/\"/>\n            <outline type=\"rss\" text=\"前端观察\" title=\"前端观察\" xmlUrl=\"http://www.qianduan.net/feed\" htmlUrl=\"http://www.qianduan.net/\"/>\n        </outline>\n        <outline text=\"编程源于生活\" title=\"编程源于生活\">\n            <outline type=\"rss\" text=\"Alon's Blog\" title=\"Alon's Blog\" xmlUrl=\"http://jinlong.github.io/atom.xml\" htmlUrl=\"http://jinlong.github.io/\"/>\n            <outline type=\"rss\" text=\"iOS技术周报\" title=\"iOS技术周报\" xmlUrl=\"http://weekly.ios-wiki.com/feed\" htmlUrl=\"http://weekly.ios-wiki.com\"/>\n            <outline type=\"rss\" text=\"用文字打败时间\" title=\"用文字打败时间\" xmlUrl=\"http://www.fengtang.com/blog/?feed=rss2\" htmlUrl=\"http://www.fengtang.com/blog\"/>\n            <outline type=\"rss\" text=\"码农日报\" title=\"码农日报\" xmlUrl=\"http://daily.manong.io/feed\" htmlUrl=\"http://daily.manong.io\"/>\n            <outline type=\"rss\" text=\"apple4us\" title=\"apple4us\" xmlUrl=\"http://apple4.us/feed\" htmlUrl=\"http://apple4us.com/\"/>\n            <outline type=\"rss\" text=\"袁家小黑球 » Feed\" title=\"袁家小黑球 » Feed\" xmlUrl=\"http://www.yuanxj.net/feed/\" htmlUrl=\"http://www.yuanxj.net\"/>\n            <outline type=\"rss\" text=\"Blog | Phodal Geek's Life\" title=\"Blog | Phodal Geek's Life\" xmlUrl=\"http://www.phodal.com/blog/feeds/rss/\" htmlUrl=\"http://www.phodal.com/blog/\"/>\n            <outline type=\"rss\" text=\"MacTalk-池建强的随想录\" title=\"MacTalk-池建强的随想录\" xmlUrl=\"http://macshuo.com/?feed=rss2\" htmlUrl=\"http://macshuo.com\"/>\n            <outline type=\"rss\" text=\"外刊IT评论\" title=\"外刊IT评论\" xmlUrl=\"http://feed.feedsky.com/aqee-net\" htmlUrl=\"http://www.vaikan.com\"/>\n            <outline type=\"rss\" text=\"粉丝日志\" title=\"粉丝日志\" xmlUrl=\"http://blog.fens.me/feed/\" htmlUrl=\"http://blog.fens.me\"/>\n            <outline type=\"rss\" text=\"小胡子哥的个人网站 - 订阅\" title=\"小胡子哥的个人网站 - 订阅\" xmlUrl=\"http://barretlee.com/atom.xml\" htmlUrl=\"http://www.barretlee.com\"/>\n            <outline type=\"rss\" text=\"GET社区新知文章\" title=\"GET社区新知文章\" xmlUrl=\"http://get.jobdeer.com/rss\" htmlUrl=\"http://get.jobdeer.com\"/>\n            <outline type=\"rss\" text=\"Lucida\" title=\"Lucida\" xmlUrl=\"http://lucida.me/atom.xml\" htmlUrl=\"http://lucida.me/\"/>\n            <outline type=\"rss\" text=\"阮一峰的网络日志\" title=\"阮一峰的网络日志\" xmlUrl=\"http://www.ruanyifeng.com/blog/atom.xml\" htmlUrl=\"http://www.ruanyifeng.com/blog/\"/>\n            <outline type=\"rss\" text=\"学而时嘻之\" title=\"学而时嘻之\" xmlUrl=\"http://www.geekonomics10000.com/feed\" htmlUrl=\"http://www.geekonomics10000.com\"/>\n            <outline type=\"rss\" text=\"码农Io\" title=\"码农Io\" xmlUrl=\"http://blog.manong.io/rss.xml\" htmlUrl=\"http://blog.manong.io/\"/>\n            <outline type=\"rss\" text=\"Meditic\" title=\"Meditic\" xmlUrl=\"http://meditic.com/feed/\" htmlUrl=\"http://meditic.com\"/>\n            <outline type=\"rss\" text=\"乱象，印迹\" title=\"乱象，印迹\" xmlUrl=\"http://www.luanxiang.org/blog/feed\" htmlUrl=\"http://www.luanxiang.org/blog\"/>\n            <outline type=\"rss\" text=\"demo@virushuo\" title=\"demo@virushuo\" xmlUrl=\"http://feeds2.feedburner.com/virushuo\" htmlUrl=\"http://blog.devep.net/virushuo/\"/>\n        </outline>\n        <outline text=\"科技资讯\" title=\"科技资讯\">\n            <outline type=\"rss\" text=\"@i黑马\" title=\"@i黑马\" xmlUrl=\"http://feed.feedsky.com/iheima\" htmlUrl=\"http://news.iheima.com\"/>\n            <outline type=\"rss\" text=\"GuAo.hk | 谷奥——探寻谷歌的奥秘\" title=\"GuAo.hk | 谷奥——探寻谷歌的奥秘\" xmlUrl=\"http://feed.google.org.cn/\" htmlUrl=\"http://each.fm\"/>\n            <outline type=\"rss\" text=\"InfoQ中文站\" title=\"InfoQ中文站\" xmlUrl=\"http://feed.feedsky.com/InfoQChina\" htmlUrl=\"http://www.infoq.com/cn/\"/>\n            <outline type=\"rss\" text=\"开源中国社区最新软件\" title=\"开源中国社区最新软件\" xmlUrl=\"http://www.oschina.net/project/rss\" htmlUrl=\"http://www.oschina.net/?from=rss\"/>\n            <outline type=\"rss\" text=\"极客公园-GeekPark\" title=\"极客公园-GeekPark\" xmlUrl=\"http://feeds.geekpark.net/\" htmlUrl=\"http://www.geekpark.net/\"/>\n            <outline type=\"rss\" text=\"博客 - 伯乐在线\" title=\"博客 - 伯乐在线\" xmlUrl=\"http://blog.jobbole.com/feed/\" htmlUrl=\"http://blog.jobbole.com\"/>\n            <outline type=\"rss\" text=\"爱范儿 · Beats of Bits\" title=\"爱范儿 · Beats of Bits\" xmlUrl=\"http://www.ifanr.com/feed\" htmlUrl=\"http://www.ifanr.com?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=\"/>\n            <outline type=\"rss\" text=\"《程序员》杂志官网\" title=\"《程序员》杂志官网\" xmlUrl=\"http://feed.feedsky.com/programmer\" htmlUrl=\"http://programmer.csdn.net\"/>\n            <outline type=\"rss\" text=\"CSDN博客推荐文章\" title=\"CSDN博客推荐文章\" xmlUrl=\"http://blog.csdn.net/rss/Expert.aspx\" htmlUrl=\"http://blog.csdn.net\"/>\n            <outline type=\"rss\" text=\"CSDN 程序员杂志\" title=\"CSDN 程序员杂志\" xmlUrl=\"http://programmer.csdn.net/rss_programmer.html\" htmlUrl=\"http://programmer.csdn.net\"/>\n            <outline type=\"rss\" text=\"36氪\" title=\"36氪\" xmlUrl=\"http://www.36kr.com/feed\" htmlUrl=\"http://36kr.com\"/>\n            <outline type=\"rss\" text=\"雷锋网\" title=\"雷锋网\" xmlUrl=\"http://www.leiphone.com/feed\" htmlUrl=\"http://www.leiphone.com\"/>\n            <outline type=\"rss\" text=\"SegmentFault 最新的问题\" title=\"SegmentFault 最新的问题\" xmlUrl=\"http://segmentfault.com/feeds\" htmlUrl=\"http://segmentfault.com\"/>\n        </outline>\n        <outline text=\"iOS\" title=\"iOS\">\n            <outline type=\"rss\" text=\"Why's Blog\" title=\"Why's Blog\" xmlUrl=\"http://blog.callmewhy.com/atom.xml\" htmlUrl=\"http://blog.callmewhy.com/\"/>\n            <outline type=\"rss\" text=\"Ted's Homepage\" title=\"Ted's Homepage\" xmlUrl=\"http://wufawei.com/feed\"/>\n            <outline type=\"rss\" text=\"Yuan博客\" title=\"Yuan博客\" xmlUrl=\"http://www.heyuan110.com/?feed=rss2\" htmlUrl=\"http://www.heyuan110.com\"/>\n            <outline type=\"rss\" text=\"vclwei\" title=\"vclwei\" xmlUrl=\"http://vclwei.com/posts.rss\" htmlUrl=\"http://vclwei.com/\"/>\n            <outline type=\"rss\" text=\"庞海礁的个人空间\" title=\"庞海礁的个人空间\" xmlUrl=\"http://www.olinone.com/?feed=rss2\" htmlUrl=\"http://www.olinone.com\"/>\n            <outline type=\"rss\" text=\"阿毛的蛋疼地\" title=\"阿毛的蛋疼地\" xmlUrl=\"http://xiangwangfeng.com/feed/\" htmlUrl=\"http://xiangwangfeng.com\"/>\n            <outline type=\"rss\" text=\"猫·仁波切\" title=\"猫·仁波切\" xmlUrl=\"https://andelf.github.io/atom.xml\" htmlUrl=\"http://andelf.github.io/\"/>\n            <outline type=\"rss\" text=\"代码手工艺人\" title=\"代码手工艺人\" xmlUrl=\"http://joeyio.com/atom.xml\" htmlUrl=\"http://www.joeyio.com\"/>\n            <outline type=\"rss\" text=\"icepy\" title=\"icepy\" xmlUrl=\"http://icepy.github.io/atom.xml\" htmlUrl=\"http://lcepy.github.io/\"/>\n            <outline type=\"rss\" text=\"Chun Tips\" title=\"Chun Tips\" xmlUrl=\"http://chun.tips/atom.xml\" htmlUrl=\"http://chun.tips/\"/>\n            <outline type=\"rss\" text=\"Hello,it works!\" title=\"Hello,it works!\" xmlUrl=\"http://helloitworks.com/feed\" htmlUrl=\"http://helloitworks.com\"/>\n            <outline type=\"rss\" text=\"Luke's Homepage\" title=\"Luke's Homepage\" xmlUrl=\"http://geeklu.com/feed/\"/>\n            <outline type=\"rss\" text=\"克伟的博客\" title=\"克伟的博客\" xmlUrl=\"http://feed.cnblogs.com/blog/u/23857/rss\" htmlUrl=\"http://www.cnblogs.com/wangkewei/\"/>\n            <outline type=\"rss\" text=\"破船之家\" title=\"破船之家\" xmlUrl=\"http://beyondvincent.com/atom.xml\" htmlUrl=\"http://beyondvincent.com/\"/>\n            <outline type=\"rss\" text=\"博客园_Kenshin Cui's Blog\" title=\"博客园_Kenshin Cui's Blog\" xmlUrl=\"http://www.cnblogs.com/kenshincui/rss\" htmlUrl=\"http://www.cnblogs.com/kenshincui/\"/>\n            <outline type=\"rss\" text=\"YIFEIYANG--易飞扬的博客\" title=\"YIFEIYANG--易飞扬的博客\" xmlUrl=\"http://www.yifeiyang.net/feed\" htmlUrl=\"http://www.yifeiyang.net\"/>\n            <outline type=\"rss\" text=\"阿峰的技术窝窝\" title=\"阿峰的技术窝窝\" xmlUrl=\"http://hufeng825.github.io/atom.xml\" htmlUrl=\"http://hufeng825.github.com\"/>\n            <outline type=\"rss\" text=\"Limboy 无网不剩\" title=\"Limboy 无网不剩\" xmlUrl=\"http://feeds.feedburner.com/lzyy\" htmlUrl=\"http://blog.leezhong.com/\"/>\n            <outline type=\"rss\" text=\"Lex iOS notes\" title=\"Lex iOS notes\" xmlUrl=\"http://ios.lextang.com/rss\" htmlUrl=\"http://ios.lextang.com/\"/>\n            <outline type=\"rss\" text=\"Cocoabit\" title=\"Cocoabit\" xmlUrl=\"http://blog.cocoabit.com/atom.xml\" htmlUrl=\"http://blog.cocoabit.com\"/>\n            <outline type=\"rss\" text=\"yulingtianxia's blog\" title=\"yulingtianxia's blog\" xmlUrl=\"http://yulingtianxia.com/atom.xml\" htmlUrl=\"http://yulingtianxia.com/\"/>\n            <outline type=\"rss\" text=\"码农人生\" title=\"码农人生\" xmlUrl=\"http://msching.github.io/atom.xml\" htmlUrl=\"http://msching.github.io/\"/>\n            <outline type=\"rss\" text=\"言无不尽\" title=\"言无不尽\" xmlUrl=\"http://tang3w.com/atom.xml\" htmlUrl=\"http://blog.tang3w.com/\"/>\n            <outline type=\"rss\" text=\"Issue Press\" title=\"Issue Press\" xmlUrl=\"http://issuepress.sugarmo.com/atom.xml\"/>\n            <outline type=\"rss\" text=\"Glow 技术团队博客\" title=\"Glow 技术团队博客\" xmlUrl=\"http://tech.glowing.com/cn/rss/\" htmlUrl=\"http://tech.glowing.com/cn/\"/>\n            <outline type=\"rss\" text=\"coderyi\" title=\"coderyi\" xmlUrl=\"http://www.coderyi.com/feed\" htmlUrl=\"http://www.coderyi.com\"/>\n            <outline type=\"rss\" text=\"里脊串的开发随笔\" title=\"里脊串的开发随笔\" xmlUrl=\"http://adad184.com/atom.xml\" htmlUrl=\"http://adad184.com/\"/>\n            <outline type=\"rss\" text=\"念茜的博客\" title=\"念茜的博客\" xmlUrl=\"http://blog.csdn.net/yiyaaixuexi/rss/list\" htmlUrl=\"http://blog.csdn.net/yiyaaixuexi\"/>\n            <outline type=\"rss\" text=\"nixzhu on scriptogr.am\" title=\"nixzhu on scriptogr.am\" xmlUrl=\"http://nixzhu.me/feed\" htmlUrl=\"http://nixzhu.me\"/>\n            <outline type=\"rss\" text=\"txx's blog\" title=\"txx's blog\" xmlUrl=\"http://blog.t-xx.me/atom.xml\" htmlUrl=\"http://blog.rpplusplus.me/\"/>\n            <outline type=\"rss\" text=\"Nonomori - Let monkeys coding for iOS\" title=\"Nonomori - Let monkeys coding for iOS\" xmlUrl=\"http://nonomori.farbox.com/feed\" htmlUrl=\"http://nonomori.farbox.com/\"/>\n            <outline type=\"rss\" text=\"技术哥的博客\" title=\"技术哥的博客\" xmlUrl=\"http://suenblog.duapp.com/rss/\" htmlUrl=\"http://suenblog.duapp.com/\"/>\n            <outline type=\"rss\" text=\"王中周的个人博客\" title=\"王中周的个人博客\" xmlUrl=\"http://blog.csdn.net/wzzvictory/rss/list\" htmlUrl=\"http://blog.csdn.net/wzzvictory_tjsd\"/>\n            <outline type=\"rss\" text=\"Casa Taloyum\" title=\"Casa Taloyum\" xmlUrl=\"http://casatwy.com/feeds/all.atom.xml\" htmlUrl=\"http://casatwy.com/\"/>\n            <outline type=\"rss\" text=\"萧宸宇\" title=\"萧宸宇\" xmlUrl=\"http://iiiyu.com/atom.xml\" htmlUrl=\"http://iiiyu.com\"/>\n            <outline type=\"rss\" text=\"不掏蜂窝的熊\" title=\"不掏蜂窝的熊\" xmlUrl=\"http://www.hotobear.com/?feed=rss2\" htmlUrl=\"http://www.hotobear.com\"/>\n            <outline type=\"rss\" text=\"Travis.Wang\" title=\"Travis.Wang\" xmlUrl=\"http://imi.im/feed\" htmlUrl=\"http://travis.wang/\"/>\n            <outline type=\"rss\" text=\"KooFrank's Blog\" title=\"KooFrank's Blog\" xmlUrl=\"http://koofrank.com/atom.xml\" htmlUrl=\"http://phpmaple.github.io/\"/>\n            <outline type=\"rss\" text=\"亚庆的 Blog\" title=\"亚庆的 Blog\" xmlUrl=\"http://billwang1990.github.io/atom.xml\" htmlUrl=\"http://billwang1990.github.io/\"/>\n            <outline type=\"rss\" text=\"NSHipster\" title=\"NSHipster\" xmlUrl=\"http://nshipster.cn/feed.xml\" htmlUrl=\"http://nshipster.cn\"/>\n            <outline type=\"rss\" text=\"土土哥的技术Blog\" title=\"土土哥的技术Blog\" xmlUrl=\"http://tutuge.me/atom.xml\" htmlUrl=\"http://tutuge.me/\"/>\n            <outline type=\"rss\" text=\"I'm Allen\" title=\"I'm Allen\" xmlUrl=\"http://www.imallen.com/atom.xml\" htmlUrl=\"http://imallen.com/\"/>\n            <outline type=\"rss\" text=\"I'm TualatriX\" title=\"I'm TualatriX\" xmlUrl=\"http://imtx.me/feed/latest/\" htmlUrl=\"http://imtx.me/\"/>\n            <outline type=\"rss\" text=\"王中周的技术博客\" title=\"王中周的技术博客\" xmlUrl=\"http://wangzz.github.io/atom.xml\" htmlUrl=\"http://wangzz.github.io/\"/>\n            <outline type=\"rss\" text=\"Xcode Dev\" title=\"Xcode Dev\" xmlUrl=\"http://blog.xcodev.com/atom.xml\" htmlUrl=\"http://blog.xcodev.com/\"/>\n            <outline type=\"rss\" text=\"KEVIN BLOG\" title=\"KEVIN BLOG\" xmlUrl=\"http://imkevin.me/rss\" htmlUrl=\"http://imkevin.me/\"/>\n            <outline type=\"rss\" text=\"Nico\" title=\"Nico\" xmlUrl=\"http://www.taofengping.com/rss.xml\" htmlUrl=\"http://www.taofengping.com\"/>\n            <outline type=\"rss\" text=\"answer_huang\" title=\"answer_huang\" xmlUrl=\"http://answerhuang.duapp.com/index.php/feed/\" htmlUrl=\"http://answerhuang.duapp.com\"/>\n            <outline type=\"rss\" text=\"煲仔饭\" title=\"煲仔饭\" xmlUrl=\"http://ivoryxiong.org/feed.xml\"/>\n            <outline type=\"rss\" text=\"OneV's Den\" title=\"OneV's Den\" xmlUrl=\"http://onevcat.com/atom.xml\" htmlUrl=\"http://onevcat.com/\"/>\n            <outline type=\"rss\" text=\"会写代码的猪\" title=\"会写代码的猪\" xmlUrl=\"http://gaosboy.com/feed/atom/\" htmlUrl=\"http://gaosboy.com/\"/>\n            <outline type=\"rss\" text=\"摇滚诗人\" title=\"摇滚诗人\" xmlUrl=\"http://feed.cnblogs.com/blog/u/35410/rss\" htmlUrl=\"http://www.cnblogs.com/biosli/\"/>\n            <outline type=\"rss\" text=\"雷纯锋的技术博客\" title=\"雷纯锋的技术博客\" xmlUrl=\"http://blog.leichunfeng.com/atom.xml\" htmlUrl=\"http://leichunfeng.github.io/\"/>\n            <outline type=\"rss\" text=\"唐巧的技术博客\" title=\"唐巧的技术博客\" xmlUrl=\"http://blog.devtang.com/atom.xml\" htmlUrl=\"http://blog.devtang.com/\"/>\n            <outline type=\"rss\" text=\"Lancy's Blog\" title=\"Lancy's Blog\" xmlUrl=\"http://gracelancy.com/atom.xml\" htmlUrl=\"http://gracelancy.com/\"/>\n            <outline type=\"rss\" text=\"Wonderffee's Blog\" title=\"Wonderffee's Blog\" xmlUrl=\"http://wonderffee.github.io/atom.xml\" htmlUrl=\"http://wonderffee.github.io/\"/>\n            <outline type=\"rss\" text=\"Shining IO\" title=\"Shining IO\" xmlUrl=\"http://shiningio.com/atom.xml\" htmlUrl=\"http://shiningio.com/\"/>\n            <outline type=\"rss\" text=\"不会开机的男孩\" title=\"不会开机的男孩\" xmlUrl=\"http://studentdeng.github.io/atom.xml\" htmlUrl=\"http://studentdeng.github.com/\"/>\n            <outline type=\"rss\" text=\"老谭笔记\" title=\"老谭笔记\" xmlUrl=\"http://www.tanhao.me/atom.xml\" htmlUrl=\"http://www.tanhao.me/\"/>\n            <outline type=\"rss\" text=\"webfrogs\" title=\"webfrogs\" xmlUrl=\"http://webfrogs.me/feed/\"/>\n        </outline>\n        <outline text=\"python\" title=\"python\">\n            <outline type=\"rss\" text=\"Django\" title=\"Django\" xmlUrl=\"http://reddit.com/r/django/.rss\" htmlUrl=\"https://www.reddit.com/r/django/\"/>\n            <outline type=\"rss\" text=\"djangosnippets.org: Latest snippets\" title=\"djangosnippets.org: Latest snippets\" xmlUrl=\"http://www.djangosnippets.org/feeds/latest/\" htmlUrl=\"https://djangosnippets.org/snippets/\"/>\n            <outline type=\"rss\" text=\"The Django weblog\" title=\"The Django weblog\" xmlUrl=\"http://www.djangoproject.com/rss/weblog/\" htmlUrl=\"https://www.djangoproject.com/weblog/\"/>\n            <outline type=\"rss\" text=\"Python 中文资料收集网\" title=\"Python 中文资料收集网\" xmlUrl=\"http://feed.feedsky.com/cnpython\" htmlUrl=\"http://www.cnpython.org\"/>\n            <outline type=\"rss\" text=\"Planet Python\" title=\"Planet Python\" xmlUrl=\"http://planet.python.org/rss10.xml\" htmlUrl=\"http://planetpython.org/\"/>\n        </outline>\n    </body>\n</opml>\n"
  },
  {
    "path": "07-Front-End-Develop-Guide-master/react/React.md",
    "content": "# React&React Native生态-探索学习\n\n## 阅读类\n\n2015年学习的重点推荐是：React.js&React Native，阅读[介绍](http://www.infoq.com/cn/articles/subversion-front-end-ui-development-framework-react?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk)，明白它是什么。\n\n##### 入门理解\n\n* [React的设计哲学 - 简单之美](http://www.infoq.com/cn/articles/react-art-of-simplity)\n* [React Native探索：背景、规划和风险](http://www.infoq.com/cn/articles/react-native-overview)\n* [一个“三端”开发者眼中的React Native](http://f2e.souche.com/blog/-ge-san-duan-kai-fa-zhe-yan-zhong-de-react-native/)\n* [WebStorm设置React Native代码智能提醒](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91webstorm%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E8%AE%BE%E7%BD%AEreact-native%E4%BB%A3%E7%A0%81%E6%99%BA%E8%83%BD%E6%8F%90%E9%86%92/)\n\n##### 文档类查阅\n  \n* [React.js 中文文档](http://reactjs.cn/)\n* [React webpack-cookbook](https://github.com/fakefish/react-webpack-cookbook)\n* [React Native](http://wiki.jikexueyuan.com/project/react-native/)\n* [awesome-react-native](https://github.com/jondot/awesome-react-native)\n* [react-native-guide](https://github.com/ele828/react-native-guide)\n* [react-native-lesson](https://github.com/vczero/react-native-lesson)\n* [A Compact React Cookbook](https://blog.oyanglul.us/javascript/react-cookbook-mini.html)\n\n##### React.js 深入阅读\n\n* [谈谈 React.js 的核心入门知识](http://gold.xitu.io/entry/55caa1db60b27cc249350218/view)\n\t* [深入浅出React（二）：React开发神器Webpack](http://www.infoq.com/cn/articles/react-and-webpack)\n\t* [深入浅出React（三）：理解JSX和组件](http://www.infoq.com/cn/articles/react-jsx-and-component)\n\t* [不可思议的 react diff](http://zhuanlan.zhihu.com/purerender/20346379)\n\t* [React虚拟DOM浅析](http://www.alloyteam.com/2015/10/react-virtual-analysis-of-the-dom/)\n\t* [深入浅出React（四）：虚拟DOM Diff算法解析](http://www.infoq.com/cn/articles/react-dom-diff)\n\t* [React.js学习笔记之JSX解读](https://segmentfault.com/a/1190000004470135)\n* [再次浅入React](http://www.wengwang.me/2015/12/11/qian-ru-react-zai-ci/)\n* [生命周期的管理艺术](http://zhuanlan.zhihu.com/purerender/20312691)\n\t* [React组件/元素与实例分析](https://github.com/yesvods/Blog/issues/5)\n\t* [如何开发并维护一个开源的 React 组件](http://zhuanlan.zhihu.com/FrontendMagazine/20341776)\n* [解密 setState](http://zhuanlan.zhihu.com/purerender/20328570)\n\t* [React 0.14：揭秘局部组件状态陷阱](http://zhuanlan.zhihu.com/FrontendMagazine/20416954)\n* [ReactJS组件间沟通的一些方法](http://www.alloyteam.com/2016/01/some-methods-of-reactjs-communication-between-components/)\n* [如何架构一个 React 项目](http://www.jointforce.com/jfperiodical/article/1186)\n\t* [Flux 架构入门教程](http://www.ruanyifeng.com/blog/2016/01/flux.html)\n\t* [Ballade: 重新诠释 Flux 架构](http://stylechen.com/ballade-reinterpreted-flux.html)\n* [React.js 2016最佳实践](http://www.alloyteam.com/2016/01/reactjs-best-practices-for-2016/)\n* [React 测试入门教程](http://www.ruanyifeng.com/blog/2016/02/react-testing-tutorial.html)\n* [Redux服务端渲染以及webpack优化](http://galen-yip.com/react/webpack/2016/02/14/redux-server-rendering-and-webpack-optimization/)\n\n##### React Native 深入阅读\n\n* [React Native探索（二）：布局篇](http://www.infoq.com/cn/articles/react-native-layout)\n* [React Native探索（三）：与 react-web 的融合](http://www.infoq.com/cn/articles/react-native-web)\n* [React Native 中组件的生命周期](http://www.race604.com/react-native-component-lifecycle)\n* [Flex 布局教程：语法篇](http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html)\n* [Flex 布局教程：实例篇](http://www.ruanyifeng.com/blog/2015/07/flex-examples.html)\n* [ReactNative开发指导](https://github.com/cnsnake11/blog)\n* [使用 LeanCloud 与 React Native 构建原生应用](https://blog.leancloud.cn/3993/)\n* [React-Native With Redux](http://richard-cao.github.io/2016/01/12/React-Native-With-Redux/)\n* [React Native JS Module 加载性能优化](https://yq.aliyun.com/articles/3208)\n* [React Native配置运行官方例子](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E9%85%8D%E7%BD%AE%E8%BF%90%E8%A1%8C%E5%AE%98%E6%96%B9%E4%BE%8B%E5%AD%90-%E5%88%9D%E5%AD%A6%E8%80%85%E7%9A%84%E7%A6%8F%E9%9F%B38/)\n* [React Native 组件学习]()\n\t* [通用组件]()\n\t\t* [View视图讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Bview%E8%A7%86%E5%9B%BE%E8%AE%B2%E8%A7%A3/) \n\t\t* [Text组件讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Btext%E7%BB%84%E4%BB%B6%E8%AE%B2%E8%A7%A3/)\n\t\t* [Image组件讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Bimage%E7%BB%84%E4%BB%B6%E8%AE%B2%E8%A7%A3%E4%B8%8E%E7%BE%8E%E5%9B%A2%E9%A6%96%E9%A1%B5%E9%A1%B6%E9%83%A8%E6%95%88/)\n\t\t* [TextInput组件讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Btextinput%E7%BB%84%E4%BB%B6%E8%AE%B2%E8%A7%A3%E4%B8%8Eqq%E7%99%BB%E5%BD%95%E7%95%8C%E9%9D%A2%E5%AE%9E%E7%8E%B011/)\n\t\t* [Switch Picker组件讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Bswitch%E4%B8%8Epicker%E7%BB%84%E4%BB%B6%E8%AE%B2%E8%A7%A3%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A816/)\n\t\t* [ScrollView组件 讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Bscrollview%E7%BB%84%E4%BB%B6%E8%AE%B2%E8%A7%A314/) \n\t\t* [Touchabel*系列组件讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Btouchable%E7%B3%BB%E5%88%97%E7%BB%84%E4%BB%B6%E8%AF%A6%E8%A7%A318/)\n\t* [Android 组件]()\n\t\t* [ProgressBarAndroid组件 讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Bprogressbarandroid%E8%BF%9B%E5%BA%A6%E6%9D%A1%E8%AE%B2%E8%A7%A312/)\n\t\t* [DrawerLayoutAndroid组件 讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Bdrawerlayoutandroid%E6%8A%BD%E5%B1%89%E5%AF%BC%E8%88%AA%E5%88%87%E6%8D%A2%E7%BB%84%E4%BB%B6%E8%AE%B2%E8%A7%A313/)\n\t\t* [ToolbarAndroid工具栏控件讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Btoolbarandroid%E5%B7%A5%E5%85%B7%E6%A0%8F%E6%8E%A7%E4%BB%B6%E8%AE%B2%E8%A7%A3%E4%BB%A5%E5%8F%8A%E4%BD%BF%E7%94%A8/)\n\t\t* [ViewPagerAndroid 控件讲解](http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Bviewpagerandroid%E8%AE%B2%E8%A7%A3%E4%BB%A5%E5%8F%8A%E7%BE%8E%E5%9B%A2%E9%A6%96%E9%A1%B5%E9%A1%B6%E9%83%A8/)\n\t* [iOS 组件]()\n* [AppState详解](http://www.lcode.org/react-native-api%E6%A8%A1%E5%9D%97%E4%B9%8Bappstate%E8%AF%A6%E8%A7%A326/)\n* [LayoutAnimation（布局动画）](http://www.lcode.org/react-native%E8%B6%85%E6%A3%92%E7%9A%84layoutanimation%E5%B8%83%E5%B1%80%E5%8A%A8%E7%94%BB)  \n\n##### For iOS\n\n* [React Native通信机制详解](http://blog.cnbang.net/tech/2698/)\n\n##### For Android    \n\n* [学习 React Native for Android：环境搭建](http://hahack.com/codes/learn-react-native-for-android-01/?from=timeline&isappinstalled=0#rd)\n* [React Native For Android初体验](http://www.jianshu.com/p/847a54e0c385)\n* [React Native: Android 的打包](http://www.liaohuqiu.net/cn/posts/react-native-android-package/)\n* [React Native For Android 架构初探](http://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=207782506&idx=1&sn=3ff6b03c0d59fbda406f64739d9272cf)\n* [使用React-Native实现app热更新的一次实践](https://github.com/fengjundev/React-Native-Remote-Update)\n* [React Native For Android の 修改React Native为本地依赖](http://www.jianshu.com/p/cca40c19faa0)\n* [Android端10个最常见采坑问题](https://github.com/yipengmu/ReactNative_Android_QA)\n\n##### Redux\n\n* [Redux教程1：环境搭建，初写Redux](http://yq.aliyun.com/articles/2628?spm=0.0.0.0.uoTmqE)\n* [Redux教程2：链接React](http://yq.aliyun.com/articles/2632?spm=0.0.0.0.uoTmqE)\n\t* [React和Redux的连接react-redux](https://leozdgao.me/reacthe-reduxde-qiao-jie-react-redux/)\n* [Redux教程3：添加倒计时](http://yq.aliyun.com/articles/2633?spm=0.0.0.0.uoTmqE)\n* [Redux 核心概念](http://www.jianshu.com/p/3334467e4b32)\n* [Redux深究](http://galen-yip.com/react/2016/02/06/go-into-redux/)\n\n##### React Router\n\n* [再谈 React Router 使用方法](https://undefinedblog.com/react-router-0-13-3/)\n\n## 专栏关注\n\n* [pure render](http://zhuanlan.zhihu.com/purerender)\n\n## 第三方框架学习类\n\n* [Redux 中文文档](http://camsong.github.io/redux-in-chinese/index.html)\n* [React Router 中文文档](http://react-guide.github.io/react-router-cn/)\n\n"
  },
  {
    "path": "08-github-FE-project-master/README.md",
    "content": "> http://microjs.com/#\n\n该网站的资源都托管到了`github`，`microjs.com`是一个可以让你选择微型的`js`类库的网站，该网站里的`js`库都是压缩后不大于5KB的，非常实用\n\n![图片描述][1]\n---\n>https://plainjs.com/（10.22更新）\n\nThe Vanilla JavaScript Repository，该仓库都是用原生`js`写的插件和组件，很实用。里面的项目也都托管到了github\n\n![图片描述][2]\n\n# 目录\n\n* [综合/资源](#综合/资源)\n* [样式/UI/css](#样式/UI/css)\n* [测试/工具](#测试/工具)\n* [构建工具](#构建工具)\n* [canvas/数据可视化](#canvas/数据可视化)\n* [模块管理/加载器](#模块管理/加载器)\n* [动画](#动画)\n* [插件](#插件)\n* [框架、库和组件](#框架、库和组件)\n* [移动端](#移动端)\n* [Node.js相关](#Node.js相关)\n* [React相关](#React相关)\n* [HTML5](#HTML5)\n* [模板引擎](#模板引擎)\n* [浏览器兼容方案](#浏览器兼容方案)\n* [菊苣](#菊苣)\n* [其他](#其他)\n* [优秀开源组织](#优秀开源组织)\n\n综合/资源\n----\n\n - [frontend-dev-bookmarks][3] 一个巨大的前端开发资源清单。`star:15000`\n\n - [front-end-collect][4] 分享自己长期关注的前端开发相关的优秀网站、博客、以及活跃开发者。`star:860`\n\n - [Front-end-Interview-questions][5]   史上最全前端开发面试问题及答案\n\n - [f2e-hub][6] 包含`Animation，UI，dialog，Carousels，color，image，workflow`等。`star:100`\n\n - [awesome-javascript][7] 一系列很棒的`javascript` 库，资源。`star:3100`\n\n - [fks][8]  前端技能汇总，包含前端知识架构，后端知识，`linux`，书籍推荐等。`star:4000`\n\n - [node123][9] `node.js`中文资料导航。`star:1200`\n\n - [mobile-web-favorites][10] 移动端web开发收藏夹。`star:200`\n\n - [gulp-book][11] `Gulp` 入门指南\n\n - [Front-end-tutorial][12] 最全的资源教程-前端涉及的所有知识体系。（12.25更新）\n - [use-gulp](https://github.com/Platform-CUF/use-gulp)\n。gulp资料收集\n\n样式/UI/css\n----\n\n - [Semantic-UI][13] 让你使用任何`HTML`标签 来表现UI控件。\n这是一款语义化设计的前端框架，为攻城师而制作的可复用的开源前端框架。`star:17500`\n\n\n![图片描述][14]\n\n - [primer][15]   `CSS`风格指南。`star:3600`\n\n - [glue][16] 一个生成CSS sprites的简单的命令行工具。star:2.5K (7.19更新)\n\n - [postcss][17] 用js插件来对css进行转换，类似Sass的预编译器，但实现了模块化，并且更加强大。`star:4.5K`(7.31更新)\n\n - [css3 PIE][18] 允许在IE上使用`CSS3`绝大部分的酷炫功能。官网：http://css3pie.com/\n\n - [mui][19] 轻量级css框架。`star:1.5K`(10.15更新)\n\n - [img2css][20] 将图片转为纯css的黑科技。`star:1.5K`（12.25更新）\n - [WeUI](https://github.com/weui/weui)为微信 Web 服务量身设计。`star:8.2K+`\n - [resume-master](https://github.com/hawx1993/resume-master) 简洁易用的简历生成项目，可部署到github pages在线浏览。\n\n测试/工具\n-----\n\n - [mocha][21] 一个简单、灵活有趣的 `JavaScript` 测试框架，用于 `Node.js` 和浏览器上的 `JavaScript` 应用测试。 `star:6680`\n\n - [csscss][23] css代码冗余分析仪，用于分析冗余 。`star:2800`\n\n - [es6-tools][24]  `es6` 工具集，包括`Grunt Tasks，Gulp Plugins，Broccoli Plugins，Brunch Plugins，Webpack plugins`等等。`star:1860`\n\n - [async][25] 一个工具模块，提供了直接而强大的 `JavaScript` 异步功能。虽然是为 `Node.js` 设计的，但是它也可以直接在浏览器中使用。`star:13000`\n\n - [simditor][26] 团队协作工具 `Tower` 使用的富文本编辑器。`star:1300`\n\n - [HTMLHint][27] `HTML` 静态代码分析工具，可以集成到`IDE`环境或编译系统中。`star:900`\n\n - [jshint][28] `js`静态代码分析工具，可以帮你检测`js`语法错误和潜在的问题。`star:5100`\n\n - [csslint][29] 分析和优化你的`CSS`样式表的工具。由[Nicholas C.\n   Zakas][30]所写。`star:2700`\n\n - [protractor][31] 一款端对端的`angular apps` 测试框架。`star:4K`\n\n - [casperjs][32] 一个基于`PhantomJS`的开源导航脚本和测试工具。`star:4.8K`\n\n - [Karma][33] 自动化完成单元测试，允许你在多个浏览器里执行`js`代码。让你的`TDD`变得简单，快速，有趣。`star:5.3K`\n\n - [jasmine][34]  是一个简易的`JS`单元测试框架， 用来测试`Javascript`代码。`star:9.1K`（6.28更新）\n\n - [chai][35] 一个针对 `Node.js` 和浏览器的`TDD`(测试驱动开发)/`BDD`(行为驱动开发)的断言框架，可与任何 `JavaScript` 测试框架集成。`star:2K`（6.29更新）\n\n - [Qunit][36] 一个很容易使用的js单元测试框架，该框架是由`jQuery`团队的成员所开发，并且是`jQuery`的官方测试套件。`star:3.3K`（6.29更新）\n\n构建工具\n-------------\n\n - [Grunt][37] 基于`Node.js`的项目构建工具。拥有数量庞大的插件，是一款优秀的前端自动化工具。`star:9500+`\n\n - [yeoman][38] 一个强健的工具，库，及工作流程的组合。`star:960+`\n\n - [gulp][39] 基于`node.js`流的新一代前端构建系统。`star:14000+`\n\n - [spm][40] 是 `CMD` 的包管理工具，需要和 `Sea.js` 配合使用。\n\n\n\ncanvas/数据可视化\n---------\n\n - [echarts][41] 基于`Canvas`，纯`Javascript`图表库，提供直观，生动，可交互，可个性化定制的数据可视化图表。`star:6900`\n\n - [Chart.js][42] 使用`<canvas>`标签的简易HTML5图表。`star:14600`\n\n - [sketch.js][43] 跨平台`JavaScript`创意编码框架，`gzip`压缩后仅有2kb。`star:1500`\n\n - [d3][44] 一个基于数据操作文档的`js`数据可视化框架，最流行的可视化库之一。`star:38000`\n\n - [zrender][45] 一个轻量级的`Canvas`类库，MVC封装，数据驱动，提供类`DOM`事件模型，让`canvas`绘图大不同！`star:850`\n\n - [c3][46] 一个基于 `D3.js` 的可重用 `JavaScript` 图表库。几乎零学习曲线。`star:4.5K`（6.28更新）\n\n - [img2css][47] 将图片转为纯css代码。（11.3更新）\n\n - [highcharts](https://github.com/highcharts/highcharts) 基于SVG的JavaScript 图表框架\n\n模块管理/加载器\n--------\n\n - [ESL][48]   是一个浏览器端、符合`AMD`的标准加载器，适合用于现代`Web`浏览器端应用的入口与模块管理。\n\n - [seajs][49] 一个遵循`CommonJS`规范的`JavaScript`模块加载器。提供简单、极致的模块化开发体验。`star:4100`\n\n - [Component][50] 一个模块化的`JavaScript`框架，同时也是面向前端的包管理器。\n\n - [webpack][51]一个模块打包工具，你可以使用`WebPack`管理你的模块依赖，并编绎输出模块们所需的静态文件。`star:9K`\n\n动画\n--\n\n - [animate.css][52] 一个跨浏览器的`CSS`动画库。简单易用易上手。`star:23000`\n\n - [move.js][53] 极小的 `JavaScript` 库,支持 `CSS3` 的动画效果,非常简单优雅。`star：2600`\n\n - [TweenJS][54] 是一个简单但强大的 `Javascript` 动画库。`CreateJS` 套件的一部分。`star:1500`\n\n - [bounce.js][55] 一个用于制作漂亮的 `CSS3` 关键帧动画的 `JavaScript`\n   库,使用其特有的方式生成的动画效果。`star:3600`\n\n - [Swipe][56] 号称最精确的`Slider`触摸库，专为移动设备优化。`star:4.7K`\n\n - [tween.js][57] 一款可生成平滑动画效果的`js`动画库。`tween.js`允许你以平滑的方式修改元素的属性值。它可以通过设置生成各种类似CSS3的动画效果。`star:2.5K`(7.15更新)\n\n - [parallax.js][58]轻量级的的视差引擎，能对智能设备的方向作出反应。。`star:9K` （10.17更新）\n\n - [Velocity][59] 是一款和jQuery的`$.animate()`有相同API的动画引擎。很适合移动端的动画开发，还打包了颜色动画，转换，循环，easing效果，类动画、滚动等功能。`star：9.5K`(12月25更新)\n\n\n\n插件\n--\n\n - [front-end-plugins](https://github.com/iamjoel/front-end-plugins) 前端常用插件汇总\n\n - [jquery.transit](https://github.com/rstacruz/jquery.transit) 超级流畅的css3 transformations 和 transitions的jQuery插件。 `star:7K+`\n\n - [zepto.fullpage][60] 专注于移动端的全屏滚动插件。`star:510`\n\n - [fullPage.js][61] pc端的全屏滚动插件。 `star:9500` [view demo][62]\n\n - [onepage-scroll][63] 可以轻松建立一个动感的响应式的滚动效果页面，比较适用于单页面的专题站。支持现代浏览器和IE8以上版本。[View demo][64] 。`star:7700`\n\n - [slick][65] 一款完全响应式的 `jQuery` 图片滚动插件，能够根据容器自动适应宽度。`star:10000` [view demo][66]\n\n - [superslides][67] 致力于解决网站大部分特效展示问题。网站上常用的“焦点图/幻灯片”“Tab标签切换”“图片滚动”“无缝滚动”等只需要一个`SuperSlide`即可解决！ [view demo][68] `star:1100`\n\n - [jQuery-One-Page-Nav][69] 当用户滚动网页时，实现平滑滚动和智能导航。`star:1100`\n\n - [slider][70] 一个`jquery`完全开源的`JavaScript`代码库，用户可以开发，调试和深度定制自己的滑块。`star:850` [view demo][71]\n\n - [github-hovercard][72] github 鼠标悬停显示用户，仓库等摘要信息。(10.15更新)\n\n - [onepage-scroll][73] 一款带有背景视觉差效果的`jQuery`整页滚动特效插件。star：8K （10.17更新）[view demo][74]\n\n - [justlazy.js][75] 轻量级js图片延迟加载插件。（10.22更新）\n\n - [awesome-browser-extensions-for-github][76] 收集关于github上优秀的浏览器插件。非常实用。star:200 (12.25更新)\n\n框架、库和组件\n-----\n\n - [polymer][77] `web`组件构建框架。一套以“一切皆组件、最少化代码量、最少框架限制”为设计理念的`Web UI`框架。 `star:9900`\n\n - [impress.js][78] 创建令人兴奋的演示。使用`CSS3`的转换和过渡，这个库允许你创建令人印象深刻的演示文稿。[view demo][79]。`star:24300`\n\n - [ionic][80] 先进的`HTML5` 移动端开发框架。帮助开发者使用HTML5, CSS3和`js`做出不可思议的`hybrid app`。`star:17000`\n\n - [reveal.js][81] 基于`CSS3`的3D幻灯片工具。能够制作绚丽的演示文稿并生成`HTML`格式，将它发布到web上。`star:21500` [view demo][82]\n\n - [pure.css][83] 一组很小的，响应式的`css`组件，你可以在网页的项目上到处使用。`star:12000`\n\n - [three.js][84] 是`JavaScript`编写的`WebGL`第三方库。提供了非常多的3D显示功能。`star:20000`\n\n - [TimelineJS][85] 轻松制作时间轴。`star:8000`\n\n - [jquery-pjax][86] 对`ajax` 和 `pushState`的封装，让你可以很方便的使用`pushState`技术，用以实现页面无刷新加载。`star:11500`\n\n - [highlight.js][87] `javascript`语法高亮。既可以运行在浏览器端也可以运行在服务端。`star:5500`\n\n - [commander.js][88] `Node.js`命令行工具。`star:3800`\n\n - [togetherjs][89] 由`Mozilla`打造的一款可以给网站添加实时协作功能的`JavaScript`库。`star:5K`\n\n - [HTML.js][90] 轻量级的简化与`DOM`操作的js库。[view demo][91] `star:1.5K`\n\n - [MEAN.JS][92] 全栈式javascript，使用`MongoDB, Express,\n   AngularJS` 和 `Node.js`。`star:2.2K`\n\n - [wechat.js][93] 微信相关的 js 操作：分享、网络、菜单。`star:700`\n\n - [JavaScript-Load-Image][94] 一个`js`加载和转换图像文件的库。 `star:1.2K` [view\n   demo][95]\n\n - [progress.js][96] 一个 `js` 和 `CSS3`的库，帮助开发人员为网页上的每个对象创建和管理进度条效果。`star:1.6K` [view demo][97]\n\n - [foundation][98] 号称世界上最先进的响应式前端框架，也是一款`Mobile First`的框架。`star:21K`\n\n - [Sugar][99] 一个`JavaScript`库。它扩展了现有的`JS`对象的方法，让你可以用更少的代码做更多的事情。`star:2.8K`\n\n - [todomvc][100] 帮你挑选一款MV*框架，它使用不同的最流行的`js MV*`框架实现了一个相同的`Todo`应用。`star:13K`\n\n - [yepnope.js][101] 这是一个异步的条件加载框架，速度超快，只为用户加载需要的脚本。使用非常简单，非常有用！`star:2.5K`\n\n - [Material UI][102] 是一个 `CSS` 框架和一组实现谷歌 Material Design 设计规范的 React\n   组件。`star:8.8K`（6.28更新）\n\n - [Pikaday][103] 是一个 `JavaScript` 日期选择器，特点是轻量级、无依赖和模块化的\n   `CSS`。`star:2.8K` [view demo][104](7.1更新)\n\n - [vuejs][106] 用于构建交互式的 Web 界面的库。它提供了 `MVVM` 数据绑定和一个可组合的组件系统,具有简单、灵活的 API。`star:6K`（7.12更新）\n\n - [meteor][107] 超简单的，数据库无处不在的，用于自动化和简化实时运行的 `Web` 应用程序的开发。纯`JavaScript`的Web框架。`star:27K`（7.12更新）\n\n - [webuploader][108]\n   一个简单的以`HTML5`为主，`FLASH`为辅的现代文件上传组件。支持大文件分片并发上传，极大的提高了文件上传效率。`star:1.8K`\n\n - [fastclick][109]触摸UI上的消除点击延迟js库。`star:1W`(10.15更新)\n\n - [wangEditor][110] 轻量级web富文本框。 (10.15更新)\n\n - [benchmark.js][111]是强大的基准测试库，几乎适用于所有`JavaScript`平台。支持`high-resolution`定时器，并返回重要的统计结果。`star:1.7k`(10.15更新)\n\n - [headroom.js][112]是一个轻量级、纯 JS 组件,用来隐藏或展现页面上的元素,为你的页面留下更多展示内容的空间。`star:7.5K` (10.15更新)\n\n\n - [tooling][113] 快速开发web app\n\n - [ua-device](https://github.com/fex-team/ua-device)史上最全面的userAgent解析库，百度FEX出品。\n\n - [judge](https://github.com/hawx1993/judge)轻量级js判断类库\n - [share.js](https://github.com/overtrue/share.js)一键分享到微博、QQ空间、QQ好友、微信、腾讯微博、豆瓣等。\n\n移动端\n---\n\n - [Swipe][114] 加速移动触摸滑块与硬件之间的转换。`star:5000`。\n\n - [hammer.js][115] 一个支持多点触摸的手势库。`star:11000`\n\n - [amDoc][116] 无线`Web`解决方案 - 文档规范指南\n\n - [amazeui][117]  移动优先的跨屏前端框架。面向`HTML5`开发，使用`css3`做动画和交互。`star:4.1K`\n\n - [Zepto][118]  一款面向移动端设备、`API`与`jQuery`兼容的基础库。\n\n - [mui][119] 最接近原生APP体验的高性能框架 。`star:1.1K`（6.28更新）\n\n - [Swiper][120]纯`javascript`打造的滑动特效插件，面向手机、平板电脑等移动终端。能实现触屏焦点图、触屏Tab切换、触屏多图切换等常用效果。`star:6K`(10月18更新)\n\n - [SUI-Mobile][121]由阿里巴巴国际UED前端出品的移动端UI库，轻量精美 `star:2K`(2016.1.14更新)\n\n - [lib-flexible][122] 淘宝出品的移动端可伸缩布局方案。`star:1.3K+`（2016.1.14更新）\n\n\nNode.js相关\n---------\n\n\n - [node-restify](https://github.com/restify/node-restify) node.js REST framework specifically meant for web service APIs。`star:5K+`\n\n - [http://nodeframework.com/][123] 专门收集`node.js`的`web`框架的网站。其项目同样均托管在`github`上。\n\n![图片描述][124]\n<br>\n\n - [nodeclub][125] 使用 `Node.js` 和 `MongoDB` 开发的社区系统。`star:3000`\n\n - [N-chat][126] 使用 `Express + Socket.IO` 搭建的多人聊天室 。`star:300`\n\n - [N-blog][127] 使用 `Express + MongoDB` 搭建多人博客。`star:1800`\n\n - [node-inspector][128] 基于`Blink`开发者工具的`Node.js`调试器。`star:7000`\n\n - [node-lessons][129]：`Node.js`包教不包会。`star:2.5K`\n\n - [nodePPT][130]  使用`nodejs`写的网络幻灯片。可能是迄今为止最好的网页版`PPT`。`star:1.6K` [view demo][131]\n\n - [hexo][132] 一款快捷，简单，强大的博客框架，基于`Nodejs`。`star:5.2K`\n\n - [koa][133] 下一代`Node.js`  Web 框架。由 `Express` 团队设计。`star:6.3K`\n\n - [awesome-nodejs][134] 关于`Nodejs` 包和资源的收集。`star:7K`\n\n - [connect][135] `Node`平台的中间件框架。`Express`就是基于`Connect`开发的。`star:5.6K`（6.29更新）\n\n - [n][136] node版本管理，tj大神所写。`star:2.7K`\n\n - [nvm][137] node版本管理，通过bash脚本来管理。`star:7.5K`\n\n\n\nReact相关\n-------\n - [react-style][138] 是 `React.js` 可维护的样式组件\n\n - [react-component][139]  基于`reactjs`的组件。\n\n - [react-native][140] 一个用`React`构建`native apps`的框架。`star:15000`\n\n - [react-native-guide][141]  汇集了`react-native`学习资源与各类开源app。`star:850`\n\n - [awesome-react][142] 关于`react`的工具，资源，视频的集合。`star:700`\n\n - [Flux][143] 是一个`Facebook`开发的、利用单向数据流实现的应用架构，用于\n   `React`。`Flux`应用有三个主要的部分组成：调度程序、存储和视图（React 组件）。`star:6.8K`（6.28更新）\n\n - [iscroll][144] 高性能，体积小，无外部依赖，跨平台的滚动组件 `star:6K`（7.19更新）\n\n - [react-tappable][145] Tappable component for React.(2016,1.4更新)\n\n - [react-native-lesson][146] `react-native`入门指南.`star:1.3K`(2016,1.4更新)\n - [react-web](https://github.com/taobaofed/react-web)用React Native构建 web app的框架。`star:1.2K+`\n\nHTML5\n-----\n - [html5-boilerplate][147] 一套专业的前端模版，主要用于开发快速、健壮、适应性强的app或网站。`star:27K` （12.25更新）\n\n - [Browserquest][148] `Mozilla`开发的`HTML5`多人在线游戏。`star:5200`\n\n - [video.js][149] 开源的HTML5和Flash视频播放器。支持自定义进度条、按钮以及工具栏的底色。`star:9.1K`\n\n - [html5shiv][150] 主要解决`HTML5`提出的新的元素不被`IE6-9`识别。`star:6K`(7.15更新)\n\n - [brunch][151] 快速的前端 `HTML5` 构建工具。star:4.5K（7.19更新）\n\n - [ulkit][152] 一个轻量级的、模块化前端框架，它被用于快速开发强大的web界面。也是一款优秀的响应式HTML5 框架。`star:5.3K` (8.3更新)\n\n\n模板引擎\n----\n\n - [Handlebars.js][153] 一个`js`语义模板库，能让你轻松高效的编写语义化模板。`star:8.6K`(6.29 update)\n\n - [artTemplate][154]  性能卓越的 `js` 模板引擎。`star:1.7K`\n\n - [jade][155] 一款高性能简洁易懂的模板引擎，`Jade`是`Haml`的`Javascript`实现。`star:8.7K`\n\n - [ejs][156] tj大神写的嵌入javascript的模板引擎，主要用于Node\n\n浏览器兼容方案\n-------\n\n - [es6-shim][157] 提供兼容性垫片，使ES6能兼容于传统的`JavaScript`引擎。`star:1.5K`(7.15更新)\n\n - [Modernizr][158] 用来检测浏览器功能支持情况的`JavaScript`库,可以检测18项`CSS3`功能以及40多项关于`HTML5`的功能。`star:16000`\n\n - [normalize.css][159] 一个可定制的 `CSS` 文件，使浏览器呈现的所有元素，更一致和符合现代标准。支持IE8+。`star:17000`\n\n - [html5shiv][160] 主要解决`HTML5`提出的新的元素不被`IE6-9`识别。`star:6K`(7.15更新)\n\n - [css3please][161] 跨浏览器自动生成`css3`前缀\n\n - [Babel][162] 是一款为了写下一代js的编译器，无需等待浏览器支持就可以使用新的语法。`star：8.3K` (7.29更新)\n\n - [f2etest](https://github.com/alibaba/f2etest) F2etest是一个面向前端、测试、产品等岗位的多浏览器兼容性测试整体解决方案。`star:1K`\n\n菊苣\n----\n\n - [Evan You][163]  前端轻量级框架`MVVM`框架`vue.js`作者，前`Google`工程师。`followers:1.6K`\n\n - [TJ Holowaychuk][164]  Luna 编程语言, `Koa, Express, Stylus, Cluster, Mocha, Jade, node-canvas, component` 等知名开源项目的创建和贡献者。 `followers:14.1K`\n\n - [PaulIrish][165] 著名的前端开发工程师，同时他也是`Chrome`开发者关系团队成员，jQuery团队成员，`Modernizr、Yeoman、CSS3 Please`和`HTML5 Boilerplate`的`lead developer`。`followers:15.7K`\n\n - [Mike Bostock][166] 知名可视化库 `D3.js`的主要作者。`followers:8.3K`\n\n - [Nicolas Gallagher][167] `Normalize.css` 作者。`followers:3.6K`\n\n\n - [司徒正美][168] 前端迷你`MVVM`框架`Avalon`作者。`followers:2.1K`\n\n - [sindresorhus](https://github.com/sindresorhus)github 排名第一的大神\n\n其他\n--\n\n - [javascript-style-guide][169] 最合理的使用`javascript`的方法。 `star:18000`\n\n - [Mars][170] 腾讯移动`Web`前端知识库。`star:1600`\n\n - [brackets][171] 一款使用 HTML，CSS，JavaScript 创建的开源的针对 Web 开发的编辑器。`star:23000`\n\n - [Ghost][172] `Node.js`开发最新博客系统, 简单简洁, 响应式设计, 支持完全自定义, 免费, 专注博客。`star:16000`\n\n - [io.js][173]  从`NodeJS`里分离出来的一条分支。`star:13000`\n\n - [2048 游戏][174] [view demo][175] `star:7000`\n\n - [ueditor][176] 百度前端团队出品的富本文编辑器。`star:1.1K`\n\n - [electron](https://github.com/electron/electron) 使用js,css,html构建跨平台的桌面应用。`star:32K+`\n\n - [hosts](https://github.com/racaljk/hosts) 最新可用的google hosts文件。`star:5.4K+`\n\n\n优秀开源组织\n----\n\n - [AlloyTeam][177] 腾讯 `Web` 前端团队。\n\n\n - [fex-team][178] 百度前端团队。\n\n - [amfe](https://github.com/amfe)阿里前端团队，有很多高质量项目和优秀文章\n\n\n>说明\n\n本篇文章会持续更新，欢迎star，可点击上面的watch下拉按钮，选中watching，以后更新会有提醒。\n\n\n\n  [1]: /img/3.jpeg\n  [2]: /img/2.jpeg\n  [3]: https://github.com/dypsilon/frontend-dev-bookmarks\n  [4]: https://github.com/foru17/front-end-collect\n  [5]: https://github.com/hawx1993/Front-end-Interview-questions\n  [6]: https://github.com/lvwzhen/f2e-hub\n  [7]: https://github.com/sorrycc/awesome-javascript\n  [8]: https://github.com/JacksonTian/fks\n  [9]: https://github.com/youyudehexie/node123\n  [10]: https://github.com/hoosin/mobile-web-favorites\n  [11]: https://github.com/nimojs/gulp-book\n  [12]: https://github.com/AutumnsWind/Front-end-tutorial\n  [13]: https://github.com/Semantic-Org/Semantic-UI\n  [14]: /img/1.jpeg\n  [15]: https://github.com/primer/primer\n  [16]: https://github.com/jorgebastida/glue#glue\n  [17]: https://github.com/postcss/postcss#plugins\n  [18]: https://github.com/lojjic/PIE\n  [19]: https://github.com/muicss/mui\n  [20]: https://github.com/javierbyte/img2css\n  [21]: https://github.com/mochajs/mocha\n  [22]: /img/5.png\n  [23]: https://github.com/zmoazeni/csscss\n  [24]: https://github.com/addyosmani/es6-tools\n  [25]: https://github.com/caolan/async\n  [26]: https://github.com/mycolorway/simditor\n  [27]: https://github.com/yaniswang/HTMLHint\n  [28]: https://github.com/jshint/jshint\n  [29]: https://github.com/CSSLint/csslint\n  [30]: http://www.nczonline.net/\n  [31]: https://github.com/angular/protractor\n  [32]: https://github.com/n1k0/casperjs\n  [33]: https://github.com/karma-runner/karma\n  [34]: https://github.com/jasmine/jasmine\n  [35]: https://github.com/chaijs/chai\n  [36]: https://github.com/jquery/qunit\n  [37]: https://github.com/gruntjs/grunt\n  [38]: https://github.com/yeoman/yo\n  [39]: https://github.com/gulpjs/gulp\n  [40]: https://github.com/spmjs/spm\n  [41]: https://github.com/ecomfe/echarts\n  [42]: https://github.com/nnnick/Chart.js\n  [43]: https://github.com/soulwire/sketch.js\n  [44]: https://github.com/mbostock/d3\n  [45]: https://github.com/ecomfe/zrender\n  [46]: https://github.com/masayuki0812/c3\n  [47]: https://github.com/javierbyte/img2css\n  [48]: https://github.com/ecomfe/esl\n  [49]: https://github.com/seajs/seajs\n  [50]: https://github.com/component\n  [51]: https://github.com/webpack/webpack\n  [52]: https://github.com/daneden/animate.css\n  [53]: https://github.com/visionmedia/move.js\n  [54]: https://github.com/CreateJS/TweenJS\n  [55]: https://github.com/tictail/bounce.js\n  [56]: https://github.com/thebird/Swipe\n  [57]: https://github.com/tweenjs/tween.js\n  [58]: https://github.com/wagerfield/parallax\n  [59]: https://github.com/julianshapiro/velocity\n  [60]: https://github.com/yanhaijing/zepto.fullpage\n  [61]: https://github.com/alvarotrigo/fullPage.js\n  [62]: http://alvarotrigo.com/fullPage/#firstPage\n  [63]: https://github.com/peachananr/onepage-scroll\n  [64]: http://www.thepetedesign.com/demos/onepage_scroll_demo.html\n  [65]: https://github.com/kenwheeler/slick\n  [66]: http://kenwheeler.github.io/slick/\n  [67]: https://github.com/nicinabox/superslides\n  [68]: http://nicinabox.com/superslides\n  [69]: https://github.com/davist11/jQuery-One-Page-Nav\n  [70]: https://github.com/jssor/slider\n  [71]: http://www.jssor.com/demos/index.html\n  [72]: https://github.com/Justineo/github-hovercard\n  [73]: https://github.com/peachananr/onepage-scroll\n  [74]: http://www.htmleaf.com/Demo/201412311045.html\n  [75]: https://github.com/fhopeman/justlazy\n  [76]: https://github.com/stefanbuck/awesome-browser-extensions-for-github\n  [77]: https://github.com/Polymer/polymer\n  [78]: https://github.com/bartaz/impress.js\n  [79]: http://bartaz.github.io/impress.js/#/bored\n  [80]: https://github.com/driftyco/ionic\n  [81]: https://github.com/hakimel/reveal.js\n  [82]: http://lab.hakim.se/reveal-js/#/\n  [83]: https://github.com/yahoo/pure/\n  [84]: https://github.com/mrdoob/three.js\n  [85]: https://github.com/NUKnightLab/TimelineJS\n  [86]: https://github.com/defunkt/jquery-pjax\n  [87]: https://github.com/isagalaev/highlight.js\n  [88]: https://github.com/tj/commander.js\n  [89]: https://github.com/mozilla/togetherjs\n  [90]: https://github.com/nbubna/HTML\n  [91]: http://nbubna.github.io/HTML/\n  [92]: https://github.com/meanjs/mean\n  [93]: https://github.com/sofish/wechat.js\n  [94]: https://github.com/blueimp/JavaScript-Load-Image\n  [95]: https://blueimp.github.io/JavaScript-Load-Image/\n  [96]: https://github.com/usablica/progress.js\n  [97]: http://usablica.github.io/progress.js/\n  [98]: https://github.com/zurb/foundation\n  [99]: https://github.com/andrewplummer/Sugar\n  [100]: https://github.com/tastejs/todomvc\n  [101]: https://github.com/SlexAxton/yepnope.js\n  [102]: https://github.com/callemall/material-ui\n  [103]: https://github.com/dbushell/Pikaday\n  [104]: http://dbushell.github.io/Pikaday/\n  [105]: /img/bVmxon\n  [106]: https://github.com/yyx990803/vue\n  [107]: https://github.com/meteor/meteor\n  [108]: https://github.com/fex-team/webuploader\n  [109]: https://github.com/ftlabs/fastclick\n  [110]: https://github.com/wangfupeng1988/wangEditor\n  [111]: https://github.com/bestiejs/benchmark.js\n  [112]: https://github.com/WickyNilliams/headroom.js\n  [113]: https://github.com/egoist/tooling\n  [114]: https://github.com/thebird/swipe\n  [115]: https://github.com/hammerjs/hammer.js\n  [116]: https://github.com/am-team/amDoc\n  [117]: https://github.com/allmobilize/amazeui\n  [118]: https://github.com/madrobby/zepto/\n  [119]: https://github.com/dcloudio/mui\n  [120]: https://github.com/nolimits4web/Swiper\n  [121]: https://github.com/sdc-alibaba/SUI-Mobile\n  [122]: https://github.com/amfe/lib-flexible\n  [123]: http://nodeframework.com/\n  [124]: /img/4.jpeg\n  [125]: https://github.com/cnodejs/nodeclub\n  [126]: https://github.com/nswbmw/N-chat\n  [127]: https://github.com/nswbmw/N-blog\n  [128]: https://github.com/node-inspector/node-inspector\n  [129]: https://github.com/alsotang/node-lessons\n  [130]: https://github.com/ksky521/nodePPT\n  [131]: http://qdemo.sinaapp.com/\n  [132]: https://github.com/hexojs/hexo\n  [133]: https://github.com/koajs/koa\n  [134]: https://github.com/sindresorhus/awesome-nodejs\n  [135]: https://github.com/senchalabs/connect\n  [136]: https://github.com/tj/n\n  [137]: https://github.com/creationix/nvm\n  [138]: https://github.com/js-next/react-style\n  [139]: https://github.com/react-component\n  [140]: https://github.com/facebook/react-native\n  [141]: https://github.com/ele828/react-native-guide\n  [142]: https://github.com/enaqx/awesome-react\n  [143]: https://github.com/facebook/flux\n  [144]: https://github.com/cubiq/iscroll/\n  [145]: https://github.com/JedWatson/react-tappable\n  [146]: https://github.com/vczero/react-native-lesson\n  [147]: https://github.com/h5bp/html5-boilerplate/\n  [148]: https://github.com/mozilla/BrowserQuest\n  [149]: https://github.com/videojs/video.js\n  [150]: https://github.com/aFarkas/html5shiv\n  [151]: https://github.com/brunch/brunch/\n  [152]: https://github.com/uikit/uikit\n  [153]: https://github.com/wycats/handlebars.js\n  [154]: https://github.com/aui/artTemplate\n  [155]: https://github.com/jadejs/jade\n  [156]: https://github.com/tj/ejs\n  [157]: https://github.com/paulmillr/es6-shim\n  [158]: https://github.com/Modernizr/Modernizr\n  [159]: https://github.com/necolas/normalize.css\n  [160]: https://github.com/aFarkas/html5shiv\n  [161]: https://github.com/paulirish/css3please\n  [162]: https://github.com/babel/babel/\n  [163]: https://github.com/yyx990803\n  [164]: https://github.com/tj\n  [165]: https://github.com/paulirish\n  [166]: https://github.com/mbostock\n  [167]: https://github.com/necolas\n  [168]: https://github.com/RubyLouvre\n  [169]: https://github.com/airbnb/javascript\n  [170]: https://github.com/AlloyTeam/Mars\n  [171]: https://github.com/adobe/brackets\n  [172]: https://github.com/TryGhost/Ghost\n  [173]: https://github.com/nodejs/io.js\n  [174]: https://github.com/gabrielecirulli/2048\n  [175]: http://gabrielecirulli.github.io/2048/\n  [176]: https://github.com/fex-team/ueditor\n  [177]: https://github.com/AlloyTeam\n  [178]: https://github.com/fex-team\n"
  },
  {
    "path": "09-front-end-collect-master/README.md",
    "content": "前端收集\n=================\n\n在前端路上摸索前行，在这里分享自己长期关注的前端开发相关的优秀网站、博客、以及活跃开发者。欢迎更新，以下各排名不分先后顺序。\n\n自己 RSS 长期订阅了一些IT 和技术相关博客，这里是我Feedly 输出的opml，可直接导入一些RSS 阅读器:\nhttps://github.com/foru17/luolei-dotfiles/blob/master/feedly.opml\n\n====\n\n#### [前端收集图谱](http://get-set.cn/front-end-collect/)\n\n此部分为[@jikeytang ](https://github.com/jikeytang)贡献\n\n- clone https://github.com/hjzheng/front-end-collect\n- cd front-end-collect\n- bower install\n- 放入你喜欢的web容器,访问index.html即可\n- 你也直接可以访问: http://get-set.cn/front-end-collect/\n- 支持Chrome, Firefox and IE10&11以上浏览器\n\n![image](https://raw.githubusercontent.com/hjzheng/front-end-collect/master/img/front-end-chart.png)\n\n#### 聚合&&周报订阅\n\n|名称 |订阅地址 | 介绍 |\n| ----- | ----- | ------ |\n|**英文推送**|||\n|Html5 Weekly|http://html5weekly.com/| Html 技术类|\n|CSS Weekly|http://css-weekly.com/| |\n|Javascript Weekly|http://javascriptweekly.com/|JS相关，同样有 html,css 和工具相关|\n|Web Design Weekly| http://web-design-weekly.com/ | 设计、技术、技巧、工具聚合|\n|UX Weekly|http://uxwkly.com/|用户体验、网页设计推送|\n|Web Tools Weekly|http://webtoolsweekly.com/|Js，工具推送|\n|RESPONSIVE DESIGN NEWSLETTER|http://responsivedesignweekly.com/|每周推送一次响应式设计相关|\n|Tutorialzine|http://tutorialzine.com/|精品教程和资源推送|\n|Sidebar|http://sidebar.io/|每天、每半周、每周推送5条设计相关|\n|The Hacker News Newsletter|http://www.hackernewsletter.com/|HN 每周精选|\n|Design News|https://news.layervault.com/|F2类资讯聚合|\n|Css Animations|http://cssanimation.rocks/|关于CSS动画的订阅\n|HACKDESIGN|http://hackdesign.org/|每周发布一个设计类课程|\n|**中文推送**|||\n|稀土:掘金|http://gold.xitu.io/|国内十分用心的开发者技术分享、交流平台|\n|SegmentFault精选 |http://segmentfault.com/|国内开发者技术问答社区每周精选问答|\n|FE Weekly|http://www.feweekly.com/|每周一次，内容主要是英文的，不过有中文导读\n|EchoJs_News|http://www.echojs.com/|每天推送若干好文，都是英文的，JS技术类|\n| 碼天狗週刊 |http://weekly.codetengu.com/|台湾的，一份開發者導向的IT 技術週刊，適合所有患有資訊焦慮症、氣血循環不順以及性受挫的軟體工程師們。|\n|前端资源分享 半月刊|http://www.hacke2.cn/monthly/|每半月发布最新高质量的前端资源|\n\n\n\n#### 专业博客\n\n注:此处`活跃度`为博客更新频率，`原创度`指的是作者原创或者翻译的文章所占博文比例。请尊重原创，大量转载其他网站资讯的网站和聚合类网站不做推荐。\n\n###### 中文博客\n|名称 |活跃度 | 原创度 | 维护者|其他|\n| ----- | ----- | ------ |----- |-----|\n|[W3Cplus](http://www.w3cplus.com/)|★★★★★|★★★★★|携程 @大漠 |国内最优秀的前端博客，原创居多|\n|[W3Cfuns](http://www.w3cfuns.com/)|★★★★★|★★★★☆|[#](http://www.w3cfuns.com/misc.php?mod=faq&action=faq&id=1) |专注于web前端开发行业的综合性门户网站|\n|[前端观察](http://www.qianduan.net/)|★★★★☆|★★★★☆|腾讯 ISUX @神飞|曾经最优秀，最近更新不频繁了|\n|[腾讯web前端 AlloyTeam 团队](http://www.alloyteam.com/)|★★★★|★★★★|[@腾讯AlloyTeam](http://t.qq.com/AlloyTeam)|来自于腾讯SNG(社交网络事业群)|\n|[张鑫旭-鑫空间-鑫生活](http://www.zhangxinxu.com/wordpress/)|★★★★☆|★★★★★|张鑫旭|重构很厉害，不少经典文章经验|\n|[ria之家](http://www.36ria.com/)|★★★★☆|★★★★☆|淘宝 @明河|#|\n|[大前端](http://www.daqianduan.com/)|★★★★☆|★★★★☆|[#](http://www.cssforest.org/blog/index.php?s=about)|#|\n|[CSS森林](http://www.cssforest.org/blog/)|★★★★☆|★★★★☆|[关于](http://www.cssforest.org/blog/index.php?s=about)|#|\n|[设计达人](http://www.shejidaren.com/)|★★★★☆|★★★☆☆|[#](http://www.cssforest.org/blog/index.php?s=about)|更新较频繁，但转载也较多|\n|[阮一峰博客](http://www.ruanyifeng.com/blog/)|★★★★☆|★★★☆☆|[#](http://www.ruanyifeng.com/about.html)|牛人一个|\n|[Be For Web - 为网而生 - 原创译文博客](http://beforweb.com/)|★★★★☆|★★★★☆|[@C7210](http://weibo.com/c7210)|关注移动应用及互联网产品、用户体验设计、前端开发|\n\n\n\n######国外博客\n|名称 |活跃度 | 原创度 | 维护者|其他|\n| ----- | ----- | ------ |----- |------|\n|[Smashing Magazine](http://www.smashingmagazine.com/)|★★★★★|★★★★★| # |业界权威，web 设计很赞|\n|[Tuts](http://hub.tutsplus.com/)|★★★★★|★★★★★| - |国外知名开发者网站|\n|[DeveloperDrive](http://www.developerdrive.com/)|★★★★★|★★★★★| - |优质前端技术信息|\n|[CSS-TRICKS](http://css-tricks.com/)|★★★★★|★★★★★| Chris Coyier |左边这位是大神|\n|[Web Designer Wall](http://webdesignerwall.com/)|★★★★★|★★★★★| Nick La.|优质 Html5,CSS3等教程|\n|[Tutorialzine](http://tutorialzine.com/)|★★★★★|★★★★★| #|大量 web 教程和资源|\n|[Inspect Element](http://inspectelement.com/)|★★★★★|★★★★★| #|CSS,wordpress 相关教程挺多|\n|[Codrops](http://tympanus.net/codrops/)|★★★★★|★★★★★| #|设计、交互、CSS|\n|[Jake Rutter](http://www.onerutter.com/)|★★★★★|★★★★★| Jake Rutter|Jquery 作者，不解释了|\n|[Paul Irish](http://www.paulirish.com/)|★★★★★|★★★★★| Paul Irish|大神,Google Chrome团队,Yeoman|\n|[Krasimir Tsonev](http://krasimirtsonev.com/blog)|★★★★★|★★★★★| Krasimir Tsonev|html5,ccs3,javascript|\n|[NCZOnline](http://www.nczonline.net/)|★★★★★|★★★★★| Nicholas C. Zakas |html5,ccs3,javascript|\n|[HTML5 Rocks](http://www.html5rocks.com/en/)|★★★★★|★★★★★| # |html5权威网站|\n|[A List Apart](http://alistapart.com/)|★★★★★|★★★★★| # |可以改变世界的文章|\n|[hakim](http://hakim.se/)|★★★★★|★★★★★| HAKIM EL HATTAB|ccs3,javascript|\n|[DailyJS](http://dailyjs.com/) | ★★★★★ | ★★★★★ | # | javascript |\n\n##### 活跃微博\n|ID |公司 | 简介 |\n|-----|------|------|\n|[@稀土圈](http://weibo.com/xitucircle)|#|强烈推荐，分享一些技术文章和Github项目|\n|[@w3c中国](http://weibo.com/w3cchina)|#|万维网联盟中国办事处官方微博|\n|[@TheFrontEnd](http://weibo.com/javascriptdev)|#|JavaScript技术资讯、新闻、教程、深度文章。|\n|[@前端快爆](http://weibo.com/fekb)|阿里巴巴|有HTML5、CSS3、JS |\n|[@HTML5中国](http://e.weibo.com/html5cn)|#|中国www.html5cn.org官方微博|\n\n#### 开发者博客\n\n微博微信流行后，明显感觉到写博客的人还是越来越少了，下面推荐的这些开发者属于在网上比较活跃的，或者博客积累了大量优质资源的。\n\n###### 国内开发者\n\n国内开发者一块欢迎大家 `Fork`提交推荐，最好能推荐一些在前端界较活跃的的开发者。\n\n|ID |博客 |微博 |Github|Twitter| 公司 |关键字|\n|-----|-----|------|------|-----|-----|------|\n|阮一峰|[阮一峰博客](http://www.ruanyifeng.com/blog/)|[@ruanyf](http://weibo.com/ruanyf)|#|[@ruanyf](https://twitter.com/ruanyf)|上海金融学院国际金融学院| 教师，博客写作人，翻译人，《黑客与画家》的译者|\n|老赵| http://blog.zhaojie.me/|[@老赵](http://weibo.com/jeffz)|#|[#]()|摩根大通（香港）| 资深码农|\n|玉伯|[岁月如歌](http://lifesinger.wordpress.com/)|[@玉伯也叫射雕](http://weibo.com/lifesinger)|[@lifesinger](https://github.com/lifesinger)|[@lifesinger](https://twitter.com/lifesinger)| 支付宝|大牛|\n| kejun |http://hikejun.com/|[@kejunz](http://weibo.com/kejunz)|[@kejunz](https://github.com/kejun)|#| 豆瓣|前端大神|\n|寒冬winter|[winter-cn](http://winter-cn.cnblogs.com/)|[@寒冬winter](http://weibo.com/wintercn)|#|#|#|#|\n|左耳朵耗子|[酷壳](http://coolshell.cn/)|[@左耳朵耗子](http://weibo.com/haoel)|#|[@haoel](https://twitter.com/haoel)|淘宝|#|\n|fool2fish|#|[@fool2fish](http://weibo.com/fool2fish)|#|#|支付宝|#|\n|朴灵|[Html5fiy](http://html5ify.com/)|[@朴灵](http://weibo.com/shyvo)|[JacksonTian](https://github.com/JacksonTian)|#|阿里巴巴|《深入浅出Node.js》作者,大牛|\n|Cat Chen|[陈广琛](http://catchen.biz/home.zh-CN.html)|[@CatChen](http://weibo.com/u/1640352230)|[@CatChen](https://github.com/CatChen)|[@CatChen](https://twitter.com/CatChen)|Facebook |大牛|\n|BYVod|[Beyond the Void](https://www.byvoid.com/)|[@BYVoid](http://weibo.com/byvoid)|[@byvoid](https://github.com/BYVoid)|[@BYVoid](https://twitter.com/byvoid)|Facebook 英国|《Node.js 开发指南》作者,大牛|\n|郭宇|[Einmal ist keinmal](http://blog.guoyu.me/)|[@郭宇](http://weibo.com/137601206)|[@turingou](https://github.com/turingou)|[@turingou](https://twitter.com/turingou)|糗事百科,原支付宝|Node.js|\n|勾三股四|#|[@勾三股四](http://weibo.com/mx006)|#|#|淘宝|#|\n|cnberg|[冰山一角](http://cnberg.com)|[@berg](http://weibo.com/berg)|@cnberg|[@cnberg]()| 百度| 骑行|\n|大猫| [意淫笔记](http://bigc.at)|[@daemao](http://weibo.com/daemao)|[@Damao](https://github.com/Damao)|[@13igcat](https://twitter.com/13igcat)|腾讯 |[知乎](http://www.zhihu.com/people/13igcat)|\n| hzlzh |[自力博客](https://zlz.im)|[@hzlzh](http://weibo.com/hzlzh)|[@hzlzh](http://github.com/hzlzh)|[@hzlzh](http://twitter.com/hzlzh)| 腾讯|前端开发|\n| C7210 |beforweb.com/|[@C7210](http://weibo.com/c7210)|[@C7210](http://twittercom/hzlzh)|[@C7210](http://github.com/hzlzh)|#|UX、交互设计师、视觉与前端|\n| kejun |http://hikejun.com/|[#](http://weibo.com/kejun)|[#](http://twittercom/kejun)|[#](http://github.com/hzlzh)| 腾讯|前端开发|\n| 张鑫旭 |[张鑫旭博客](http://www.zhangxinxu.com/wordpress/)|[@张鑫旭](http://weibo.com/zhangxinxu)|[@zhangxinxu](https://github.com/zhangxinxu)|[@zhangxinxu](https://twitter.com/zhangxinxu)| 腾讯 上海 ISUX|前端开发|\n| lucifr |http://lucifr.com/|[@lucifr](http://weibo.com/lucifr)|[@lucifr](http://twittercom/lucifr)|[@lucifr](http://github.com/lucifr)| #|Mac,ios|\n| smallni |http://www.smallni.com/|[#](http://weibo.com/hzlzh)|[@Smallni](https://twitter.com/smallniding/)|[#](http://github.com/hzlzh)| 腾讯|前端开发|\n| TQ |http://targetkiller.net/|[@Piser-TQ](http://weibo.com/targetkiller)|[@tqtan](https://twitter.com/tqtan/)|[@targetkiller](https://github.com/targetkiller)| 腾讯 ISUX | 网页重构|\n|LOO2K|[LOO2K](http://loo2k.com/blog/)|[@LOO2K](http://weibo.com/loo2k)|[LOO2K](https://github.com/loo2k)|[LOO2K](https://twitter.com/loo2k/)|墨筹网|少年才俊|\n|qiqiboy|[qiqiboy](http://www.qiqiboy.com/)|[@qiqiboy](http://weibo.com/qiqiboy)|#|#|金山网络 UX|吐槽清理大师开发者|\n|foru17|[罗磊的独立博客](http://luolei.org)|[@罗罗磊磊](http://weibo.com/foru17)|[@foru17](https://github.com/foru17)|[@foru17](https://twitter.com/foru17)||打酱油的|\n|周爱民|[aimingoo专栏](http://blog.csdn.net/aimingoo/)|#|#|#|支付宝|JavaScript语言精髓与编程实践作者|\n|hax|[hax的技术部落格](http://hax.iteye.com/)|#|#|#|#|前端大牛|\n|三生石上|[三生石上](http://www.cnblogs.com/sanshi)|#|#|#|#|js秘密花园译者|\n|司徒正美|[Ruby's Louvre](http://www.cnblogs.com/rubylouvre)|#|#|#|#|前端开发|\n|叶小钗|[叶小钗](http://www.cnblogs.com/yexiaochai)|#|#|#|#|前端开发|\n|聂微东|[Darren](http://www.cnblogs.com/Darren_code/)|#|#|#|百度移动云|前端开发|\n|当耐特|[iamzhanglei](http://www.cnblogs.com/iamzhanglei/)|#|#|#|#|HTML5实验室作者|\n|教主|[_frank](http://www.cnblogs.com/_franky)|#|#|#|#|又一牛|\n|typeof|[typeof](http://typeof.net/)|#|#|#|#|又一牛|\n|Gray Zhang|[Gray Zhang](http://www.cnblogs.com/GrayZhang)|#|#|#|#|百度一牛|\n|李松峰|[为之漫笔](http://www.cn-cuckoo.com)|#|#|#|#|高程2等书的译者|\n|小鱼|[sofish](http://sofish.de/)|[@sofish](http://weibo.com/sofish)|#|#|#|饿了么前端Leader|\n|vilic|[vilic](http://vilic.info/)|#|#|#|#|年轻一牛|\n|彬Go|[彬Go](http://blog.bingo929.com/)|#|#|#|#|人人网一牛|\n|PuterJam|[PuterJam's Blog](http://www.pjhome.net)|#|#|#|#|腾讯一牛|\n|css森林|[cssforest](http://www.cssforest.org)|#|#|#|#|前端博客|\n|99css|[99css](http://www.99css.com/)|[@ytzong](http://weibo.com/ytzong)|#|#|#|腾讯一牛|\n|秦歌|[Kaven](http://dancewithnet.com/)|#|[@kavenyan](http://twitter.com/kavenyan)|#|#|js语言精粹译者|\n|linxz|[linxz](http://www.linxz.de/)|#|#|#|#|css那些事儿的作者|\n|米随随|[米随随](http://s5s5.me/)|#|#|#|#|腾讯ISUX 一牛|\n|飘飘|[飘飘](http://pufen.net/)|#|#|#|#|腾讯一牛|\n|Along|[Along's Blog](http://jinlong.github.io/)|[@newwave](http://weibo.com/newwave)|#|#|#|Opera 欧朋一牛|\n|安记|[cssha](http://www.cssha.com/)|[@hanan321](http://weibo.com/hanan321)|[hanan198501](https://github.com/hanan198501)|#|#|去哪网一牛|\n| 余弦 | [EVILCOS](http://evilcos.me/) | [余弦](http://weibo.com/evilcos) | [evilcos](https://github.com/evilcos) | # | [知道创宇](http://www.knownsec.com/) | 安全（黑客）、架构、团队的各种观点与分享 | # | [冯大辉](http://dbanotes.net/) | 现在就职于丁香园 (http://dxy.cn) ，担任技术团队负责人.\n|汤姆大叔|[汤姆大叔的博客](http://www.cnblogs.com/TomXu/)|#|#|#|#|《深入理解Bootstrap》、《JavaScript启示录》、《JavaScript设计模式》等多本前端书籍翻译作者|\n|屈光宇|[Jerry Qu的小站](https://imququ.com/)|[屈光宇](http://weibo.com/jerryqu)|#|#|#|奇虎360前端，对WEB性能研究很深入|\n\n\n####一些社区\n\n|名称 |地址 |介绍 |\n|-----|-----|------|\n|V2EX|http://v2ex.com/|小众活跃社区|\n|知乎|http://www.zhihu.com/|综合问答社区|\n|前端乱炖|http://www.html-js.com/|专业的前端知识平台|\n|segmentfault|http://segmentfault.com/|综合问答社区|\n|果壳问答|http://www.guokr.com/ask/pending/|综合问答社区|\n|Ruby|http://ruby-china.org/|同 V2EX 氛围类似，不局限于Ruby|\n|Node.js 中文社区|http://cnodejs.org/|Node.js 国内最活跃的社区|\n|Code Wall|https://coderwall.com/|国外技术社区|\n| DIV.IO | http://div.io/ | 国内前端技术社区 |\n| w3ctech | http://www.w3ctech.com/ | 国内前端技术社区，常有一些线下活动发布 |\n\n\n##### 企业官方博客\n\n在开头我的 Feedly 订阅 opml 文件里比较全面。\n\n|名称 |公司 | 部门|活跃度 | 简介|微博|\n| ----- | ----- | ------ | ------ |-----|-----|\n| [ISUX 社交用户体验设计](http://isux.tencent.com/) | 腾讯 |  ISUX| ★★★★☆|负责腾讯的社交网络相关产品的用户体验设计与研究。|#|\n| [腾讯 CDC](http://cdc.tencent.com/) | 腾讯 |  CDC| ★★★★☆| 简介 |#|\n| [腾讯Web前端 Alloy 团队 Blog](http://www.alloyteam.com/) | 腾讯 | SNG| ★★★★☆|主要负责手机QQ、QQ互联、腾讯Q+、WebQQ项目的团队。 |[alloyteam](http://weibo.com/alloyteam)|\n| [TID-财付通设计中心](http://tid.tenpay.com/) | 腾讯 |  TID| ★★★★☆|简介 |#|\n| [腾讯MXD移动互联网设计中心](http://mxd.tencent.com/) | 腾讯 |  MXD| ★★★★☆|简介 |[@腾讯MXD](http://e.t.qq.com/tencent_mxd)|\n| [人人网FED Team](http://fed.renren.com/) | 人人网 |   FED| ★★★★☆|简介 |#|\n| [微博UDC](http://udc.weibo.com/) | 新浪 |   UDC| ★★★★☆|简介 |[@微博UDC设计中心](http://weibo.com/sudc)|\n| [新浪UED](http://ued.sina.com.cn/) | 新浪 |   UED| ★★★★☆|简介 |[#](http://weibo.com/sudc)|\n| [网易用户体验设计中心](http://uedc.163.com/) | 网易 |   UED| ★★★★☆|简介 |[#](http://weibo.com/sudc)|\n| [阿里巴巴（中国站）用户体验设计部博客](http://www.aliued.cn/) | 阿里巴巴 |   UED| ★★★★☆|简介 |[@Alibaba-UED](http://weibo.com/aliued)|\n| [携程UED-携程旅行前端开发团队](http://ued.ctrip.com/blog/) | 携程网 |   UED| ★★★☆☆|携程UED,携程前端开发团队,UED,Javascript,重构,ux|#|\n| [百度FEX](http://fex.baidu.com/) | 百度 |   FEX| ★★★★☆| 百度前端团队Blog,关注前端技术，还更重视全端及全栈的能力。|#|\n|[淘宝UED](http://ued.taobao.org/blog/)|淘宝网|UED|★★★★☆|用户体验、交互设计、视觉设计、前端技术博客|[@淘宝UED](http://weibo.com/taobaoued)|\n\n\n## 书籍\n\n|名称 | 作者 | 价格 | 出版社|简评 |\n| ----- | ----- | ------ |----- |------|\n| [Web标准设计](http://book.douban.com/subject/3327829/) | 刘杰（嗷嗷） | RMB 60.00  | 清华大学出版社 |基础入门|\n| [大巧不工 : Web前端设计修炼之道](http://book.douban.com/subject/4914146/) | 赖定清 / 林坚  | RMB 59.00  | 机械工业出版社|适合入门，了解前端全局|\n|[高性能网站建设指南:前端工程师技能精髓](http://book.douban.com/subject/3132277/)|Steve Souders |RMB 35.00|电子工业出版社|能从原理层理解各种方法|\n|[高性能网站建设指南:Web开发者性能优化最佳实践](http://book.douban.com/subject/4719162/)|Steve Souders |RMB 49.80|电子工业出版社|#|\n|[Web站点优化 : Web站点优化](http://book.douban.com/subject/4124141/)|金  |RMB 55.00|#|#|\n|[Node.js开发指南](http://book.douban.com/subject/10789820/)| 郭家寶  |RMB 45.00|#|作者很牛|\n|[JavaScript高级程序设计](http://book.douban.com/subject/10546125/)| Nicholas C. Zakas   |RMB 99.00|人民邮电出版社|适合没事就翻翻|\n|[JavaScript权威指南](http://book.douban.com/subject/2228378/)| 弗拉纳根    |RMB 109.00|机械工业出版社|犀牛书|\n|[JavaScript语言精粹](http://book.douban.com/subject/3590768/)| Douglas Crockford    |RMB 35.00| 电子工业出版社|绝对经典，相信看完后，对Javascript这门语言有了重新认识，原来这个语言是这么的美丽！|\n|[深入浅出node.js](http://book.douban.com/subject/25768396/)|朴灵|RMB 69.00|人民邮电出版社|一本从前端通往全端的好书|\n|[CSS开发王](http://book.douban.com/subject/3137282/)|张亚飞|RMB 49.00|电子工业出版社|适合有一定基础后CSS进阶用|\n|[JavaScript DOM编程艺术](http://book.douban.com/subject/6038371/)|Jeremy Keith /Jeffrey Sambells|RMB 49.00|人民邮电出版社|适合Javascript入门看|\n\n\n\n=======\n\n####线上的一些翻译版好书\n\n|书名|地址|作者|译者|介绍|\n|----|----|----|----|----|\n|JavaScript秘密花园|http://bonsaiden.github.io/JavaScript-Garden/zh/|伊沃·韦特泽尔&张易江|[三生石上](http://sanshi.me/)|完整书籍，界面美观，有详细demo|\n| Material Design 中文版 | http://design.1sters.com/ | Google设计手册 | 协同翻译 | Google I/O 2014 发布的 Material Design 官方手册的中文翻译 |\n\n\n##关于\n======\n\n本 repo 会 不断更新，感谢推荐和分享新资源的朋友。\n"
  },
  {
    "path": "09-front-end-collect-master/css/style.css",
    "content": "/*Dendrogram*/\n.node circle {\n  fill: #fff;\n  stroke: steelblue;\n  stroke-width: 1.5px;\n}\n\n.node {\n  font: 16px sans-serif;\n  cursor: pointer;\n}\n\n.node text:hover {\n  fill: steelblue;\n}\n\n.link {\n  fill: none;\n  stroke: #ccc;\n  stroke-width: 1.5px;\n}\n\n/*tooltip*/\n#tooltip {\n  position: fixed;\n  width: 200px;\n  height: auto;\n  padding: 10px;\n  background-color: #444;\n  -webkit-border-radius: 10px;\n  -moz-border-radius: 10px;\n  border-radius: 10px;\n  -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  pointer-events: none;\n  color: #fff;\n}\n\n#tooltip.hidden {\n  display: none;\n}\n\n#tooltip p {\n  margin: 0;\n  font-family: sans-serif;\n  font-size: 16px;\n  line-height: 20px;\n}\n\n.title { \n  width: 460px; \n  position: fixed;\n  top: 10px;\n  right: -40px;\n  height: auto;\n  padding: 10px;\n  margin: 15px;\n  background-color: #444;\n  -webkit-border-radius: 10px;\n  -moz-border-radius: 10px;\n  border-radius: 10px;\n  -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);\n  color: #fff;\n}\n\na:hover {\n  text-decoration: none;\n}\n\n/*fix IE10, IE11 type=range can not display in bootstrap style*/\ninput[type=range] {\n    width: 200px\\0;\n    display: inline;\n}\n"
  },
  {
    "path": "09-front-end-collect-master/data/front-end.json",
    "content": "{\n  \"name\": \"前端资料收集\",\n  \"description\": \"在前端路上摸索前行，在这里分享自己长期关注的前端开发相关的优秀网站、博客、以及活跃开发者。\",\n  \"url\": \"https://github.com/hjzheng/front-end-collect\",\n  \"children\": [\n    {\n      \"name\": \"聚合&&周报订阅\",\n      \"description\": \"无\",\n      \"children\": [\n        {\n          \"name\": \"Html5 Weekly\",\n          \"size\": 5534,\n          \"url\": \"http://html5weekly.com/\",\n          \"description\": \"Html相关文章\"\n        },\n        {\n          \"name\": \"CSS Weekly\",\n          \"size\": 5731,\n          \"url\": \"http://css-weekly.com/\",\n          \"description\": \"CSS相关文章\"\n        },\n        {\n          \"name\": \"Javascript Weekly\",\n          \"size\": 7840,\n          \"url\": \"http://javascriptweekly.com/\",\n          \"description\": \"JS相关文章，同样也有 html,css 和工具相关\"\n        },\n        {\n          \"name\": \"Web Design Weekly\",\n          \"size\": 7914,\n          \"url\": \"http://web-design-weekly.com/\",\n          \"description\": \"设计、技术、技巧、工具聚合\"\n        },\n        {\n          \"name\": \"UX Weekly\",\n          \"size\": 4416,\n          \"url\": \"http://uxwkly.com/\",\n          \"description\": \"用户体验、网页设计相关\"\n        },\n        {\n          \"name\": \"Web Tools Weekly\",\n          \"size\": 7700,\n          \"url\": \"http://webtoolsweekly.com/\",\n          \"description\": \"JS, 工具推送\"\n        },\n        {\n          \"name\": \"RESPONSIVE DESIGN NEWSLETTER\",\n          \"size\": 8900,\n          \"url\": \"http://responsivedesignweekly.com/\",\n          \"description\": \"每周推送一次响应式设计相关\"\n        },\n        {\n          \"name\": \"Tutorialzine\",\n          \"size\": 5000,\n          \"url\": \"http://tutorialzine.com/\",\n          \"description\": \"精品教程和资源推送\"\n        },\n        {\n          \"name\": \"Sidebar\",\n          \"size\": 4600,\n          \"url\": \"http://sidebar.io/\",\n          \"description\": \"每天、每半周、每周推送5条设计相关\"\n        },\n        {\n          \"name\": \"The Hacker News Newsletter\",\n          \"size\": 9600,\n          \"url\": \"http://www.hackernewsletter.com/\",\n          \"description\": \"HN 每周精选\"\n        },\n        {\n          \"name\": \"Design News\",\n          \"size\": 5600,\n          \"url\": \"https://news.layervault.com/\",\n          \"description\": \"F2类资讯聚合\"\n        },\n        {\n          \"name\": \"HACKDESIGN\",\n          \"size\": 4600,\n          \"url\": \"http://hackdesign.org/\",\n          \"description\": \"每周发布一个设计类课程\"\n        }\n      ]\n    },\n    {\n      \"name\": \"专业博客\",\n      \"description\": \"无\",\n      \"children\": [\n        {\n          \"name\": \"中文博客\",\n          \"description\": \"无\",\n          \"children\": [\n            {\n              \"name\": \"W3Cplus\",\n              \"size\": 4700,\n              \"url\": \"http://www.w3cplus.com/\",\n              \"description\": \"国内最优秀的前端博客，原创居多\"\n            },\n            {\n              \"name\": \"W3Cfuns\",\n              \"size\": 4700,\n              \"url\": \"http://www.w3cfuns.com/\",\n              \"description\": \"专注于web前端开发行业的综合性门户网站\"\n            },\n            {\n              \"name\": \"前端观察\",\n              \"size\": 6700,\n              \"url\": \"http://www.qianduan.net/\",\n              \"description\": \"曾经最优秀，最近更新不频繁了\"\n            },\n            {\n              \"name\": \"腾讯web前端\",\n              \"size\": 7800,\n              \"url\": \"http://www.alloyteam.com/\",\n              \"description\": \"来自于腾讯SNG(社交网络事业群)\"\n            },\n            {\n              \"name\": \"张鑫旭-鑫空间-鑫生活\",\n              \"size\": 8000,\n              \"url\": \"http://www.zhangxinxu.com/wordpress/\",\n              \"description\": \"重构很厉害，不少经典文章经验\"\n            },\n            {\n              \"name\": \"ria之家\",\n              \"size\": 4000,\n              \"url\": \"http://www.36ria.com/\",\n              \"description\": \"无\"\n            },\n            {\n              \"name\": \"大前端\",\n              \"size\": 4000,\n              \"url\": \"http://www.daqianduan.com/\",\n              \"description\": \"无\"\n            },\n            {\n              \"name\": \"CSS森林\",\n              \"size\": 8000,\n              \"url\": \"http://www.cssforest.org/blog/\",\n              \"description\": \"无\"\n            },\n            {\n              \"name\": \"设计达人\",\n              \"size\": 8000,\n              \"url\": \"http://www.shejidaren.com/\",\n              \"description\": \"更新较频繁，但转载也较多\"\n            },\n            {\n              \"name\": \"Be For Web\",\n              \"size\": 5000,\n              \"url\": \"http://beforweb.com/\",\n              \"description\": \"关注移动应用及互联网产品、用户体验设计、前端开发\"\n            }\n          ]\n        },\n        {\n          \"name\": \"国外博客\",\n          \"description\": \"无\",\n          \"children\": [\n            {\n              \"name\": \"Smashing Magazine\",\n              \"size\": 6700,\n              \"url\": \"http://www.smashingmagazine.com/\",\n              \"description\": \"业界权威，web 设计很赞\"\n            },\n            {\n              \"name\": \"Tuts\",\n              \"size\": 3200,\n              \"url\": \"http://tutsplus.com/tutorials\",\n              \"description\": \"国外知名开发者网站\"\n            },\n            {\n              \"name\": \"Developer Drive\",\n              \"size\": 5600,\n              \"url\": \"http://www.developerdrive.com/\",\n              \"description\": \"优质前端技术信息\"\n            },\n            {\n              \"name\": \"CSS-TRICKS\",\n              \"size\": 5000,\n              \"url\": \"http://css-tricks.com/\",\n              \"description\": \"无\"\n            },\n            {\n              \"name\": \"Web Designer Wall\",\n              \"size\": 7000,\n              \"url\": \"http://webdesignerwall.com/\",\n              \"description\": \"优质 Html5,CSS3等教程\"\n            },\n            {\n              \"name\": \"Tutorialzine\",\n              \"size\": 5200,\n              \"url\": \"http://tutorialzine.com/\",\n              \"description\": \"大量 web 教程和资源\"\n            },\n            {\n              \"name\": \"Inspect Element\",\n              \"size\": 6302,\n              \"url\": \"http://inspectelement.com/\",\n              \"description\": \"CSS,wordpress 相关教程挺多\"\n            },\n            {\n              \"name\": \"Codrops\",\n              \"size\": 4100,\n              \"url\": \"http://tympanus.net/codrops/\",\n              \"description\": \"设计、交互、CSS\"\n            },\n            {\n              \"name\": \"Jake Rutter\",\n              \"size\": 4700,\n              \"url\": \"http://www.onerutter.com/\",\n              \"description\": \"Jquery 作者，不解释了\"\n            },\n            {\n              \"name\": \"Paul Irish\",\n              \"size\": 4600,\n              \"url\": \"http://www.paulirish.com/\",\n              \"description\": \"大神,Google Chrome团队,Yeoman\"\n            },\n            {\n              \"name\": \"Krasimir Tsonev\",\n              \"size\": 5600,\n              \"url\": \"http://krasimirtsonev.com/blog\",\n              \"description\": \"html5,css3,javascript\"\n            },\n            {\n              \"name\": \"NCZOnline\",\n              \"size\": 4500,\n              \"url\": \"http://www.nczonline.net/\",\n              \"description\": \"html5,css3,javascript\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"name\": \"活跃微博\",\n      \"description\": \"无\",\n      \"children\": [\n        {\n          \"name\": \"@w3c中国\",\n          \"size\": 3600,\n          \"url\": \"http://weibo.com/w3cchina\",\n          \"description\": \"万维网联盟中国办事处官方微博\"\n        },\n        {\n          \"name\": \"@TheFrontEnd\",\n          \"size\": 3800,\n          \"url\": \"http://weibo.com/javascriptdev\",\n          \"description\": \"JavaScript技术资讯、新闻、教程、深度文章。\"\n        },\n        {\n          \"name\": \"@前端快爆\",\n          \"size\": 4600,\n          \"url\": \"http://weibo.com/fekb\",\n          \"description\": \"爆前端资讯，谈中外技术\"\n        },\n        {\n          \"name\": \"@HTML5中国\",\n          \"size\": 4200,\n          \"url\": \"http://weibo.com/html5cn\",\n          \"description\": \"html5学习、实战、交流平台html5中国www.html5cn.org官方微博\"\n        },\n        {\n          \"name\": \"@developerWorks\",\n          \"size\": 4700,\n          \"url\": \"http://weibo.com/developerworks\",\n          \"description\": \"码农周刊（manong.io）& 开发者头条（toutiao.io）\"\n        }\n      ]\n    },\n    {\n      \"name\": \"开发者\",\n      \"description\": \"微博微信流行后，明显感觉到写博客的人还是越来越少了，下面推荐的这些开发者属于在网上比较活跃的，或者博客积累了大量优质资源的。\",\n      \"children\": [\n        {\n          \"name\": \"阮一峰\",\n          \"size\": 2600,\n          \"url\": \"http://www.ruanyifeng.com/blog/\",\n          \"description\": \"阮一峰，70后，英文名Frank。他原是上海财经大学世界经济博士研究生。主要研究宏观金融、货币政策与美国经济。\"\n        },\n        {\n          \"name\": \"老赵\",\n          \"size\": 2700,\n          \"url\": \"http://blog.zhaojie.me/\",\n          \"description\": \"赵劼，网名老赵，洋名Jeffrey Zhao，花名赵姐夫，金融行业程序员，目前就职于摩根大通（香港）。\"\n        },\n        {\n          \"name\": \"玉伯\",\n          \"size\": 2800,\n          \"url\": \"https://github.com/lifesinger\",\n          \"description\": \"seajs作者\"\n        },\n        {\n          \"name\": \"kejun\",\n          \"size\": 2600,\n          \"url\": \"http://hikejun.com/\",\n          \"description\": \"张克军，豆瓣前端工程师\"\n        },\n        {\n          \"name\": \"winter\",\n          \"size\": 2900,\n          \"url\": \"http://winter-cn.cnblogs.com/\",\n          \"description\": \"无\"\n        },\n        {\n          \"name\": \"左耳朵耗子\",\n          \"size\": 3400,\n          \"url\": \"http://coolshell.cn/\",\n          \"description\": \"陈皓（@左耳朵耗子），酷壳coolshell.cn博主。14年软件开发相关工作经验，8年以上项目和团队管理经验，6年的软件行业咨询经验。\"\n        },\n        {\n          \"name\": \"朴灵\",\n          \"size\": 2500,\n          \"url\": \"https://github.com/JacksonTian\",\n          \"description\": \"淘宝数据平台产品部资深前端开发工程师 朴灵\"\n        },\n        {\n          \"name\": \"陈广琛\",\n          \"size\": 3000,\n          \"url\": \"http://catchen.biz/home.zh-CN.html\",\n          \"description\": \"陈广琛（网名 Cat Chen），前端工程师，现就职于 Facebook。\"\n        },\n        {\n          \"name\": \"BYVod\",\n          \"size\": 3200,\n          \"url\": \"https://www.byvoid.com/\",\n          \"description\": \"就职于Facebook(英国)\"\n        },\n        {\n          \"name\": \"郭宇\",\n          \"size\": 2800,\n          \"url\": \"http://blog.guoyu.me/\",\n          \"description\": \"就职于支付宝\"\n        },\n        {\n          \"name\": \"大猫\",\n          \"size\": 2600,\n          \"url\": \"http://bigc.at/\",\n          \"description\": \"无\"\n        },\n        {\n          \"name\": \"C7120\",\n          \"size\": 2700,\n          \"url\": \"http://beforweb.com/\",\n          \"description\": \"UX玩家、交互设计师、猫奴、guitar fucker，现就职于腾讯ISUX(上海)\"\n        },\n        {\n          \"name\": \"lucifr\",\n          \"size\": 3000,\n          \"url\": \"\",\n          \"description\": \"Geek | 拖延症患者 | 间歇性话痨 | 爱 Google | 爱 Mac | Hackintosher | Octopressor | Nikon D90 | Bookmarker | and more.\"\n        },\n        {\n          \"name\": \"Smallni\",\n          \"size\": 3200,\n          \"url\": \"http://www.smallni.com\",\n          \"description\": \"本名丁小倪，小名小倪，英文名Smallni，混迹于互联网，目前在南极洲企鹅村打杂，崇尚简单一目了然的设计风格，注重代码的性能和易维护性，也关注信息无障碍和用户心理学。有点不自信，所以正在努力学习，为早日成为祖国的可树之才而努力。目前同时兼职于W3C CSS工作组和HTML工作组，致力于为WEB标准贡献自己的绵薄之力。\"\n        },\n        {\n          \"name\": \"TQ\",\n          \"size\": 2700,\n          \"url\": \"http://targetkiller.net/\",\n          \"description\": \"Hi，我是TQ，刚毕业小前端，现就职腾讯ISUX。喜欢折腾前端技术，关注互联网前沿资讯，崇尚简洁至上的设计和交互。\"\n        },\n        {\n          \"name\": \"LOO2K\",\n          \"size\": 3400,\n          \"url\": \"http://loo2k.com/blog/\",\n          \"description\": \"无\"\n        },\n        {\n          \"name\": \"周爱民\",\n          \"size\": \"3200\",\n          \"url\": \"http://blog.csdn.net/aimingoo/\",\n          \"description\": \"国内软件开发界资深软件工程师，从1996年开始涉足商业软件开发，历任部门经理、区域总经理、高级软件工程师、平台架构师等职。周爱民先生在软件开发、软件工程、团队建设以及部门管理方面经验丰富，是Borland Delphi产品技术专家，也是Qomo开源项目（JavaScript）的发起者。在JavaScript开发方面，有超过9年的实践经验。\"\n        },\n        {\n          \"name\": \"司徒正美\",\n          \"size\": 3500,\n          \"url\": \"http://www.cnblogs.com/rubylouvre\",\n          \"description\": \"无\"\n        },\n        {\n          \"name\": \"安记\",\n          \"size\": 2200,\n          \"url\": \"http://cssha.com/\",\n          \"description\": \"Hi，我是阿安,双子座，宅男，喜欢编程，更爱足球。现居北京，就职于去哪儿网，前端开发工程师。\"\n        }\n      ]\n    },\n    {\n      \"name\": \"社区\",\n      \"description\": \"\",\n      \"children\": [\n        {\n          \"name\": \"V2EX\",\n          \"size\": 3000,\n          \"url\": \"http://v2ex.com/\",\n          \"description\": \"小众活跃社区\"\n        },\n        {\n          \"name\": \"Node.js 中文社区\",\n          \"size\": 6000,\n          \"url\": \"http://cnodejs.org/\",\n          \"description\": \"Node.js 国内最活跃的社区\"\n        }\n      ]\n    },\n    {\n      \"name\": \"企业博客\",\n      \"description\": \"\",\n      \"children\": [\n        {\n          \"name\": \"ISUX 社交用户体验设计\",\n          \"size\": 9000,\n          \"url\": \"http://isux.tencent.com/\",\n          \"description\": \"负责腾讯的社交网络相关产品的用户体验设计与研究。\"\n        },\n        {\n          \"name\":\"腾讯 CDC\",\n          \"size\": 4700,\n          \"url\": \"http://cdc.tencent.com/\",\n          \"description\":\"CDC成立于2006年5月18日,全称是Customer Research & User Experience Design Center（即用户研究与体验设计中心）作为腾讯的核心部门之一。CDC自成立以来，就一直向着“做世界一流的互联网设计团队，为用户创造优质‘在线生活’体验”这一愿景努力，致力于不断提升腾讯全线产品的用户体验。\"\n        },\n        {\n          \"name\":\"TID\",\n          \"size\":7000,\n          \"url\":\"http://tid.tenpay.com/\",\n          \"description\":\"腾讯财付通设计中心\"\n        },\n        {\n          \"name\":\"MXD\",\n          \"size\":7000,\n          \"url\":\"http://mxd.tencent.com/\",\n          \"description\": \"腾讯MXD移动互联网设计中心\"\n        },\n        {\n          \"name\":\"新浪UED\",\n          \"size\":5000,\n          \"url\":\"http://ued.sina.com.cn/\",\n          \"description\": \"无\"\n        },\n        {\n          \"name\":\"网易UED\",\n          \"size\":4000,\n          \"url\":\"http://uedc.163.com/\",\n          \"description\":\"网易用户体验设计中心（User Experience Design Center），简称“设计中心（UEDC）”，成立于2008年底。\"\n        },\n        {\n          \"name\":\"阿里巴巴（中国站）UED\",\n          \"size\": 6000,\n          \"url\":\"http://www.aliued.cn/\",\n          \"description\":\"阿里巴巴中国站UED成立于1999年，全称是用户体验设计部（User Experience Design Department），花名为“有一点”，是阿里巴巴集团最资深的部门之一。\"\n        },\n        {\n          \"name\":\"携程UED\",\n          \"size\": 6000,\n          \"url\":\"http://ued.ctrip.com/blog/\",\n          \"description\":\"携程UED,携程前端开发团队,UED,Javascript,重构,ux\"\n        },\n        {\n          \"name\":\"百度FEX\",\n          \"size\": 6000,\n          \"url\":\"http://fex.baidu.com/\",\n          \"description\":\"百度前端团队Blog,关注前端技术，还更重视全端及全栈的能力\"\n        }\n      ]\n    },\n    {\n      \"name\": \"书籍\",\n      \"description\": \"\",\n      \"children\": [\n        {\n          \"name\": \"JavaScript语言精粹\",\n          \"size\": 3000,\n          \"url\": \"http://book.douban.com/subject/3590768/\",\n          \"description\": \"绝对经典，相信看完后，对Javascript这门语言有了重新认识，原来这个语言是这么的美丽！\"\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "09-front-end-collect-master/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"bower_components/bootstrap/dist/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\">\n    <script src=\"bower_components/angular/angular.min.js\"></script>\n    <script src=\"bower_components/d3/d3.min.js\"></script>\n    <script src=\"js/app.js\"></script>\n  </head>\n  <body ng-app=\"frontEnd\" ng-controller=\"frontEndCtrl\" class=\"container-fluid\">\n     <div id=\"tooltip\" class=\"hidden\">\n        <p><strong id=\"name\"></strong></p>\n        <p><span id=\"desc\"></span></p>\n     </div>\n     <h2 class=\"title\">\n         <a href=\"https://github.com/hjzheng/front-end-collect\" target=\"_blank\">Front-end-collect</a> Chart\n         <p class=\"lead\" style=\"padding-left:150px;\"> Follow me on Github <a href=\"https://github.com/hjzheng\" target=\"_blank\">hjzheng</a></p>\n     </h2>\n\n     <div class=\"row\">\n         <form role=\"form\" class=\"col-sm-6\">\n             <label class=\"radio-inline\">\n                 <input type=\"radio\" ng-model=\"type\" value=\"tree\"> Tree\n             </label>\n             <label class=\"radio-inline\">\n                 <input type=\"radio\" ng-model=\"type\" value=\"cluster\"> Cluster\n             </label>\n             <label class=\"radio-inline\">\n                 <input type=\"range\" ng-model=\"rotate\" min=\"0\" max=\"60\" ng-disabled=\"type !== 'cluster'\">\n             </label>\n             <label class=\"radio-inline\">\n                 <span>{{ rotate * 6 }}</span>\n             </label>\n         </form>\n     </div>\n     <div class=\"row\">\n        <front-end-chart></front-end-chart>\n     </div>\n  </body>\n</html>\n"
  },
  {
    "path": "09-front-end-collect-master/js/app.js",
    "content": "angular.module('frontEnd', [])\n  .factory('data', ['$http', function($http) {\n    return {\n      getFrontEndData: function() {\n        var url = 'data/front-end.json';\n        return $http.get(url);\n      }\n    };\n  }])\n  .controller('frontEndCtrl', ['$scope', '$window', 'data',\n    function($scope, $window, data) {\n      $scope.type = 'cluster';\n      $scope.frontEndData = '';\n      $scope.rotate = 0;\n\n      $window.addEventListener('resize', function() {\n        $scope.$broadcast('windowResize');\n      });\n\n      data.getFrontEndData()\n        .success(function(res) {\n          if (res.error) {\n            throw new Error(res.message);\n          } else {\n            $scope.frontEndData = res\n          }\n        });\n    }\n  ]).directive('frontEndChart', ['data','$window', '$timeout', function(data, $window, $timeout) {\n\n    var link = function($scope, $el, $attrs) {\n\n      var radius = 960 / 2;\n\n      var tree = d3.layout.tree()\n           .size([radius*2, radius*2]);\n\n      var diagonalTree = d3.svg.diagonal()\n           .projection(function(d) { return [d.y, d.x]; });\n\n      var cluster = d3.layout.cluster()\n        .size([360, radius - 120]);\n\n      var diagonalCluster = d3.svg.diagonal.radial()\n        .projection(function(d) {\n          return [d.y, d.x / 180 * Math.PI];\n        });\n\n      var svg = d3.select($el[0]).append(\"svg\")\n        .attr(\"width\", document.documentElement.clientWidth)\n        .attr(\"height\", document.documentElement.clientHeight - 30)\n        .call(\n          d3.behavior.zoom().scaleExtent([0.6, 3]).on(\"zoom\", zoom)\n        );\n\n      var g = svg.append(\"g\")\n        .attr(\"transform\", \"translate(\" + radius + \",\" + radius + \")\");\n\n      function zoom () {\n         //TODO: set translate range\n         //TODO: after rotate, we need add rotate for zoom translate\n         g.attr(\"transform\", \"translate(\" + d3.event.translate + \")scale(\" + d3.event.scale + \")\" );\n      }\n\n      var timeout;\n\n      function rotate(oldValue, newValue){\n          if (timeout) $timeout.cancel(timeout);\n          timeout = $timeout(function() {\n              var rotate = $scope.rotate*6;\n              var trans = g.attr(\"transform\");\n              if(trans.indexOf(\"rotate\") !== -1){\n                  trans = trans.replace(/rotate\\([^()]*\\)/, \"rotate(\" + rotate + \")\");\n              }else{\n                  trans += \"rotate(\" + rotate + \")\";\n              }\n              g.transition().duration(600).attr(\"transform\", trans);\n          }, 350);\n      }\n\n      var update = function() {\n        if ($scope.frontEndData === '') return;\n\n        var data = $scope.frontEndData;\n\n        var nodes = cluster.nodes(data);\n        var links = cluster.links(nodes);\n        var diagonal = diagonalCluster;\n\n        g.remove();\n\n        g = svg.append(\"g\")\n           .attr(\"transform\", \"translate(\" + radius + \",\" + radius + \")\");\n\n        if($scope.type == 'tree') {\n            nodes = tree.nodes(data);\n            links = tree.links(nodes);\n            diagonal = diagonalTree;\n            g.attr(\"transform\", \"translate(\" + 160 + \",\" + 0 + \")\");\n        }\n\n        var link = g.selectAll(\"path.link\")\n          .data(links)\n          .enter().append(\"path\")\n          .attr(\"class\", \"link\")\n          .attr(\"d\", diagonal);\n\n        var node = g.selectAll(\"g.node\")\n          .data(nodes)\n          .enter().append(\"g\")\n          .attr(\"class\", \"node\")\n          .attr(\"transform\", function(d) {\n            if ($scope.type == 'tree') {\n                return \"translate(\" + d.y + \",\" + d.x + \")\";\n            } else {\n                return \"rotate(\" + (d.x - 90) + \")translate(\" + d.y + \")\";\n            }\n\n          });\n\n        node.append(\"circle\")\n          .attr(\"r\", 4.5);\n\n        node.append(\"text\")\n          .attr(\"dy\", \".31em\")\n          .attr(\"dx\", function(d) {\n            if($scope.type == 'tree') {\n                return d.children ? -8 : 8;\n            } else {\n                return 0;\n            }\n          })\n          .attr(\"text-anchor\", function(d) {\n            if($scope.type == 'tree') {\n                return d.children ? \"end\" : \"start\";\n            } else {\n                return d.x < 180 ? \"start\" : \"end\";\n            }\n          })\n          .attr(\"transform\", function(d) {\n            if ($scope.type == 'tree') {\n                return \"\";\n            } else {\n                return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\";\n            }\n          })\n          .text(function(d) {\n            return d.name;\n          })\n          .attr(\"fill\", \"#000\")\n          .on(\"click\", function(d){\n              if(typeof d.url !== \"undefined\" ){\n                $window.open(d.url, \"_blank\");\n              }\n          }).on(\"mouseover\", function(d) {\n\n              //Update the tooltip position and value\n              d3.select(\"#tooltip\")\n                .style(\"left\", 10 + \"px\")\n                .style(\"top\", 40 + \"px\")\n                .select(\"#desc\")\n                .text(d.description)\n                \n              d3.select(\"#name\")\n                .text(d.name);\n \n              //Show the tooltip\n              d3.select(\"#tooltip\").classed(\"hidden\", false);\n           })\n           .on(\"mouseout\", function() {\n              d3.select(\"#tooltip\").classed(\"hidden\", true);\n           });\n      };\n\n      $scope.$watch('frontEndData', update);\n      $scope.$watch('type', update);\n      $scope.$watch('rotate', rotate);\n\n    };\n    return {\n      template: '<div></div>',\n      replace: true,\n      link: link,\n      restrict: 'E'\n    };\n  }\n]);"
  },
  {
    "path": "09-front-end-collect-master/qq.md",
    "content": "# QQ交流群规\n[在线地址](http://t.cn/Rw2qmAS) `http://t.cn/Rw2qmAS`\n\n这是一份公共的QQ交流规则，供各群主引用。规则会不断的修改调整，希望得到各个行业群主的支持。\n\n---\n\n\n###前言\n1. 宗旨：高效，高质量的交流，禁止无意义的闲扯，话题内容尽量保持在技术与职业相关范围内。原则上：白天上班时间禁止闲聊，业余时间话题可以稍为宽松。\n2. 随着群人数越来越多，为了使群的价值能够保持技术的高质量输送或新鲜度，也为了使新人能够快速的溶入这个团队，特编写此约定，希望大伙能够积极遵守或推进，谢谢各位的支持或厚爱。此群规是原来\n3. 此群规是待运行版，公布出之后默认是大伙已经阅读并认可通过，如有违反，可能采取相应的措施。我们的目的侧重于引导，并不是把谁要T出去，我们希望自此群规出台之后不要有一个人是被T出去的。\n4. 此群规也是引导大于惩罚，我们是前端相关从业人士，注重用户感知或行为约定，所以引导为辅，自觉为主。另外氛围还是需要大伙共同参与维护，我们鄙视每一个不尊重时间或浪费青春的人，我们希望在激情岁月里边能够留下成长的痕迹，我们希望这份共同的回忆能够N年后还能念念不忘或值得回忆。今天因为你在此群与各高手交流而感到自豪，明天此群因为有你的存在而感到骄傲，后天因为我们回忆中有你的身影而感到难忘。\n\n###一. 如何提问:\n1. 提问请提供重现问题场景的demo文件或在线url地址。(必须是完整的静态资源包，换个环境之后能够完整重现所说bug，如果团队对代码有保密要求，请找其它解决办法，不建议继续提问)。\n2. 文字描述不清的bug，建议发文件后用截图示意，明确表明某处某问题。\n3. 没有图片的代码建议发：\n- [Runjs](http://runjs.cn)\n- [Jsbin](http://jsbin.com)\n- [Jsbin 的用法](http://w3cshare.com/jsbin-editor/)\n4. 国内免费云引擎\n- [Sina云](http://sae.sina.com.cn/)\n优点：不需要手工发布，只需三级域名就可以访问，支持语言：php,python,java，\n缺点：需要身份证验证获取免费云豆\n版本控制工具：svn\n- [京东云](http://jae.jd.com/)\n优点：不需要身份验证，支持：java,php,nodejs,python,ruby\n缺点：需要在控制台手动发布才能在线上预览\n版本控制工具：git\n- [github](http://github.com)\n优点：注册即有，方便\n缺点：只支持静态\n版本控制工具：git\n\n###二. 禁问:\n\n- 早上问早，晚上道晚安。聊天起于问早，止于呵呵。\n- 有没有人在？\n- 谁能帮我解决一个问题？\n- 有没有jQuery高手在等？\n\n###三. 禁发:\n\n- 广告，求职，推广，八卦。\n- 尽量不要发无意义的大图片，建议发qq提供的默认的等于行距表情，约束这个目的在于：\n    1. 人脑对图片的接受速度明显快于文字，过多的无意义图片会分散讨论的主题。\n    2. 不方便回查，或聊天记录中寻找有价值的消息。\n    3. 另外这是一个信息爆炸时代，人脑的接收是有上限的，过多的垃圾信息会占用有限的带宽。\n- 尽量不要在群邮件中无意义回复，每次一个人回复是一次消息的广播，每个人都会收到，会产生信息垃圾。\n\n###四. 警告:\n\n- 字体在10-12号之间，字体颜色不建议特别刺眼的颜色。\n- 禁止闲聊，或无意义回复。\n- 提问之前最好百度，google过，着重培养的是一种能力或方法，不是一个结果。\n- 不建议直接索要代码，可以追问技术实现的思路或方法。\n\n###五. 综合类资源:\n\n- [前端知识体系](http://www.cnblogs.com/sb19871023/p/3894452.html)\n- [前端知识结构](https://github.com/JacksonTian/fks)\n- [免费的编程中文书籍索引](https://github.com/justjavac/free-programming-books-zh_CN)\n- [前端书籍](https://github.com/dypsilon/frontend-dev-bookmarks)\n\n###六. API:\n\n####1. jQuery\n\n* [jQuery API 中文文档](http://jquery.bootcss.com/)\n* [hemin 在线版](http://hemin.cn/jq/)\n* [css88 jq api](http://www.css88.com/jqapi-1.9/on/)\n* [css88 jqui api](http://www.css88.com/jquery-ui-api/)\n* [devdocs](http://devdocs.io/)\n* [jqschool](http://api.jq-school.com/)\n* [学习jquery](http://learn.jquery.com/)\n\n####2. Ecmascript\n\n- [阮一峰 es6](http://es6.ruanyifeng.com/)\n- [阮一峰 Javascript](http://javascript.ruanyifeng.com/)\n- [ECMA-262，第 5 版](http://yanhaijing.com/es5/)\n- [es5](http://es5.github.io/)\n\n####3. Js template\n\n- [artTemplate](https://github.com/aui/artTemplate)\n- [tomdjs](https://github.com/aui/tmodjs/blob/master/README.md)\n- [淘宝模板juicer模板](http://juicer.name/docs/docs_zh_cn.html)\n- [Fxtpl v1.0 繁星前端模板引擎](http://koen301.github.io/fxtpl/)\n- [laytpl](http://sentsin.com/layui/laytpl/)\n\n####4. 弹出层\n\n- [artDialog 最新版](https://github.com/aui/artDialog)\n- [artDialog 文档](http://aui.github.io/artDialog/doc/index.html)\n- [google code 下载地址](https://code.google.com/p/artdialog/downloads/list)\n- [贤心弹出层](http://sentsin.com/jquery/layer/)\n\n####5. Nodejs\n\n- [nodejs 篇幅比较巨大](http://liuqing.pw/)\n- [篇幅比较少](http://rainweb.cn/article/category/Nodejs)\n- [node express 入门教程](http://www.w3cfuns.com/article-5598538-1-1.html)\n- [nodejs定时任务](http://my.oschina.net/u/568264/blog/193773)\n- [一个nodejs博客](http://60sky.com/)\n- [【NodeJS 学习笔记04】新闻发布系统](http://www.cnblogs.com/yexiaochai/p/3536547.html)\n- [过年7天乐，学nodejs 也快乐](http://www.cnblogs.com/qqloving/p/3541099.html)\n- [七天学会NodeJS](https://github.com/nqdeng/7-days-nodejs)\n- [Nodejs学习笔记（二）--- 事件模块](http://www.cnblogs.com/zhongweiv/p/nodejs_events.html)\n- [nodejs入门](http://www.cnblogs.com/liusuqi/p/3735491.html)\n- [angularjs nodejs](https://github.com/zensh/jsgen)\n- [从零开始nodejs系列文章](http://blog.fens.me/series-nodejs/)\n- [理解nodejs](http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb)\n- [nodejs事件轮询](http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/)\n- [node入门](http://www.nodebeginner.org/index-zh-cn.html)\n- [nodejs cms](http://ourjs.com/detail/53e1f281c5910a9806000001)\n\n####6. Angularjs\n\n- [angularjs中文社区](http://angularjs.cn/)\n- [Angularjs源码学习](http://www.cnblogs.com/xuwenmin888/p/3739096.html)\n- [Angularjs源码学习](http://www.ifeenan.com/?c=AngularJS)\n- [angular对bootstrap的封装](http://angular-ui.github.io/bootstrap/)\n- [angularjs + nodejs](http://cnodejs.org/topic/51404e0f069911196d2e3923)\n- [吕大豹 Angularjs](http://www.cnblogs.com/lvdabao/tag/AngularJs/)\n- [AngularJS 最佳实践](http://www.infoq.com/cn/news/2013/02/angular-web-app)\n- [Angular的一些扩展指令](http://www.lovelucy.info/angularjs-best-practices.html)\n- [Angular数据绑定原理](https://github.com/Pasvaz/bindonce)\n- [一些扩展Angular UI组件](https://github.com/angular-ui/)\n- [Ember和AngularJS的性能测试](http://voidcanvas.com/emberjs-vs-angularjs-performance-testing/)\n- [带你走近AngularJS - 基本功能介绍](http://www.cnblogs.com/powertoolsteam/p/angularjs-introdection.html)\n- [Angularjs开发指南](http://angular.duapp.com/docs/guide)\n- [Angularjs学习](http://www.cnblogs.com/amosli/p/3710648.html)\n- [不要带着jQuery的思维去学习AngularJS](http://www.rainweb.cn/article/angularjs-jquery.html)\n- [angularjs 学习笔记](http://wangjiatao.diandian.com/?tag=angularjs)\n- [angularjs 开发指南](http://www.angularjs.cn/T008)\n- [angularjs 英文资料](https://github.com/jmcunningham/AngularJS-Learning)\n- [angular bootstrap](http://angular-ui.github.io/bootstrap/)\n- [angular jq mobile](https://github.com/opitzconsulting/jquery-mobile-angular-adapter)\n- [angular ui](http://mgcrea.github.io/angular-strap/)\n- [整合jQuery Mobile+AngularJS经验谈](http://www.tuicool.com/articles/7ZZVr2)\n- [有jQuery背景，该如何用AngularJS编程思想](http://blog.jobbole.com/46589/ )\n\n####7. 移动端API\n\n- [99移动端知识集合](https://github.com/jtyjty99999/mobileTech)\n- [司徒正美移动知识集合](https://github.com/RubyLouvre/mobileTech)\n- [移动端前端开发知识库](https://github.com/AlloyTeam/Mars)\n- [zepto 1.0 中文手册](http://mweb.baidu.com/zeptoapi/)\n- [zepto 1.0 中文手册](http://www.html-5.cn/Manual/Zepto/)\n- [zepto 1.1.2](http://www.css88.com/doc/zeptojs_api/)\n- [zepto 中文注释](http://www.cnblogs.com/sky000/archive/2013/03/29/2988952.html)\n- [jqmobile 手册](http://app-framework-software.intel.com/api.php)\n- [移动浏览器开发集合](https://github.com/maxzhang/maxzhang.github.com/issues)\n- [js移动调试](http://thx.github.io/mobile/debugging-in-mobile/)\n- [移动开发大杂烩](https://github.com/hoosin/mobile-web-favorites)\n\n####8. 图表类\n\n- [Highcharts 中文API](http://www.hcharts.cn/api/index.php)\n- [Highcharts 英文API](http://api.highcharts.com/highcharts)\n- [ECharts 百度的图表软件](http://echarts.baidu.com/ )\n- [高德地图](http://lbs.amap.com/api/)\n\n####9. Requriejs\n\n- [Javascript模块化编程（一）：模块的写法 ](http://www.ruanyifeng.com/blog/2012/10/javascript_module.html)\n- [Javascript模块化编程（二）：AMD规范](http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html)\n- [Javascript模块化编程（三）：require.js的用法](http://www.ruanyifeng.com/blog/2012/11/require_js.html)\n- [RequireJS入门（一）](http://www.cnblogs.com/snandy/archive/2012/05/22/2513652.html)\n- [RequireJS入门（二）](http://www.cnblogs.com/snandy/archive/2012/05/23/2513712.html)\n- [RequireJS进阶（三）](http://www.cnblogs.com/snandy/archive/2012/06/08/2538001.html)\n- [requrie源码学习](http://www.cnblogs.com/yexiaochai/p/3632580.html )\n- [requrie 入门指南](http://www.oschina.net/translate/getting-started-with-the-requirejs-library )\n- [requrieJS 学习笔记](http://www.cnblogs.com/yexiaochai/p/3214926.html )\n- [requriejs 其一 ](http://cyj.me/why-seajs/requirejs/ )\n- [require backbone结合](http://www.cnblogs.com/yexiaochai/p/3221081.html )\n\n####10. Seajs\n\n- [seajs](http://seajs.org/)\n- [seajs 中文手册](http://cyj.me/why-seajs/zh/)\n\n####11. less,sass\n\n- [less](http://less.bootcss.com/)\n- [sass](http://www.w3cplus.com/sassguide/)\n- [sass中国](http://www.cn-sass.com/)\n\n###七. 开发规范\n\n- [前端编码规范之js](http://yuwenhui.github.io/)\n- [前端编码规范之js](http://www.cnblogs.com/hustskyking/p/javascript-spec.html)\n- [最流行的PHP 代码规范](http://segmentfault.com/a/1190000000443795)\n- [最流行的PHP 代码规范](https://github.com/hfcorriez/fig-standards/blob/zh_CN/%E6%8E%A5%E5%8F%97/PSR-2-coding-style-guide.md)\n- [AMD与CMD规范的区别](http://www.zhihu.com/question/20351507)\n- [AMD与CMD规范的区别](http://www.cnblogs.com/tugenhua0707/p/3507957.html)\n- [KISSY 源码规范](http://docs.kissyui.com/1.4/docs/html/tutorials/style-guide/kissy-source-style.html)\n- [bt编码规范](http://codeguide.bootcss.com/)\n- [规范加强版](https://github.com/Suxiaogang/Code_Guide)\n- [前端代码规范 及 最佳实践](http://blog.jobbole.com/79075/)\n- [百度前端规范](http://coderlmn.github.io/code-standards/)\n- [百度前端规范](http://isobar-idev.github.io/code-standards/)\n- [百度前端规范](http://zhuanlan.zhihu.com/fuyun/19884834)\n- [【敏捷开发】Android团队开发规范](http://www.cnblogs.com/lcw/p/3619181.html)"
  },
  {
    "path": "10-awesome-fe-team-master/README.md",
    "content": "# Awesome Front-end Teams [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)\n\n国内知名 IT 公司前端团队 (排名不分先后)\n\n##### 百度 ( Baidu )\n\n- FEX: http://fex.baidu.com/ ( [GitHub](https://github.com/fex-team/) )\n- EFE: http://efe.baidu.com/ ( [GitHub](https://github.com/ecomfe) )\n\n##### 阿里巴巴 ( Alibaba )\n\n- FED (淘宝前端): http://taobaofed.org/ ( [GitHub](https://github.com/taobaofed) )\n- TaobaoUED (淘宝): http://ued.taobao.org/ \n- AMFE (淘宝手机前端): https://github.com/amfe/article\n- Alinode: http://alinode.aliyun.com/blog\n- TmallFE (天猫前端): https://tmallfe.github.io/\n- THX (阿里妈妈 MUX): http://thx.github.io/\n\n##### 腾讯 ( Tencent )\n\n- IMWeb: http://imweb.io/ ( [GitHub](https://github.com/imweb/) )\n- AlloyTeam: http://www.alloyteam.com/ ( [GitHub](https://github.com/alloyteam) )\n- ISUX: http://isux.tencent.com/\n- TID: http://tid.tenpay.com/\n\n##### 奇虎 360 ( Qihoo 360 )\n\n- 奇舞团: http://www.75team.com/ ( [GitHub](https://github.com/75team/) )\n\n##### 新浪 ( Sina )\n\n- 新浪 UED: http://ued.sina.com.cn/\n\n##### 京东 ( JD )\n\n- 凹凸实验室: http://aotu.io/ ( [GitHub](https://github.com/o2team/) )\n\n##### 美团 ( Meituan )\n\n- 美团前端: http://fe.meituan.com/\n\n##### 去哪儿 ( Qunar )\n\n- UED: http://ued.qunar.com/\n- MFE: http://ued.qunar.com/mobile/blog/\n\n##### 携程 ( Ctrip )\n\n- 携程设计委员会: http://ued.ctrip.com/\n\n##### 大搜车（Souche）\n\n- 大搜车前端团队：http://f2e.souche.com/blog/\n\n##### 豆瓣 ( Douban )\n\n- 豆瓣前端: https://github.com/douban-f2e\n"
  },
  {
    "path": "11-about-reading/Readme.md",
    "content": "\n<p class=\"lead\">昨天在一个爱折腾但对读书非常不屑的少年的博客下面评论了一些大牛们的读书单，然后今天又发现了一些，干脆就一起整理一下</p>\n\n**国外（排名不分先后）**\n\n- StackOverflow 上推荐读书排行榜：[http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read](http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read)\n- 《软件随想录》作者 Joel Spolsky 的书评：[http://www.joelonsoftware.com/navlinks/fog0000000262.html](http://www.joelonsoftware.com/navlinks/fog0000000262.html)\n- Rails 发明者 David Heinemeier Hansson (dhh) 推荐书籍：[https://signalvnoise.com/posts/3375-the-five-programming-books-that-meant-most-to-me](https://signalvnoise.com/posts/3375-the-five-programming-books-that-meant-most-to-me)\n- jQuery 核心成员 Addy Osmani 推荐书籍（JavaScript）：[https://plus.google.com/+AddyOsmani/posts/H3onog42Msj](https://plus.google.com/+AddyOsmani/posts/H3onog42Msj)\n- Google 大牛 Steve Yegge 推荐书籍：[https://sites.google.com/site/steveyegge2/ten-great-books](https://sites.google.com/site/steveyegge2/ten-great-books)\n- M$ 大牛 Scott Hanselman 推荐书籍：[http://www.hanselman.com/blog/SixEssentialLanguageAgnosticProgrammingBooks.aspx](http://www.hanselman.com/blog/SixEssentialLanguageAgnosticProgrammingBooks.aspx)\n- Stack Overflow 创始人 Jeff Atwood 谈读书：[http://blog.codinghorror.com/programmers-dont-read-books-but-you-should/](http://blog.codinghorror.com/programmers-dont-read-books-but-you-should/)\n- Stiff 对九位卓越程序员的采访：[http://blog.jobbole.com/27072/](http://blog.jobbole.com/27072/)\n\n**国内（排名不分先后）**\n\n- Livid：[https://book.douban.com/people/livid/](https://book.douban.com/people/livid/)\n- 阮一峰：[https://github.com/ruanyf/reading-list](https://github.com/ruanyf/reading-list)\n- Fenng：[http://book.douban.com/people/Fenng/](https://github.com/ruanyf/reading-list)\n- 陈皓：[http://book.douban.com/people/haoel/](http://book.douban.com/people/haoel/)\n- RednaxelaFX：[http://book.douban.com/people/RednaxelaFX/](http://book.douban.com/people/RednaxelaFX/)\n- vczh：[http://www.cppblog.com/vczh/archive/2013/03/24/198769.html](http://www.cppblog.com/vczh/archive/2013/03/24/198769.html)\n- 刘未鹏：[https://book.douban.com/people/pongba/](https://book.douban.com/people/pongba/)\n- 邹欣：[https://book.douban.com/people/xinz/](https://book.douban.com/people/xinz/)\n- Milo：[https://book.douban.com/people/miloyip/](https://book.douban.com/people/miloyip/)\n- 陈硕：[http://book.douban.com/people/solstice/](http://book.douban.com/people/solstice/)\n- 勾三股四：[http://book.douban.com/people/Jinjiang/](http://book.douban.com/people/Jinjiang/)\n- Cat：[http://book.douban.com/people/cat_hsfz/](http://book.douban.com/people/cat_hsfz/)\n- justjavac：[http://book.douban.com/people/justjavac/](http://book.douban.com/people/justjavac/)\n- Phodal：[https://book.douban.com/people/phodal/](https://book.douban.com/people/phodal/)\n- Tinyfool：[https://book.douban.com/people/tinyfool/](https://book.douban.com/people/tinyfool/)\n- Rei：[https://book.douban.com/people/chloerei/](https://book.douban.com/people/chloerei/)\n- 李华顺：[https://book.douban.com/people/huacnlee/](https://book.douban.com/people/huacnlee/)\n- Lucida：[http://lucida.me/blog/developer-reading-list/](http://lucida.me/blog/developer-reading-list/)\n\n**我关注的人（排名不分先后）**\n\n- 寻海：[http://book.douban.com/people/62719021/](http://book.douban.com/people/62719021/)\n- alsotang：[http://book.douban.com/people/alsotang/](http://book.douban.com/people/alsotang/)\n- 颜海镜：[http://book.douban.com/people/yanhaijing/](http://book.douban.com/people/yanhaijing/)\n- 张秋怡：[http://book.douban.com/people/joyee-cheung/](http://book.douban.com/people/joyee-cheung/)\n- kshift：[http://book.douban.com/people/kshift/](http://book.douban.com/people/kshift/)\n"
  },
  {
    "path": "12-JavaScript-project/README.md",
    "content": "Github个人收集的优秀JavaScript项目\n- [Angular和Webpack种子文件](https://github.com/AngularClass/angular2-webpack-starter)\n- [Fis3面向前端的工程构建系统](https://github.com/fex-team/fis3)\n- [Fis3 DEMO](https://github.com/fex-team/fis3-demo)\n- [前端JQuery系列：入门教程 | 源码剖析 | 框架设计 | 慕课网教程](https://github.com/JsAaron/jQuery)\n- [avalon框架](https://github.com/RubyLouvre/avalon)\n- [Microsoft ChakraCore 微软的Chakra引擎](https://github.com/Microsoft/ChakraCore)\n- [Quintus HTML游戏引擎](https://github.com/cykod/Quintus)\n- [一个用node.js搭建的有趣博客](https://github.com/STRML/strml.net)\n- [Web前端助手--FeHelper（Chrome扩展）](https://github.com/zxlie/FeHelper)\n- [百度前端技术学院](https://github.com/baidu-ife/ife)\n- [Cheerio（node.js中的jQuery）](https://github.com/cheeriojs/cheerio)\n- [nodejs的一个聊天软件 类似微信](https://github.com/BryanYang/freechat)\n- [使用html5和node.js构建的网易云音乐](https://github.com/stkevintan/Cube)\n- [babel ES6转换为ES5](https://github.com/babel/babel)\n- [一个JS富文本编辑器](https://github.com/fex-team/ueditor)\n- [一个JS脑图可视化工具](https://github.com/fex-team/kityminder-core)\n- [一个JS写的Flappy Bird Game](https://github.com/ellisonleao/clumsy-bird)\n- [一个JS写的GBA模拟器](https://github.com/taisel/IodineGBA)\n- [SegmentFault写的Markdown解析器](https://github.com/SegmentFault/HyperDown.js)\n- [基于node.js的Ghost博客](https://github.com/TryGhost/Ghost)\n- [学习react的demos](https://github.com/ruanyf/react-demos)\n"
  },
  {
    "path": "13-free-programming-books-zh_CN-master/.editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# http://editorconfig.org\n\nroot = true\n\n[*]\n# Change these settings to your own preference\nindent_style = space\nindent_size = 4\n\n# We recommend you to keep these unchanged\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\nindent_size = 2\n\n[{package.json,bower.json}]\nindent_size = 2\n"
  },
  {
    "path": "13-free-programming-books-zh_CN-master/.travis.yml",
    "content": "language: ruby\nrvm:\n  - 2.2\nbefore_script: gem install awesome_bot\n"
  },
  {
    "path": "13-free-programming-books-zh_CN-master/CONTRIBUTING.md",
    "content": "贡献者名单: https://github.com/justjavac/free-programming-books-zh_CN/graphs/contributors\n"
  },
  {
    "path": "13-free-programming-books-zh_CN-master/LICENSE",
    "content": "GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    {one line to give the program's name and a brief idea of what it does.}\n    Copyright (C) {year}  {name of author}\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    {project}  Copyright (C) {year}  {fullname}\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "13-free-programming-books-zh_CN-master/README.md",
    "content": "免费的编程中文书籍索引\n============================\n\n[![](https://img.shields.io/github/issues/justjavac/free-programming-books-zh_CN.svg)](https://github.com/justjavac/free-programming-books-zh_CN/issues)  [![](https://img.shields.io/github/forks/justjavac/free-programming-books-zh_CN.svg)](https://github.com/justjavac/free-programming-books-zh_CN/network) [![](https://img.shields.io/github/stars/justjavac/free-programming-books-zh_CN.svg)](https://github.com/justjavac/free-programming-books-zh_CN/stargazers) [![](https://travis-ci.org/justjavac/free-programming-books-zh_CN.svg?branch=master)](https://travis-ci.org/justjavac/free-programming-books-zh_CN) [![](https://img.shields.io/github/release/justjavac/free-programming-books-zh_CN.svg)](https://github.com/justjavac/free-programming-books-zh_CN/releases)\n\n免费的编程中文书籍索引，欢迎投稿。\n\n- 国外程序员在 [stackoverflow](http://stackoverflow.com/questions/1711/what-is-the-single-most-influential-book-every-programmer-should-read/1713%231713) 推荐的程序员必读书籍，[中文版](http://justjavac.com/other/2012/05/15/qualified-programmer-should-read-what-books.html \"一个合格的程序员应该读过哪些书\")。\n- [stackoverflow](http://stackoverflow.com/questions/38210/what-non-programming-books-should-programmers-read) 上的程序员应该阅读的非编程类书籍有哪些？ [中文版](what-non-programming-books-should-programmers-read.md)\n- [github](https://github.com/vhf/free-programming-books) 上的一个流行的编程书籍索引  [中文版](https://github.com/vhf/free-programming-books/blob/master/free-programming-books-zh.md)\n\n欢迎订阅我的微信公众帐号，只推送原创文字。欢迎扫描二维码订阅：\n\n![justjavac微信公众帐号](http://justjavac.com/assets/images/weixin-justjavac.jpg)\n\n感谢 [@siberiawolf](https://github.com/siberiawolf) 使用 Bootstrap 开发了网页版，地址：http://siberiawolf.com/free_programming/index.html\n\n## 参与交流\n\n欢迎大家将珍藏已久的经典免费书籍共享出来，您可以：\n\n* 使用 [Issues](https://github.com/justjavac/free-programming-books-zh_CN/issues) 以及 Pull Request\n\n贡献者名单: https://github.com/justjavac/free-programming-books-zh_CN/graphs/contributors\n\n## 目录\n\n* [语言无关类](#语言无关类)\n  * [操作系统](#操作系统)\n  * [智能系统](#智能系统)\n  * [分布式系统](#分布式系统)\n  * [编译原理](#编译原理)\n  * [函数式概念](#函数式概念)\n  * [计算机图形学](#计算机图形学)\n  * [WEB服务器](#web服务器)\n  * [版本控制](#版本控制)\n  * [编辑器](#编辑器)\n  * [NoSQL](#nosql)\n  * [PostgreSQL](#postgresql)\n  * [MySQL](#mysql)\n  * [管理和监控](#管理和监控)\n  * [项目相关](#项目相关)\n  * [设计模式](#设计模式)\n  * [Web](#web)\n  * [大数据](#大数据)\n  * [编程艺术](#编程艺术)\n  * [其它](#其它)\n\n* [语言相关类](#语言相关类)\n  * [Android](#android)\n  * [APP](#app)\n  * [AWK](#awk)\n  * [C/C++](#cc)\n  * [C#](#c)\n  * [Clojure](#clojure)\n  * [CSS/HTML](#csshtml)\n  * [Dart](#dart)\n  * [Elixir](#elixir)\n  * [Erlang](#erlang)\n  * [Fortran](#fortran)\n  * [Go](#go)\n  * [Groovy](#groovy)\n  * [Haskell](#haskell)\n  * [iOS](#ios)\n  * [Java](#java)\n  * [JavaScript](#javascript)\n  * [LaTeX](#latex)\n  * [LISP](#lisp)\n  * [Lua](#lua)\n  * [OCaml](#OCaml)\n  * [Perl](#perl)\n  * [PHP](#php)\n  * [Prolog](#prolog)\n  * [Python](#python)\n  * [R](#r)\n  * [Ruby](#ruby)\n  * [Rust](#rust)\n  * [Scala](#scala)\n  * [Shell](#shell)\n  * [Swift](#swift)\n\n* [读书笔记及其它](#读书笔记及其它)\n* [测试相关](#测试相关)\n\n## 语言无关类\n\n### 操作系统\n\n* [开源世界旅行手册](http://i.linuxtoy.org/docs/guide/index.html)\n* [鸟哥的Linux私房菜](http://vbird.dic.ksu.edu.tw/)\n* [The Linux Command Line](http://billie66.github.io/TLCL/index.html) (中英文版)\n* [Linux 设备驱动](http://oss.org.cn/kernel-book/ldd3/index.html) (第三版)\n* [深入分析Linux内核源码](http://www.kerneltravel.net/kernel-book/%E6%B7%B1%E5%85%A5%E5%88%86%E6%9E%90Linux%E5%86%85%E6%A0%B8%E6%BA%90%E7%A0%81.html)\n* [UNIX TOOLBOX](http://cb.vu/unixtoolbox_zh_CN.xhtml)\n* [Docker中文指南](https://github.com/widuu/chinese_docker)\n* [Docker —— 从入门到实践](https://github.com/yeasy/docker_practice)\n* [Docker入门实战](http://yuedu.baidu.com/ebook/d817967416fc700abb68fca1)\n* [Docker Cheat Sheet](https://github.com/wsargent/docker-cheat-sheet/tree/master/zh-cn#docker-cheat-sheet)\n* [FreeRADIUS新手入门](http://freeradius.akagi201.org)\n* [Mac 开发配置手册](https://aaaaaashu.gitbooks.io/mac-dev-setup/content/)\n* [FreeBSD 使用手册](https://www.freebsd.org/doc/zh_CN/books/handbook/index.html)\n* [Linux 命令行(中文版)](http://billie66.github.io/TLCL/book/)\n* [Linux 构建指南](http://works.jinbuguo.com/lfs/lfs62/index.html)\n* [Linux工具快速教程](https://github.com/me115/linuxtools_rst)\n* [Linux Documentation (中文版)](https://www.gitbook.com/book/tinylab/linux-doc/details)\n* [嵌入式 Linux 知识库 (eLinux.org 中文版)](https://www.gitbook.com/book/tinylab/elinux/details)\n* [理解Linux进程](https://github.com/tobegit3hub/understand_linux_process)\n* [命令行的艺术](https://github.com/jlevy/the-art-of-command-line/blob/master/README-zh.md)\n* [SystemTap新手指南](https://spacewander.gitbooks.io/systemtapbeginnersguide_zh/content/index.html)\n* [操作系统思考](https://github.com/wizardforcel/think-os-zh)\n\n#### 智能系统\n* [一步步搭建物联网系统](https://github.com/phodal/designiot)\n\n### 分布式系统\n* [走向分布式](http://dcaoyuan.github.io/papers/pdfs/Scalability.pdf)\n\n### 编译原理\n* [《计算机程序的结构和解释》公开课 翻译项目](https://github.com/DeathKing/Learning-SICP)\n\n### 函数式概念\n* [傻瓜函数编程](https://github.com/justinyhuang/Functional-Programming-For-The-Rest-of-Us-Cn)\n\n### 计算机图形学\n* [OpenGL 教程](https://github.com/zilongshanren/opengl-tutorials)\n* [WebGL自学网](http://html5.iii.org.tw/course/webgl/)\n\n### WEB服务器\n\n* [Nginx开发从入门到精通](http://tengine.taobao.org/book/index.html) (淘宝团队出品)\n* [Nginx教程从入门到精通](http://www.ttlsa.com/nginx/nginx-stu-pdf/)(PDF版本，运维生存时间出品)\n* [OpenResty最佳实践](https://www.gitbook.com/book/moonbingbing/openresty-best-practices/details)\n* [Apache 中文手册](http://works.jinbuguo.com/apache/menu22/index.html)\n\n### 版本控制\n\n* [Git教程](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) （本文由 [廖雪峰](http://www.liaoxuefeng.com) 创作，如果觉得本教程对您有帮助，可以去 [iTunes](https://itunes.apple.com/cn/app/git-jiao-cheng/id876420437) 购买）\n* [git - 简易指南](http://rogerdudler.github.io/git-guide/index.zh.html)\n* [猴子都能懂的GIT入门](http://backlogtool.com/git-guide/cn/)\n* [Git 参考手册](http://gitref.justjavac.com)\n* [Pro Git](http://git-scm.com/book/zh/v2)\n* [Pro Git 中文版](https://www.gitbook.com/book/0532/progit/details) (整理在gitbook上)\n* [Git Magic](http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/)\n* [GotGitHub](http://www.worldhello.net/gotgithub/index.html)\n* [Git权威指南](http://www.worldhello.net/gotgit/)\n* [Git Community Book 中文版](http://gitbook.liuhui998.com/index.html)\n* [Mercurial 使用教程](https://www.mercurial-scm.org/wiki/ChineseTutorial)\n* [HgInit (中文版)](http://bucunzai.net/hginit/)\n* [沉浸式学 Git](http://igit.linuxtoy.org)\n* [Git-Cheat-Sheet](https://github.com/flyhigher139/Git-Cheat-Sheet) （感谢 @flyhigher139 翻译了中文版）\n* [GitHub秘籍](https://snowdream86.gitbooks.io/github-cheat-sheet/content/zh/index.html)\n* [GitHub帮助文档](https://github.com/waylau/github-help)\n* [git-flow 备忘清单](http://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.html)\n* [svn 手册](http://svnbook.red-bean.com/nightly/zh/index.html)\n* [GitHub漫游指南](https://github.com/phodal/github-roam)\n\n### 编辑器\n\n* [exvim--vim 改良成IDE项目](http://exvim.github.io/docs-zh/intro/)\n* [笨方法学Vimscript 中译本](http://learnvimscriptthehardway.onefloweroneworld.com/)\n* [Vim中文文档](https://github.com/vimcn/vimcdoc)\n* [所需即所获：像 IDE 一样使用 vim](https://github.com/yangyangwithgnu/use_vim_as_ide)\n* [Atom飞行手册中文版](https://github.com/wizardforcel/atom-flight-manual-zh-cn)\n* [Markdown·简单的世界](https://github.com/wizardforcel/markdown-simple-world)\n* [一年成为 Emacs 高手](https://github.com/redguardtoo/mastering-emacs-in-one-year-guide/blob/master/guide-zh.org)\n* [Emacs 生存指南](http://lifegoo.pluskid.org/upload/blog/152/Survive.in.Emacs.pdf)\n* [Atom官方手册](https://atom-china.org/t/atom/62)\n\n### NoSQL\n\n* [NoSQL数据库笔谈](http://old.sebug.net/paper/databases/nosql/Nosql.html)\n* [Redis 设计与实现](http://redisbook.com/)\n* [Redis 命令参考](http://redisdoc.com/)\n* [带有详细注释的 Redis 3.0 代码](https://github.com/huangz1990/redis-3.0-annotated)\n* [带有详细注释的 Redis 2.6 代码](https://github.com/huangz1990/annotated_redis_source)\n* [The Little MongoDB Book](https://github.com/justinyhuang/the-little-mongodb-book-cn/blob/master/mongodb.md)\n* [The Little Redis Book](https://github.com/JasonLai256/the-little-redis-book/blob/master/cn/redis.md)\n* [Neo4j 简体中文手册 v1.8](http://docs.neo4j.org.cn/)\n* [Neo4j .rb 中文資源](http://neo4j.tw/)\n* [Disque 使用教程](http://disquebook.com)\n* [Apache Spark 设计与实现](https://github.com/JerryLead/SparkInternals/tree/master/markdown)\n\n### PostgreSQL\n\n* [PostgreSQL 8.2.3 中文文档](http://works.jinbuguo.com/postgresql/menu823/index.html)\n* [PostgreSQL 9.3.1 中文文档](http://www.postgres.cn/docs/9.3/index.html)\n* [PostgreSQL 9.5.3 中文文档](http://www.postgres.cn/docs/9.5/index.html)\n\n### MySQL\n\n* [MySQL索引背后的数据结构及算法原理](http://blog.codinglabs.org/articles/theory-of-mysql-index.html)\n* [21分钟MySQL入门教程](http://www.cnblogs.com/mr-wid/archive/2013/05/09/3068229.html)\n\n### 管理和监控\n\n* [ELKstack 中文指南](http://kibana.logstash.es)\n* [Mastering Elasticsearch(中文版)](http://udn.yyuap.com/doc/mastering-elasticsearch/)\n* [ElasticSearch 权威指南](https://www.gitbook.com/book/fuxiaopang/learnelasticsearch/details)\n* [Elasticsearch 权威指南（中文版）](http://es.xiaoleilu.com)\n* [Logstash 最佳实践](https://github.com/chenryn/logstash-best-practice-cn)\n* [Puppet 2.7 Cookbook 中文版](http://bbs.konotes.org/workdoc/puppet-27/)\n\n### 项目相关\n\n* [持续集成（第二版）](http://article.yeeyan.org/view/2251/94882) (译言网)\n* [让开发自动化系列专栏](http://www.ibm.com/developerworks/cn/java/j-ap/)\n* [追求代码质量](http://www.ibm.com/developerworks/cn/java/j-cq/)\n* [selenium 中文文档](https://github.com/fool2fish/selenium-doc)\n* [Selenium Webdriver 简易教程](http://it-ebooks.flygon.net/selenium-simple-tutorial/)\n* [Joel谈软件](http://local.joelonsoftware.com/wiki/Chinese_\\(Simplified\\))\n* [約耳談軟體(Joel on Software)](http://local.joelonsoftware.com/wiki/%E9%A6%96%E9%A0%81)\n* [Gradle 2 用户指南](https://github.com/waylau/Gradle-2-User-Guide)\n* [Gradle 中文使用文档](http://yuedu.baidu.com/ebook/f23af265998fcc22bcd10da2)\n* [编码规范](https://github.com/ecomfe/spec)\n* [开源软件架构](http://www.ituring.com.cn/book/1143)\n* [GNU make 指南](http://docs.huihoo.com/gnu/linux/gmake.html)\n* [GNU make 中文手册](http://www.yayu.org/book/gnu_make/)\n* [The Twelve-Factor App](http://12factor.net/zh_cn/)\n\n### 设计模式\n\n* [图说设计模式](https://github.com/me115/design_patterns)\n* [史上最全设计模式导学目录](http://blog.csdn.net/lovelion/article/details/17517213)\n* [design pattern 包教不包会](https://github.com/AlfredTheBest/Design-Pattern)\n* [设计模式 Java 版](https://quanke.gitbooks.io/design-pattern-java/content/)\n\n### Web\n\n* [关于浏览器和网络的 20 项须知](http://www.20thingsilearned.com/zh-CN/home)\n* [浏览器开发工具的秘密](http://jinlong.github.io/2013/08/29/devtoolsecrets/)\n* [Chrome 开发者工具中文手册](https://github.com/CN-Chrome-DevTools/CN-Chrome-DevTools)\n* [Chrome扩展开发文档](http://open.chrome.360.cn/extension_dev/overview.html)\n* [Grunt中文文档](http://www.gruntjs.net/)\n* [gulp中文文档](http://www.gulpjs.com.cn/docs/)\n* [Gulp 入门指南](https://github.com/nimojs/gulp-book)\n* [移动Web前端知识库](https://github.com/AlloyTeam/Mars)\n* [正则表达式30分钟入门教程](http://deerchao.net/tutorials/regex/regex.htm)\n* [前端开发体系建设日记](https://github.com/fouber/blog/issues/2)\n* [移动前端开发收藏夹](https://github.com/hoosin/mobile-web-favorites)\n* [JSON风格指南](https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md)\n* [HTTP 接口设计指北](https://github.com/bolasblack/http-api-guide)\n* [前端资源分享（一）](https://github.com/hacke2/hacke2.github.io/issues/1)\n* [前端资源分享（二）](https://github.com/hacke2/hacke2.github.io/issues/3)\n* [前端代码规范 及 最佳实践](http://coderlmn.github.io/code-standards/)\n* [前端开发者手册](https://www.gitbook.com/book/dwqs/frontenddevhandbook/details)\n* [前端工程师手册](https://www.gitbook.com/book/leohxj/front-end-database/details)\n* [w3school教程整理](https://github.com/wizardforcel/w3school)\n* [Wireshark用户手册](http://man.lupaworld.com/content/network/wireshark/index.html)\n* [一站式学习Wireshark](https://community.emc.com/thread/194901)\n* [HTTP 下午茶](http://happypeter.github.io/tealeaf-http/)\n* [HTTP/2.0 中文翻译](http://yuedu.baidu.com/ebook/478d1a62376baf1ffc4fad99?pn=1)\n* [RFC 7540 - HTTP/2 中文翻译版](https://github.com/abbshr/rfc7540-translation-zh_cn)\n* [http2讲解](https://www.gitbook.com/book/ye11ow/http2-explained/details)\n* [3 Web Designs in 3 Weeks](https://www.gitbook.com/book/juntao/3-web-designs-in-3-weeks/details)\n* [站点可靠性工程](https://github.com/hellorocky/Site-Reliability-Engineering)\n\n### 大数据\n\n* [大数据/数据挖掘/推荐系统/机器学习相关资源](https://github.com/Flowerowl/Big-Data-Resources)\n* [面向程序员的数据挖掘指南](https://github.com/egrcc/guidetodatamining)\n* [大型集群上的快速和通用数据处理架构](https://code.csdn.net/CODE_Translation/spark_matei_phd)\n* [数据挖掘中经典的算法实现和详细的注释](https://github.com/linyiqun/DataMiningAlgorithm)\n* [Spark 编程指南简体中文版](https://aiyanbo.gitbooks.io/spark-programming-guide-zh-cn/content/)\n\n## 编程艺术\n\n* [程序员编程艺术](https://github.com/julycoding/The-Art-Of-Programming-by-July)\n* [每个程序员都应该了解的内存知识(译)](http://www.oschina.net/translate/what-every-programmer-should-know-about-memory-part1?print)【第一部分】\n* [取悦的工序：如何理解游戏](http://read.douban.com/ebook/4972883/) (豆瓣阅读，免费书籍)\n\n## 其它\n\n* [OpenWrt智能、自动、透明翻墙路由器教程](https://www.gitbook.com/book/softwaredownload/openwrt-fanqiang/details)\n* [SAN 管理入门系列](https://community.emc.com/docs/DOC-16067)\n* [Sketch 中文手册](http://sketchcn.com/sketch-chinese-user-manual.html#introduce)\n* [深入理解并行编程](http://ifeve.com/perfbook/)\n* [程序员的自我修养](http://www.kancloud.cn/kancloud/a-programmer-prepares)\n* [Growth: 全栈增长工程师指南](https://github.com/phodal/growth-ebook)\n\n## 语言相关类\n\n### Android\n\n* [Android Design(中文版)](http://www.apkbus.com/design/index.html)\n* Google Material Design 正體中文版 ([译本一](https://wcc723.gitbooks.io/google_design_translate/content/style-icons.html) [译本二](https://github.com/1sters/material_design_zh))\n* [Material Design 中文版](http://wiki.jikexueyuan.com/project/material-design/)\n* [Google Android官方培训课程中文版](http://hukai.me/android-training-course-in-chinese/index.html)\n* [Android学习之路](http://www.stormzhang.com/android/2014/07/07/learn-android-from-rookie/)\n* [Android开发技术前线(android-tech-frontier)](https://github.com/bboyfeiyu/android-tech-frontier)\n* [Point-of-Android](https://github.com/FX-Max/Point-of-Android) Android 一些重要知识点解析整理\n* [Android6.0新特性详解](http://leanote.com/blog/post/561658f938f41126b2000298?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io)\n\n### APP\n\n* [Apache Cordova 开发指南](https://github.com/waylau/cordova-dev-guide)\n\n### AWK\n\n* [awk程序设计语言](https://github.com/wuzhouhui/awk)\n* [awk中文指南](http://awk.readthedocs.org/en/latest/index.html)\n\n### C/C++\n\n* [C/C++ 中文参考手册](http://zh.cppreference.com/) (欢迎大家参与在线翻译和校对)\n* [C 语言编程透视](https://www.gitbook.com/book/tinylab/cbook/details)\n* [C++ 并发编程指南](https://github.com/forhappy/Cplusplus-Concurrency-In-Practice)\n* [Linux C编程一站式学习](http://akaedu.github.io/book/) (宋劲杉, 北京亚嵌教育研究中心)\n* [CGDB中文手册](https://github.com/leeyiw/cgdb-manual-in-chinese)\n* [100个gdb小技巧](https://github.com/hellogcc/100-gdb-tips/blob/master/src/index.md)\n* [100个gcc小技巧](https://github.com/hellogcc/100-gcc-tips/blob/master/src/index.md)\n* [ZMQ 指南](https://github.com/anjuke/zguide-cn)\n* [How to Think Like a Computer Scientist](http://www.ituring.com.cn/book/1203) (中英文版)\n* [跟我一起写Makefile(PDF)](http://scc.qibebt.cas.cn/docs/linux/base/%B8%FA%CE%D2%D2%BB%C6%F0%D0%B4Makefile-%B3%C2%F0%A9.pdf)\n* [GNU make中文手册](http://www.yayu.org/book/gnu_make/)\n* [GNU make 指南](http://docs.huihoo.com/gnu/linux/gmake.html)\n* [Google C++ 风格指南](http://zh-google-styleguide.readthedocs.org/en/latest/google-cpp-styleguide/contents/)\n* [C/C++ Primer](https://github.com/andycai/cprimer) (by @andycai)\n* [简单易懂的C魔法](http://www.nowamagic.net/librarys/books/contents/c)\n* [Cmake 实践](http://sewm.pku.edu.cn/src/paradise/reference/CMake%20Practice.pdf) (PDF版)\n* [C++ FAQ LITE(中文版)](http://www.sunistudio.com/cppfaq/)\n* [C++ Primer 5th Answers](https://github.com/Mooophy/Cpp-Primer)\n* [C++ 并发编程(基于C++11)](https://www.gitbook.com/book/chenxiaowei/cpp_concurrency_in_action/details)\n* [QT 教程](http://www.kuqin.com/qtdocument/tutorial.html)\n* [DevBean的《Qt学习之路2》(Qt5)](http://www.devbean.net/category/qt-study-road-2/)\n* [C++ Template 进阶指南](https://github.com/wuye9036/CppTemplateTutorial)\n* [libuv中文教程](https://github.com/luohaha/Chinese-uvbook)\n* [Boost 库中文教程](http://zh.highscore.de/cpp/boost/)\n* [笨办法学C](https://github.com/wizardforcel/lcthw-zh)\n\n### C&#35;\n\n* [MSDN C# 中文文档](https://msdn.microsoft.com/zh-cn/library/kx37x362.aspx)\n* [.NET 类库参考](https://msdn.microsoft.com/zh-cn/library/gg145045.aspx)\n* [ASP.NET MVC 5 入门指南](http://www.cnblogs.com/powertoolsteam/p/aspnetmvc5-tutorials-grapecity.html)\n* [超全面的 .NET GDI+ 图形图像编程教程](http://www.cnblogs.com/LonelyShadow/p/4162318.html)\n* [.NET控件开发基础](https://github.com/JackWangCUMT/customcontrol)\n* [.NET开发要点精讲（初稿）](https://github.com/sherlockchou86/-free-ebook-.NET-)\n\n### Clojure\n\n* [Clojure入门教程](http://xumingming.sinaapp.com/302/clojure-functional-programming-for-the-jvm-clojure-tutorial/)\n\n<h3 id=\"csshtml\">CSS/HTML</h3>\n\n* [学习CSS布局](http://zh.learnlayout.com/)\n* [通用 CSS 笔记、建议与指导](https://github.com/chadluo/CSS-Guidelines/blob/master/README.md)\n* [CSS参考手册](http://css.doyoe.com/)\n* [Emmet 文档](http://yanxyz.github.io/emmet-docs/)\n* [前端代码规范](http://alloyteam.github.io/CodeGuide/) (腾讯 AlloyTeam 团队)\n* [HTML和CSS编码规范](http://codeguide.bootcss.com/)\n* [Sass Guidelines 中文](http://sass-guidelin.es/zh/)\n* [CSS3 Tutorial 《CSS3 教程》](https://github.com/waylau/css3-tutorial)\n* [MDN HTML 中文文档](https://developer.mozilla.org/zh-CN/docs/Web/HTML)\n* [MDN CSS 中文文档](https://developer.mozilla.org/zh-CN/docs/Web/CSS)\n\n### Dart\n\n* [Dart 语言导览](http://dart.lidian.info/wiki/Language_Tour)\n\n### Elixir\n\n* [Elixir编程入门](https://github.com/straightdave/programming_elixir)\n\n### Erlang\n\n* [21天学通Erlang](http://xn--21erlang-p00o82pmp3o.github.io/)\n\n### Fortran\n\n* [Fortran77和90/95编程入门](http://micro.ustc.edu.cn/Fortran/ZJDing/)\n\n### Go\n\n* [Go编程基础](https://github.com/Unknwon/go-fundamental-programming)\n* [Go入门指南](https://github.com/Unknwon/the-way-to-go_ZH_CN)\n* [学习Go语言](http://mikespook.com/learning-go/)\n* [Go Web 编程](https://github.com/astaxie/build-web-application-with-golang) (此书已经出版，希望开发者们去购买，支持作者的创作)\n* [Go实战开发](https://github.com/astaxie/Go-in-Action) (当我收录此项目时，作者已经写完第三章，如果读完前面章节觉得有帮助，可以给作者[捐赠](https://me.alipay.com/astaxie)，以鼓励作者的继续创作)\n* [Network programming with Go 中文翻译版本](https://github.com/astaxie/NPWG_zh)\n* [Effective Go](http://www.hellogcc.org/effective_go.html)\n* [Go 语言标准库](https://github.com/polaris1119/The-Golang-Standard-Library-by-Example)\n* [Golang标准库文档](http://godoc.ml/)\n* [Revel 框架手册](http://gorevel.cn/docs/manual/index.html)\n* [Java程序员的Golang入门指南](http://blog.csdn.net/dc_726/article/details/46565241)\n* [Go命令教程](https://github.com/hyper-carrot/go_command_tutorial)\n* [Go语言博客实践](https://github.com/achun/Go-Blog-In-Action)\n* [Go 官方文档翻译](https://github.com/golang-china/golangdoc.translations)\n* [深入解析Go](https://github.com/tiancaiamao/go-internals)\n* [Go语言圣经(中文版)](https://bitbucket.org/golang-china/gopl-zh/wiki/Home) ([GitBook](https://www.gitbook.com/book/wizardforcel/gopl-zh/details))\n\n### Groovy\n\n* [实战 Groovy 系列](http://www.ibm.com/developerworks/cn/java/j-pg/)\n\n### Haskell\n\n* [Real World Haskell 中文版](http://rwh.readthedocs.org/en/latest/)\n* [Haskell趣学指南](http://fleurer-lee.com/lyah/)\n\n### iOS\n\n* [iOS开发60分钟入门](https://github.com/qinjx/30min_guides/blob/master/ios.md)\n* [iOS7人机界面指南](http://isux.tencent.com/ios-human-interface-guidelines-ui-design-basics-ios7.html)\n* [Google Objective-C Style Guide 中文版](http://zh-google-styleguide.readthedocs.org/en/latest/google-objc-styleguide/)\n* [iPhone 6 屏幕揭秘](http://wileam.com/iphone-6-screen-cn/)\n* [Apple Watch开发初探](http://nilsun.github.io/apple-watch/)\n* [马上着手开发 iOS 应用程序](https://developer.apple.com/library/ios/referencelibrary/GettingStarted/RoadMapiOSCh/index.html)\n* [网易斯坦福大学公开课：iOS 7应用开发字幕文件](https://github.com/jkyin/Subtitle)\n\n### Java\n\n* [Apache Shiro 用户指南](https://github.com/waylau/apache-shiro-1.2.x-reference)\n* [Jersey 2.x 用户指南](https://github.com/waylau/Jersey-2.x-User-Guide)\n* [Spring Framework 4.x参考文档](https://github.com/waylau/spring-framework-4-reference)\n* [Spring Boot参考指南](https://github.com/qibaoguang/Spring-Boot-Reference-Guide) (翻译中)\n* [MyBatis中文文档](http://mybatis.org/mybatis-3/zh/index.html)\n* [MyBatis Generator 中文文档](http://mbg.cndocs.tk/)\n* [用jersey构建REST服务](https://github.com/waylau/RestDemo)\n* [Activiti 5.x 用户指南](https://github.com/waylau/activiti-5.x-user-guide)\n* [Google Java编程风格指南](http://www.hawstein.com/posts/google-java-style.html)\n* [Netty 4.x 用户指南](https://github.com/waylau/netty-4-user-guide)\n* [Netty 实战(精髓)](https://github.com/waylau/essential-netty-in-action)\n* [REST 实战](https://github.com/waylau/rest-in-action)\n* [Java 编码规范](https://github.com/waylau/java-code-conventions)\n* [Apache MINA 2 用户指南](https://github.com/waylau/apache-mina-2.x-user-guide)\n* [H2 Database 教程](https://github.com/waylau/h2-database-doc)\n* [Java Servlet 3.1 规范](https://github.com/waylau/servlet-3.1-specification)\n* [JSSE 参考指南](https://github.com/waylau/jsse-reference-guide)\n* [Java开源实现及最佳实践](https://github.com/biezhi/jb)\n* [Java 编程要点](https://github.com/waylau/essential-java)\n* [Think Java](http://www.ituring.com.cn/minibook/69)\n* [Java 8 简明教程](https://github.com/wizardforcel/modern-java-zh)\n\n### JavaScript\n\n* [Google JavaScript 代码风格指南](http://bq69.com/blog/articles/script/868/google-javascript-style-guide.html)\n* [Google JSON 风格指南](https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md)\n* [Airbnb JavaScript 规范](https://github.com/adamlu/javascript-style-guide)\n* [JavaScript 标准参考教程（alpha）](http://javascript.ruanyifeng.com/)\n* [Javascript编程指南](http://pij.robinqu.me/) ([源码](https://github.com/RobinQu/Programing-In-Javascript))\n* [javascript 的 12 个怪癖](https://github.com/justjavac/12-javascript-quirks)\n* [JavaScript 秘密花园](http://bonsaiden.github.io/JavaScript-Garden/zh/)\n* [JavaScript核心概念及实践](http://icodeit.org/jsccp/) (PDF) (此书已由人民邮电出版社出版发行，但作者依然免费提供PDF版本，希望开发者们去购买，支持作者)\n* [《JavaScript 模式》](https://github.com/jayli/javascript-patterns) “JavaScript patterns”中译本\n* [命名函数表达式探秘](http://justjavac.com/named-function-expressions-demystified.html)  (注:原文由[为之漫笔](http://www.cn-cuckoo.com)翻译，原始地址无法打开，所以此处地址为我博客上的备份)\n* [学用 JavaScript 设计模式](http://www.oschina.net/translate/learning-javascript-design-patterns) (开源中国)\n* [深入理解JavaScript系列](http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html)   \n* [ECMAScript 5.1 中文版](http://yanhaijing.com/es5)   \n* [ECMAScript 6 入门](http://es6.ruanyifeng.com/) (作者：阮一峰)\n* [JavaScript Promise迷你书](http://liubin.github.io/promises-book/)\n* [You-Dont-Know-JS](https://github.com/getify/You-Dont-Know-JS) (深入JavaScript语言核心机制的系列图书)\n* [JavaScript 教程](http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000) 廖雪峰\n* [MDN JavaScript 中文文档](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)\n* jQuery\n    * [jQuery 解构](http://www.cn-cuckoo.com/deconstructed/jquery.html)\n    * [简单易懂的JQuery魔法](http://www.nowamagic.net/librarys/books/contents/jquery)\n    * [How to write jQuery plugin](http://i5ting.github.io/How-to-write-jQuery-plugin/build/jquery.plugin.html)\n    * [You Don't Need jQuery](https://github.com/oneuijs/You-Dont-Need-jQuery/blob/master/README.zh-CN.md)\n    * [如何实现一个类jQuery？](https://github.com/MeCKodo/forchange)\n* Node.js\n    * [Node入门](http://www.nodebeginner.org/index-zh-cn.html)\n    * [七天学会NodeJS](http://nqdeng.github.io/7-days-nodejs/)\n    * [Nodejs Wiki Book](https://github.com/nodejs-tw/nodejs-wiki-book) (繁体中文)\n    * [express.js 中文文档](http://expressjs.jser.us/)\n    * [koa 中文文档](https://github.com/guo-yu/koa-guide)\n    * [一起学koa](http://base-n.github.io/koa-generator-examples/)\n    * [使用 Express + MongoDB 搭建多人博客](https://github.com/nswbmw/N-blog)\n    * [Express框架](http://javascript.ruanyifeng.com/nodejs/express.html)\n    * [Node.js 包教不包会](https://github.com/alsotang/node-lessons)\n    * [Learn You The Node.js For Much Win! (中文版)](https://www.npmjs.com/package/learnyounode-zh-cn)\n    * [Node debug 三法三例](http://i5ting.github.io/node-debug-tutorial/)\n    * [nodejs中文文档](https://www.gitbook.com/book/0532/nodejs/details)\n    * [orm2 中文文档](https://github.com/wizardforcel/orm2-doc-zh-cn)\n* underscore.js\n    * [Underscore.js中文文档](http://learningcn.com/underscore/)\n* backbone.js\n    * [backbone.js中文文档](http://www.css88.com/doc/backbone/)\n    * [backbone.js入门教程](http://www.the5fire.com/backbone-js-tutorials-pdf-download.html) (PDF)\n    * [Backbone.js入门教程第二版](https://github.com/the5fire/backbonejs-learning-note)\n    * [Developing Backbone.js Applications(中文版)](http://feliving.github.io/developing-backbone-applications/)\n* AngularJS\n    * [AngularJS最佳实践和风格指南](https://github.com/mgechev/angularjs-style-guide/blob/master/README-zh-cn.md)\n    * [AngularJS中译本](https://github.com/peiransun/angularjs-cn)\n    * [AngularJS入门教程](https://github.com/zensh/AngularjsTutorial_cn)\n    * [构建自己的AngularJS](https://github.com/xufei/Make-Your-Own-AngularJS/blob/master/01.md)\n    * [在Windows环境下用Yeoman构建AngularJS项目](http://www.waylau.com/build-angularjs-app-with-yeoman-in-windows/)\n* Zepto.js\n    * [Zepto.js 中文文档](http://mweb.baidu.com/zeptoapi/)\n* Sea.js\n    * [Hello Sea.js](http://island205.com/HelloSea.js/)\n* React.js\n    * [React.js 中文文档](http://reactjs.cn/)\n    * [React webpack-cookbook](https://github.com/fakefish/react-webpack-cookbook)\n    * [React 入门教程](http://fraserxu.me/intro-to-react/)\n    * [React Native 中文文档(含最新Android内容)](http://wiki.jikexueyuan.com/project/react-native/)\n    * [Learn React & Webpack by building the Hacker News front page](https://github.com/theJian/build-a-hn-front-page)\n* impress.js\n    * [impress.js的中文教程](https://github.com/kokdemo/impress.js-tutorial-in-Chinese)\n* CoffeeScript\n    * [CoffeeScript Cookbook](http://island205.com/coffeescript-cookbook.github.com/)\n    * [The Little Book on CoffeeScript中文版](http://island205.com/tlboc/)\n    * [CoffeeScript 编码风格指南](https://github.com/geekplux/coffeescript-style-guide)\n* TypeScipt\n    * [TypeScript Handbook](https://zhongsp.gitbooks.io/typescript-handbook/content/)\n* ExtJS\n    * [Ext4.1.0 中文文档](http://extjs-doc-cn.github.io/ext4api/)\n* Meteor\n    * [Discover Meteor](http://zh.discovermeteor.com/)\n    * [Meteor 中文文档](http://docs.meteorhub.org/#/basic/)\n    * [Angular-Meteor 中文教程](http://angular.meteorhub.org/)\n* [Chrome扩展及应用开发](http://www.ituring.com.cn/minibook/950)\n\n### LaTeX\n\n* [一份其实很短的 LaTeX 入门文档](http://liam0205.me/2014/09/08/latex-introduction/)\n* [一份不太简短的 LATEX 2ε 介绍](http://www.mohu.org/info/lshort-cn.pdf) （PDF版）\n\n### LISP\n* Common Lisp\n    * [ANSI Common Lisp 中文翻譯版](http://acl.readthedocs.org/en/latest/)\n    * [On Lisp 中文翻译版本](http://www.ituring.com.cn/minibook/862)\n* Scheme\n    * [Yet Another Scheme Tutorial Scheme入门教程](http://deathking.github.io/yast-cn/)\n    * [Scheme语言简明教程](http://songjinghe.github.io/TYS-zh-translation/)\n    * Racket\n        * [Racket book](https://github.com/tyrchen/racket-book)\n\n### Lua\n\n* [Lua编程入门](https://github.com/andycai/luaprimer)\n* [Lua 5.1 参考手册 中文翻译](http://www.codingnow.com/2000/download/lua_manual.html)\n* [Lua 5.3 参考手册 中文翻译](http://cloudwu.github.io/lua53doc/)\n* [Lua源码欣赏](http://www.codingnow.com/temp/readinglua.pdf)\n\n### OCaml\n\n* [Real World OCaml](https://github.com/zforget/translation/tree/master/real_world_ocaml)\n\n### Perl\n\n* [Modern Perl 中文版](https://github.com/horus/modern_perl_book)\n* [Perl 程序员应该知道的事](http://perl.linuxtoy.org/)\n\n### PHP\n\n* [PHP 官方手册](http://php.net/manual/zh/)\n* [PHP调试技术手册](http://www.laruence.com/2010/06/21/1608.html)(PDF)\n* PHP之道：php-the-right-way ([@wulijun版](http://wulijun.github.io/php-the-right-way/) [PHPHub版](http://laravel-china.github.io/php-the-right-way/))\n* [PHP 最佳实践](https://github.com/justjavac/PHP-Best-Practices-zh_CN)\n* [PHP 开发者实践](https://ryancao.gitbooks.io/php-developer-prepares/content/)\n* [深入理解PHP内核](https://github.com/reeze/tipi)\n* [PHP扩展开发及内核应用](http://www.walu.cc/phpbook/)\n* [Laravel5.1 中文文档](http://laravel-china.org/docs/5.1)\n* [Laravel 5.1 LTS 速查表](https://cs.phphub.org/)\n* [Symfony2 Cookbook 中文版](http://wiki.jikexueyuan.com/project/symfony-cookbook/)(版本 2.7.0 LTS)\n* [Symfony2中文文档](http://symfony-docs-chs.readthedocs.org/en/latest/) (未译完)\n* [YiiBook几本Yii框架的在线教程](http://yiibook.com//doc)\n* [深入理解 Yii 2.0](http://www.digpage.com/)\n* [Yii 框架中文文檔](http://www.yiichina.com/)\n* [简单易懂的PHP魔法](http://www.nowamagic.net/librarys/books/contents/php)\n* [swoole文档及入门教程](https://github.com/LinkedDestiny/swoole-doc)\n* [Composer 中文网](http://www.phpcomposer.com)\n* [Slim 中文文档](http://ww1.minimee.org/php/slim)\n* [Lumen 中文文档](http://lumen.laravel-china.org/)\n* [PHPUnit 中文文档](https://phpunit.de/manual/current/zh_cn/installation.html)\n\n### Prolog\n\n* [笨办法学Prolog](http://fengdidi.github.io/blog/2011/11/15/qian-yan/)\n\n### Python\n\n* [廖雪峰 Python 2.7 中文教程](http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000)\n* [廖雪峰 Python 3 中文教程](http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000)\n* [简明Python教程](http://www.kuqin.com/abyteofpython_cn/)\n* [零基础学 Python 第一版](http://www.kancloud.cn/kancloud/python-basic)\n* [零基础学 Python 第二版](http://www.kancloud.cn/kancloud/starter-learning-python)\n* [可爱的 Python](http://lovelypython.readthedocs.org/en/latest/)\n* [Python 2.7 官方教程中文版](http://www.pythondoc.com/pythontutorial27/index.html)\n* [Python 3.3 官方教程中文版](http://www.pythondoc.com/pythontutorial3/index.html)\n* [Python Cookbook 中文版](http://www.kancloud.cn/thinkphp/python-cookbook)\n* [Python3 Cookbook 中文版](https://github.com/yidao620c/python3-cookbook)\n* [深入 Python](http://www.kuqin.com/docs/diveintopythonzh-cn-5.4b/html/toc/)\n* [深入 Python 3](http://old.sebug.net/paper/books/dive-into-python3/)\n* [PEP8 Python代码风格规范](https://code.google.com/p/zhong-wiki/wiki/PEP8)\n* [Google Python 风格指南 中文版](http://zh-google-styleguide.readthedocs.org/en/latest/google-python-styleguide/)\n* [Python入门教程](http://liam0205.me/2013/11/02/Python-tutorial-zh_cn/) ([PDF](http://liam0205.me/attachment/Python/The_Python_Tutorial_zh-cn.pdf))\n* [笨办法学 Python](http://old.sebug.net/paper/books/LearnPythonTheHardWay/) ([PDF](http://liam0205.me/attachment/Python/PyHardWay/Learn_Python_The_Hard_Way_zh-cn.pdf) [EPUB](https://www.gitbook.com/download/epub/book/wizardforcel/lpthw))\n* [Python自然语言处理中文版](http://pan.baidu.com/s/1qW4pvnY) （感谢陈涛同学的翻译，也谢谢 [@shwley](https://github.com/shwley) 联系了作者）\n* [Python 绘图库 matplotlib 官方指南中文翻译](http://liam0205.me/2014/09/11/matplotlib-tutorial-zh-cn/)\n* [Scrapy 0.25 文档](http://scrapy-chs.readthedocs.org/zh_CN/latest/)\n* [ThinkPython](https://github.com/carfly/thinkpython-cn)\n* [ThinkPython 2ed](https://github.com/bingjin/ThinkPython2-CN)\n* [Python快速教程](http://www.cnblogs.com/vamei/archive/2012/09/13/2682778.html)\n* [Python 正则表达式操作指南](http://wiki.ubuntu.org.cn/Python正则表达式操作指南)\n* [python初级教程：入门详解](http://www.crifan.com/files/doc/docbook/python_beginner_tutorial/release/html/python_beginner_tutorial.html)\n* [Twisted 与异步编程入门](https://www.gitbook.com/book/likebeta/twisted-intro-cn/details)\n* [TextGrocery 中文 API](http://textgrocery.readthedocs.org/zh/latest/index.html) ( 基于svm算法的一个短文本分类 Python 库 )\n* [Requests: HTTP for Humans](http://requests-docs-cn.readthedocs.org/zh_CN/latest/)\n* [Pillow 中文文档](http://pillow-cn.readthedocs.org/en/latest/#)\n* [PyMOTW 中文版](http://pymotwcn.readthedocs.org/en/latest/index.html)\n* [Python 官方文档中文版](http://data.digitser.net/zh-CN/python_index.html)\n* [Fabric 中文文档](http://fabric-chs.readthedocs.org)\n* [Beautiful Soup 4.2.0 中文文档](http://beautifulsoup.readthedocs.org/zh_CN/latest/)\n* [用Python做科学计算](http://old.sebug.net/paper/books/scipydoc)\n* [Sphinx 中文文档](http://www.pythondoc.com/sphinx/index.html)\n* [精通 Python 设计模式](https://github.com/cundi/Mastering.Python.Design.Patterns)\n* [python 安全编程教程](https://github.com/smartFlash/pySecurity)\n* [程序设计思想与方法](https://www.gitbook.com/book/wizardforcel/sjtu-cs902-courseware/details)\n* [知乎周刊·编程小白学Python](https://read.douban.com/ebook/16691849/)\n* [Scipy 讲义](https://github.com/cloga/scipy-lecture-notes_cn)\n* [Python 学习笔记 基础篇](http://www.kuqin.com/docs/pythonbasic.html)\n* [Python 学习笔记 模块篇](http://www.kuqin.com/docs/pythonmodule.html)\n* [Python 标准库 中文版](http://old.sebug.net/paper/books/python/%E3%80%8APython%E6%A0%87%E5%87%86%E5%BA%93%E3%80%8B%E4%B8%AD%E6%96%87%E7%89%88.pdf)\n* [Python进阶](https://www.gitbook.com/book/eastlakeside/interpy-zh/details)\n* [Python 核心编程 第二版](https://wizardforcel.gitbooks.io/core-python-2e/content/) CPyUG译\n* [Python最佳实践指南](http://pythonguidecn.readthedocs.io/zh/latest/)\n* [Python 精要教程](https://www.gitbook.com/book/wizardforcel/python-essential-tutorial/details)\n* [Python 量化交易教程](https://www.gitbook.com/book/wizardforcel/python-quant-uqer/details)\n* Django\n    * [Django 1.5 文档中文版](http://django-chinese-docs.readthedocs.org/en/latest/) 正在翻译中\n    * [Diango 1.7 文档中文版](http://django-1-7-doc.coding.io/)  正在翻译中，目前只翻译了目录\n    * [Django 1.8.2 文档中文版](http://python.usyiyi.cn/django/index.html)\n     正在翻译中\n    * [Django 最佳实践](https://github.com/yangyubo/zh-django-best-practices)\n    * [Django搭建简易博客教程](https://www.gitbook.com/book/andrew-liu/django-blog/details)\n    * [The Django Book 中文版](http://djangobook.py3k.cn/2.0/)\n    * [Django 设计模式与最佳实践](https://github.com/cundi/Django-Design-Patterns-and-Best-Practices)\n    * [Django 网站开发 Cookbook](https://github.com/cundi/Web.Development.with.Django.Cookbook)\n    * [Django Girls 學習指南](https://www.gitbook.com/book/djangogirlstaipei/django-girls-taipei-tutorial/details)\n* Flask\n    * [Flask 文档中文版](http://docs.jinkan.org/docs/flask/)\n    * [Jinja2 文档中文版](http://docs.jinkan.org/docs/jinja2/)\n    * [Werkzeug 文档中文版](http://werkzeug-docs-cn.readthedocs.org/zh_CN/latest/)\n    * [Flask之旅](http://spacewander.github.io/explore-flask-zh/)\n    * [Flask 扩展文档汇总](https://www.gitbook.com/book/wizardforcel/flask-extension-docs/details)\n    * [Flask 大型教程](http://www.pythondoc.com/flask-mega-tutorial/index.html)\n    * [SQLAlchemy 中文文档](https://github.com/sixu05202004/sqlalchemy-docs-cn)\n* web.py\n    * [web.py 0.3 新手指南](http://webpy.org/tutorial3.zh-cn)\n    * [Web.py Cookbook 简体中文版](http://webpy.org/cookbook/index.zh-cn)\n* Tornado\n    * [Introduction to Tornado 中文翻译](http://demo.pythoner.com/itt2zh/index.html)\n    * [Tornado源码解析](http://www.nowamagic.net/academy/detail/13321002)\n    * [Tornado 4.3 文档中文版](https://tornado-zh.readthedocs.org/zh/latest/)\n\n### R\n\n* [R语言忍者秘笈](https://github.com/yihui/r-ninja)\n\n### Ruby\n\n* [Ruby 风格指南](https://github.com/JuanitoFatas/ruby-style-guide/blob/master/README-zhCN.md)\n* [Rails 风格指南](https://github.com/JuanitoFatas/rails-style-guide/blob/master/README-zhCN.md)\n* [笨方法學 Ruby](http://lrthw.github.io/)\n* [Ruby on Rails 指南](http://guides.ruby-china.org/)\n* [Ruby on Rails 實戰聖經](https://ihower.tw/rails4/index.html)\n* [Ruby on Rails Tutorial 原书第 3 版](http://railstutorial-china.org/) (本书网页版免费提供，电子版以 PDF、EPub 和 Mobi 格式提供购买，仅售 9.9 美元)\n* [Rails 实践](http://rails-practice.com/content/index.html)\n* [Rails 5 开发进阶(Beta)](https://www.gitbook.com/book/kelby/rails-beginner-s-guide/details)\n* [Rails 102](https://www.gitbook.com/book/rocodev/rails-102/details)\n* [编写Ruby的C拓展](https://wusuopu.gitbooks.io/write-ruby-extension-with-c/content/)\n* [Ruby 源码解读](https://ruby-china.org/topics/22386)\n* [Ruby中的元编程](http://deathking.github.io/metaprogramming-in-ruby/)\n\n### Rust\n\n* [rust book 中文翻译](https://www.gitbook.com/book/kaisery/rust-book-chinese/details)\n* [rust primer](https://github.com/rustcc/RustPrimer)\n\n### Scala\n\n* [Scala课堂](http://twitter.github.io/scala_school/zh_cn/index.html) (Twitter的Scala中文教程)\n* [Effective Scala](http://twitter.github.io/effectivescala/index-cn.html)(Twitter的Scala最佳实践的中文翻译)\n* [Scala指南](http://zh.scala-tour.com/)\n\n### Shell\n\n* [Shell脚本编程30分钟入门](https://github.com/qinjx/30min_guides/blob/master/shell.md)\n* [Bash脚本15分钟进阶教程](http://blog.sae.sina.com.cn/archives/3606)\n* [Linux工具快速教程](https://github.com/me115/linuxtools_rst)\n* [shell十三问](https://github.com/wzb56/13_questions_of_shell)\n* [Shell编程范例](https://www.gitbook.com/book/tinylab/shellbook/details)\n\n### Swift\n\n* [The Swift Programming Language 中文版](http://numbbbbb.github.io/the-swift-programming-language-in-chinese/)\n* [Swift 语言指南](http://dev.swiftguide.cn)\n* [Stanford 公开课，Developing iOS 8 Apps with Swift 字幕翻译文件](https://github.com/x140yu/Developing_iOS_8_Apps_With_Swift)   \n* [C4iOS - COSMOS](http://c4ios.swift.gg)   \n\n### 读书笔记及其它\n\n* [编译原理（紫龙书）中文第2版习题答案](https://github.com/fool2fish/dragon-book-exercise-answers)\n* [把《编程珠玑》读薄](http://www.hawstein.com/posts/make-thiner-programming-pearls.html)\n* [Effective C++读书笔记](https://github.com/XiaolongJason/ReadingNote/blob/master/Effective%20C%2B%2B/Effective%20C%2B%2B.md)\n* [Golang 学习笔记、Python 学习笔记、C 学习笔记](https://github.com/qyuhen/book) (PDF)\n* [Jsoup 学习笔记](https://github.com/code4craft/jsoup-learning)\n* [学习笔记: Vim、Python、memcached](https://github.com/lzjun567/note)\n* [图灵开放书翻译计划--C++、Python、Java等](http://www.ituring.com.cn/activity/details/2004)\n* [蒂姆·奥莱利随笔](http://g.yeeyan.org/books/2095) （由译言网翻译，电子版免费）\n* [SICP 解题集](http://sicp.readthedocs.org/en/latest/)\n* [精彩博客集合](https://github.com/hacke2/hacke2.github.io/issues/2)\n* [中文文案排版指北](https://github.com/sparanoid/chinese-copywriting-guidelines)\n* [Standard C 语言标准函数库速查 (Cheat Sheet)](http://ganquan.info/standard-c/)\n* [Git Cheatsheet Chs](http://gh.amio.us/git-cheatsheet-chs/)\n* [GitBook简明教程](http://www.chengweiyang.cn/gitbook/index.html)\n* [JavaScript语言精粹](https://github.com/qibaoguang/Study-Step-by-Step/blob/master/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/javascript_the_good_parts.md)\n* [制造开源软件](http://producingoss.com/zh/)\n* [提问的智慧](http://www.dianbo.org/9238/stone/tiwendezhihui.htm)\n* [Markdown 入门参考](https://github.com/LearnShare/Learning-Markdown)\n* [AsciiDoc简明指南](https://github.com/stanzgy/wiki/blob/master/markup/asciidoc-guide.asciidoc)\n* [背包问题九讲](http://love-oriented.com/pack/)\n* [老齐的技术资料](https://github.com/qiwsir/ITArticles)\n* [前端技能汇总](https://github.com/JacksonTian/fks)\n* [借助开源项目，学习软件开发](https://github.com/zhuangbiaowei/learn-with-open-source)\n* [前端工作面试问题](https://github.com/h5bp/Front-end-Developer-Interview-Questions/tree/master/Translations/Chinese)\n* [leetcode/lintcode题解/算法学习笔记](https://www.gitbook.com/book/yuanbin/algorithm/details)\n* [前端开发笔记本](https://github.com/li-xinyang/FEND_Note)\n\n### 测试相关\n\n* [移动APP自动化测试优秀框架Appium API Reference V1.2.0 CN](http://appium.io/slate/cn/v1.2.0/)\n\n\n"
  },
  {
    "path": "13-free-programming-books-zh_CN-master/gulpfile.js",
    "content": "var gulp = require('gulp');\nvar markdown = require('gulp-markdown');\n\ngulp.task('default', function () {\n    return gulp.src('README.md')\n        .pipe(markdown())\n        .pipe(gulp.dest('html'));\n});\n"
  },
  {
    "path": "13-free-programming-books-zh_CN-master/what-non-programming-books-should-programmers-read.md",
    "content": "在 stackoverflow 上有人提问 [程序员应该阅读的非编程类书籍有哪些？](http://stackoverflow.com/q/38210/343194) 本来只想整理编程类书籍，\n不过突然眼前一亮，发现了《The Art of War - Sun Tzu》回答者的推荐说明引用 Wikipedia 上的：\n\n亚马逊提供免费的　Kindle　版读本：[孙子兵法](http://www.amazon.cn/gp/product/B00AA7KMKG/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B00AA7KMKG&linkCode=as2&tag=favbook-23)\n\n> Much of the text is about how to fight wars without actually having to do battle: \n> it gives tips on how to outsmart one's opponent so that physical battle is not necessary. \n> As such, it has found application as a training guide for many competitive endeavors that do not involve actual combat.\n\n> This knowledge would surely be useful in the everyday \"battles\" we have to fight in and out of the office. \n> It's also filled with quotes you can impress your fellow programmers with... :)\n\n\n## 《哥德尔、艾舍尔、巴赫——集异璧之大成》Gödel, Escher, Bach: an Eternal Golden Braid, \n\n这本书通常被称为[《GEB》](http://www.amazon.cn/gp/product/B0049MPCAS/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B0049MPCAS&linkCode=as2&tag=favbook-23)，\n它绝对是一本神书，一本奇书，一本神奇的书。在豆瓣读书的科普类排名中稳居第一。我在博客中，和即将出版的书中，也一而再，再而三的提及此书。\n\n书有点儿厚，而且价格不菲，大概五六十吧。我也曾经不止一次的向朋友们推荐此书，并赠书此书。\n\n作者也乘中文版出版之际，为自己取了一个雅致的汉名──侯世达（Douglas Richard Hofstadter）。侯世达应该是 Hofstadter 的音译。\n\n如果你喜爱理科，此书必读。如果你是文科，那就读读《银河系漫游指南》。\n\n## 《银河系漫游指南》The Hitchhiker's Guide to the Galaxy\n\n亚马逊翻译为[《银河系搭车客指南》](http://www.amazon.cn/gp/product/B00590XCO2/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B00590XCO2&linkCode=as2&tag=favbook-23)，\n略带喜感。\n\n突如其来的寂静笼罩了地球。\n\n这事实上比噪音更加可怕。\n\n有一会儿，什么也没有发生。\n\n巨大的飞船一动不动地挂在空中，覆盖了地球上的每个国家。\n\n在黯然退场之前，地球首先被改造成了最终极的声音重放器件，这是有史以来建造过的最伟大的播音系统。\n\n但伴之而来的不是演奏会，不是音乐，没有开场号曲，而仅仅是一条简短的信息。\n\n“地球人，请注意了。” \n一个声音说，这声音堪称完美，仿佛来自四声道系统，完美得无懈可击，失真度低得能让勇敢的男人洒下眼泪。\n\n“这里是银河超空间规划委员会。诸位无疑已经知道，银河系边远地区的开发规划要求建造一条穿过贵恒星系的超空间快速通道，令人遗憾的是，贵行星属于计划中预定毁灭的星球之一。毁灭过程将在略少于贵地球时间两分钟后开始。谢谢合作。”\n\n## 《人性的弱点》How to Win Friends and Influence People\n\n[《人性的弱点 Kindle版》](http://www.amazon.cn/gp/product/B008F5WMEE/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B008F5WMEE&linkCode=as2&tag=favbook-23)只售 2.9 元。\n\n[《人性的弱点》](http://www.amazon.cn/gp/product/B00119B1AM/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B00119B1AM&linkCode=as2&tag=favbook-23)的作者戴尔·卡耐基，美国“成人教育之父”。\n20世纪早期，美国经济陷入萧条，战争和贫困导致人们失去了对美好生活的愿望，而卡耐基独辟蹊径地开创了一套融演讲、推销、为人处世、智能开发于一体的教育方式，他运用社会学和心理学知识，对人性进行了深刻的探讨和分析。\n《人性的弱点》讲述的许多普通人通过奋斗获得成功的真实故事，激励了无数陷和迷茫和困境的人，帮助他们重新找到了自己的人生。\n\n接受卡耐基教育的有社会各界人士，其中不乏军政要员，甚至包括几位美国总结。\n千千万万的人从卡耐基的教育中获益匪浅。 \n\n《人性的弱点》汇集了卡耐基的思想精华和最激动人心的内容，是作者最成功的励志经典，出版后立即获得了广大读者的欢迎，成为西方世界最持久的人文畅销书。\n无数读者通过阅读和实践书中介绍的各种方法，不仅走出困境，有的还成为世人仰慕的杰出人士。\n只要不断研读《人性的弱点全集》，相信你也可以发掘自己的无穷潜力，创造辉煌的人生。\n\n## 《别逗了,费曼先生!》Surely You're Joking, Mr. Feynman!\n\n[《别逗了,费曼先生》](http://www.amazon.cn/gp/product/B009QVEA8M/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B009QVEA8M&linkCode=as2&tag=favbook-23)是一本很棒的读物：挥霍无忌、惊世骇俗，却仍然温馨，很有人情味儿。\n\nR·P·费曼，他因盘子电动力学方面的研究荣获诺贝尔物理学奖。\n除了作为一个物理学家外，费曼在不同时期还曾是故事大王、艺术家、鼓手和密码破泽专家。\n\n\n> “费曼的一生，或可比作连锁反应。从一点儿临界质量的灰质开始，这个生命向四面八方炸开，产生出热和光。”\n> ——《时代》\n\n> “费曼以其才华和怪癖，在他的同事们中间，成了一个传奇人物——您在阅读本书的时候，不从头笑到尾，是很难的。”\n> ——《新闻周刊》\n\n> “眉飞色舞，肆意笑闹……费曼的语言，生动活泼，直率真朴一真正令人耳目一新。”\n> ——《芝加哥太阳报》\n\n> “如果您以为物理学或物理学家中间没有什么乐子一那么来会会费曼吧——一个用一团原子变戏法的最令人捧腹的伙计。”\n> ——《联合日报》\n\n> “科学家都是枯燥无味之人，这样一种老生常谈，一本书就能打破，这本书就是。”\n> ——《底特律自由报》\n\n## 《尽管去做》Getting Things Done\n\n如果你增加听说过一个词——GTD，没错，就是这本书 Getting Things Done，还有一种译法是[《搞定1:无压工作的艺术》](http://www.amazon.cn/gp/product/B00368C0FG/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B00368C0FG&linkCode=as2&tag=favbook-23)也很信、达，至于雅嘛，呵呵。\n\n在今天这个信息量和工作量倍增的世界，一些老的工作方法已经失去了效用。\n每一个职场中人或多或少都有这样的体验：压力重重；太多事情都理不清头绪；似乎永远被各种任务和目标追赶着……\n\n时间管理大师戴维•艾伦将指导你走出规划和执行工作中的泥沼，通向高效、轻松的彼岸。\n要想让事情井井有条，关键便是——从容、放松。\n\n## 《别让我思考》Don't Make Me Think\n\n先推荐一篇知乎上的文章：[Chrome 浏览器的哪些设计符合「Don't make me think」原则？](http://www.zhihu.com/question/20564451)\n\n在豆瓣和亚马逊搜索了很久中文版，居然没找到，不得已求助 Google，原来被翻译成了[《点石成金:访客至上的网页设计秘笈》](http://www.amazon.cn/gp/product/B0011BTJV8/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B0011BTJV8&linkCode=as2&tag=favbook-23)。\n\n如果你在进行网站设计，为网站编程，或者管理网站，那么一定要读一读此书。\n\n* 有些网站看起来很杂乱；\n* 有些网站能让你轻松地找到资料；\n* 有些网站让你犹如置身迷宫，\n\n为什么网站的可用性会有如此大的反差？用户在访问网站时有怎样的心理？\n遵循什么样的原则来设计网站才能吸引访客？\n这本全球 Web 设计人员的必读经典会给出答案。\n\n## 《禅与摩托车维修艺术》Zen and the Art of Motorcycle Maintenance\n\n这是什么书？\n\n[《禅与摩托车维修艺术》](http://www.amazon.cn/gp/product/B005O4PUFC/ref=as_li_ss_tl?ie=UTF8&camp=536&creative=3132&creativeASIN=B005O4PUFC&linkCode=as2&tag=favbook-23)：累积销量超过一千万册，美国大学“禅与现代美国文学”课程的必读参考书。\n\n70年代的梭罗——罗伯特•M. 波西格，《时代》周刊评选20世纪70年代十本最有影响力的书之一。\n\n《禅与摩托车维修艺术》主要内容简介：在一个炎热的夏天，父子两人和约翰夫妇骑摩托车从明尼苏达到加州，跨越美国大陆，旅行的过程与一个青年斐德洛研修科学技术与西方经典，寻求自我的解脱，以及探寻生命的意义的过程相互穿插。\n\n一路上父亲以一场哲学肖陶扩的形式，将见到的自然景色，野外露营的经历，夜晚旅店的谈话，机车修护技术等等日常生活与西方从苏格拉底以来的理性哲学的深入浅出的阐述与评论相结合，进行了对形而上学传统的主客体二元论的反思，以及对科学与艺术，知识与价值，古典主义与浪漫主义，精神与物质，机械论与神秘主义，西方与东方等西方二分法划分下的事物间的关系的思考。\n\n并潜入自己的过去，探寻在现代文明下自己精神的分裂的起源，完成了一次自我心灵与人类文明 的探索。\n\n## 《编码宝典》(Cryptonomicon)\n\n貌似没有中国版。\n"
  },
  {
    "path": "14-frontend-dev-bookmarks-master/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013 张正雄\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "14-frontend-dev-bookmarks-master/README.md",
    "content": "# 前端开发书签\n\n做这份文档本来是看了英文版的[前端书签](https://github.com/dypsilon/frontend-dev-bookmarks?source=cc),后来发现了中文版有两个类似的，[justjavac](https://github.com/justjavac/free-programming-books-zh_CN)和[JacksonTian](https://github.com/JacksonTian/fks)，首先严重推荐他们的，然后有空我也会更新。\n\n+ HTML\n  + [HTML教程](http://www.w3school.com.cn/html/) W3C入门教程\n  + [HTML语义化](http://justineo.github.io/slideshows/semantic-html/) 一定要了解，否则很容易标签乱用\n\n+ CSS\n  + [CSS教程](http://www.w3school.com.cn/css/index.asp) W3C入门教程\n  + [DIV+CSS](http://www.divcss5.com/) 比W3C详细些，作为参考\n\n+ JavaScript\n  + [JavaScript教程](http://www.w3school.com.cn/js/index.asp) W3C入门教程\n  + [Google JavaScript代码风格指南](http://chajn.org/jsguide/javascriptguide.html) Google的，适合作为企业规范\n  + [JavaScript编程风格](http://www.ruanyifeng.com/blog/2012/04/javascript_programming_style.html) 必须了解，否则有可能出现错误自己还不知道\n  + [Web技术文档](https://developer.mozilla.org/zh-CN/docs/Web) Mozilla权威标准\n  + [JavaScript的单线程性质以及定时器的工作原理](http://www.phpweblog.net/rainman/archive/2009/01/05/6267.html) 来自John Resig的文章，一次讨论，发现我组长也不理解JavaScript单线程，这也是理解异步回调的基础。\n  + [JavaScript严格模式详解](http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mode.html)\n  + [深入理解JavaScript系列](http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html) 来自博客园的汤姆大叔，从浅到深的讲解JS，大多翻译国外文章，我看到了JS设计模式，通读下来会发现对JS理解会上一层\n \n+ jQuery\n  + [jQuery教程](http://www.w3school.com.cn/jquery/) W3C入门教程\n  + [jQuery的deferred对象详解](http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html)\n  + [jQuery源码分析](http://www.cnblogs.com/nuysoft/archive/2011/11/14/2248023.html)\n  + [jQuery 2.0.3 源码分析系列](http://www.cnblogs.com/aaronjs/p/3279314.html) 刚开始我也在写jQuery分析，后来看到他的，就没写了，写得比我好太多。\n  + [jQuery Coding Standards & Best Practices](http://lab.abhinayrathore.com/jquery-standards/) 一直觉得语言的规范文档是值得反复看的\n\n+ 前端知识\n  + [响应式Web设计](http://beforweb.com/node/6) 看起来高大上，其实很容易理解实践\n  + [BEM的定义](http://www.w3cplus.com/css/bem-definitions.html) 只了解，没用过\n  + [Shadow DOM](http://www.toobug.net/article/what_is_shadow_dom.html) 理解Web Components必须先理解Shadow DOM\n  + [Fiddler 教程](http://www.cnblogs.com/tankxiao/archive/2012/02/06/2337728.html) 必备神器，每天必用，要是界面更友好点就更好了。\n  + [浏览器的工作原理：新式网络浏览器幕后揭秘](http://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/) 浏览器对于我们一直是一个黑箱，通读这篇文章可以窥一孔。\n  + [浏览器开发工具的秘密](http://jinlong.github.io/blog/2013/08/29/devtoolsecrets/) 发现很多前端竟然不知道console.log()和debugger，出了错几乎一遍遍修改源文件。\n  + [Chrome Developer Tools之调试代码](http://www.kazaff.me/2014/01/14/chrome-developer-tools%E4%B9%8B%E8%B0%83%E8%AF%95%E4%BB%A3%E7%A0%81/)越来越感觉Chrome Dev Tools比FireBug强大很多，现在的IE11也有了很大改进，想更深入的调式，看看他写的这几篇文章吧。\n\n+ JS资源\n  + [Bootstrap中文文档](http://www.bootcss.com/) 很容易上手，做出的东西不会很丑\n  + [Underscore.js中文文档](http://www.css88.com/doc/underscore/) 超级实用的JS库，短小，精悍\n  + [jQuery Mobile 中文API站](http://www.jqmapi.com/) 排版很乱，翻译错字也多，仅作中文参考\n  + [Raphaël中文帮助文档](http://lab.julying.com/raphael-js/docs/) 真的很炫很酷嘞\n\n+ 工具网站\n  + [HTML Validation](http://validator.w3.org/) 检测HTML错误\n  + [JSLint](http://www.jslint.com/) 检测js错误\n  + [JSFIDDLE](http://jsfiddle.net/) 在线前端开发工具\n  + [jsPerf](http://jsperf.com/) 在线js性能测试工具\n  + [UglifyJS](http://marijnhaverbeke.nl/uglifyjs) 在线js压缩工具\n  + [Grunt](http://www.gruntjs.org/article/home.html) 构建工具\n \n+ 前端成长\n  + [十日谈](https://github.com/jayli/jayli.github.com/issues) 看过几遍，对我这种刚入门有点迷茫的人特别有用\n  + [WEB前端研发工程师编程能力成长之路](http://www.cnblogs.com/eric6/archive/2011/03/23/1991777.html) 我大概输入登堂那级别吧，长路漫漫\n\n+ 书籍\n  + [CSS权威指南](http://book.douban.com/subject/1240134/) 权威指南的书，水准都有保证，适合度也很广\n  + [精通CSS](http://book.douban.com/subject/4736167/) CSS权威指南作为入门和参考书籍比较好，入门后进阶可以看着一本书\n  + [JavaScript高级程序设计](http://book.douban.com/subject/10546125/) 我的JS入门书，从浅到深，讲得很详细，五星推荐\n  + [JavaScript权威指南](http://book.douban.com/subject/10549733/) 传说中的犀牛书，一直被奉为经典\n  + [JavaScript语言精粹](http://book.douban.com/subject/3590768/) 老道的书，对JS的规范有很大影响，不可不读\n  + [JavaScript DOM编程艺术](http://book.douban.com/subject/1921890/) 能写原生JS的被视为牛人必备，原生JS大部分都是DOM操作\n  + [高性能网站建设指南](http://book.douban.com/subject/3132277/) 前端性能优化必读，“雅虎军规”的来源\n  + [高性能网站建设进阶指南](http://book.douban.com/subject/4719162/) 看名字就知道是前一本的姊妹篇，包含更多的牛人，更深入的知识\n  + [Web安全测试](http://book.douban.com/subject/4725272/) 我的Web安全入门书，讲了很多测试技巧和测试工具，五星推荐\n  + [HTTP权威指南](http://book.douban.com/subject/10746113/) 有时候很可悲，发现身边很多前端对HTTP根本不了解，包括常见的状态码，请求和响应头。\n  + [JAVASCRIPT语言精髓与编程实践](http://book.douban.com/subject/3012828/) 如果不是看到很多人推荐，很可能错过这本好书，将JS放到编程语言长河中，分析它的特性，足见作者的功底，这本书难度有点高，可以反复看\n  + [精通正则表达式](http://book.douban.com/subject/2154713/) 以前写稍微复杂点的正则就去网上找一下《30分钟精通正则》，看了这本书，就再也没去了。\n  + [JavaScript异步编程](http://book.douban.com/subject/24319975/) JS进阶必须了解的，书是好书，翻译得很难懂\n  + [深入浅出Node.js](http://book.douban.com/subject/25768396/) 因为在GitHub上找了书中两个失误，免费得到这本书，没有一定功力的人真心写不出来，不适合初学Node者\n  \n  \n\n\n\n"
  },
  {
    "path": "14-frontend-dev-bookmarks-master/about.md",
    "content": "## 关于这个项目\n\n本项目是本人在前端开发中访问过比较好的网站"
  },
  {
    "path": "15-fun-front-end-tutorials-master/README.md",
    "content": "# Fun Front-end Tutorials\n\n收集有趣的、富有交互的前端学习教程。\n\n**收集标准：**通过富有交互的、有趣的 Demo 来准确的介绍或讲解一个前端知识点。内容要求严谨准确，Demo 与内容关系密切、让人眼前一亮，并可以非常直观的解释枯燥的理论内容。\n\n通常可以是：\n\n* 一步步讲解某个知识点并附带对应 Demo 的文章，例如 [Flexbox adventures](http://chriswrightdesign.com/experiments/flexbox-adventures/) 和 [Cascading sequences\n](http://chriswrightdesign.com/experiments/cascading/)。\n* 富有交互的在线课程，例如：[玩转KISSY框架](http://www.imooc.com/code/3684) 和 [Try Git](https://try.github.io/levels/1/challenges/1)。\n* 附带在线交互练习的视频教程，例如：[Discover DevTools: Code School](http://discover-devtools.codeschool.com/)。\n* 以及富有交互的 PPT 等，例如： [HTML5 Presentation](http://slides.html5rocks.com/#landing-slide)。\n\n\n追求质量而非数量，同一知识点及同一难度（入门级、中级、高级等）的多个资源，仅保留最准确、全面、有价值的。单纯的讲解类视频、PPT 等缺乏交互不在考虑之列，除非特别优秀以及经典的资料。\n\n你可以通过 Issue 来推荐资源，也可以 Fork & PR，但为了保证质量，我们将会在 QQ 群里讨论该资源是否符合标准，因此不一定会全部通过。欢迎加入讨论 QQ 群：**399485758**。\n\n最后，该项目的目标是：通过使用最好的教程，尽量减少学习时间，尽量快的掌握某一个前端有关的技能或知识点。\n\n/* 部分国外资源可能需要翻墙查看 */\n\n## CSS\n\n### CSS3\n\n#### Flexbox\n\n* Flexbox 入门：[Using Flexbox today](http://chriswrightdesign.com/experiments/using-flexbox-today/)\n* Flexbox 中级：[Flexbox adventures](http://chriswrightdesign.com/experiments/flexbox-adventures/)\n\n#### transition\n\n* Transition 入门：[CSS动画简介](http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html)\n\n\n#### animation\n\n* Animation 入门：[CSS动画简介](http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html)\n* Animation 实际应用：[Cascading sequences](http://chriswrightdesign.com/experiments/cascading/)\n\n\n## HTML5\n\n* HTML5 API 走马观花：[HTML5 Presentation](http://slides.html5rocks.com/#landing-slide)\n\n## JavaScript\n\n### JavaScript 入门\n\n\n### JavaScript 中级\n\n* [Learning Advanced JavaScript](http://ejohn.org/apps/learn/)\n\n\n### ES6\n\n* [Expert ES6](http://tagtree.io/courses/expert-es6/do)\n\n\n## Nodejs / Iojs\n\n### Nodejs 入门\n\n* 一系列的命令行交互的教程：[nodeschool.io](http://nodeschool.io/)\n\n\n## 其他前端相关\n\n### Git & Github\n\n* [Try Git](https://try.github.io/levels/1/challenges/1)\n\n### Chrome Devtools\n\n* [Discover DevTools: Code School](http://discover-devtools.codeschool.com/)\n\n### 程序员解决能力提升\n\n在线解决有趣又实用的问题，可以通过多种语言（包括 JavaScript）实现，提高综合编程能力。\n\n* [CodeWars](http://www.codewars.com/)\n* [Talentbuddy](https://www.talentbuddy.co/)"
  },
  {
    "path": "16-front-end-code-checklist-master/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 JiangShui Yu\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "16-front-end-code-checklist-master/README.md",
    "content": "# front-end-code-checklist\n\n前端代码审查清单。\n\n## 是什么？为什么？\n\n前端代码审查清单是一个保证前端代码质量的审查清单。当我们在开发写代码的时候，总会各种各样的问题，自测的时候由于太熟悉自己的代码逻辑往往测试不够充分，无法发现问题。\n\n前端代码审查清单就是为了解决这个问题！清单存放了一些常见的问题，当我们开发完成之后，对照清单思考一下这些问题在代码中是否遇到或者妥善处理，从而提高代码质量。\n\n## 前端\n\n### 前端安全\n\n- [ ] 所有的用户可以在页面中输入信息的地方，是否做了防 XSS 以及特殊字符的过滤处理？\n- [ ] 与后端接口交互，获取信息使用 GET 方式，传送信息使用 POST 方式。后端接口应对各项参数做校验。前端也要判断接口是否返回合法、正确。\n- [ ] 开发与 DOM 操作有关的代码时，是否对 DOM 不存在或者被人为修改的情况做处理？\n- [ ] 获取数据和信息时，是否对类型做过处理和转换并设置为空时的默认值？比如：var num = parseInt(Str);\n- [ ] 在所有会发生错误的地方，是否编写了错误处理逻辑？比如：阻止继续执行、显示错误信息、记录错误日志和信息等。\n- [ ] 代码里获取 window.location 相关属性的地方，是否对里面的 XSS 字符做了过滤处理？\n\n### 前端性能\n\n- [ ] JS 代码是否尽量放在底部？CSS 代码是否尽量放在了顶部？\n- [ ] 是否部署 CDN 或者开启了缓存功能？\n- [ ] 上线或者发布前，是否对静态资源进行打包、压缩处理？\n- [ ] 正确使用预加载、懒加载等技术手段提高性能。\n- [ ] 是否对图片等资源进行压缩以及 CSS Sprite 处理？\n\n\n## 代码质量\n\n- [ ] 你的代码是否遵循团队要求的代码规范？\n- [ ] 是否有冗余代码没有注释掉或者删掉？例如：删除或者注释 console.log 避免低端 IE 报错等。\n- [ ] 关键功能是否还有优化的空间？\n- [ ] 代码是否简单易懂，逻辑清晰，模块化？\n- [ ] 变量名是否简单易懂？是否拼写正确？\n- [ ] CSS 属性是否有拼写错误？\n- [ ] HTML 标签是否书写正确，是否嵌套正确？\n- [ ] JS 代码是否经过 JSLint 或者 ESLint 等工具校验？\n- [ ] 是否将核心功能尽可能独立，从而避免其他功能出现问题影响到核心功能？\n\n\n## 注释\n\n- [ ] 是否在重要功能附近添加合适的注释？\n- [ ] 注释是否包含了开发人员信息、开发时间、开发者联系方式以及相关功能说明？\n- [ ] 换位思考，你能根据你的注释推断出下面代码的功能吗？\n- [ ] 代码里是否还存在 TODO ？是否可以删掉或者完善功能？\n- [ ] 可能产生意外情况的地方是否留下说明？\n\n\n## 测试\n\n- [ ] 代码逻辑是否正确、可用、符合需求？\n- [ ] 在进行各种操作的时候，是否有报错出现？\n- [ ] 是否有资源加载出错或者失败？\n- [ ] 是否按照项目要求，使用相关设备以及浏览器进行测试和体验？\n- [ ] 是否对边界条件以及看起来比较极端的情况做过测试？\n\n\n## 故障处理\n\n- [ ] 是否考虑过如果发生线上故障，如何做回滚处理？处理什么文件？\n- [ ] 功能与功能之间是否足够独立？是否设置开关？当某个功能发生故障是否可以通过开关关掉？\n\n\n## 贡献\n\n由于本人才疏学浅，部分场景没有覆盖，欢迎大家补充更多审查点，提高前端代码质量！\n"
  },
  {
    "path": "17-Mobile-front-end-tutorial-master/README.md",
    "content": "# Mobile-front-end-tutorial\n\n*本资源教程参考了许多资源合集，在此表示感谢。同时希望有相关移动端开发资源的朋友帮忙完善。*\n\n- Ionic\n\t- [Ionic官网](http://www.ionicframework.com/)\n\t- [Ionic中文网](http://www.ionic.wang/)\n\t- [Ionic+phonegap基础视频教程](http://bbs.phonegap100.com/thread-2047-1-1.html)\n\t- [Ionic菜鸟教程](http://www.runoob.com/ionic/ionic-tutorial.html)\n\t- [Ionic-Material](https://github.com/zachfitz/Ionic-Material)\n\t- [官方例子：ionic-weather](https://github.com/driftyco/ionic-weather)\n\n- Ionic2\n\t- [Ionic2简介](http://ionic.io/2)\n\t- [Ionic2官方教程](http://ionicframework.com/docs/v2/)\n\t- [Ionic2官方教程中文整理](https://github.com/Raineye/ionic2)\n\t- [Ionic2相关教程](http://my.oschina.net/boogoogle/blog?catalog=3408736)\n\n- TypeScript\n\t- [TypeScript官网](http://www.typescriptlang.org/)\n\t- [TypeScript中文手册](https://davidcai1993.gitbooks.io/typescript-handbook/content/)\n\n\n- Angularjs\n\t- [Angular.js 的一些学习资源](https://github.com/dolymood/AngularLearning)\n\t- [Angular官网](http://docs.angularjs.org)\n\t- angularjs官方网站已被墙，可看 [http://www.ngnice.com/](http://www.ngnice.com/)\n\t- [angularjs中文社区](http://angularjs.cn)\n\t- [Angularjs源码学习](http://www.cnblogs.com/xuwenmin888/p/3739096.html)\n\t- [Angularjs源码学习](http://www.ifeenan.com/?c=AngularJS)\n\t- [angular对bootstrap的封装](http://angular-ui.github.io/bootstrap)\n\t- [一些扩展的Angular组件](https://github.com/angular-ui)\n\t- [不要带着JQuery的思维去学习AngularJS](http://www.rainweb.cn/article/angularjs-jquery.html)\n\t- [angular在线教程](http://each.sinaapp.com/angular/)\n\t- [angular学习笔记](http://www.zouyesheng.com/angular.html)\n\t- [《AngularJS》5个实例详解Directive（指令）机制](http://damoqiongqiu.iteye.com/blog/1917971)\n\n- Angular2\n\t- [Angular2官方开发指南翻译](https://github.com/gf-rd/blog/issues/21)\n\t- [Angular2入门](http://www.hubwiz.com/course/5599d367a164dd0d75929c76/)\n\t- [理解Zone](https://github.com/kittencup/angular2-ama-cn/issues/60)\n\t- [Angular 2 中的 ViewChildren 和 ContentChildren](https://github.com/kittencup/angular2-ama-cn/issues/66)\n\t- [Angular 2 VS. React： 血色将至](http://www.zcfy.cc/article/142)\n\t- [Angular 1 vs. Angular 2 深度比较](http://www.oschina.net/translate/angular-1-vs-angular-2-a-high-level-comparison)\n\t- [Angular 1 和 Angular 2 集成：无缝升级的方法](http://www.oschina.net/translate/angular-1-and-angular-2-coexistence)\n\t- [在angular2服务中注入服务](http://kittencup.com/javascript/2015/11/11/%E5%9C%A8angular2%E6%9C%8D%E5%8A%A1%E4%B8%AD%E6%B3%A8%E5%85%A5%E6%9C%8D%E5%8A%A1.html)\n\t- [ECMAScript 6入门](http://es6.ruanyifeng.com/)\n\t- [Angular 2依赖注入](http://kittencup.com/javascript/2015/07/23/Angular%202%E4%B8%AD%E7%9A%84%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5.html)\n\t- [Angular 2模板语法](http://kittencup.com/javascript/2015/07/20/Angular%202%E6%A8%A1%E6%9D%BF%E8%AF%AD%E6%B3%95.html)\n\t- [Angular 2的核心概念](http://kittencup.com/javascript/2015/07/17/Angular%202%E7%9A%84%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5.html)\n\t- [Angular 2的变化检测](http://kittencup.com/javascript/2015/07/18/Angular%202%E7%9A%84%E5%8F%98%E5%8C%96%E6%A3%80%E6%B5%8B.html)\n\t- [Angular 2简介](http://zhuanlan.zhihu.com/FrontendMagazine/20058966)\n\t- [Angular 2浅入浅出](http://segmentfault.com/a/1190000002637529)\n\t- [Angular 2和1比较](http://www.html-js.com/article/AngularJS-mass-Angular-2-and-1x-comparison)\n\t- [Angular 2初体验](http://www.reqianduan.com/2758.html)\n\t- [Angular2使用体验](http://web.jobbole.com/83017/)\n\t- [Angular 2的设计方法和原则](http://blog.jobbole.com/63264/)\n\t- [Annotation和Decorator之间的区别](http://kittencup.com/javascript/2015/08/05/Annotation%E5%92%8CDecorator%E4%B9%8B%E9%97%B4%E7%9A%84%E5%8C%BA%E5%88%AB.html)\n\t- [使用Angular2构建一个简单的Todo应用](https://github.com/jnotnull/JavaScript-Sturcture/wiki/%E4%BD%BF%E7%94%A8Angular2%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84Todo%E5%BA%94%E7%94%A8)\n\t- [Angular2路由模块简介](http://chensd.com/2015-06/Angular-New-Router.html)\n\t- [Angular 2.0 的设计方法和原则](http://blog.jobbole.com/63264/)\n\t- [Angular2 依赖注入](http://gabriel0402.github.io/2015/12/25/angular-dependency-injection/)\n\t- [Angular2 表单验证](http://gabriel0402.github.io/2015/12/24/angular2-form/)\n"
  },
  {
    "path": "18-fun-front-end-tutorials-master/README.md",
    "content": "# Fun Front-end Tutorials\n\n收集有趣的、富有交互的前端学习教程。\n\n**收集标准：**通过富有交互的、有趣的 Demo 来准确的介绍或讲解一个前端知识点。内容要求严谨准确，Demo 与内容关系密切、让人眼前一亮，并可以非常直观的解释枯燥的理论内容。\n\n通常可以是：\n\n* 一步步讲解某个知识点并附带对应 Demo 的文章，例如 [Flexbox adventures](http://chriswrightdesign.com/experiments/flexbox-adventures/) 和 [Cascading sequences\n](http://chriswrightdesign.com/experiments/cascading/)。\n* 富有交互的在线课程，例如：[玩转KISSY框架](http://www.imooc.com/code/3684) 和 [Try Git](https://try.github.io/levels/1/challenges/1)。\n* 附带在线交互练习的视频教程，例如：[Discover DevTools: Code School](http://discover-devtools.codeschool.com/)。\n* 以及富有交互的 PPT 等，例如： [HTML5 Presentation](http://slides.html5rocks.com/#landing-slide)。\n\n\n追求质量而非数量，同一知识点及同一难度（入门级、中级、高级等）的多个资源，仅保留最准确、全面、有价值的。单纯的讲解类视频、PPT 等缺乏交互不在考虑之列，除非特别优秀以及经典的资料。\n\n你可以通过 Issue 来推荐资源，也可以 Fork & PR，但为了保证质量，我们将会在 QQ 群里讨论该资源是否符合标准，因此不一定会全部通过。欢迎加入讨论 QQ 群：**399485758**。\n\n最后，该项目的目标是：通过使用最好的教程，尽量减少学习时间，尽量快的掌握某一个前端有关的技能或知识点。\n\n/* 部分国外资源可能需要翻墙查看 */\n\n## CSS\n\n### CSS3\n\n#### Flexbox\n\n* Flexbox 入门：[Using Flexbox today](http://chriswrightdesign.com/experiments/using-flexbox-today/)\n* Flexbox 中级：[Flexbox adventures](http://chriswrightdesign.com/experiments/flexbox-adventures/)\n\n#### transition\n\n* Transition 入门：[CSS动画简介](http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html)\n\n\n#### animation\n\n* Animation 入门：[CSS动画简介](http://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html)\n* Animation 实际应用：[Cascading sequences](http://chriswrightdesign.com/experiments/cascading/)\n\n\n## HTML5\n\n* HTML5 API 走马观花：[HTML5 Presentation](http://slides.html5rocks.com/#landing-slide)\n\n## JavaScript\n\n### JavaScript 入门\n\n\n### JavaScript 中级\n\n* [Learning Advanced JavaScript](http://ejohn.org/apps/learn/)\n\n\n### ES6\n\n* [Expert ES6](http://tagtree.io/courses/expert-es6/do)\n\n\n## Nodejs / Iojs\n\n### Nodejs 入门\n\n* 一系列的命令行交互的教程：[nodeschool.io](http://nodeschool.io/)\n\n\n## 其他前端相关\n\n### Git & Github\n\n* [Try Git](https://try.github.io/levels/1/challenges/1)\n\n### Chrome Devtools\n\n* [Discover DevTools: Code School](http://discover-devtools.codeschool.com/)\n\n### 程序员解决能力提升\n\n在线解决有趣又实用的问题，可以通过多种语言（包括 JavaScript）实现，提高综合编程能力。\n\n* [CodeWars](http://www.codewars.com/)\n* [Talentbuddy](https://www.talentbuddy.co/)"
  },
  {
    "path": "19-about-resume/Readme.md",
    "content": "---\nlayout: post\ntitle:  \"关于程序员求职简历\"\ncategories:\ncomments: true\nshare: true\n---\n\n<p class=\"lead\">最近在网上看见了一些关于程序员如何写求职简历的博客，还有之前也收集过一些优秀的简历，在此做个整理。</p>\n<p class=\"lead\">同时我从这些资料里我总结出，一份简历最核心的两个要素：1. 向 HR 准确且高效地传递信息；2. 作为面试官考察个人能力的线索。</p>\n\n### 1. 一些链接\n\n#### 1.1 大牛向\n\n**[精益技术简历之道——改善技术简历的47条原则](http://lucida.me/blog/lean-technical-resume/)**  （Lucida，Google）\n\n**[如何写面向互联网公司的求职简历](http://blog.devtang.com/blog/2013/12/22/how-to-write-resume-for-it-company/)**（唐巧，猿题库）\n\n**[禅与写简历的艺术](http://www.zoomfeng.com/blog/shan-yu-xie-jian-li-de-yi-zhu.html)**（ZoomFeng，阿里巴巴）\n\n#### 1.2 普通向\n\n**[如何写好技术简历 —— 实例、模板及工具](http://blog.devtang.com/blog/2013/12/22/how-to-write-resume-for-it-company/)**（Get 社区 @Easy）\n\n**[程序员简历应该怎么写？—— 知乎](https://www.zhihu.com/question/25002833)**\n\n**[应聘互联网公司的简历应该是怎么样的？—— 知乎](https://www.zhihu.com/question/23631182)**\n\n#### 1.3 行业通用\n\n**[优秀简历要遵循哪些规则？—— 知乎](https://www.zhihu.com/question/20184884)**\n\n**[如何制作高水平简历？—— 知乎](https://www.zhihu.com/question/21187514)**\n\n**[普通人如何做出有设计感的PPT简历？—— 知乎](https://www.zhihu.com/question/36943039)**\n\n#### 1.4 应届程序员简历\n\n**[应届生应聘程序员，简历上能写书单吗？最好有哪些信息？—— 知乎](https://www.zhihu.com/question/24887072)**\n\n**[计算机应届生简历中，「贪吃蛇，俄罗斯方块」等小项目有必要写到简历中吗？—— 知乎](https://www.zhihu.com/question/36280350)**\n\n**[大学生活一片空白的人简历应该怎么写？—— 知乎](https://www.zhihu.com/question/19883567)**\n\n#### 1.5 一些细节\n\n**[面试者是否应该带简历前去面试？ 单位又是否应该要求面试者带简历去面试？—— 知乎](https://www.zhihu.com/question/21601933)**\n\n**[在简历上造假是可以被接受的吗？—— 知乎](https://www.zhihu.com/question/21660867)**\n\n**[为什么有人说简历留 QQ 邮箱不好？—— 知乎](https://www.zhihu.com/question/25162039)**\n\n**[如何让我的简历被HR青睐？—— 知乎](https://www.zhihu.com/question/34016505)**\n\n### 2. 一些优秀简历示例\n\n> 大部分是国内的年轻前端工程师\n\n**[Joy Neop — Resume](https://joyneop.xyz/resume/)**：Joy Neop，计蒜客 UX\n\n**[Resume](http://ming.today/resume)**：阴明，稀土掘金，前端/联合创始人\n\n**[罗礼权的个人简历](http://cv.heeroluo.net/)**：罗礼权，56网，前端\n\n**[张雯莉的简历](http://zhangwenli.com/cv/cn.html)**：张雯莉，上海交通大学，前端\n\n**[张秋怡 - 个人简历](http://joyeecheung.github.io/resume/)**：张秋怡，阿里巴巴，前端\n\n**[范文杰的简历](http://html.love/)**：范文杰，丁香园，前端\n\n**[前端工程师-赵可简介](http://natee.github.io/)**：赵可，保密，前端\n\n**[无标题](http://fakefish.github.io/)**：王佳裕，360 搜索，前端\n\n### 3. 总结\n\n关于怎么做简历上面的链接已经说的相当详细，以上列出的优秀简历也大都是开源的。在此就补充一点关于在线简历的问题：有些简历做的非常炫酷，但是 HR 无法打印，或者说打印出来的效果比在线的差得多。很多时候面试官可能没有那么多时间去看在线简历上的内容，所以在提供炫酷的在线简历的同时也提供有良好设计感的 PDF 版简历也是很有必要的，如果是彩色的最好在面试的时候自己带一份彩色硬纸打印的简历。\n\n### 4. 扩展阅读\n\n**[关于前端面试](https://mdluo.github.io/blog/about-front-end-interview/)**\n"
  },
  {
    "path": "20-about-front-end-interview/Readme.md",
    "content": "---\nlayout: post\ntitle:  \"关于前端面试\"\ncategories:\ncomments: true\nshare: true\n---\n\n<p class=\"lead\">继上一篇 <a href=\"https://mdluo.github.io/blog/about-resume/\">关于程序员求职简历</a> 之后如果顺利的话就应该是面试了，在此也整理一下最近在网上收集的前端面试相关资料，包括预备知识、书籍、面试考点、面经等。前端方面资料其实太多太多，就光从知乎、前端乱炖、w3cplus 等网站就能找到很多，所以针对细节不发散，仅挑一些内容丰富的合集，更多的资料可以从其中找到。</p>\n\n### 1. 前端团队\n\n参考我整理的列表（部分维护了网站、技术型前端团队）：\n**[国内知名前端团队](https://github.com/mdluo/awesome-fe-team)**\n\n### 2. 知识技能\n\n**[前端技能汇总 Frontend Knowledge Structure](http://html5ify.com/fks/)** （[源码](https://github.com/JacksonTian/fks)）（朴灵，阿里巴巴）\n\n**[大前端的瑞士军刀，只记录有用的](http://www.fefork.com/fetool/)**（[源码](https://github.com/nieweidong/fetool)）（聂微东，百度）\n\n**[前端收集](https://github.com/foru17/front-end-collect)**（罗磊，腾讯阅文）\n\n**[知乎上前端开发领域有哪些值得推荐的问答？——知乎](https://www.zhihu.com/question/20246142)**\n\n**[2015-2016前端知识体系图谱](http://www.w3ctech.com/topic/1690)**（w3ctech）\n\n**[前端收藏夹](http://collect.w3ctrain.com/)**（[源码](https://github.com/w3ctrain/w3ctrain.github.io)）（w3ctrian）\n\n**[QQ联盟群交流(492107297)群规](https://github.com/jsfront/src/blob/master/qq.md)**（有大量的教程、资料、面试题）（豪情）\n\n### 3. 学习路线、书籍\n\n**[前端开发者手册](https://github.com/dwqs/fedHandlebook)**（Pomy，美团）\n\n**[Front-End-Develop-Guide 前端开发指南](https://github.com/icepy/Front-End-Develop-Guide)**（icepy，音悦台）\n\n**[有哪些关于前端开发技术（HTML、CSS 和 JavaScript 等）的值得推荐的书籍？](https://www.zhihu.com/question/19809484/answer/13215239)**（李路，Knewone）\n\n**[前端路上的旅行](http://www.w3cplus.com/front-end-trip-on-road.html)**（大漠，淘宝）\n\n**[Developer进阶书单](https://github.com/phodal/booktree)**（phodal，ThoughtWorks）\n\n**[年后跳槽如何准备？](http://www.cnblogs.com/jikey/p/5201185.html)**（豪情）\n\n**[学习前端的这一年](http://www.w3ctrain.com/2016/01/16/my-frontend-way/)**（Helkyle @ w3ctrian）\n\n**[零基础的前端开发初学者应如何系统地学习？——知乎](https://www.zhihu.com/question/19834302)**\n\n### 4. 面试考点、面经\n\n**[写给前端面试者](https://github.com/amfe/article/issues/5)**（大漠，淘宝）\n\n**[谈谈面试与面试题](https://github.com/wintercn/blog/issues/4)、[谈谈面试与面试题 II ](https://github.com/wintercn/blog/issues/8)**（winter，淘宝）\n\n**[互联网公司技术岗实习/求职经验（实习内推+简历+面试+offer篇）](http://www.cnblogs.com/joyeecheung/p/5003980.html)**（张秋怡，阿里巴巴）\n\n**[史上最全 前端开发面试问题及答案整理](https://github.com/hawx1993/Front-end-Interview-questions)**（trigkit4，口袋购物）\n\n**[前端开发面试题](https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions)**（马云云，ZTE）\n\n**[收集的前端面试题和答案](https://github.com/qiu-deqing/FE-interview)**（邱德清，阿里妈妈）\n\n**[web前端面试相关的知识点](https://github.com/wangwenjie1314/webQd)**（王文杰，乐视云）\n\n**[2016十家公司前端面试小记](http://www.cnblogs.com/xxcanghai/p/5205998.html)**（沧海）\n\n**[一道常被人轻视的前端JS面试题](http://www.cnblogs.com/xxcanghai/p/5189353.html)**（沧海）\n\n**[Web前端开发测试题](http://www.w3cplus.com/css/front-end-web-development-quiz.html)**（大漠，淘宝）\n\n**[常见前端面试题及答案](http://www.cnblogs.com/syfwhu/p/4434132.html)**（默语，腾讯）\n\n**[前端工作面试问题（一）](http://blog.zhangruipeng.me/2015/03/15/JavaScript-Interview-1/)**（Ruipeng Zhang，哈工大）\n\n**[面试经验分享之数据结构、算法题](http://frank19900731.github.io/blog/2014/11/18/mian-shi-jing-yan-fen-xiang-zhi-shu-ju-jie-gou-suan-fa-fen-xiang/)**（Song Chengru，清华）\n\n**[名企笔试](http://group.jobbole.com/category/tech/interview-test/)**（伯乐在线）\n\n**[如何面试一名前端开发工程师？](http://www.html-js.com/article/2961)**（芋头，大搜车）\n\n**[国内大型互联网公司（如BAT）对于web前端开发方向校招都考些什么？——知乎](https://www.zhihu.com/question/26188893)**\n\n**[如何面试前端工程师？——知乎](https://www.zhihu.com/question/19568008)**\n\n**[初级前端面试需要带什么作品？——知乎](https://www.zhihu.com/question/39486348)**\n\n### 5. 网站、专栏、周刊\n\n**[前端开发 —— 知乎](https://www.zhihu.com/topic/19550901/top-answers)**\n\n**[前端 —— 稀土掘金](http://gold.xitu.io/#/tag/%E5%89%8D%E7%AB%AF)**\n\n**[前端乱炖](http://www.html-js.com/)**\n\n**[w3cplus](http://www.w3cplus.com/)**\n\n**[w3ctech](http://www.w3ctech.com/)**\n\n**[前端开发博客](http://caibaojian.com/c/feature)**\n\n**[前端观察](https://www.qianduan.net/)**\n\n**[前端De早读课](http://www.zaoduke.net/)**\n\n**[前端大全 —— 伯乐在线](http://web.jobbole.com/)**\n\n**[前端 —— 开发早读课](http://www.devtoutiao.com/frontend)**\n\n**[imweb前端社区](http://imweb.io/)**\n\n**[奇舞周刊](http://www.75team.com/weekly/)**\n\n**[精华 —— CNode社区](https://cnodejs.org/?tab=good)**\n\n**[web前端开发 —— segmentfault](https://segmentfault.com/t/web%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/blogs)**\n\n**[发现：前端 —— 开发者头条](http://toutiao.io/explore?q=%E5%89%8D%E7%AB%AF)**\n\n### 6. 前端新技术\n\n**[谈谈前端『新』技术](http://weibo.com/p/1001603934708609234550)**（尤雨溪，Meteor）\n\n**[为什么整个互联网行业都缺前端工程师？](http://100offer.com/blog/posts/83)**（100offer）\n\n**[近几年前端技术盘点以及 2016 年技术发展方向](http://www.barretlee.com/blog/2015/12/10/after-framework-we-gonna-to-hug-data/)**（小胡子哥，淘宝）\n\n**[如何跟上前端开发的最新前沿](https://uptodate.frontendrescue.org/zh/)**（GitHub）\n"
  },
  {
    "path": "21-Front-end-Interview-questions/README.md",
    "content": "本文旨在加深对前端知识点的理解，资料来源于网络，由本人(博客：http://segmentfault.com/u/trigkit4) 收集整理。\n\n\n\n#### 一些开放性题目\n\n    1.自我介绍：除了基本个人信息以外，面试官更想听的是你与众不同的地方和你的优势。\n\n    2.项目介绍\n\n    3.如何看待前端开发？\n\n    4.平时是如何学习前端开发的？\n\n    5.未来三到五年的规划是怎样的？\n\n<br>\n\n\n\n#### position的值， relative和absolute分别是相对于谁进行定位的？\n\n\n- `absolute` :生成绝对定位的元素， 相对于最近一级的 定位不是 static 的父元素来进行定位。\n\n- `fixed` （老IE不支持）生成绝对定位的元素，通常相对于浏览器窗口或 frame 进行定位。\n\n- `relative` 生成相对定位的元素，相对于其在普通流中的位置进行定位。\n\n- `static`  默认值。没有定位，元素出现在正常的流中\n\n- `sticky` 生成粘性定位的元素，容器的位置根据正常文档流计算得出\n\n<br>\n\n\n\n#### 如何解决跨域问题\n\n>JSONP：\n\n原理是：动态插入`script`标签，通过`script`标签引入一个`js`文件，这个js文件载入成功后会执行我们在url参数中指定的函数，并且会把我们需要的`json`数据作为参数传入。\n\n\n\n由于同源策略的限制，`XmlHttpRequest`只允许请求当前源（域名、协议、端口）的资源，为了实现跨域请求，可以通过`script`标签实现跨域请求，然后在服务端输出JSON数据并执行回调函数，从而解决了跨域的数据请求。\n\n\n\n优点是兼容性好，简单易用，支持浏览器与服务器双向通信。缺点是只支持GET请求。\n\n`JSONP`：`json+padding`（内填充），顾名思义，就是把JSON填充到一个盒子里\n\n```js\n<script>\n    function createJs(sUrl){\n\n        var oScript = document.createElement('script');\n        oScript.type = 'text/javascript';\n        oScript.src = sUrl;\n        document.getElementsByTagName('head')[0].appendChild(oScript);\n    }\n\n    createJs('jsonp.js');\n\n    box({\n       'name': 'test'\n    });\n\n    function box(json){\n        alert(json.name);\n    }\n</script>\n```\n\n\n>CORS\n\n服务器端对于`CORS`的支持，主要就是通过设置`Access-Control-Allow-Origin`来进行的。如果浏览器检测到相应的设置，就可以允许`Ajax`进行跨域的访问。\n\n\n\n>通过修改document.domain来跨子域\n\n将子域和主域的`document.domain`设为同一个主域.前提条件：这两个域名必须属于同一个基础域名!而且所用的协议，端口都要一致，否则无法利用`document.domain`进行跨域\n\n\n\n主域相同的使用`document.domain`\n\n>使用window.name来进行跨域\n\n\n\n`window`对象有个`name`属性，该属性有个特征：即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个`window.name`的，每个页面对`window.name`都有读写的权限，`window.name`是持久存在一个窗口载入过的所有页面中的\n\n\n\n\n>使用HTML5中新引进的`window.postMessage`方法来跨域传送数据\n\n\n\n还有flash、在服务器上设置代理页面等跨域方式。个人认为`window.name`的方法既不复杂，也能兼容到几乎所有浏览器，这真是极好的一种跨域方法。\n\n\n\n\n\n#### `XML`和`JSON`的区别？\n\n```html\n(1).数据体积方面。\n\nJSON相对于XML来讲，数据的体积小，传递的速度更快些。\n\n(2).数据交互方面。\n\nJSON与JavaScript的交互更加方便，更容易解析处理，更好的数据交互。\n\n(3).数据描述方面。\n\nJSON对数据的描述性比XML较差。\n\n(4).传输速度方面。\n\nJSON的速度要远远快于XML。\n```\n\n\n\n#### 谈谈你对webpack的看法\n\n\n\n`WebPack` 是一个模块打包工具，你可以使用`WebPack`管理你的模块依赖，并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web开发中所用到的`HTML、Javascript、CSS`以及各种静态文件（图片、字体等），让开发过程更加高效。对于不同类型的资源，`webpack`有对应的模块加载器。`webpack`模块打包器会分析模块间的依赖关系，最后 生成了优化且合并后的静态资源。\n\n\n`webpack`的两大特色：\n\n    1.code splitting（可以自动完成）\n\n    2.loader 可以处理各种类型的静态文件，并且支持串联操作\n\n\n`webpack` 是以` commonJS `的形式来书写脚本滴，但对 `AMD/CMD` 的支持也很全面，方便旧项目进行代码迁移。\n\n`webpack`具有`requireJs`和`browserify`的功能，但仍有很多自己的新特性：\n\n\n```\n1. 对 CommonJS 、 AMD 、ES6的语法做了兼容\n\n2. 对js、css、图片等资源文件都支持打包\n\n3. 串联式模块加载器以及插件机制，让其具有更好的灵活性和扩展性，例如提供对CoffeeScript、ES6的支持\n\n4. 有独立的配置文件webpack.config.js\n\n5. 可以将代码切割成不同的chunk，实现按需加载，降低了初始化时间\n\n6. 支持 SourceUrls 和 SourceMaps，易于调试\n\n7. 具有强大的Plugin接口，大多是内部插件，使用起来比较灵活\n\n8.webpack 使用异步 IO 并具有多级缓存。这使得 webpack 很快且在增量编译上更加快\n```\n\n#### 说说TCP传输的三次握手四次挥手策略\n\n 为了准确无误地把数据送达目标处，`TCP`协议采用了三次握手策略。用TCP协议把数据包送出去后，`TCP`不会对传送    后的情况置之不理，它一定会向对方确认是否成功送达。握手过程中使用了TCP的标志：`SYN`和`ACK`。\n\n发送端首先发送一个带`SYN`标志的数据包给对方。接收端收到后，回传一个带有`SYN/ACK`标志的数据包以示传达确认信息。\n最后，发送端再回传一个带`ACK`标志的数据包，代表“握手”结束。\n若在握手过程中某个阶段莫名中断，`TCP`协议会再次以相同的顺序发送相同的数据包。\n\n\n\n<br>\n\n>断开一个TCP连接则需要“四次握手”：\n\n- 第一次挥手：主动关闭方发送一个`FIN`，用来关闭主动方到被动关闭方的数据传送，也就是主动关闭方告诉被动关闭方：我已经不 会再给你发数据了(当然，在fin包之前发送出去的数据，如果没有收到对应的ack确认报文，主动关闭方依然会重发这些数据)，但是，此时主动关闭方还可 以接受数据。\n\n- 第二次挥手：被动关闭方收到`FIN`包后，发送一个`ACK`给对方，确认序号为收到序号`+1`（与`SYN`相同，一个`FIN`占用一个序号）。\n\n- 第三次挥手：被动关闭方发送一个`FIN`，用来关闭被动关闭方到主动关闭方的数据传送，也就是告诉主动关闭方，我的数据也发送完了，不会再给你发数据了。\n\n- 第四次挥手：主动关闭方收到`FIN`后，发送一个`ACK`给被动关闭方，确认序号为收到序号+1，至此，完成四次挥手。\n\n\n#### TCP和UDP的区别\n\n`TCP`（Transmission Control Protocol，传输控制协议）是基于连接的协议，也就是说，在正式收发数据前，必须和对方建立可靠的连接。一个`TCP`连接必须要经过三次“对话”才能建立起来\n\n`UDP`（User Data Protocol，用户数据报协议）是与TCP相对应的协议。它是面向非连接的协议，它不与对方建立连接，而是直接就把数据包发送过去！\n  UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。\n\n\n#### 说说你对作用域链的理解\n\n作用域链的作用是保证执行环境里有权访问的变量和函数是有序的，作用域链的变量只能向上访问，变量访问到`window`对象即被终止，作用域链向下访问变量是不被允许的。\n\n\n#### 创建ajax过程\n\n```js\n(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.\n\n(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.\n\n(3)设置响应HTTP请求状态变化的函数.\n\n(4)发送HTTP请求.\n\n(5)获取异步调用返回的数据.\n\n(6)使用JavaScript和DOM实现局部刷新.\n```\n\n#### 渐进增强和优雅降级\n\n渐进增强 ：针对低版本浏览器进行构建页面，保证最基本的功能，然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。\n\n\n\n优雅降级 ：一开始就构建完整的功能，然后再针对低版本浏览器进行兼容。\n\n\n\n#### 常见web安全及防护原理\n\n>sql注入原理\n\n就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串，最终达到欺骗服务器执行恶意的SQL命令。\n\n总的来说有以下几点：\n\n```\n\n    1.永远不要信任用户的输入，要对用户的输入进行校验，可以通过正则表达式，或限制长度，对单引号和双\"-\"进行转换等。\n\n    2.永远不要使用动态拼装SQL，可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。\n\n    3.永远不要使用管理员权限的数据库连接，为每个应用使用单独的权限有限的数据库连接。\n\n    4.不要把机密信息明文存放，请加密或者hash掉密码和敏感的信息。\n```\n\n>XSS原理及防范\n\nXss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意 `html`标签或者`javascript`代码。比如：攻击者在论坛中放一个\n\n看似安全的链接，骗取用户点击后，窃取`cookie`中的用户私密信息；或者攻击者在论坛中加一个恶意表单，\n\n当用户提交表单的时候，却把信息传送到攻击者的服务器中，而不是用户原本以为的信任站点。\n\n\n\n>XSS防范方法\n\n首先代码里对用户输入的地方和变量都需要仔细检查长度和对`”<”,”>”,”;”,”’”`等字符做过滤；其次任何内容写到页面之前都必须加以`encode`，避免不小心把`html tag` 弄出来。这一个层面做好，至少可以堵住超过一半的`XSS` 攻击。\n\n\n首先，避免直接在`cookie` 中泄露用户隐私，例如email、密码等等。\n\n\n其次，通过使`cookie` 和系统`ip` 绑定来降低`cookie` 泄露后的危险。这样攻击者得到的`cookie` 没有实际价值，不可能拿来重放。\n\n\n如果网站不需要再浏览器端对`cookie` 进行操作，可以在`Set-Cookie` 末尾加上`HttpOnly` 来防止`javascript` 代码直接获取`cookie` 。\n\n\n尽量采用`POST` 而非`GET` 提交表单\n\n\n\n>XSS与CSRF有什么区别吗？\n\n`XSS`是获取信息，不需要提前知道其他用户页面的代码和数据包。`CSRF`是代替用户完成指定的动作，需要知道其他用户页面的代码和数据包。\n\n\n要完成一次`CSRF`攻击，受害者必须依次完成两个步骤：\n\n```\n登录受信任网站A，并在本地生成Cookie。\n\n在不登出A的情况下，访问危险网站B。\n```\n\n\n>CSRF的防御\n\n- 服务端的`CSRF`方式方法很多样，但总的思想都是一致的，就是在客户端页面增加伪随机数。\n\n- 通过验证码的方法\n\n\n#### Web Worker 和webSocket\n\n>worker主线程:\n\n\n```js\n    1.通过 worker = new Worker( url ) 加载一个JS文件来创建一个worker，同时返回一个worker实例。\n\n    2.通过worker.postMessage( data ) 方法来向worker发送数据。\n\n    3.绑定worker.onmessage方法来接收worker发送过来的数据。\n\n    4.可以使用 worker.terminate() 来终止一个worker的执行。\n```\n\n`WebSocket`是`Web`应用程序的传输协议，它提供了双向的，按序到达的数据流。他是一个`HTML5`协议，`WebSocket`的连接是持久的，他通过在客户端和服务器之间保持双工连接，服务器的更新可以被及时推送给客户端，而不需要客户端以一定时间间隔去轮询。\n\n\n\n#### HTTP和HTTPS\n\n`HTTP`协议通常承载于TCP协议之上，在`HTTP`和`TCP`之间添加一个安全协议层（`SSL`或`TSL`），这个时候，就成了我们常说的HTTPS。\n\n\n默认HTTP的端口号为80，`HTTPS`的端口号为443。\n\n\n\n#### 为什么`HTTPS`安全\n\n因为网络请求需要中间有很多的服务器路由器的转发。中间的节点都可能篡改信息，而如果使用`HTTPS`，密钥在你和终点站才有。`https`之所以比`http`安全，是因为他利用`ssl/tls`协议传输。它包含证书，卸载，流量转发，负载均衡，页面适配，浏览器适配，refer传递等。保障了传输过程的安全性\n\n\n\n#### 对前端模块化的认识\n\n\n\n>AMD 是 `RequireJS` 在推广过程中对模块定义的规范化产出。\n\n>CMD 是 `SeaJS` 在推广过程中对模块定义的规范化产出。\n\n\n\n`AMD` 是提前执行，`CMD` 是延迟执行。\n\n`AMD`推荐的风格通过返回一个对象做为模块对象，`CommonJS`的风格通过对`module.exports`或`exports`的属性赋值来达到暴露模块对象的目的。\n\n\n\n>CMD模块方式\n\n\n```js\n    define(function(require, exports, module) {\n\n      // 模块代码\n\n    });\n```\n\n\n#### Javascript垃圾回收方法\n\n>标记清除（mark and sweep）\n\n这是JavaScript最常见的垃圾回收方式，当变量进入执行环境的时候，比如函数中声明一个变量，垃圾回收器将其标记为“进入环境”，当变量离开环境的时候（函数执行结束）将其标记为“离开环境”。\n\n垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记，然后去掉环境中的变量以及被环境中变量所引用的变量（闭包），在这些完成之后仍存在标记的就是要删除的变量了\n\n>引用计数(reference counting)\n\n在低版本IE中经常会出现内存泄露，很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数，当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1，如果该变量的值变成了另外一个，则这个值得引用次数减1，当这个值的引用次数变为0的时 候，说明没有变量在使用，这个值没法被访问了，因此可以将其占用的空间回收，这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。\n\n\n在IE中虽然`JavaScript`对象通过标记清除的方式进行垃圾回收，但BOM与DOM对象却是通过引用计数回收垃圾的，\n也就是说只要涉及`BOM`及DOM就会出现循环引用问题。\n\n\n\n#### 你觉得前端工程的价值体现在哪\n\n\n\n    为简化用户使用提供技术支持（交互部分）\n\n    为多个浏览器兼容性提供支持\n\n    为提高用户浏览速度（浏览器性能）提供支持\n\n    为跨平台或者其他基于webkit或其他渲染引擎的应用提供支持\n\n    为展示数据提供支持（数据接口）\n\n\n\n#### 谈谈性能优化问题\n\n\n\n代码层面：避免使用css表达式，避免使用高级选择器，通配选择器。\n\n缓存利用：缓存Ajax，使用CDN，使用外部js和css文件以便缓存，添加Expires头，服务端配置Etag，减少DNS查找等\n\n请求数量：合并样式和脚本，使用css图片精灵，初始首屏之外的图片资源按需加载，静态资源延迟加载。\n\n请求带宽：压缩文件，开启GZIP，\n\n\n\n>代码层面的优化\n\n\n\n- 用`hash-table`来优化查找\n\n- 少用全局变量\n\n- 用`innerHTML`代替`DOM`操作，减少`DOM`操作次数，优化`javascript`性能\n\n- 用`setTimeout`来避免页面失去响应\n\n- 缓存DOM节点查找的结果\n\n- 避免使用CSS Expression\n\n- 避免全局查询\n\n- 避免使用with(with会创建自己的作用域，会增加作用域链长度)\n\n- 多个变量声明合并\n\n- 避免图片和iFrame等的空Src。空Src会重新加载当前页面，影响速度和效率\n- 尽量避免写在HTML标签中写Style属性\n\n#### 移动端性能优化\n\n- 尽量使用css3动画，开启硬件加速。\n- 适当使用`touch`事件代替`click`事件。\n- 避免使用`css3`渐变阴影效果。\n- 可以用`transform: translateZ(0)`来开启硬件加速。\n- 不滥用Float。Float在渲染时计算量比较大，尽量减少使用\n- 不滥用Web字体。Web字体需要下载，解析，重绘当前页面，尽量减少使用。\n- 合理使用requestAnimationFrame动画代替setTimeout\n- CSS中的属性（CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video）会触发GPU渲染，请合理使用。过渡使用会引发手机过耗电增加\n- PC端的在移动端同样适用\n\n>相关阅读：[如何做到一秒渲染一个移动页面](https://github.com/cssmagic/blog/issues/20)\n\n\n#### 什么是Etag？\n\n\n当发送一个服务器请求时，浏览器首先会进行缓存过期判断。浏览器根据缓存过期时间判断缓存文件是否过期。<br>\n\n情景一：若没有过期，则不向服务器发送请求，直接使用缓存中的结果，此时我们在浏览器控制台中可以看到  `200 OK`(from cache) ，此时的情况就是完全使用缓存，浏览器和服务器没有任何交互的。\n\n\n情景二：若已过期，则向服务器发送请求，此时请求中会带上①中设置的文件修改时间，和`Etag`\n\n\n\n然后，进行资源更新判断。服务器根据浏览器传过来的文件修改时间，判断自浏览器上一次请求之后，文件是不是没有被修改过；根据`Etag`，判断文件内容自上一次请求之后，有没有发生变化\n\n情形一：若两种判断的结论都是文件没有被修改过，则服务器就不给浏览器发`index.html`的内容了，直接告诉它，文件没有被修改过，你用你那边的缓存吧—— `304 Not Modified`，此时浏览器就会从本地缓存中获取`index.html`的内容。此时的情况叫协议缓存，浏览器和服务器之间有一次请求交互。<br>\n\n情形二：若修改时间和文件内容判断有任意一个没有通过，则服务器会受理此次请求，之后的操作同①\n\n<br>\n\n① 只有get请求会被缓存，post请求不会\n\n\n#### Expires和Cache-Control\n\n\n\n`Expires`要求客户端和服务端的时钟严格同步。`HTTP1.1`引入`Cache-Control`来克服Expires头的限制。如果max-age和Expires同时出现，则max-age有更高的优先级。\n\n\n```js\n    Cache-Control: no-cache, private, max-age=0\n\n    ETag: abcde\n\n    Expires: Thu, 15 Apr 2014 20:00:00 GMT\n\n    Pragma: private\n\n    Last-Modified: $now // RFC1123 format\n```\n\n\n#### ETag应用:\n\n\n`Etag`由服务器端生成，客户端通过`If-Match`或者说`If-None-Match`这个条件判断请求来验证资源是否修改。常见的是使用`If-None-Match`。请求一个文件的流程可能如下：\n\n====第一次请求===\n\n\n    1.客户端发起 HTTP GET 请求一个文件；\n\n    2.服务器处理请求，返回文件内容和一堆Header，当然包括Etag(例如\"2e681a-6-5d044840\")(假设服务器支持Etag生成和已经开启了Etag).状态码200\n\n\n\n====第二次请求===\n\n\n\n    客户端发起 HTTP GET 请求一个文件，注意这个时候客户端同时发送一个If-None-Match头，这个头的内容就是第一次请求时服务器返回的Etag：2e681a-6-5d0448402.服务器判断发送过来的Etag和计算出来的Etag匹配，因此If-None-Match为False，不返回200，返回304，客户端继续使用本地缓存；流程很简单，问题是，如果服务器又设置了Cache-Control:max-age和Expires呢，怎么办\n\n\n答案是同时使用，也就是说在完全匹配`If-Modified-Since`和`If-None-Match`即检查完修改时间和`Etag`之后，\n\n服务器才能返回304.(不要陷入到底使用谁的问题怪圈)\n\n\n\n为什么使用Etag请求头?\n\nEtag 主要为了解决 `Last-Modified` 无法解决的一些问题。\n\n\n\n#### 栈和队列的区别?\n\n\n\n    栈的插入和删除操作都是在一端进行的，而队列的操作却是在两端进行的。\n\n    队列先进先出，栈先进后出。\n\n    栈只允许在表尾一端进行插入和删除，而队列只允许在表尾一端进行插入，在表头一端进行删除\n\n\n\n#### 栈和堆的区别？\n\n    栈区（stack）—   由编译器自动分配释放   ，存放函数的参数值，局部变量的值等。\n\n    堆区（heap）   —   一般由程序员分配释放，   若程序员不释放，程序结束时可能由OS回收。\n\n    堆（数据结构）：堆可以被看成是一棵树，如：堆排序；\n\n    栈（数据结构）：一种先进后出的数据结构。\n\n\n#### 快速 排序的思想并实现一个快排？\n\n\n\n\"快速排序\"的思想很简单，整个排序过程只需要三步：\n\n　　（1）在数据集之中，找一个基准点\n\n　　（2）建立两个数组，分别存储左边和右边的数组\n\n　　（3）利用递归进行下次比较\n\n\n```js\n    <script type=\"text/javascript\">\n\n        function quickSort(arr){\n            if(arr.length<=1){\n                return arr;//如果数组只有一个数，就直接返回；\n            }\n\n            var num = Math.floor(arr.length/2);//找到中间数的索引值，如果是浮点数，则向下取整\n\n            var numValue = arr.splice(num,1);//找到中间数的值\n            var left = [];\n            var right = [];\n\n            for(var i=0;i<arr.length;i++){\n                if(arr[i]<numValue){\n                    left.push(arr[i]);//基准点的左边的数传到左边数组\n                }\n                else{\n                   right.push(arr[i]);//基准点的右边的数传到右边数组\n                }\n            }\n\n            return quickSort(left).concat([numValue],quickSort(right));//递归不断重复比较\n        }\n\n        alert(quickSort([32,45,37,16,2,87]));//弹出“2,16,32,37,45,87”\n\n    </script>\n```\n\n\n#### 你觉得jQuery或zepto源码有哪些写的好的地方\n\n(答案仅供参考)\n\n`jquery`源码封装在一个匿名函数的自执行环境中，有助于防止变量的全局污染，然后通过传入window对象参数，可以使window对象作为局部变量使用，好处是当`jquery`中访问window对象的时候，就不用将作用域链退回到顶层作用域了，从而可以更快的访问`window`对象。同样，传入`undefined`参数，可以缩短查找undefined时的作用域链。\n\n\n\n\n```js\n    (function( window, undefined ) {\n\n         //用一个函数域包起来，就是所谓的沙箱\n\n         //在这里边var定义的变量，属于这个函数域内的局部变量，避免污染全局\n\n         //把当前沙箱需要的外部变量通过函数参数引入进来\n\n         //只要保证参数对内提供的接口的一致性，你还可以随意替换传进来的这个参数\n\n        window.jQuery = window.$ = jQuery;\n\n    })( window );\n```\n\n\njquery将一些原型属性和方法封装在了`jquery.prototype`中，为了缩短名称，又赋值给了`jquery.fn`，这是很形象的写法。\n\n\n\n有一些数组或对象的方法经常能使用到，jQuery将其保存为局部变量以提高访问速度。\n\n\n\n\n`jquery`实现的链式调用可以节约代码，所返回的都是同一个对象，可以提高代码效率。\n\n\n\n#### ES6的了解\n\n新增模板字符串（为JavaScript提供了简单的字符串插值功能）、箭头函数（操作符左边为输入的参数，而右边则是进行的操作以及返回的值`Inputs=>outputs`。）、`for-of`（用来遍历数据—例如数组中的值。）`arguments`对象可被不定参数和默认参数完美代替。`ES6`将`promise`对象纳入规范，提供了原生的`Promise`对象。增加了`let`和`const`命令，用来声明变量。增加了块级作用域。let命令实际上就增加了块级作用域。ES6规定，`var`命令和`function`命令声明的全局变量，属于全局对象的属性；`let`命令、`const`命令、`class`命令声明的全局变量，不属于全局对象的属性。。还有就是引入`module`模块的概念\n\n\n\n#### js继承方式及其优缺点\n\n\n\n>原型链继承的缺点\n\n\n    一是字面量重写原型会中断关系，使用引用类型的原型，并且子类型还无法给超类型传递参数。\n\n\n>借用构造函数（类式继承）\n\n\n\n    借用构造函数虽然解决了刚才两种问题，但没有原型，则复用无从谈起。所以我们需要原型链+借用构造函数的模式，这种模式称为组合继承\n\n\n\n>组合式继承\n\n\n\n    组合式继承是比较常用的一种继承方法，其背后的思路是 使用原型链实现对原型属性和方法的继承，而通过借用构造函数来实现对实例属性的继承。这样，既通过在原型上定义方法实现了函数复用，又保证每个实例都有它自己的属性。\n\n具体请看：[JavaScript继承方式详解](http://segmentfault.com/a/1190000002440502)\n\n\n\n#### 关于Http 2.0 你知道多少？\n\n\n\n`HTTP/2`引入了“服务端推（server push）”的概念，它允许服务端在客户端需要数据之前就主动地将数据发送到客户端缓存中，从而提高性能。\n\n`HTTP/2`提供更多的加密支持\n\n`HTTP/2`使用多路技术，允许多个消息在一个连接上同时交差。\n\n它增加了头压缩（header compression），因此即使非常小的请求，其请求和响应的`header`都只会占用很小比例的带宽。\n\n\n\n<br>\n#### defer和async\n>defer并行加载js文件，会按照页面上script标签的顺序执行\n>async并行加载js文件，下载完成立即执行，不会按照页面上script标签的顺序执行\n\n\n\n#### 谈谈浮动和清除浮动\n\n浮动的框可以向左或向右移动，直到他的外边缘碰到包含框或另一个浮动框的边框为止。由于浮动框不在文档的普通流中，所以文档的普通流的块框表现得就像浮动框不存在一样。浮动的块框会漂浮在文档普通流的块框上。\n\n\n\n#### 如何评价AngularJS和BackboneJS\n\n`backbone`具有依赖性，依赖`underscore.js`。`Backbone + Underscore + jQuery(or Zepto)` 就比一个`AngularJS` 多出了2 次HTTP请求.\n\n<br>\n\n`Backbone`的`Model`没有与UI视图数据绑定，而是需要在View中自行操作DOM来更新或读取UI数据。`AngularJS`与此相反，Model直接与UI视图绑定，`Model`与UI视图的关系，通过`directive`封装，`AngularJS`内置的通用`directive`，就能实现大部分操作了，也就是说，基本不必关心`Model`与UI视图的关系，直接操作Model就行了，UI视图自动更新。\n\n<br>\n\n`AngularJS`的`directive`，你输入特定数据，他就能输出相应UI视图。是一个比较完善的前端MVW框架，包含模板，数据双向绑定，路由，模块化，服务，依赖注入等所有功能，模板功能强大丰富，并且是声明式的，自带了丰富的 Angular 指令。\n\n\n\n#### 用过哪些设计模式？\n\n\n\n>工厂模式：\n\n    主要好处就是可以消除对象间的耦合，通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复。\n\n        工厂模式解决了重复实例化的问题 ，但还有一个问题,那就是识别问题，因为根本无法 搞清楚他们到底是哪个对象的实例。\n\n\n    function createObject(name,age,profession){//集中实例化的函数var obj = new Object();\n        obj.name = name;\n        obj.age = age;\n        obj.profession = profession;\n        obj.move = function () {\n            return this.name + ' at ' + this.age + ' engaged in ' + this.profession;\n        };\n        return obj;\n    }\n    var test1 = createObject('trigkit4',22,'programmer');//第一个实例var test2 = createObject('mike',25,'engineer');//第二个实例\n\n\n<br>\n\n\n\n>构造函数模式\n\n\n使用构造函数的方法 ，即解决了重复实例化的问题 ，又解决了对象识别的问题，该模式与工厂模式的不同之处在于：\n\n\n\n    1.构造函数方法没有显示的创建对象 (new Object());\n\n    2.直接将属性和方法赋值给 this 对象;\n\n    3.没有 renturn 语句。\n\n\n\n\n#### 说说你对闭包的理解\n\n\n\n使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染，缺点是闭包会常驻内存，会增大内存使用量，使用不当很容易造成内存泄露。在js中，函数即闭包，只有函数才会产生作用域的概念\n\n\n闭包有三个特性：\n\n>1.函数嵌套函数\n\n>2.函数内部可以引用外部的参数和变量\n\n>3.参数和变量不会被垃圾回收机制回收\n\n\n 具体请看：[详解js闭包](http://segmentfault.com/a/1190000000652891)\n\n\n#### 请你谈谈Cookie的弊端\n\n\n`cookie`虽然在持久保存客户端数据提供了方便，分担了服务器存储的负担，但还是有很多局限性的。\n\n第一：每个特定的域名下最多生成20个`cookie`\n\n\n\n    1.IE6或更低版本最多20个cookie\n\n    2.IE7和之后的版本最后可以有50个cookie。\n\n    3.Firefox最多50个cookie\n\n    4.chrome和Safari没有做硬性限制\n\n\n\n`IE`和`Opera` 会清理近期最少使用的`cookie`，`Firefox`会随机清理`cookie`。\n\n\n\n`cookie`的最大大约为`4096`字节，为了兼容性，一般不能超过`4095`字节。\n\n\n\nIE 提供了一种存储可以持久化用户数据，叫做`userdata`，从`IE5.0`就开始支持。每个数据最多128K，每个域名下最多1M。这个持久化数据放在缓存中，如果缓存没有清理，那么会一直存在。\n\n\n\n\n\n>优点：极高的扩展性和可用性\n\n\n\n    1.通过良好的编程，控制保存在cookie中的session对象的大小。\n\n    2.通过加密和安全传输技术（SSL），减少cookie被破解的可能性。\n\n    3.只在cookie中存放不敏感数据，即使被盗也不会有重大损失。\n\n    4.控制cookie的生命期，使之不会永远有效。偷盗者很可能拿到一个过期的cookie。\n\n\n>缺点：\n\n    1.`Cookie`数量和长度的限制。每个domain最多只能有20条cookie，每个cookie长度不能超过4KB，否则会被截掉.\n\n\n    2.安全性问题。如果cookie被人拦截了，那人就可以取得所有的session信息。即使加密也与事无补，因为拦截者并不需要知道cookie的意义，他只要原样转发cookie就可以达到目的了。\n\n    3.有些状态不可能保存在客户端。例如，为了防止重复提交表单，我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端，那么它起不到任何作用。\n\n\n\n#### 浏览器本地存储\n\n\n在较高版本的浏览器中，`js`提供了`sessionStorage`和`globalStorage`。在`HTML5`中提供了`localStorage`来取代`globalStorage`。\n\n\n`html5`中的`Web Storage`包括了两种存储方式：`sessionStorage`和`localStorage`。\n\n\n`sessionStorage`用于本地存储一个会话（session）中的数据，这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此`sessionStorage`不是一种持久化的本地存储，仅仅是会话级别的存储。\n\n\n而`localStorage`用于持久化的本地存储，除非主动删除数据，否则数据是永远不会过期的。\n\n\n\n#### web storage和cookie的区别\n\n\n`Web Storage`的概念和`cookie`相似，区别是它是为了更大容量存储设计的。`Cookie`的大小是受限的，并且每次你请求一个新的页面的时候`Cookie`都会被发送过去，这样无形中浪费了带宽，另外`cookie`还需要指定作用域，不可以跨域调用。\n\n\n除此之外，`Web Storage`拥有`setItem,getItem,removeItem,clear`等方法，不像`cookie`需要前端开发者自己封装`setCookie，getCookie`。\n\n\n但是`cookie`也是不可以或缺的：`cookie`的作用是与服务器进行交互，作为`HTTP`规范的一部分而存在 ，而`Web Storage`仅仅是为了在本地“存储”数据而生\n\n\n\n浏览器的支持除了`IE７`及以下不支持外，其他标准浏览器都完全支持(ie及FF需在web服务器里运行)，值得一提的是IE总是办好事，例如IE7、IE6中的`userData`其实就是`javascript`本地存储的解决方案。通过简单的代码封装可以统一到所有的浏览器都支持`web storage`。\n\n\n`localStorage`和`sessionStorage`都具有相同的操作方法，例如`setItem、getItem`和`removeItem`等\n\n\n#### cookie 和session 的区别：\n\n     1、cookie数据存放在客户的浏览器上，session数据放在服务器上。\n\n     2、cookie不是很安全，别人可以分析存放在本地的COOKIE并进行COOKIE欺骗\n\n        考虑到安全应当使用session。\n\n     3、session会在一定时间内保存在服务器上。当访问增多，会比较占用你服务器的性能\n\n         考虑到减轻服务器性能方面，应当使用COOKIE。\n\n     4、单个cookie保存的数据不能超过4K，很多浏览器都限制一个站点最多保存20个cookie。\n\n     5、所以个人建议：\n\n        将登陆信息等重要信息存放为SESSION\n\n        其他信息如果需要保留，可以放在COOKIE中\n\n\n\n\n\n>`display:none`和`visibility:hidden`的区别？\n\n\n    display:none  隐藏对应的元素，在文档布局中不再给它分配空间，它各边的元素会合拢，就当他从来不存在。\n\n    visibility:hidden  隐藏对应的元素，但是在文档布局中仍保留原来的空间。\n\n\n\n>CSS中` link` 和`@import `的区别是？\n\n    (1) link属于HTML标签，而@import是CSS提供的;\n\n    (2) 页面被加载的时，link会同时被加载，而@import被引用的CSS会等到引用它的CSS文件被加载完再加载;\n\n    (3) import只在IE5以上才能识别，而link是HTML标签，无兼容问题;\n\n    (4) link方式的样式的权重 高于@import的权重.\n\n\n\n>`position:absolute`和`float`属性的异同\n\n\n\n- 共同点：对内联元素设置`float`和`absolute`属性，可以让元素脱离文档流，并且可以设置其宽高。\n\n\n- 不同点：`float`仍会占据位置，`absolute`会覆盖文档流中的其他元素。\n\n\n\n>介绍一下box-sizing属性？\n\n\n`box-sizing`属性主要用来控制元素的盒模型的解析模式。默认值是`content-box`。\n\n\n- `content-box`：让元素维持W3C的标准盒模型。元素的宽度/高度由`border + padding + content`的宽度/高度决定，设置`width/height`属性指的是`content`部分的宽/高\n\n- `border-box`：让元素维持IE传统盒模型（IE6以下版本和IE6~7的怪异模式）。设置`width/height`属性指的是`border + padding + content`\n\n\n\n标准浏览器下，按照W3C规范对盒模型解析，一旦修改了元素的边框或内距，就会影响元素的盒子尺寸，就不得不重新计算元素的盒子尺寸，从而影响整个页面的布局。\n\n>CSS 选择符有哪些？哪些属性可以继承？优先级算法如何计算？ CSS3新增伪类有那些？\n\n```css\n    1.id选择器（ # myid）\n\n    2.类选择器（.myclassname）\n\n    3.标签选择器（div, h1, p）\n\n    4.相邻选择器（h1 + p）\n\n    5.子选择器（ul > li）\n\n    6.后代选择器（li a）\n\n    7.通配符选择器（ * ）\n\n    8.属性选择器（a[rel = \"external\"]）\n\n    9.伪类选择器（a: hover, li:nth-child）\n```\n\n\n**优先级为:**\n\n\n`!important >  id > class > tag `\n\n`important` 比 内联优先级高,但内联比 `id` 要高\n\n\n\n>CSS3新增伪类举例：\n\n```css\n    p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。\n\n    p:last-of-type  选择属于其父元素的最后 <p> 元素的每个 <p> 元素。\n\n    p:only-of-type  选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。\n\n    p:only-child    选择属于其父元素的唯一子元素的每个 <p> 元素。\n\n    p:nth-child(2)  选择属于其父元素的第二个子元素的每个 <p> 元素。\n\n    :enabled  :disabled 控制表单控件的禁用状态。\n\n    :checked        单选框或复选框被选中。\n```\n\n>CSS3有哪些新特性？\n\n    CSS3实现圆角（border-radius），阴影（box-shadow），\n\n    对文字加特效（text-shadow、），线性渐变（gradient），旋转（transform）\n\n    transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);//旋转,缩放,定位,倾斜\n\n    增加了更多的CSS选择器  多背景 rgba\n\n    在CSS3中唯一引入的伪元素是::selection.\n\n    媒体查询，多栏布局\n\n    border-image\n\nCSS3中新增了一种盒模型计算方式：`box-sizing`。盒模型默认的值是`content-box`, 新增的值是`padding-box`和`border-box`，几种盒模型计算元素宽高的区别如下：\n\n#### `content-box（默认）`\n\n布局所占宽度Width：\n\n```css\nWidth = width + padding-left + padding-right + border-left + border-right\n\n```\n\n布局所占高度Height:\n\n```css\nHeight = height + padding-top + padding-bottom + border-top + border-bottom\n\n```\n#### `padding-box`\n\n布局所占宽度Width：\n\n```css\nWidth = width(包含padding-left + padding-right) + border-top + border-bottom\n\n```\n\n布局所占高度Height:\n\n```css\nHeight = height(包含padding-top + padding-bottom) + border-top + border-bottom\n\n\n```\n\n#### `border-box`\n\n布局所占宽度Width：\n\n```css\nWidth = width(包含padding-left + padding-right + border-left + border-right)\n```\n\n布局所占高度Height:\n\n```css\nHeight = height(包含padding-top + padding-bottom + border-top + border-bottom)\n```\n\n>对BFC规范的理解？\n\n          BFC，块级格式化上下文，一个创建了新的BFC的盒子是独立布局的，盒子里面的子元素的样式不会影响到外面的元素。在同一个BFC中的两个毗邻的块级盒在垂直方向（和布局方向有关系）的margin会发生折叠。\n\n        （W3C CSS 2.1 规范中的一个概念，它决定了元素如何对其内容进行布局，以及与其他元素的关系和相互作用。\n\n\n\n#### 说说你对语义化的理解？\n\n    1，去掉或者丢失样式的时候能够让页面呈现出清晰的结构\n\n    2，有利于SEO：和搜索引擎建立良好沟通，有助于爬虫抓取更多的有效信息：爬虫依赖于标签来确定上下文和各个关键字的权重；\n\n    3，方便其他设备解析（如屏幕阅读器、盲人阅读器、移动设备）以意义的方式来渲染网页；\n\n    4，便于团队开发和维护，语义化更具可读性，是下一步吧网页的重要动向，遵循W3C标准的团队都遵循这个标准，可以减少差异化。\n\n\n\n#### Doctype作用? 严格模式与混杂模式如何区分？它们有何意义?\n\n\n\n1）、`<!DOCTYPE>` 声明位于文档中的最前面，处于 `<html>` 标签之前。告知浏览器以何种模式来渲染文档。\n\n\n2）、严格模式的排版和 `JS` 运作模式是  以该浏览器支持的最高标准运行。\n\n\n3）、在混杂模式中，页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。\n\n\n4）、`DOCTYPE`不存在或格式不正确会导致文档以混杂模式呈现。\n\n\n\n#### 你知道多少种`Doctype`文档类型？\n\n     该标签可声明三种 DTD 类型，分别表示严格版本、过渡版本以及基于框架的 HTML 文档。\n\n     HTML 4.01 规定了三种文档类型：Strict、Transitional 以及 Frameset。\n\n     XHTML 1.0 规定了三种 XML 文档类型：Strict、Transitional 以及 Frameset。\n\n    Standards （标准）模式（也就是严格呈现模式）用于呈现遵循最新标准的网页，而 Quirks\n\n     （包容）模式（也就是松散呈现模式或者兼容模式）用于呈现为传统浏览器而设计的网页。\n\n\n\n#### HTML与XHTML——二者有什么区别\n\n    区别：\n\n    1.所有的标记都必须要有一个相应的结束标记\n\n    2.所有标签的元素和属性的名字都必须使用小写\n\n    3.所有的XML标记都必须合理嵌套\n\n    4.所有的属性必须用引号\"\"括起来\n\n    5.把所有<和&特殊符号用编码表示\n\n    6.给所有属性赋一个值\n\n    7.不要在注释内容中使“--”\n\n    8.图片必须有说明文字\n\n\n#### 常见兼容性问题？\n\n\n    png24位的图片在iE6浏览器上出现背景，解决方案是做成PNG8.也可以引用一段脚本处理.\n\n    浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。\n\n    IE6双边距bug:块属性标签float后，又有横行的margin情况下，在ie6显示margin比设置的大。\n\n    浮动ie产生的双倍距离（IE6双边距问题：在IE6下，如果对元素设置了浮动，同时又设置了margin-left或margin-right，margin值会加倍。）\n\n    #box{ float:left; width:10px; margin:0 0 0 100px;}\n\n    这种情况之下IE会产生20px的距离，解决方案是在float的标签样式控制中加入\n    _display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)\n\n    渐进识别的方式，从总体中逐渐排除局部。\n\n\n      首先，巧妙的使用“\\9”这一标记，将IE游览器从所有情况中分离出来。\n\n      接着，再次使用“+”将IE8和IE7、IE6分离开来，这样IE8已经独立识别。\n\n      css\n\n          .bb{\n\n           background-color:#f1ee18;/*所有识别*/\n\n          .background-color:#00deff\\9; /*IE6、7、8识别*/\n\n          +background-color:#a200ff;/*IE6、7识别*/\n\n          _background-color:#1e0bd1;/*IE6识别*/\n\n          }\n\n\n    怪异模式问题：漏写DTD声明，Firefox仍然会按照标准模式来解析网页，但在IE中会触发\n    怪异模式。为避免怪异模式给我们带来不必要的麻烦，最好养成书写DTD声明的好习惯。现在\n    可以使用[html5](http://www.w3.org/TR/html5/single-page.html)推荐的写法：`<doctype html>`\n\n\n\n>上下margin重合问题\n\n    ie和ff都存在，相邻的两个div的margin-left和margin-right不会重合，但是margin-top和margin-bottom却会发生重合。\n\n    解决方法，养成良好的代码编写习惯，同时采用margin-top或者同时采用margin-bottom。\n\n\n\n#### 解释下浮动和它的工作原理？清除浮动的技巧\n\n\n\n    浮动元素脱离文档流，不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。\n\n\n    1.使用空标签清除浮动。\n\n       这种方法是在所有浮动标签后面添加一个空标签 定义css clear:both. 弊端就是增加了无意义标签。\n\n    2.使用overflow。\n\n       给包含浮动元素的父标签添加css属性 overflow:auto; zoom:1; zoom:1用于兼容IE6。\n\n    3.使用after伪对象清除浮动。\n\n       该方法只适用于非IE浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置 height:0，否则该元素会比实际高出若干像素；\n\n\n\n#### 浮动元素引起的问题和解决办法？\n\n\n    浮动元素引起的问题：\n\n    （1）父元素的高度无法被撑开，影响与父元素同级的元素\n\n    （2）与浮动元素同级的非浮动元素（内联元素）会跟随其后\n\n    （3）若非第一个元素浮动，则该元素之前的元素也需要浮动，否则会影响页面显示的结构\n\n\n\n>解决方法：\n\n使用`CSS`中的`clear:both`;属性来清除元素的浮动可解决2、3问题，对于问题1，添加如下样式，给父元素添加`clearfix`样式：\n\n```css\n    .clearfix:after{content: \".\";display: block;height: 0;clear: both;visibility: hidden;}\n\n    .clearfix{display: inline-block;} /* for IE/Mac */\n```\n\n**清除浮动的几种方法：**\n\n\n```css\n    1，额外标签法，<div style=\"clear:both;\"></div>（缺点：不过这个办法会增加额外的标签使HTML结构看起来不够简洁。）\n\n    2，使用after伪类\n\n    #parent:after{\n\n        content:\".\";\n\n        height:0;\n\n        visibility:hidden;\n\n        display:block;\n\n        clear:both;\n\n        }\n\n\n    3,浮动外部元素\n\n    4,设置overflow为hidden或者auto\n```\n\n\n\n#### DOM操作——怎样添加、移除、移动、复制、创建和查找节点。\n\n\n>1）创建新节点\n\n          createDocumentFragment()    //创建一个DOM片段\n\n          createElement()   //创建一个具体的元素\n\n          createTextNode()   //创建一个文本节点\n\n\n>2）添加、移除、替换、插入\n\n          appendChild()\n\n          removeChild()\n\n          replaceChild()\n\n          insertBefore() //并没有insertAfter()\n\n\n\n>3）查找\n\n\n\n          getElementsByTagName()    //通过标签名称\n\n          getElementsByName()    //通过元素的Name属性的值(IE容错能力较强，\n          会得到一个数组，其中包括id等于name值的)\n\n          getElementById()    //通过元素Id，唯一性\n\n\n\n#### html5有哪些新特性、移除了那些元素？如何处理HTML5新标签的浏览器兼容问题？如何区分 HTML 和 HTML5？\n\n\n\n      HTML5 现在已经不是 SGML 的子集，主要是关于图像，位置，存储，多任务等功能的增加。\n\n      拖拽释放(Drag and drop) API\n\n      语义化更好的内容标签（header,nav,footer,aside,article,section）\n\n      音频、视频API(audio,video)\n\n      画布(Canvas) API\n\n      地理(Geolocation) API\n\n      本地离线存储 localStorage 长期存储数据，浏览器关闭后数据不丢失；\n\n      sessionStorage 的数据在浏览器关闭后自动删除\n\n\n      表单控件，calendar、date、time、email、url、search\n\n      新的技术webworker, websocket, Geolocation\n\n\n\n\n>移除的元素\n\n\n    纯表现的元素：basefont，big，center，font, s，strike，tt，u；\n\n    对可用性产生负面影响的元素：frame，frameset，noframes；\n\n\n>支持HTML5新标签：\n\n\n```\n\n    IE8/IE7/IE6支持通过document.createElement方法产生的标签，\n\n    可以利用这一特性让这些浏览器支持HTML5新标签，\n\n    当然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架\n\n       <!--[if lt IE 9]>\n\n       <script> src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\"</script>\n\n       <![endif]-->\n\n    如何区分： DOCTYPE声明\\新增的结构元素\\功能元素\n```\n\n\n\n\n#### 如何实现浏览器内多个标签页之间的通信?\n\n\n```js\n    调用localstorge、cookies等本地存储方式\n```\n\n#### 什么是 FOUC（无样式内容闪烁）？你如何来避免 FOUC？\n\n\n```html\n     FOUC - Flash Of Unstyled Content 文档样式闪烁\n\n     <style type=\"text/css\" media=\"all\">@import \"../fouc.css\";</style>\n\n    而引用CSS文件的@import就是造成这个问题的罪魁祸首。IE会先加载整个HTML文档的DOM，然后再去导入外部的CSS文件，因此，在页面DOM加载完成到CSS导入完成中间会有一段时间页面上的内容是没有样式的，这段时间的长短跟网速，电脑速度都有关系。\n\n     解决方法简单的出奇，只要在<head>之间加入一个<link>或者<script>元素就可以了。\n```\n\n\n#### null和undefined的区别？\n\n\n`null`是一个表示\"无\"的对象，转为数值时为0；`undefined`是一个表示\"无\"的原始值，转为数值时为`NaN`。\n\n\n当声明的变量还未被初始化时，变量的默认值为`undefined`。\n\n`null`用来表示尚未存在的对象，常用来表示函数企图返回一个不存在的对象。\n\n\n`undefined`表示\"缺少值\"，就是此处应该有一个值，但是还没有定义。典型用法是：\n\n\n\n    （1）变量被声明了，但没有赋值时，就等于undefined。\n\n\n    （2) 调用函数时，应该提供的参数没有提供，该参数等于undefined。\n\n\n    （3）对象没有赋值的属性，该属性的值为undefined。\n\n\n    （4）函数没有返回值时，默认返回undefined。\n\n\n\n`null`表示\"没有对象\"，即该处不应该有值。典型用法是：\n\n\n    （1） 作为函数的参数，表示该函数的参数不是对象。\n\n    （2） 作为对象原型链的终点。\n\n\n\n#### new操作符具体干了什么呢?\n\n\n       1、创建一个空对象，并且 this 变量引用该对象，同时还继承了该函数的原型。\n\n       2、属性和方法被加入到 this 引用的对象中。\n\n       3、新创建的对象由 this 所引用，并且最后隐式的返回 this 。\n\n\n\n    var obj  = {};\n\n    obj.__proto__ = Base.prototype;\n\n    Base.call(obj);\n\n#### js延迟加载的方式有哪些？\n\n\n    defer和async、动态创建DOM方式（创建script，插入到DOM中，加载完毕后callBack）、按需异步载入js\n\n\n#### `call()` 和 `apply()` 的区别和作用？\n\n\n作用：动态改变某个类的某个方法的运行环境（执行上下文）。\n\n区别参见：[JavaScript学习总结（四）function函数部分][3]\n\n\n\n#### 哪些操作会造成内存泄漏？\n\n\n    内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。\n\n    垃圾回收器定期扫描对象，并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0（没有其他对象引用过该对象），或对该对象的惟一引用是循环的，那么该对象的内存即可回收。\n\n\n\n    setTimeout 的第一个参数使用字符串而非函数的话，会引发内存泄漏。\n\n    闭包、控制台日志、循环（在两个对象彼此引用且彼此保留时，就会产生一个循环）\n\n\n\n详见：[详解js变量、作用域及内存][4]\n\n\n\n\n\n#### 列举IE 与其他浏览器不一样的特性？\n\n\n\n- IE支持`currentStyle`，Firefox使用`getComputedStyle`\n\n- IE  使用`innerText`，Firefox使用`textContent`\n\n- 滤镜方面：IE:`filter:alpha(opacity= num)`；Firefox：`-moz-opacity:num`\n\n- 事件方面：IE：`attachEvent`：火狐是`addEventListener`\n\n- 鼠标位置：IE是`event.clientX`；火狐是`event.pageX`\n\n- IE使用`event.srcElement`；Firefox使用`event.target`\n\n- IE中消除list的原点仅需margin:0即可达到最终效果；FIrefox需要设置`margin:0;padding:0以及list-style:none`\n\n- CSS圆角：ie7以下不支持圆角\n\n\n\n\n\n\n#### WEB应用从服务器主动推送Data到客户端有那些方式？\n\n\n\nJavascript数据推送\n\n- `Commet`：基于HTTP长连接的服务器推送技术\n\n\n- 基于`WebSocket`的推送方案\n\n\n- `SSE`（Server-Send Event）：服务器推送数据新方式\n\n\n\n#### 对前端界面工程师这个职位是怎么样理解的？它的前景会怎么样？\n\n\n    前端是最贴近用户的程序员，比后端、数据库、产品经理、运营、安全都近。\n\n        1、实现界面交互\n\n        2、提升用户体验\n\n        3、有了Node.js，前端可以实现服务端的一些事情\n\n\n    前端是最贴近用户的程序员，前端的能力就是能让产品从 90分进化到 100 分，甚至更好，\n\n\n\n     参与项目，快速高质量完成实现效果图，精确到1px；\n\n     与团队成员，UI设计，产品经理的沟通；\n\n     做好的页面结构，页面重构和用户体验；\n\n     处理hack，兼容、写出优美的代码格式；\n\n     针对服务器的优化、拥抱最新前端技术。\n\n\n\n\n#### 一个页面从输入 URL 到页面加载显示完成，这个过程中都发生了什么？\n\n\n        分为4个步骤：\n\n        （1），当发送一个URL请求时，不管这个URL是Web页面的URL还是Web页面上每个资源的URL，浏览器都会开启一个线程来处理这个请求，同时在远程DNS服务器上启动一个DNS查询。这能使浏览器获得请求对应的IP地址。\n\n        （2）， 浏览器与远程`Web`服务器通过`TCP`三次握手协商来建立一个`TCP/IP`连接。该握手包括一个同步报文，一个同步-应答报文和一个应答报文，这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信，而后服务器应答并接受客户端的请求，最后由客户端发出该请求已经被接受的报文。\n\n        （3），一旦`TCP/IP`连接建立，浏览器会通过该连接向远程服务器发送`HTTP`的`GET`请求。远程服务器找到资源并使用HTTP响应返回该资源，值为200的HTTP响应状态表示一个正确的响应。\n\n        （4），此时，`Web`服务器提供资源服务，客户端开始下载资源。\n\n\n\n    请求返回后，便进入了我们关注的前端模块\n\n    简单来说，浏览器会解析`HTML`生成`DOM Tree`，其次会根据CSS生成CSS Rule Tree，而`javascript`又可以根据`DOM API`操作`DOM`\n\n\n\n详情：[从输入 URL 到浏览器接收的过程中发生了什么事情？][8]\n\n\n\n\n\n\n#### javascript对象的几种创建方式\n\n    1，工厂模式\n\n    2，构造函数模式\n\n    3，原型模式\n\n    4，混合构造函数和原型模式\n\n    5，动态原型模式\n\n    6，寄生构造函数模式\n\n    7，稳妥构造函数模式\n\n\n\n#### javascript继承的6种方法\n\n    1，原型链继承\n\n    2，借用构造函数继承\n\n    3，组合继承(原型+借用构造)\n\n    4，原型式继承\n\n    5，寄生式继承\n\n    6，寄生组合式继承\n\n\n\n详情：[JavaScript继承方式详解][9]\n\n\n#### 创建ajax的过程\n\n```js\n    (1)创建`XMLHttpRequest`对象,也就是创建一个异步调用对象.\n\n    (2)创建一个新的`HTTP`请求,并指定该`HTTP`请求的方法、`URL`及验证信息.\n\n    (3)设置响应`HTTP`请求状态变化的函数.\n\n    (4)发送`HTTP`请求.\n\n    (5)获取异步调用返回的数据.\n\n    (6)使用JavaScript和DOM实现局部刷新.\n\n\n    var xmlHttp = new XMLHttpRequest();\n\n    xmlHttp.open('GET','demo.php','true');\n\n    xmlHttp.send()\n\n    xmlHttp.onreadystatechange = function(){\n\n        if(xmlHttp.readyState === 4 & xmlHttp.status === 200){\n\n        }\n\n    }\n```\n\n\n\n详情：[JavaScript学习总结（七）Ajax和Http状态字][10]\n\n\n\n#### 异步加载和延迟加载\n\n    1.异步加载的方案： 动态插入script标签\n\n    2.通过ajax去获取js代码，然后通过eval执行\n\n    3.script标签上添加defer或者async属性\n\n    4.创建并插入iframe，让它异步执行js\n\n    5.延迟加载：有些 js 代码并不是页面初始化的时候就立刻需要的，而稍后的某些情况才需要的。\n\n\n\n#### ie各版本和chrome可以并行下载多少个资源\n\n\n    IE6 两个并发，iE7升级之后的6个并发，之后版本也是6个\n    Firefox，chrome也是6个\n\n\n\n####`Flash`、`Ajax`各自的优缺点，在使用中如何取舍？\n\n- `Flash`适合处理多媒体、矢量图形、访问机器；对`CSS`、处理文本上不足，不容易被搜索。\n\n-` Ajax`对`CSS`、文本支持很好，支持搜索；多媒体、矢量图形、机器访问不足。\n\n- 共同点：与服务器的无刷新传递消息、用户离线和在线状态、操作DOM\n\n\n\n#### 请解释一下 JavaScript 的同源策略。\n\n\n概念:同源策略是客户端脚本（尤其是`Javascript`）的重要的安全度量标准。它最早出自`Netscape Navigator2.0`，其目的是防止某个文档或脚本从多个不同源装载。\n\n\n这里的同源策略指的是：协议，域名，端口相同，同源策略是一种安全协议。\n\n指一段脚本只能读取来自同一来源的窗口和文档的属性。\n\n\n\n#### 为什么要有同源限制？\n\n   我们举例说明：比如一个黑客程序，他利用`Iframe`把真正的银行登录页面嵌到他的页面上，当你使用真实的用户名，密码登录时，他的页面就可以通过`Javascript`读取到你的表单中`input`中的内容，这样用户名，密码就轻松到手了。\n\n\n缺点：\n\n现在网站的`JS` 都会进行压缩，一些文件用了严格模式，而另一些没有。这时这些本来是严格模式的文件，被 `merge` 后，这个串就到了文件的中间，不仅没有指示严格模式，反而在压缩后浪费了字节。\n\n\n\n#### GET和POST的区别，何时使用POST？\n\n\n        GET：一般用于信息获取，使用URL传递参数，对所发送信息的数量也有限制，一般在2000个字符\n\n        POST：一般用于修改服务器上的资源，对所发送的信息没有限制。\n\n\n        GET方式需要使用Request.QueryString来取得变量的值，而POST方式通过Request.Form来获取变量的值，\n\n        也就是说Get是通过地址栏来传值，而Post是通过提交表单来传值。\n\n\n\n    然而，在以下情况中，请使用 POST 请求：\n\n    无法使用缓存文件（更新服务器上的文件或数据库）\n\n    向服务器发送大量数据（POST 没有数据量限制）\n\n    发送包含未知字符的用户输入时，POST 比 GET 更稳定也更可靠\n\n\n\n\n#### 事件、IE与火狐的事件机制有什么区别？ 如何阻止冒泡？\n\n\n\n     1. 我们在网页中的某个操作（有的操作对应多个事件）。例如：当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为。\n\n     2. 事件处理机制：IE是事件冒泡、firefox同时支持两种事件模型，也就是：捕获型事件和冒泡型事件。；\n\n     3. `ev.stopPropagation()`;注意旧ie的方法 `ev.cancelBubble = true`;\n\n\n\n#### ajax的缺点和在IE下的问题？\n\n详情请见：[JavaScript学习总结（七）Ajax和Http状态字][14]\n\n\n\n>ajax的缺点\n\n\n      1、ajax不支持浏览器back按钮。\n\n      2、安全问题 AJAX暴露了与服务器交互的细节。\n\n      3、对搜索引擎的支持比较弱。\n\n      4、破坏了程序的异常机制。\n\n      5、不容易调试。\n\n\n>IE缓存问题\n\n在IE浏览器下，如果请求的方法是`GET`，并且请求的`URL`不变，那么这个请求的结果就会被缓存。解决这个问题的办法可以通过实时改变请求的`URL`，只要URL改变，就不会被缓存，可以通过在URL末尾添加上随机的时间戳参数(`'t'= + new Date().getTime()`)\n\n\n\n或者：\n\n\n```\nopen('GET','demo.php?rand='+Math.random(),true);//\n```\n\n\n>Ajax请求的页面历史记录状态问题\n\n可以通过锚点来记录状态，`location.hash`。让浏览器记录Ajax请求时页面状态的变化。\n\n\n\n还可以通过`HTML5`的`history.pushState`，来实现浏览器地址栏的无刷新改变\n\n\n\n\n#### 谈谈你对重构的理解\n\n网站重构：在不改变外部行为的前提下，简化结构、添加可读性，而在网站前端保持一致的行为。也就是说是在不改变UI的情况下，对网站进行优化，\n在扩展的同时保持一致的UI。\n\n\n    对于传统的网站来说重构通常是：\n\n    表格(table)布局改为DIV+CSS\n\n    使网站前端兼容于现代浏览器(针对于不合规范的CSS、如对IE6有效的)\n\n    对于移动平台的优化\n\n    针对于SEO进行优化\n\n    深层次的网站重构应该考虑的方面\n\n\n    减少代码间的耦合\n\n    让代码保持弹性\n\n    严格按规范编写代码\n\n    设计可扩展的API\n\n    代替旧有的框架、语言(如VB)\n\n    增强用户体验\n\n    通常来说对于速度的优化也包含在重构中\n\n\n\n    压缩JS、CSS、image等前端资源(通常是由服务器来解决)\n\n    程序的性能优化(如数据读写)\n\n    采用CDN来加速资源加载\n\n    对于JS DOM的优化\n\n    HTTP服务器的文件缓存\n\n\n#### HTTP状态码\n\n\n```html\n\n    100  Continue  继续，一般在发送post请求时，已发送了http header之后服务端将返回此信息，表示确认，之后发送具体参数信息\n\n    200  OK   正常返回信息\n\n    201  Created  请求成功并且服务器创建了新的资源\n\n    202  Accepted  服务器已接受请求，但尚未处理\n\n    301  Moved Permanently  请求的网页已永久移动到新位置。\n\n    302 Found  临时性重定向。\n\n    303 See Other  临时性重定向，且总是使用 GET 请求新的 URI。\n\n    304  Not Modified  自从上次请求后，请求的网页未修改过。\n\n\n    400 Bad Request  服务器无法理解请求的格式，客户端不应当尝试再次使用相同的内容发起请求。\n\n    401 Unauthorized  请求未授权。\n\n    403 Forbidden  禁止访问。\n\n    404 Not Found  找不到如何与 URI 相匹配的资源。\n\n    500 Internal Server Error  最常见的服务器端错误。\n\n    503 Service Unavailable 服务器端暂时无法处理请求（可能是过载或维护）。\n\n```\n\n\n#### 说说你对Promise的理解\n\n\n\n依照 `Promise/A+` 的定义，`Promise` 有四种状态：\n\n\tpending: 初始状态, 非 fulfilled 或 rejected.\n\n\tfulfilled: 成功的操作.\n\n\trejected: 失败的操作.\n\n\tsettled: Promise已被fulfilled或rejected，且不是pending\n\n\n\n另外， `fulfilled` 与 `rejected` 一起合称 `settled`。\n\n\n\n`Promise` 对象用来进行延迟(deferred) 和异步(asynchronous ) 计算。\n\n\n\n>Promise 的构造函数\n\n\n\n构造一个 `Promise`，最基本的用法如下：\n\n\n```js\n\tvar promise = new Promise(function(resolve, reject) {\n\n\t    if (...) {  // succeed\n\n\t        resolve(result);\n\n\t    } else {   // fails\n\n\t        reject(Error(errMessage));\n\n\t    }\n\t});\n```\n\n\n`Promise` 实例拥有 `then` 方法（具有 `then` 方法的对象，通常被称为 `thenable`）。它的使用方法如下：\n\n```js\npromise.then(onFulfilled, onRejected)\n```\n\n接收两个函数作为参数，一个在 `fulfilled` 的时候被调用，一个在 `rejected` 的时候被调用，接收参数就是 `future，onFulfilled` 对应 `resolve`, `onRejected` 对应 `reject`。\n\n\n\n#### 说说你对前端架构师的理解\n\n\n负责前端团队的管理及与其他团队的协调工作，提升团队成员能力和整体效率；\n带领团队完成研发工具及平台前端部分的设计、研发和维护；\n带领团队进行前端领域前沿技术研究及新技术调研，保证团队的技术领先\n负责前端开发规范制定、功能模块化设计、公共组件搭建等工作，并组织培训。\n\n\n\n#### 实现一个函数clone，可以对JavaScript中的5种主要的数据类型（包括Number、String、Object、Array、Boolean）进行值复制\n\n\n```js\n    Object.prototype.clone = function(){\n\n            var o = this.constructor === Array ? [] : {};\n\n            for(var e in this){\n\n                    o[e] = typeof this[e] === \"object\" ? this[e].clone() : this[e];\n\n            }\n\n            return o;\n    }\n```\n\n#### 说说严格模式的限制\n\n\n\n严格模式主要有以下限制：\n\n    变量必须声明后再使用\n\n    函数的参数不能有同名属性，否则报错\n\n    不能使用with语句\n\n    不能对只读属性赋值，否则报错\n\n    不能使用前缀0表示八进制数，否则报错\n\n    不能删除不可删除的属性，否则报错\n\n    不能删除变量delete prop，会报错，只能删除属性delete global[prop]\n\n    eval不会在它的外层作用域引入变量\n\n    eval和arguments不能被重新赋值\n\n    arguments不会自动反映函数参数的变化\n\n    不能使用arguments.callee\n\n    不能使用arguments.caller\n\n    禁止this指向全局对象\n\n    不能使用fn.caller和fn.arguments获取函数调用的堆栈\n\n    增加了保留字（比如protected、static和interface）\n\n\n\n设立\"严格模式\"的目的，主要有以下几个：\n\n\n- 消除`Javascript`语法的一些不合理、不严谨之处，减少一些怪异行为;\n\n- 消除代码运行的一些不安全之处，保证代码运行的安全；\n\n- 提高编译器效率，增加运行速度；\n\n- 为未来新版本的`Javascript`做好铺垫。\n\n\n\n注：经过测试`IE6,7,8,9`均不支持严格模式。\n\n\n\n\n#### 如何删除一个cookie\n\n\n\n>1.将时间设为当前时间往前一点。\n\n\n```js\nvar date = new Date();\n\ndate.setDate(date.getDate() - 1);//真正的删除\n```\n\n\n`setDate() `方法用于设置一个月的某一天。\n\n>2.expires的设置\n\n```js\n    document.cookie = 'user='+ encodeURIComponent('name')  + ';expires = ' + new Date(0)\n```\n\n\n#### `<strong>`，`<em>`和`<b>`，`<i>`标签\n\n\n```html\n<strong> 标签和 <em> 标签一样，用于强调文本，但它强调的程度更强一些。\n\nem 是 斜体强调标签，更强烈强调，表示内容的强调点。相当于html元素中的 <i>...</i>;\n\n< b > < i >是视觉要素，分别表示无意义的加粗，无意义的斜体。\n\nem 和 strong 是表达要素(phrase elements)。\n```\n\n\n#### 说说你对AMD和Commonjs的理解\n\n\n\n`CommonJS`是服务器端模块的规范，Node.js采用了这个规范。`CommonJS`规范加载模块是同步的，也就是说，只有加载完成，才能执行后面的操作。AMD规范则是非同步加载模块，允许指定回调函数。\n\n`AMD`推荐的风格通过返回一个对象做为模块对象，`CommonJS`的风格通过对`module.exports`或`exports`的属性赋值来达到暴露模块对象的目的。\n\n>详情：[也谈webpack及其开发模式](https://segmentfault.com/a/1190000004888589)\n\n#### document.write()的用法\n\n\n\n` document.write()`方法可以用在两个方面：页面载入过程中用实时脚本创建页面内容，以及用延时脚本创建本窗口或新窗口的内容。\n\n`document.write`只能重绘整个页面。`innerHTML`可以重绘页面的一部分\n\n\n#### 编写一个方法 求一个字符串的字节长度\n\n假设：一个英文字符占用一个字节，一个中文字符占用两个字节\n\n```js\n function GetBytes(str){\n\n        var len = str.length;\n\n        var bytes = len;\n\n        for(var i=0; i<len; i++){\n\n            if (str.charCodeAt(i) > 255) bytes++;\n\n        }\n\n        return bytes;\n\n    }\n\nalert(GetBytes(\"你好,as\"));\n```\n\n\n### git fetch和git pull的区别\n\n\n```js\ngit pull：相当于是从远程获取最新版本并merge到本地\n\ngit fetch：相当于是从远程获取最新版本到本地，不会自动merge\n```\n\n\n\n\n#### 说说你对MVC和MVVM的理解\n\n>`MVC`\n\n    View 传送指令到 Controller\n\n    Controller 完成业务逻辑后，要求 Model 改变状态\n\n    Model 将新的数据发送到 View，用户得到反馈\n\n\n\n所有通信都是单向的。\n\n`Angular`它采用双向绑定（data-binding）：`View`的变动，自动反映在 `ViewModel`，反之亦然。\n\n\n    组成部分Model、View、ViewModel\n\n    View：UI界面\n\n    ViewModel：它是View的抽象，负责View与Model之间信息转换，将View的Command传送到Model；\n\n    Model：数据访问层\n\n\n#### 请解释什么是事件代理\n\n\n\n事件代理（Event Delegation），又称之为事件委托。是 `JavaScript` 中常用绑定事件的常用技巧。顾名思义，“事件代理”即是把原本需要绑定的事件委托给父元素，让父元素担当事件监听的职务。事件代理的原理是`DOM`元素的事件冒泡。使用事件代理的好处是可以提高性能。\n\n\n\n#### attribute和property的区别是什么？\n\n\n\n`attribute`是`dom`元素在文档中作为`html`标签拥有的属性；\n\n\n`property`就是`dom`元素在`js`中作为对象拥有的属性。\n\n\n\n所以：\n\n对于`html`的标准属性来说，`attribute`和`property`是同步的，是会自动更新的，\n\n但是对于自定义的属性来说，他们是不同步的，\n\n\n\n#### 说说网络分层里七层模型是哪七层\n\n- 应用层：应用层、表示层、会话层（从上往下）（`HTTP、FTP、SMTP、DNS`）\n\n- 传输层（`TCP`和`UDP`）\n\n- 网络层（`IP`）\n\n- 物理和数据链路层（以太网）\n\n\n\n>每一层的作用如下：\n\n```js\n\n物理层：通过媒介传输比特,确定机械及电气规范（比特Bit）\n数据链路层：将比特组装成帧和点到点的传递（帧Frame）\n网络层：负责数据包从源到宿的传递和网际互连（包PackeT）\n传输层：提供端到端的可靠报文传递和错误恢复（段Segment）\n会话层：建立、管理和终止会话（会话协议数据单元SPDU）\n表示层：对数据进行翻译、加密和压缩（表示协议数据单元PPDU）\n应用层：允许访问OSI环境的手段（应用协议数据单元APDU）\n```\n\n>各种协议\n\n`ICMP协议`： 因特网控制报文协议。它是TCP/IP协议族的一个子协议，用于在IP主机、路由器之间传递控制消息。\n`TFTP协议`： 是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议，提供不复杂、开销不大的文件传输服务。\n`HTTP协议`： 超文本传输协议，是一个属于应用层的面向对象的协议，由于其简捷、快速的方式，适用于分布式超媒体信息系统。\n`DHCP协议`： 动态主机配置协议，是一种让系统得以连接到网络上，并获取所需要的配置参数手段。\n\n\n\n#### 说说mongoDB和MySQL的区别\n\n\n\n`MySQL`是传统的关系型数据库，`MongoDB`则是非关系型数据库\n\n `mongodb`以`BSON`结构（二进制）进行存储，对海量数据存储有着很明显的优势。\n\n对比传统关系型数据库,NoSQL有着非常显著的性能和扩展性优势，与关系型数据库相比，MongoDB的优点有：\n①弱一致性（最终一致），更能保证用户的访问速度：\n②文档结构的存储方式，能够更便捷的获取数据。\n\n\n#### 讲讲304缓存的原理\n\n\n\n服务器首先产生`ETag`，服务器可在稍后使用它来判断页面是否已经被修改。本质上，客户端通过将该记号传回服务器要求服务器验证其（客户端）缓存。\n\n<br>\n\n304是HTTP状态码，服务器用来标识这个文件没修改，不返回内容，浏览器在接收到个状态码后，会使用浏览器已缓存的文件\n\n<br>\n\n客户端请求一个页面（A）。 服务器返回页面A，并在给`A`加上一个`ETag`。 客户端展现该页面，并将页面连同`ETag`一起缓存。 客户再次请求页面`A`，并将上次请求时服务器返回的`ETag`一起传递给服务器。 服务器检查该`ETag`，并判断出该页面自上次客户端请求之后还未被修改，直接返回响应`304`（未修改——`Not Modified`）和一个空的响应体。\n\n\n\n<br>\n\n\n\n#### 什么样的前端代码是好的\n\n\n高复用低耦合，这样文件小，好维护，而且好扩展。\n\n\n#### 代码题\n\n- [css代码题](./readme.html)\n- [js代码题](./readme.js)\n\n\n  [16]: /imgs/what-is-html5.jpg\n\n\n  [2]: http://segmentfault.com/blog/trigkit4/1190000000718840\n\n  [3]: http://segmentfault.com/blog/trigkit4/1190000000660786#articleHeader15\n\n  [4]: http://segmentfault.com/blog/trigkit4/1190000000687844\n\n  [5]: http://segmentfault.com/blog/trigkit4/1190000000758184#articleHeader5\n\n  [6]: http://segmentfault.com/blog/trigkit4/1190000000800711#articleHeader30\n\n  [7]: http://segmentfault.com/blog/trigkit4/1190000000656717\n\n  [8]: http://segmentfault.com/blog/trigkit4/1190000000697254\n\n  [9]: http://segmentfault.com/blog/trigkit4/1190000002440502\n\n  [10]: http://segmentfault.com/blog/trigkit4/1190000000691919\n\n  [11]: http://segmentfault.com/blog/trigkit4/1190000002585760\n\n  [12]: http://segmentfault.com/blog/trigkit4/1190000000652891\n\n  [13]: http://segmentfault.com/blog/trigkit4/1190000002174034\n\n  [14]: http://segmentfault.com/blog/trigkit4/1190000000691919\n\n  [15]: http://segmentfault.com/blog/trigkit4/1190000000733959\n"
  },
  {
    "path": "21-Front-end-Interview-questions/readme.html",
    "content": "<!-- 1.如何居中一个浮动元素 -->\n\n<!-- 父元素和子元素同时左浮动，然后父元素相对左移动50%，再然后子元素相对右移动50%，或者子元素相对左移动-50%也就可以了。 -->\n\n\n<style type=\"text/css\">\n    .p{\n\n        position:relative;\n\n        left:50%;\n\n        float:left;\n\n    }\n    .c{\n\n        position:relative;\n\n        float:left;\n\n        right:50%;\n\n    }\n</style>\n\n\n<div class=\"p\">\n\n    <h1 class=\"c\">Test Float Element Center</h1>\n\n</div>\n\n\n\n<!-- 2.css实现水平垂直居中 -->\n\n<style type=\"text/css\">\n\n    .align-center{\n        /**\n         * 负边距+定位：水平垂直居中（Negative Margin）\n         * 使用绝对定位将content的定点定位到body的中心，然后使用负margin（content宽高的一半），\n         * 将content的中心拉回到body的中心，已到达水平垂直居中的效果。\n         */\n\n        position:absolute;\n\n        left:50%;\n\n        top:50%;\n\n        width:400px;\n\n        height:400px;\n\n        margin-top:-200px;\n\n        margin-left:-200px;\n\n        border:1px dashed #333;\n\n    }\n</style>\n\n<!-- 3.css实现三栏布局，中间自适应 -->\n\n\n\n/*方法一：自身浮动法。左栏左浮动，右栏右浮动。*/\n\n<style type='text/css'>\n.left , .right{\n            height: 300px;\n\n            width: 200px;\n        }\n\n        .right{\n            float: right;\n            background-color: red;\n        }\n\n        .left{\n            float: left;\n            background-color: #080808;\n        }\n\n        .middle{\n\n            height: 300px;\n\n            margin: 0 200px;//没有这行，当宽度缩小到一定程度的时候，中间的内容可能换行\n\n            background-color: blue;\n        }\n</style>\n\n\n\n\n<!-- 方法二：margin负值法 -->\n\n<style type=\"text/css\">\n\n            body{\n\n                margin: 0;\n\n                padding: 0;\n\n            }\n\n            .left , .right{\n\n                height: 300px;\n\n                width: 200px;\n\n                float: left;\n\n            }\n\n            .right{\n\n                margin-left: -200px;\n\n                background-color: red;\n            }\n\n            .left{\n                margin-left: -100%;\n\n                background-color: #080808;\n            }\n\n            .middle{\n                height: 300px;\n                width: 100%;\n                float: left;\n                background-color: blue;\n            }\n</style>\n\n\n\n    <!--放第一行-->\n\n    <div class=\"middle\">middle</div>\n\n    <div class=\"left\">left</div>\n\n    <div class=\"right\">right</div>\n\n\n\n\n\n<!-- 方法三：绝对定位法。左右两栏采用绝对定位，分别固定于页面的左右两侧，中间的主体栏用左右margin值撑开距离。 -->\n\n\n\n<style>\n    body{\n\n        margin: 0;\n\n        padding: 0;\n\n    }\n\n    .left , .right{\n\n        top: 0;\n\n        height: 300px;\n\n        width: 200px;\n\n        position: absolute;\n\n    }\n\n    .right{\n\n        right: 0;\n\n        background-color: red;\n\n    }\n\n    .left{\n\n        left: 0;\n\n        background-color: #080808;\n\n    }\n\n    .middle{\n\n        margin: 0 200px;\n\n        height: 300px;\n\n        background-color: blue;\n\n    }\n</style>\n\n\n<div class=\"left\">left</div>\n\n<!--这种方法没有严格限定中间这栏放置何处-->\n\n<div class=\"middle\">middle</div>\n\n<div class=\"right\">right</div>\n\n```\n"
  },
  {
    "path": "21-Front-end-Interview-questions/readme.js",
    "content": "// js对象的深度克隆\n\n\nfunction clone(Obj) {\n\n    var buf;\n\n    if (Obj instanceof Array) {\n\n        buf = []; //创建一个空的数组\n\n        var i = Obj.length;\n\n        while (i--) {\n\n            buf[i] = clone(Obj[i]);\n\n        }\n\n        return buf;\n\n    } else if (Obj instanceof Object) {\n\n        buf = {}; //创建一个空对象\n\n        for (var k in Obj) { //为这个对象添加新的属性\n\n            buf[k] = clone(Obj[k]);\n\n        }\n\n        return buf;\n\n    } else {\n\n        return Obj;\n\n    }\n\n}\n\n\n// js数组去重\n\n// 以下是数组去重的三种方法：\n\n\nArray.prototype.unique1 = function() {\n\n    var n = []; //一个新的临时数组\n\n    for (var i = 0; i < this.length; i++) //遍历当前数组\n\n    {\n\n        //如果当前数组的第i已经保存进了临时数组，那么跳过，\n\n        //否则把当前项push到临时数组里面\n\n        if (n.indexOf(this[i]) == -1) n.push(this[i]);\n\n    }\n\n    return n;\n\n}\n\n\n\nArray.prototype.unique2 = function()\n\n{\n\n    var n = {},\n        r = []; //n为hash表，r为临时数组\n\n    for (var i = 0; i < this.length; i++) { //遍历当前数组\n\n        if (!n[this[i]]) { //如果hash表中没有当前项\n\n            n[this[i]] = true; //存入hash表\n\n            r.push(this[i]); //把当前数组的当前项push到临时数组里面\n\n        }\n\n    }\n    return r;\n\n}\n\n\n\nArray.prototype.unique3 = function(){\n\n    var n = [this[0]]; //结果数组\n\n    for (var i = 1; i < this.length; i++) //从第二项开始遍历\n\n    {\n\n        //如果当前数组的第i项在当前数组中第一次出现的位置不是i，\n\n        //那么表示第i项是重复的，忽略掉。否则存入结果数组\n\n        if (this.indexOf(this[i]) == i) n.push(this[i]);\n\n    }\n\n    return n;\n\n}\n\n\n// js常用设计模式的实现思路，单例，工厂，代理，装饰，观察者模式等\n\n    // 1) 单例：　任意对象都是单例，无须特别处理\n\n    var obj = {name: 'michaelqin', age: 30};\n\n    // 2) 工厂: 就是同样形式参数返回不同的实例\n    function Person() { this.name = 'Person1'; }\n    function Animal() { this.name = 'Animal1'; }\n\n    function Factory() {}\n    Factory.prototype.getInstance = function(className) {\n        return eval('new ' + className + '()');\n    }\n\n    var factory = new Factory();\n    var obj1 = factory.getInstance('Person');\n    var obj2 = factory.getInstance('Animal');\n    console.log(obj1.name); // Person1\n    console.log(obj2.name); // Animal1\n\n    //3) 代理: 就是新建个类调用老类的接口,包一下\n    function Person() { }\n    Person.prototype.sayName = function() { console.log('michaelqin'); }\n    Person.prototype.sayAge = function() { console.log(30); }\n\n    function PersonProxy() {\n        this.person = new Person();\n        var that = this;\n        this.callMethod = function(functionName) {\n            console.log('before proxy:', functionName);\n            that.person[functionName](); // 代理\n            console.log('after proxy:', functionName);\n        }\n    }\n\n    var pp = new PersonProxy();\n    pp.callMethod('sayName'); // 代理调用Person的方法sayName()\n    pp.callMethod('sayAge'); // 代理调用Person的方法sayAge()\n\n    //4) 观察者: 就是事件模式，比如按钮的onclick这样的应用.\n    function Publisher() {\n        this.listeners = [];\n    }\n    Publisher.prototype = {\n        'addListener': function(listener) {\n            this.listeners.push(listener);\n        },\n\n        'removeListener': function(listener) {\n            delete this.listeners[listener];\n        },\n\n        'notify': function(obj) {\n            for(var i = 0; i < this.listeners.length; i++) {\n                var listener = this.listeners[i];\n                if (typeof listener !== 'undefined') {\n                    listener.process(obj);\n                }\n            }\n        }\n    }; // 发布者\n\n    function Subscriber() {\n\n    }\n    Subscriber.prototype = {\n        'process': function(obj) {\n            console.log(obj);\n        }\n    };　// 订阅者\n\n    var publisher = new Publisher();\n    publisher.addListener(new Subscriber());\n    publisher.addListener(new Subscriber());\n    publisher.notify({name: 'michaelqin', ageo: 30}); // 发布一个对象到所有订阅者\n    publisher.notify('2 subscribers will both perform process'); // 发布一个字符串到所有订阅者\n"
  },
  {
    "path": "22-Front-end-Developer-Interview-Questions-master/README.md",
    "content": "#前端工作面试问题\n\n本文包含了一些用于考查候选者的前端面试问题。不建议对单个候选者问及每个问题 (那需要好几个小时)。只要从列表里挑选一些，就能帮助你考查候选者是否具备所需要的技能。\n\n**备注：** 这些问题中很多都是开放性的，可以引发有趣的讨论。这比直接的答案更能体现此人的能力。\n\n## <a name='toc'>目录</a>\n\n  1. [常见问题](#general-questions)\n  1. [HTML 相关问题](#html-questions)\n  1. [CSS 相关问题](#css-questions)\n  1. [JS 相关问题](#js-questions)\n  1. [测试相关问题](#testing-questions)\n  1. [效能相关问题](#performance-questions)\n  1. [网络相关问题](#network-questions)\n  1. [代码相关问题](#coding-questions)\n  1. [趣味问题](#fun-questions)\n\n## 参与协作\n\n  1. [贡献者](#contributors)\n  1. [如何参与贡献](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/master/CONTRIBUTING.md)\n  1. [许可协议](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/master/LICENSE.md)\n\n#### <a name='general-questions'>常见问题：</a>\n\n* 你在昨天/本周学到了什么？\n* 编写代码的哪些方面能够使你兴奋或感兴趣？\n* 你最近遇到过什么技术挑战？你是如何解决的？\n* 在制作一个网页应用或网站的过程中，你是如何考虑其 UI、安全性、高性能、SEO、可维护性以及技术因素的？\n* 请谈谈你喜欢的开发环境。\n* 你最熟悉哪一套版本控制系统？\n* 你能描述当你制作一个网页的工作流程吗？\n* 假若你有 5 个不同的样式文件 (stylesheets), 整合进网站的最好方式是?\n* 你能描述渐进增强 (progressive enhancement) 和优雅降级 (graceful degradation) 之间的不同吗?\n* 你如何对网站的文件和资源进行优化？\n* 浏览器同一时间可以从一个域名下载多少资源？\n  * 有什么例外吗？\n* 请说出三种减少页面加载时间的方法。(加载时间指感知的时间或者实际加载时间)\n* 如果你参与到一个项目中，发现他们使用 Tab 来缩进代码，但是你喜欢空格，你会怎么做？\n* 请写一个简单的幻灯效果页面。\n* 如果今年你打算熟练掌握一项新技术，那会是什么？\n* 请谈谈你对网页标准和标准制定机构重要性的理解。\n* 什么是 FOUC (无样式内容闪烁)？你如何来避免 FOUC？\n* 请解释什么是 ARIA 和屏幕阅读器 (screenreaders)，以及如何使网站实现无障碍访问 (accessible)。\n* 请解释 CSS 动画和 JavaScript 动画的优缺点。\n* 什么是跨域资源共享 (CORS)？它用于解决什么问题？\n\n#### <a name='html-questions'>HTML 相关问题：</a>\n\n* `doctype`(文档类型) 的作用是什么？\n* 浏览器标准模式 (standards mode) 、几乎标准模式（almost standards mode）和怪异模式 (quirks mode) 之间的区别是什么？\n* HTML 和 XHTML 有什么区别？\n* 如果页面使用 'application/xhtml+xml' 会有什么问题吗？\n* 如果网页内容需要支持多语言，你会怎么做？\n* 在设计和开发多语言网站时，有哪些问题你必须要考虑？\n* 使用 `data-` 属性的好处是什么？\n* 如果把 HTML5 看作做一个开放平台，那它的构建模块有哪些？\n* 请描述 `cookies`、`sessionStorage` 和 `localStorage` 的区别。\n* 请解释 `<script>`、`<script async>` 和 `<script defer>` 的区别。\n* 为什么通常推荐将 CSS `<link>` 放置在 `<head></head>` 之间，而将 JS `<script>` 放置在 `</body>` 之前？你知道有哪些例外吗？\n* 什么是渐进式渲染 (progressive rendering)？\n* 你用过哪些不同的 HTML 模板语言？\n\n#### <a name='css-questions'>CSS 相关问题：</a>\n\n* CSS 中类 (classes) 和 ID 的区别。\n* 请问 \"resetting\" 和 \"normalizing\" CSS 之间的区别？你会如何选择，为什么？\n* 请解释浮动 (Floats) 及其工作原理。\n* 描述`z-index`和叠加上下文是如何形成的。\n* 请描述 BFC(Block Formatting Context) 及其如何工作。\n* 列举不同的清除浮动的技巧，并指出它们各自适用的使用场景。\n* 请解释 CSS sprites，以及你要如何在页面或网站中实现它。\n* 你最喜欢的图片替换方法是什么，你如何选择使用。\n* 你会如何解决特定浏览器的样式问题？\n* 如何为有功能限制的浏览器提供网页？\n  * 你会使用哪些技术和处理方法？\n* 有哪些的隐藏内容的方法 (如果同时还要保证屏幕阅读器可用呢)？\n* 你用过栅格系统 (grid system) 吗？如果使用过，你最喜欢哪种？\n* 你用过媒体查询，或针对移动端的布局/CSS 吗？\n* 你熟悉 SVG 样式的书写吗？\n* 如何优化网页的打印样式？\n* 在书写高效 CSS 时会有哪些问题需要考虑？\n* 使用 CSS 预处理器的优缺点有哪些？\n  * 请描述你曾经使用过的 CSS 预处理器的优缺点。\n* 如果设计中使用了非标准的字体，你该如何去实现？\n* 请解释浏览器是如何判断元素是否匹配某个 CSS 选择器？\n* 请描述伪元素 (pseudo-elements) 及其用途。\n* 请解释你对盒模型的理解，以及如何在 CSS 中告诉浏览器使用不同的盒模型来渲染你的布局。\n* 请解释 ```* { box-sizing: border-box; }``` 的作用, 并且说明使用它有什么好处？\n* 请罗列出你所知道的 display 属性的全部值\n* 请解释 inline 和 inline-block 的区别？\n* 请解释 relative、fixed、absolute 和 static 元素的区别\n* CSS 中字母 'C' 的意思是叠层 (Cascading)。请问在确定样式的过程中优先级是如何决定的 (请举例)？如何有效使用此系统？\n* 你在开发或生产环境中使用过哪些 CSS 框架？你觉得应该如何改善他们？\n* 请问你有尝试过 CSS Flexbox 或者 Grid 标准规格吗？\n* 为什么响应式设计 (responsive design) 和自适应设计 (adaptive design) 不同？\n* 你有兼容 retina 屏幕的经历吗？如果有，在什么地方使用了何种技术？\n* 请问为何要使用 `translate()` 而非 *absolute positioning*，或反之的理由？为什么？\n\n#### <a name='js-questions'>JS 相关问题：</a>\n\n* 请解释事件代理 (event delegation)。\n* 请解释 JavaScript 中 `this` 是如何工作的。\n* 请解释原型继承 (prototypal inheritance) 的原理。\n* 你怎么看 AMD vs. CommonJS？\n* 请解释为什么接下来这段代码不是 IIFE (立即调用的函数表达式)：`function foo(){ }();`.\n  * 要做哪些改动使它变成 IIFE?\n* 描述以下变量的区别：`null`，`undefined` 或 `undeclared`？\n  * 该如何检测它们？\n* 什么是闭包 (closure)，如何使用它，为什么要使用它？\n* 请举出一个匿名函数的典型用例？\n* 你是如何组织自己的代码？是使用模块模式，还是使用经典继承的方法？\n* 请指出 JavaScript 宿主对象 (host objects) 和原生对象 (native objects) 的区别？\n* 请指出以下代码的区别：`function Person(){}`、`var person = Person()`、`var person = new Person()`？\n* `.call` 和 `.apply` 的区别是什么？\n* 请解释 `Function.prototype.bind`？\n* 在什么时候你会使用 `document.write()`？\n* 请指出浏览器特性检测，特性推断和浏览器 UA 字符串嗅探的区别？\n* 请尽可能详尽的解释 Ajax 的工作原理。\n* 使用 Ajax 都有哪些优劣？\n* 请解释 JSONP 的工作原理，以及它为什么不是真正的 Ajax。\n* 你使用过 JavaScript 模板系统吗？\n  * 如有使用过，请谈谈你都使用过哪些库？\n* 请解释变量声明提升 (hoisting)。\n* 请描述事件冒泡机制 (event bubbling)。\n* \"attribute\" 和 \"property\" 的区别是什么？\n* 为什么扩展 JavaScript 内置对象不是好的做法？\n* 请指出 document load 和 document DOMContentLoaded 两个事件的区别。\n* `==` 和 `===` 有什么不同？\n* 请解释 JavaScript 的同源策略 (same-origin policy)。\n* 如何实现下列代码：\n```javascript\n[1,2,3,4,5].duplicator(); // [1,2,3,4,5,1,2,3,4,5]\n```\n* 什么是三元表达式 (Ternary expression)？“三元 (Ternary)” 表示什么意思？\n* 什么是 `\"use strict\";` ? 使用它的好处和坏处分别是什么？\n* 请实现一个遍历至 `100` 的 for loop 循环，在能被 `3` 整除时输出 **\"fizz\"**，在能被 `5` 整除时输出 **\"buzz\"**，在能同时被 `3` 和 `5` 整除时输出 **\"fizzbuzz\"**。\n* 为何通常会认为保留网站现有的全局作用域 (global scope) 不去改变它，是较好的选择？\n* 为何你会使用 `load` 之类的事件 (event)？此事件有缺点吗？你是否知道其他替代品，以及为何使用它们？\n* 请解释什么是单页应用 (single page app), 以及如何使其对搜索引擎友好 (SEO-friendly)。\n* What is the extent of your experience with Promises and/or their polyfills?\n* 使用 Promises 而非回调 (callbacks) 优缺点是什么？\n* 使用一种可以编译成 JavaScript 的语言来写 JavaScript 代码有哪些优缺点？\n* 你使用哪些工具和技术来调试 JavaScript 代码？\n* 你会使用怎样的语言结构来遍历对象属性 (object properties) 和数组内容？\n* 请解释可变 (mutable) 和不变 (immutable) 对象的区别。\n  * 请举出 JavaScript 中一个不变性对象 (immutable object) 的例子？\n  * 不变性 (immutability) 有哪些优缺点？\n  * 如何用你自己的代码来实现不变性 (immutability)？\n* 请解释同步 (synchronous) 和异步 (asynchronous) 函数的区别。\n* 什么是事件循环 (event loop)？\n  * 请问调用栈 (call stack) 和任务队列 (task queue) 的区别是什么？\n* 解释 `function foo() {}` 与 `var foo = function() {}` 用法的区别\n\n#### <a name='testing-questions'>测试相关问题：</a>\n\n* 对代码进行测试的有什么优缺点？\n* 你会用什么工具测试你的代码功能？\n* 单元测试与功能/集成测试的区别是什么？\n* 代码风格 linting 工具的作用是什么？\n\n#### <a name='performance-questions'>效能相关问题：</a>\n\n* 你会用什么工具来查找代码中的性能问题？\n* 你会用什么方式来增强网站的页面滚动效能？\n* 请解释 layout、painting 和 compositing 的区别。\n\n#### <a name='network-questions'>网络相关问题：</a>\n\n* 为什么传统上利用多个域名来提供网站资源会更有效？\n* 请尽可能完整得描述从输入 URL 到整个网页加载完毕及显示在屏幕上的整个流程。\n* Long-Polling、Websockets 和 Server-Sent Event 之间有什么区别？\n* 请描述以下 request 和 response headers：\n  * Diff. between Expires, Date, Age and If-Modified-...\n  * Do Not Track\n  * Cache-Control\n  * Transfer-Encoding\n  * ETag\n  * X-Frame-Options\n* 什么是 HTTP method？请罗列出你所知道的所有 HTTP method，并给出解释。\n\n#### <a name='coding-questions'>代码相关的问题：</a>\n\n*问题：`foo`的值是什么？*\n```javascript\nvar foo = 10 + '20';\n```\n\n*问题：如何实现以下函数？*\n```javascript\nadd(2, 5); // 7\nadd(2)(5); // 7\n```\n\n*问题：下面的语句的返回值是什么？*\n```javascript\n\"i'm a lasagna hog\".split(\"\").reverse().join(\"\");\n```\n\n*问题：`window.foo`的值是什么？*\n```javascript\n( window.foo || ( window.foo = \"bar\" ) );\n```\n\n*问题：下面两个 alert 的结果是什么？*\n```javascript\nvar foo = \"Hello\";\n(function() {\n  var bar = \" World\";\n  alert(foo + bar);\n})();\nalert(foo + bar);\n```\n\n*问题：`foo.length`的值是什么？*\n```javascript\nvar foo = [];\nfoo.push(1);\nfoo.push(2);\n```\n\n*问题：`foo.x`的值是什么？*\n```javascript\nvar foo = {n: 1};\nvar bar = foo;\nfoo.x = foo = {n: 2};\n```\n\n*问题：下面代码的输出是什么？*\n```javascript\nconsole.log('one');\nsetTimeout(function() {\n  console.log('two');\n}, 0);\nconsole.log('three');\n```\n\n#### <a name='fun-questions'>趣味问题：</a>\n\n* 你最近写过什么的很酷的项目吗？\n* 在你使用的开发工具中，最喜欢哪些方面？\n* 谁使你踏足了前端开发领域？\n* 你有什么业余项目吗？是哪种类型的？\n* 你最爱的 IE 特性是什么？\n* 你对咖啡有没有什么喜好？\n\n\n#### <a name='contributors'>贡献者：</a>\n\n本文档始于 2009 年，是以下作者的合作成果：[@paul_irish](https://twitter.com/paul_irish) [@bentruyman](https://twitter.com/bentruyman) [@cowboy](https://twitter.com/cowboy) [@ajpiano](https://twitter.com/ajpiano) [@SlexAxton](https://twitter.com/slexaxton) [@boazsender](https://twitter.com/boazsender) [@miketaylr](https://twitter.com/miketaylr) [@vladikoff](https://twitter.com/vladikoff) [@gf3](https://twitter.com/gf3) [@jon_neal](https://twitter.com/jon_neal) [@sambreed](https://twitter.com/sambreed) 和 [@iansym](https://twitter.com/iansym)。\n\n时至今日，文档已经融入超过 [100 位开发者](https://github.com/h5bp/Front-end-Developer-Interview-Questions/graphs/contributors)的贡献。\n"
  },
  {
    "path": "23-FE-interview-master/README.md",
    "content": "转载请注明出处: [https://github.com/qiu-deqing/FE-interview](https://github.com/qiu-deqing/FE-interview)\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*\n\n- [FE-interview](#fe-interview)\n  - [$HTML， HTTP，web综合问题](#$html，-http，web综合问题)\n    - [常见排序算法的时间复杂度,空间复杂度](#常见排序算法的时间复杂度空间复杂度)\n    - [前端需要注意哪些SEO](#前端需要注意哪些seo)\n    - [web开发中会话跟踪的方法有哪些](#web开发中会话跟踪的方法有哪些)\n    - [`<img>`的`title`和`alt`有什么区别](#img的title和alt有什么区别)\n    - [doctype是什么,举例常见doctype及特点](#doctype是什么举例常见doctype及特点)\n    - [HTML全局属性(global attribute)有哪些](#html全局属性global-attribute有哪些)\n    - [什么是web语义化,有什么好处](#什么是web语义化有什么好处)\n    - [HTTP method](#http-method)\n    - [从浏览器地址栏输入url到显示页面的步骤(以HTTP为例)](#从浏览器地址栏输入url到显示页面的步骤以http为例)\n    - [HTTP request报文结构是怎样的](#http-request报文结构是怎样的)\n    - [HTTP response报文结构是怎样的](#http-response报文结构是怎样的)\n    - [如何进行网站性能优化](#如何进行网站性能优化)\n    - [什么是渐进增强](#什么是渐进增强)\n    - [HTTP状态码及其含义](#http状态码及其含义)\n  - [$CSS部分](#$css部分)\n    - [CSS选择器有哪些](#css选择器有哪些)\n    - [css sprite是什么,有什么优缺点](#css-sprite是什么有什么优缺点)\n    - [`display: none;`与`visibility: hidden;`的区别](#display-none与visibility-hidden的区别)\n    - [css hack原理及常用hack](#css-hack原理及常用hack)\n    - [specified value,computed value,used value计算方法](#specified-valuecomputed-valueused-value计算方法)\n    - [`link`与`@import`的区别](#link与@import的区别)\n    - [``display: block;``和``display: inline;``的区别](#display-block和display-inline的区别)\n    - [PNG,GIF,JPG的区别及如何选](#pnggifjpg的区别及如何选)\n    - [CSS有哪些继承属性](#css有哪些继承属性)\n    - [IE6浏览器有哪些常见的bug,缺陷或者与标准不一致的地方,如何解决](#ie6浏览器有哪些常见的bug缺陷或者与标准不一致的地方如何解决)\n    - [容器包含若干浮动元素时如何清理(包含)浮动](#容器包含若干浮动元素时如何清理包含浮动)\n    - [什么是FOUC?如何避免](#什么是fouc如何避免)\n    - [如何创建块级格式化上下文(block formatting context),BFC有什么用](#如何创建块级格式化上下文block-formatting-contextbfc有什么用)\n    - [display,float,position的关系](#displayfloatposition的关系)\n    - [外边距折叠(collapsing margins)](#外边距折叠collapsing-margins)\n    - [如何确定一个元素的包含块(containing block)](#如何确定一个元素的包含块containing-block)\n    - [stacking context,布局规则](#stacking-context布局规则)\n    - [如何水平居中一个元素](#如何水平居中一个元素)\n    - [如何竖直居中一个元素](#如何竖直居中一个元素)\n  - [$javascript概念部分](#$javascript概念部分)\n    - [DOM元素e的e.getAttribute(propName)和e.propName有什么区别和联系](#dom元素e的egetattributepropname和epropname有什么区别和联系)\n    - [offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别](#offsetwidthoffsetheightclientwidthclientheight与scrollwidthscrollheight的区别)\n    - [XMLHttpRequest通用属性和方法](#xmlhttprequest通用属性和方法)\n    - [focus/blur与focusin/focusout的区别与联系](#focusblur与focusinfocusout的区别与联系)\n    - [mouseover/mouseout与mouseenter/mouseleave的区别与联系](#mouseovermouseout与mouseentermouseleave的区别与联系)\n    - [sessionStorage,localStorage,cookie区别](#sessionstoragelocalstoragecookie区别)\n    - [javascript跨域通信](#javascript跨域通信)\n    - [javascript有哪几种数据类型](#javascript有哪几种数据类型)\n    - [什么闭包,闭包有什么用](#什么闭包闭包有什么用)\n    - [javascript有哪几种方法定义函数](#javascript有哪几种方法定义函数)\n    - [应用程序存储和离线web应用](#应用程序存储和离线web应用)\n    - [客户端存储localStorage和sessionStorage](#客户端存储localstorage和sessionstorage)\n    - [cookie及其操作](#cookie及其操作)\n    - [javascript有哪些方法定义对象](#javascript有哪些方法定义对象)\n    - [===运算符判断相等的流程是怎样的](#===运算符判断相等的流程是怎样的)\n    - [==运算符判断相等的流程是怎样的](#==运算符判断相等的流程是怎样的)\n    - [对象到字符串的转换步骤](#对象到字符串的转换步骤)\n    - [对象到数字的转换步骤](#对象到数字的转换步骤)\n    - [<,>,<=,>=的比较规则](#==的比较规则)\n    - [+运算符工作流程](#运算符工作流程)\n    - [函数内部arguments变量有哪些特性,有哪些属性,如何将它转换为数组](#函数内部arguments变量有哪些特性有哪些属性如何将它转换为数组)\n    - [DOM事件模型是如何的,编写一个EventUtil工具类实现事件管理兼容](#dom事件模型是如何的编写一个eventutil工具类实现事件管理兼容)\n    - [评价一下三种方法实现继承的优缺点,并改进](#评价一下三种方法实现继承的优缺点并改进)\n  - [$javascript编程部分](#$javascript编程部分)\n    - [请用原生js实现一个函数,给页面制定的任意一个元素添加一个透明遮罩(透明度可变,默认0.2),使这个区域点击无效,要求兼容IE8+及各主流浏览器,遮罩层效果如下图所示:](#请用原生js实现一个函数给页面制定的任意一个元素添加一个透明遮罩透明度可变默认02使这个区域点击无效要求兼容ie8及各主流浏览器遮罩层效果如下图所示)\n    - [请用代码写出(今天是星期x)其中x表示当天是星期几,如果当天是星期一,输出应该是\"今天是星期一\"](#请用代码写出今天是星期x其中x表示当天是星期几如果当天是星期一输出应该是今天是星期一)\n    - [下面这段代码想要循环延时输出结果0 1 2 3 4,请问输出结果是否正确,如果不正确,请说明为什么,并修改循环内的代码使其输出正确结果](#下面这段代码想要循环延时输出结果0-1-2-3-4请问输出结果是否正确如果不正确请说明为什么并修改循环内的代码使其输出正确结果)\n    - [现有一个Page类,其原型对象上有许多以post开头的方法(如postMsg);另有一拦截函数chekc,只返回ture或false.请设计一个函数,该函数应批量改造原Page的postXXX方法,在保留其原有功能的同时,为每个postXXX方法增加拦截验证功能,当chekc返回true时继续执行原postXXX方法,返回false时不再执行原postXXX方法](#现有一个page类其原型对象上有许多以post开头的方法如postmsg另有一拦截函数chekc只返回ture或false请设计一个函数该函数应批量改造原page的postxxx方法在保留其原有功能的同时为每个postxxx方法增加拦截验证功能当chekc返回true时继续执行原postxxx方法返回false时不再执行原postxxx方法)\n    - [完成下面的tool-tip](#完成下面的tool-tip)\n    - [编写javascript深度克隆函数deepClone](#编写javascript深度克隆函数deepclone)\n    - [补充代码,鼠标单击Button1后将Button1移动到Button2的后面](#补充代码鼠标单击button1后将button1移动到button2的后面)\n    - [网页中实现一个计算当年还剩多少时间的倒数计时程序,要求网页上实时动态显示\"××年还剩××天××时××分××秒\"](#网页中实现一个计算当年还剩多少时间的倒数计时程序要求网页上实时动态显示××年还剩××天××时××分××秒)\n    - [完成一个函数,接受数组作为参数,数组元素为整数或者数组,数组元素包含整数或数组,函数返回扁平化后的数组](#完成一个函数接受数组作为参数数组元素为整数或者数组数组元素包含整数或数组函数返回扁平化后的数组)\n    - [如何判断一个对象是否为数组](#如何判断一个对象是否为数组)\n    - [请评价以下事件监听器代码并给出改进意见](#请评价以下事件监听器代码并给出改进意见)\n    - [如何判断一个对象是否为函数](#如何判断一个对象是否为函数)\n    - [编写一个函数接受url中query string为参数,返回解析后的Object,query string使用application/x-www-form-urlencoded编码](#编写一个函数接受url中query-string为参数返回解析后的objectquery-string使用applicationx-www-form-urlencoded编码)\n    - [解析一个完整的url,返回Object包含域与window.location相同](#解析一个完整的url返回object包含域与windowlocation相同)\n    - [完成函数getViewportSize返回指定窗口的视口尺寸](#完成函数getviewportsize返回指定窗口的视口尺寸)\n    - [完成函数getScrollOffset返回窗口滚动条偏移量](#完成函数getscrolloffset返回窗口滚动条偏移量)\n    - [现有一个字符串richText,是一段富文本,需要显示在页面上.有个要求,需要给其中只包含一个img元素的p标签增加一个叫pic的class.请编写代码实现.可以使用jQuery或KISSY.](#现有一个字符串richtext是一段富文本需要显示在页面上有个要求需要给其中只包含一个img元素的p标签增加一个叫pic的class请编写代码实现可以使用jquery或kissy)\n    - [请实现一个Event类,继承自此类的对象都会拥有两个方法on,off,once和trigger](#请实现一个event类继承自此类的对象都会拥有两个方法onoffonce和trigger)\n    - [编写一个函数将列表子元素顺序反转](#编写一个函数将列表子元素顺序反转)\n    - [以下函数的作用是?空白区域应该填写什么](#以下函数的作用是空白区域应该填写什么)\n    - [编写一个函数实现form的序列化(即将一个表单中的键值序列化为可提交的字符串)](#编写一个函数实现form的序列化即将一个表单中的键值序列化为可提交的字符串)\n    - [使用原生javascript给下面列表中的li节点绑定点击事件,点击时创建一个Object对象,兼容IE和标准浏览器](#使用原生javascript给下面列表中的li节点绑定点击事件点击时创建一个object对象兼容ie和标准浏览器)\n    - [有一个大数组,var a = ['1', '2', '3', ...];a的长度是100,内容填充随机整数的字符串.请先构造此数组a,然后设计一个算法将其内容去重](#有一个大数组var-a-=-1-2-3-a的长度是100内容填充随机整数的字符串请先构造此数组a然后设计一个算法将其内容去重)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n# FE-interview\n\n个人收集的前端知识点、面试题和答案，参考答案仅代表个人观点，方便复习，目录如下，通过文档内搜索目录可快速定位章节\n\n## $HTML， HTTP，web综合问题\n\n### 常见排序算法的时间复杂度,空间复杂度\n\n![排序算法比较](img/sort-compare.png)\n\n### 前端需要注意哪些SEO\n\n1. 合理的title、description、keywords：搜索对着三项的权重逐个减小，title值强调重点即可，重要关键词出现不要超过2次，而且要靠前，不同页面title要有所不同；description把页面内容高度概括，长度合适，不可过分堆砌关键词，不同页面description有所不同；keywords列举出重要关键词即可\n2. 语义化的HTML代码，符合W3C规范：语义化代码让搜索引擎容易理解网页\n3. 重要内容HTML代码放在最前：搜索引擎抓取HTML顺序是从上到下，有的搜索引擎对抓取长度有限制，保证重要内容一定会被抓取\n4. 重要内容不要用js输出：爬虫不会执行js获取内容\n5. 少用iframe：搜索引擎不会抓取iframe中的内容\n6. 非装饰性图片必须加alt\n7. 提高网站速度：网站速度是搜索引擎排序的一个重要指标\n\n### web开发中会话跟踪的方法有哪些\n\n1. cookie\n2. session\n3. url重写\n4. 隐藏input\n5. ip地址\n\n### `<img>`的`title`和`alt`有什么区别\n\n1. `title`是[global attributes](http://www.w3.org/TR/html-markup/global-attributes.html#common.attrs.core)之一，用于为元素提供附加的advisory information。通常当鼠标滑动到元素上的时候显示。\n2. `alt`是`<img>`的特有属性，是图片内容的等价描述，用于图片无法加载时显示、读屏器阅读图片。可提图片高可访问性，除了纯装饰图片外都必须设置有意义的值，搜索引擎会重点分析。\n\n### doctype是什么,举例常见doctype及特点\n\n1. `<!doctype>`声明必须处于HTML文档的头部，在`<html>`标签之前，HTML5中不区分大小写\n2. `<!doctype>`声明不是一个HTML标签，是一个用于告诉浏览器当前HTMl版本的指令\n3. 现代浏览器的html布局引擎通过检查doctype决定使用兼容模式还是标准模式对文档进行渲染，一些浏览器有一个接近标准模型。\n3. 在HTML4.01中`<!doctype>`声明指向一个DTD，由于HTML4.01基于SGML，所以DTD指定了标记规则以保证浏览器正确渲染内容\n4. HTML5不基于SGML，所以不用指定DTD\n\n常见dotype：\n\n1. **HTML4.01 strict**：不允许使用表现性、废弃元素（如font）以及frameset。声明：`<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">`\n2. **HTML4.01 Transitional**:允许使用表现性、废弃元素（如font），不允许使用frameset。声明：`<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">`\n3. **HTML4.01 Frameset**:允许表现性元素，废气元素以及frameset。声明：`<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">`\n4. **XHTML1.0 Strict**:不使用允许表现性、废弃元素以及frameset。文档必须是结构良好的XML文档。声明：``<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">``\n5. **XHTML1.0 Transitional**:允许使用表现性、废弃元素，不允许frameset，文档必须是结构良好的XMl文档。声明： ``<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">``\n6. **XHTML 1.0 Frameset**:允许使用表现性、废弃元素以及frameset，文档必须是结构良好的XML文档。声明：``<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">``\n7. **HTML 5**: `<!doctype html>`\n\n### HTML全局属性(global attribute)有哪些\n\n参考资料：[MDN: html global attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes)或者[W3C HTML global-attributes](http://www.w3.org/TR/html-markup/global-attributes.html#common.attrs.core)\n\n- `accesskey`:设置快捷键，提供快速访问元素如<a href=\"#\" accesskey=\"a\">aaa</a>在windows下的firefox中按``alt + shift + a``可激活元素\n- `class`:为元素设置类标识，多个类名用空格分开，CSS和javascript可通过class属性获取元素\n- `contenteditable`: 指定元素内容是否可编辑\n- `contextmenu`: 自定义鼠标右键弹出菜单内容\n- `data-*`: 为元素增加自定义属性\n- `dir`: 设置元素文本方向\n- `draggable`: 设置元素是否可拖拽\n- `dropzone`: 设置元素拖放类型： copy, move, link\n- `hidden`: 表示一个元素是否与文档。样式上会导致元素不显示，但是不能用这个属性实现样式效果\n- `id`: 元素id，文档内唯一\n- `lang`: 元素内容的的语言\n- `spellcheck`: 是否启动拼写和语法检查\n- `style`: 行内css样式\n- `tabindex`: 设置元素可以获得焦点，通过tab可以导航\n- `title`: 元素相关的建议信息\n- `translate`: 元素和子孙节点内容是否需要本地化\n\n### 什么是web语义化,有什么好处\n\nweb语义化是指通过HTML标记表示页面包含的信息，包含了HTML标签的语义化和css命名的语义化。\nHTML标签的语义化是指：通过使用包含语义的标签（如h1-h6）恰当地表示文档结构\ncss命名的语义化是指：为html标签添加有意义的class，id补充未表达的语义，如[Microformat](http://en.wikipedia.org/wiki/Microformats)通过添加符合规则的class描述信息\n为什么需要语义化：\n\n- 去掉样式后页面呈现清晰的结构\n- 盲人使用读屏器更好地阅读\n- 搜索引擎更好地理解页面，有利于收录\n- 便团队项目的可持续运作及维护\n\n### HTTP method\n\n1. 一台服务器要与HTTP1.1兼容，只要为资源实现**GET**和**HEAD**方法即可\n2. **GET**是最常用的方法，通常用于**请求服务器发送某个资源**。\n3. **HEAD**与GET类似，但**服务器在响应中值返回首部，不返回实体的主体部分**\n4. **PUT**让服务器**用请求的主体部分来创建一个由所请求的URL命名的新文档，或者，如果那个URL已经存在的话，就用干这个主体替代它**\n5. **POST**起初是用来向服务器输入数据的。实际上，通常会用它来支持HTML的表单。表单中填好的数据通常会被送给服务器，然后由服务器将其发送到要去的地方。\n6. **TRACE**会在目的服务器端发起一个环回诊断，最后一站的服务器会弹回一个TRACE响应并在响应主体中携带它收到的原始请求报文。TRACE方法主要用于诊断，用于验证请求是否如愿穿过了请求/响应链。\n7. **OPTIONS**方法请求web服务器告知其支持的各种功能。可以查询服务器支持哪些方法或者对某些特殊资源支持哪些方法。\n8. **DELETE**请求服务器删除请求URL指定的资源\n\n### 从浏览器地址栏输入url到显示页面的步骤(以HTTP为例)\n\n1. 在浏览器地址栏输入URL\n2. 浏览器查看**缓存**，如果请求资源在缓存中并且新鲜，跳转到转码步骤\n    1. 如果资源未缓存，发起新请求\n    2. 如果已缓存，检验是否足够新鲜，足够新鲜直接提供给客户端，否则与服务器进行验证。\n    3. 检验新鲜通常有两个HTTP头进行控制`Expires`和`Cache-Control`：\n        - HTTP1.0提供Expires，值为一个绝对时间表示缓存新鲜日期\n        - HTTP1.1增加了Cache-Control: max-age=,值为以秒为单位的最大新鲜时间\n3. 浏览器**解析URL**获取协议，主机，端口，path\n4. 浏览器**组装一个HTTP（GET）请求报文**\n5. 浏览器**获取主机ip地址**，过程如下：\n    1. 浏览器缓存\n    2. 本机缓存\n    3. hosts文件\n    4. 路由器缓存\n    5. ISP DNS缓存\n    6. DNS递归查询（可能存在负载均衡导致每次IP不一样）\n6. **打开一个socket与目标IP地址，端口建立TCP链接**，三次握手如下：\n    1. 客户端发送一个TCP的**SYN=1，Seq=X**的包到服务器端口\n    2. 服务器发回**SYN=1， ACK=X+1， Seq=Y**的响应包\n    3. 客户端发送**ACK=Y+1， Seq=Z**\n7. TCP链接建立后**发送HTTP请求**\n8. 服务器接受请求并解析，将请求转发到服务程序，如虚拟主机使用HTTP Host头部判断请求的服务程序\n9. 服务器检查**HTTP请求头是否包含缓存验证信息**如果验证缓存新鲜，返回**304**等对应状态码\n10. 处理程序读取完整请求并准备HTTP响应，可能需要查询数据库等操作\n11. 服务器将**响应报文通过TCP连接发送回浏览器**\n12. 浏览器接收HTTP响应，然后根据情况选择**关闭TCP连接或者保留重用，关闭TCP连接的四次握手如下**：\n    1. 主动方发送**Fin=1， Ack=Z， Seq= X**报文\n    2. 被动方发送**ACK=X+1， Seq=Z**报文\n    3. 被动方发送**Fin=1， ACK=X， Seq=Y**报文\n    4. 主动方发送**ACK=Y， Seq=X**报文\n13. 浏览器检查响应状态吗：是否为1XX，3XX， 4XX， 5XX，这些情况处理与2XX不同\n14. 如果资源可缓存，**进行缓存**\n15. 对响应进行**解码**（例如gzip压缩）\n16. 根据资源类型决定如何处理（假设资源为HTML文档）\n17. **解析HTML文档，构件DOM树，下载资源，构造CSSOM树，执行js脚本**，这些操作没有严格的先后顺序，以下分别解释\n18. **构建DOM树**：\n    1. **Tokenizing**：根据HTML规范将字符流解析为标记\n    2. **Lexing**：词法分析将标记转换为对象并定义属性和规则\n    3. **DOM construction**：根据HTML标记关系将对象组成DOM树\n19. 解析过程中遇到图片、样式表、js文件，**启动下载**\n20. 构建**CSSOM树**：\n    1. **Tokenizing**：字符流转换为标记流\n    2. **Node**：根据标记创建节点\n    3. **CSSOM**：节点创建CSSOM树\n21. **[根据DOM树和CSSOM树构建渲染树](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction)**:\n    1. 从DOM树的根节点遍历所有**可见节点**，不可见节点包括：1）`script`,`meta`这样本身不可见的标签。2)被css隐藏的节点，如`display: none`\n    2. 对每一个可见节点，找到恰当的CSSOM规则并应用\n    3. 发布可视节点的内容和计算样式\n22. **js解析如下**：\n    1. 浏览器创建Document对象并解析HTML，将解析到的元素和文本节点添加到文档中，此时**document.readystate为loading**\n    2. HTML解析器遇到**没有async和defer的script时**，将他们添加到文档中，然后执行行内或外部脚本。这些脚本会同步执行，并且在脚本下载和执行时解析器会暂停。这样就可以用document.write()把文本插入到输入流中。**同步脚本经常简单定义函数和注册事件处理程序，他们可以遍历和操作script和他们之前的文档内容**\n    3. 当解析器遇到设置了**async**属性的script时，开始下载脚本并继续解析文档。脚本会在它**下载完成后尽快执行**，但是**解析器不会停下来等它下载**。异步脚本**禁止使用document.write()**，它们可以访问自己script和之前的文档元素\n    4. 当文档完成解析，document.readState变成interactive\n    5. 所有**defer**脚本会**按照在文档出现的顺序执行**，延迟脚本**能访问完整文档树**，禁止使用document.write()\n    6. 浏览器**在Document对象上触发DOMContentLoaded事件**\n    7. 此时文档完全解析完成，浏览器可能还在等待如图片等内容加载，等这些**内容完成载入并且所有异步脚本完成载入和执行**，document.readState变为complete,window触发load事件\n23. **显示页面**（HTML解析过程中会逐步显示页面）\n\n### HTTP request报文结构是怎样的\n[rfc2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html)中进行了定义：\n\n1. 首行是**Request-Line**包括：**请求方法**，**请求URI**，**协议版本**，**CRLF**\n2. 首行之后是若干行**请求头**，包括**general-header**，**request-header**或者**entity-header**，每个一行以CRLF结束\n3. 请求头和消息实体之间有一个**CRLF分隔**\n4. 根据实际请求需要可能包含一个**消息实体**\n一个请求报文例子如下：\n\n```\nGET /Protocols/rfc2616/rfc2616-sec5.html HTTP/1.1\nHost: www.w3.org\nConnection: keep-alive\nCache-Control: max-age=0\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36\nReferer: https://www.google.com.hk/\nAccept-Encoding: gzip,deflate,sdch\nAccept-Language: zh-CN,zh;q=0.8,en;q=0.6\nCookie: authorstyle=yes\nIf-None-Match: \"2cc8-3e3073913b100\"\nIf-Modified-Since: Wed, 01 Sep 2004 13:24:52 GMT\n\nname=qiu&age=25\n```\n\n### HTTP response报文结构是怎样的\n\n[rfc2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html)中进行了定义：\n\n1. 首行是状态行包括：**HTTP版本，状态码，状态描述**，后面跟一个CRLF\n2. 首行之后是**若干行响应头**，包括：**通用头部，响应头部，实体头部**\n3. 响应头部和响应实体之间用**一个CRLF空行**分隔\n4. 最后是一个可能的**消息实体**\n响应报文例子如下：\n\n```\nHTTP/1.1 200 OK\nDate: Tue, 08 Jul 2014 05:28:43 GMT\nServer: Apache/2\nLast-Modified: Wed, 01 Sep 2004 13:24:52 GMT\nETag: \"40d7-3e3073913b100\"\nAccept-Ranges: bytes\nContent-Length: 16599\nCache-Control: max-age=21600\nExpires: Tue, 08 Jul 2014 11:28:43 GMT\nP3P: policyref=\"http://www.w3.org/2001/05/P3P/p3p.xml\"\nContent-Type: text/html; charset=iso-8859-1\n\n{\"name\": \"qiu\", \"age\": 25}\n```\n\n### 如何进行网站性能优化\n\n[雅虎Best Practices for Speeding Up Your Web Site](https://developer.yahoo.com/performance/rules.html)：\n\n- content方面\n    1. 减少HTTP请求：合并文件、CSS精灵、inline Image\n    2. 减少DNS查询：DNS查询完成之前浏览器不能从这个主机下载任何任何文件。方法：DNS缓存、将资源分布到恰当数量的主机名，平衡并行下载和DNS查询\n    3. 避免重定向：多余的中间访问\n    4. 使Ajax可缓存\n    5. 非必须组件延迟加载\n    6. 未来所需组件预加载\n    7. 减少DOM元素数量\n    8. 将资源放到不同的域下：浏览器同时从一个域下载资源的数目有限，增加域可以提高并行下载量\n    9. 减少iframe数量\n    10. 不要404\n\n- Server方面\n    1. 使用CDN\n    2. 添加Expires或者Cache-Control响应头\n    3. 对组件使用Gzip压缩\n    4. 配置ETag\n    5. Flush Buffer Early\n    6. Ajax使用GET进行请求\n    7. 避免空src的img标签\n- Cookie方面\n    1. 减小cookie大小\n    2. 引入资源的域名不要包含cookie\n- css方面\n    1. 将样式表放到页面顶部\n    2. 不使用CSS表达式\n    3. 使用<link>不使用@import\n    4. 不使用IE的Filter\n- Javascript方面\n    1. 将脚本放到页面底部\n    2. 将javascript和css从外部引入\n    3. 压缩javascript和css\n    4. 删除不需要的脚本\n    5. 减少DOM访问\n    6. 合理设计事件监听器\n- 图片方面\n    1. 优化图片：根据实际颜色需要选择色深、压缩\n    2. 优化css精灵\n    3. 不要在HTML中拉伸图片\n    4. 保证favicon.ico小并且可缓存\n- 移动方面\n    1. 保证组件小于25k\n    2. Pack Components into a Multipart Document\n\n\n### 什么是渐进增强\n\n渐进增强是指在web设计时强调可访问性、语义化HTML标签、外部样式表和脚本。保证所有人都能访问页面的基本内容和功能同时为高级浏览器和高带宽用户提供更好的用户体验。核心原则如下:\n\n- 所有浏览器都必须能访问基本内容\n- 所有浏览器都必须能使用基本功能\n- 所有内容都包含在语义化标签中\n- 通过外部CSS提供增强的布局\n- 通过非侵入式、外部javascript提供增强功能\n- end-user web browser preferences are respected\n\n### HTTP状态码及其含义\n\n参考[RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)\n\n- 1XX：信息状态码\n    - **100 Continue**：客户端应当继续发送请求。这个临时相应是用来通知客户端它的部分请求已经被服务器接收，且仍未被拒绝。客户端应当继续发送请求的剩余部分，或者如果请求已经完成，忽略这个响应。服务器必须在请求万仇向客户端发送一个最终响应\n    - **101 Switching Protocols**：服务器已经理解力客户端的请求，并将通过Upgrade消息头通知客户端采用不同的协议来完成这个请求。在发送完这个响应最后的空行后，服务器将会切换到Upgrade消息头中定义的那些协议。\n- 2XX：成功状态码\n    - **200 OK**：请求成功，请求所希望的响应头或数据体将随此响应返回\n    - **201 Created**：\n    - **202 Accepted**：\n    - **203 Non-Authoritative Information**：\n    - **204 No Content**：\n    - **205 Reset Content**：\n    - **206 Partial Content**：\n- 3XX：重定向\n    - **300 Multiple Choices**：\n    - **301 Moved Permanently**：\n    - **302 Found**：\n    - **303 See Other**：\n    - **304 Not Modified**：\n    - **305 Use Proxy**：\n    - **306 （unused）**：\n    - **307 Temporary Redirect**：\n- 4XX：客户端错误\n    - **400 Bad Request**:\n    - **401 Unauthorized**:\n    - **402 Payment Required**:\n    - **403 Forbidden**:\n    - **404 Not Found**:\n    - **405 Method Not Allowed**:\n    - **406 Not Acceptable**:\n    - **407 Proxy Authentication Required**:\n    - **408 Request Timeout**:\n    - **409 Conflict**:\n    - **410 Gone**:\n    - **411 Length Required**:\n    - **412 Precondition Failed**:\n    - **413 Request Entity Too Large**:\n    - **414 Request-URI Too Long**:\n    - **415 Unsupported Media Type**:\n    - **416 Requested Range Not Satisfiable**:\n    - **417 Expectation Failed**:\n- 5XX: 服务器错误\n    - **500 Internal Server Error**:\n    - **501 Not Implemented**:\n    - **502 Bad Gateway**:\n    - **503 Service Unavailable**:\n    - **504 Gateway Timeout**:\n    - **505 HTTP Version Not Supported**:\n\n## $CSS部分\n\n### CSS选择器有哪些\n\n1. ***通用选择器**：选择所有元素，**不参与计算优先级**，兼容性IE6+\n2. **#X id选择器**：选择id值为X的元素，兼容性：IE6+\n3. **.X 类选择器**： 选择class包含X的元素，兼容性：IE6+\n4. **X Y后代选择器**： 选择满足X选择器的后代节点中满足Y选择器的元素，兼容性：IE6+\n5. **X 元素选择器**： 选择标所有签为X的元素，兼容性：IE6+\n6. **:link，：visited，：focus，：hover，：active链接状态**： 选择特定状态的链接元素，顺序LoVe HAte，兼容性: IE4+\n7. **X + Y直接兄弟选择器**：在**X之后第一个兄弟节点**中选择满足Y选择器的元素，兼容性： IE7+\n8. **X > Y子选择器**： 选择X的子元素中满足Y选择器的元素，兼容性： IE7+\n9. **X ~ Y兄弟**： 选择**X之后所有兄弟节点**中满足Y选择器的元素，兼容性： IE7+\n10. **[attr]**：选择所有设置了attr属性的元素，兼容性IE7+\n11. **[attr=value]**：选择属性值刚好为value的元素\n12. **[attr~=value]**：选择属性值为空白符分隔，其中一个的值刚好是value的元素\n13. **[attr|=value]**：选择属性值刚好为value或者value-开头的元素\n14. **[attr^=value]**：选择属性值以value开头的元素\n15. **[attr$=value]**：选择属性值以value结尾的元素\n16. **[attr*=value]**：选择属性值中包含value的元素\n17. **[:checked]**：选择单选框，复选框，下拉框中选中状态下的元素，兼容性：IE9+\n18. **X:after, X::after**：after伪元素，选择元素虚拟子元素（元素的最后一个子元素），CSS3中::表示伪元素。兼容性:after为IE8+，::after为IE9+\n18. **:hover**：鼠标移入状态的元素，兼容性a标签IE4+， 所有元素IE7+\n19. **:not(selector)**：选择不符合selector的元素。**不参与计算优先级**，兼容性：IE9+\n20. **::first-letter**：伪元素，选择块元素第一行的第一个字母，兼容性IE5.5+\n21. **::first-line**：伪元素，选择块元素的第一行，兼容性IE5.5+\n22. **:nth-child(an + b)**：伪类，选择前面有an + b - 1个兄弟节点的元素，其中n\n&gt;= 0， 兼容性IE9+\n23. **:nth-last-child(an + b)**：伪类，选择后面有an + b - 1个兄弟节点的元素\n其中n &gt;= 0，兼容性IE9+\n24. **X:nth-of-type(an+b)**：伪类，X为选择器，**解析得到元素标签**，选择**前面**有an + b - 1个**相同标签**兄弟节点的元素。兼容性IE9+\n25. **X:nth-last-of-type(an+b)**：伪类，X为选择器，解析得到元素标签，选择**后面**有an+b-1个相同**标签**兄弟节点的元素。兼容性IE9+\n26. **X:first-child**：伪类，选择满足X选择器的元素，且这个元素是其父节点的第一个子元素。兼容性IE7+\n27. **X:last-child**：伪类，选择满足X选择器的元素，且这个元素是其父节点的最后一个子元素。兼容性IE9+\n28. **X:only-child**：伪类，选择满足X选择器的元素，且这个元素是其父元素的唯一子元素。兼容性IE9+\n29. **X:only-of-type**：伪类，选择X选择的元素，**解析得到元素标签**，如果该元素没有相同类型的兄弟节点时选中它。兼容性IE9+\n30. **X:first-of-type**：伪类，选择X选择的元素，**解析得到元素标签**，如果该元素\n是此此类型元素的第一个兄弟。选中它。兼容性IE9+\n\n\n### css sprite是什么,有什么优缺点\n\n概念：将多个小图片拼接到一个图片中。通过background-position和元素尺寸调节需要显示的背景图案。\n\n优点：\n\n1. 减少HTTP请求数，极大地提高页面加载速度\n2. 增加图片信息重复度，提高压缩比，减少图片大小\n3. 更换风格方便，只需在一张或几张图片上修改颜色或样式即可实现\n\n缺点：\n\n1. 图片合并麻烦\n2. 维护麻烦，修改一个图片可能需要从新布局整个图片，样式\n\n\n### `display: none;`与`visibility: hidden;`的区别\n联系：它们都能让元素不可见\n\n区别：\n\n1. display:none;会让元素完全从渲染树中消失，渲染的时候不占据任何空间；visibility: hidden;不会让元素从渲染树消失，渲染师元素继续占据空间，只是内容不可见\n2. display: none;是非继承属性，子孙节点消失由于元素从渲染树消失造成，通过修改子孙节点属性无法显示；visibility: hidden;是继承属性，子孙节点消失由于继承了hidden，通过设置visibility: visible;可以让子孙节点显式\n3. 修改常规流中元素的display通常会造成文档重排。修改visibility属性只会造成本元素的重绘。\n4. 读屏器不会读取display: none;元素内容；会读取visibility: hidden;元素内容\n\n### css hack原理及常用hack\n\n原理：利用**不同浏览器对CSS的支持和解析结果不一样**编写针对特定浏览器样式。常见的hack有1）属性hack。2）选择器hack。3）IE条件注释\n\n- IE条件注释：适用于[IE5, IE9]常见格式如下\n\n```\n<!--[if IE 6]>\nSpecial instructions for IE 6 here\n<![endif]-->\n```\n\n- 选择器hack：不同浏览器对选择器的支持不一样\n\n```\n/***** Selector Hacks ******/\n\n/* IE6 and below */\n* html #uno  { color: red }\n\n/* IE7 */\n*:first-child+html #dos { color: red }\n\n/* IE7, FF, Saf, Opera  */\nhtml>body #tres { color: red }\n\n/* IE8, FF, Saf, Opera (Everything but IE 6,7) */\nhtml>/**/body #cuatro { color: red }\n\n/* Opera 9.27 and below, safari 2 */\nhtml:first-child #cinco { color: red }\n\n/* Safari 2-3 */\nhtml[xmlns*=\"\"] body:last-child #seis { color: red }\n\n/* safari 3+, chrome 1+, opera9+, ff 3.5+ */\nbody:nth-of-type(1) #siete { color: red }\n\n/* safari 3+, chrome 1+, opera9+, ff 3.5+ */\nbody:first-of-type #ocho {  color: red }\n\n/* saf3+, chrome1+ */\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n #diez  { color: red  }\n}\n\n/* iPhone / mobile webkit */\n@media screen and (max-device-width: 480px) {\n #veintiseis { color: red  }\n}\n\n/* Safari 2 - 3.1 */\nhtml[xmlns*=\"\"]:root #trece  { color: red  }\n\n/* Safari 2 - 3.1, Opera 9.25 */\n*|html[xmlns*=\"\"] #catorce { color: red  }\n\n/* Everything but IE6-8 */\n:root *> #quince { color: red  }\n\n/* IE7 */\n*+html #dieciocho {  color: red }\n\n/* Firefox only. 1+ */\n#veinticuatro,  x:-moz-any-link  { color: red }\n\n/* Firefox 3.0+ */\n#veinticinco,  x:-moz-any-link, x:default  { color: red  }\n```\n\n- 属性hack：不同浏览器解析bug或方法\n\n```\n/* IE6 */\n#once { _color: blue }\n\n/* IE6, IE7 */\n#doce { *color: blue; /* or #color: blue */ }\n\n/* Everything but IE6 */\n#diecisiete { color/**/: blue }\n\n/* IE6, IE7, IE8 */\n#diecinueve { color: blue\\9; }\n\n/* IE7, IE8 */\n#veinte { color/*\\**/: blue\\9; }\n\n/* IE6, IE7 -- acts as an !important */\n#veintesiete { color: blue !ie; } /* string after ! can be anything */\n```\n\n### specified value,computed value,used value计算方法\n\n- specified value: 计算方法如下：\n    1. 如果样式表设置了一个值，使用这个值\n    2. 如果没有设置值，这个属性是继承属性，从父元素继承\n    3. 如果没设置，并且不是继承属性，使用css规范指定的初始值\n\n- computed value: 以specified value根据规范定义的行为进行计算，通常将相对值计算为绝对值，例如em根据font-size进行计算。一些使用百分数并且需要布局来决定最终值的属性，如width，margin。百分数就直接作为computed value。line-height的无单位值也直接作为computed value。这些值将在计算used value时得到绝对值。**computed value的主要作用是用于继承**\n\n- used value：属性计算后的最终值，对于大多数属性可以通过window.getComputedStyle获得，尺寸值单位为像素。以下属性依赖于布局，\n    - background-position\n    - bottom, left, right, top\n    - height, width\n    - margin-bottom, margin-left, margin-right, margin-top\n    - min-height, min-width\n    - padding-bottom, padding-left, padding-right, padding-top\n    - text-indent\n\n### `link`与`@import`的区别\n\n1. ``link``是HTML方式， ``@import``是CSS方式\n2. ``link``最大限度支持并行下载，``@import``过多嵌套导致串行下载，出现[FOUC](http://www.bluerobot.com/web/css/fouc.asp/)\n4. ``link``可以通过``rel=\"alternate stylesheet\"``指定候选样式\n5. 浏览器对``link``支持早于``@import``，可以使用``@import``对老浏览器隐藏样式\n6. ``@import``必须在样式规则之前，可以在css文件中引用其他文件\n6. 总体来说：**[link优于@import](http://www.stevesouders.com/blog/2009/04/09/dont-use-import/)**\n\n### ``display: block;``和``display: inline;``的区别\n\n``block``元素特点：\n\n1.处于常规流中时，如果``width``没有设置，会自动填充满父容器\n2.可以应用``margin/padding``\n3.在没有设置高度的情况下会扩展高度以包含常规流中的子元素\n4.处于常规流中时布局时在前后元素位置之间（独占一个水平空间）\n5.忽略``vertical-align``\n\n``inline``元素特点\n\n1.水平方向上根据``direction``依次布局\n2.不会在元素前后进行换行\n3.受``white-space``控制\n4.``margin/padding``在竖直方向上无效，水平方向上有效\n5.``width/height``属性对非替换行内元素无效，宽度由元素内容决定\n6.非替换行内元素的行框高由``line-height``确定，替换行内元素的行框高由``height``,``margin``,``padding``,``border``决定\n6.浮动或绝对定位时会转换为``block``\n7.``vertical-align``属性生效\n\n\n\n### PNG,GIF,JPG的区别及如何选\n参考资料： [选择正确的图片格式](http://www.yuiblog.com/blog/2008/11/04/imageopt-2/)\n**GIF**:\n\n1. 8位像素，256色\n2. 无损压缩\n3. 支持简单动画\n4. 支持boolean透明\n5. 适合简单动画\n\n**JPEG**：\n\n1. 颜色限于256\n2. 有损压缩\n3. 可控制压缩质量\n4. 不支持透明\n5. 适合照片\n\n**PNG**：\n\n1. 有PNG8和truecolor PNG\n2. PNG8类似GIF颜色上限为256，文件小，支持alpha透明度，无动画\n3. 适合图标、背景、按钮\n\n### CSS有哪些继承属性\n\n- 关于文字排版的属性如：\n  +  [font](https://developer.mozilla.org/en-US/docs/Web/CSS/font)\n  +  [word-break](https://developer.mozilla.org/en-US/docs/Web/CSS/word-break)\n  +  [letter-spacing](https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing)\n  +  [text-align](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align)\n  +  [text-rendering](https://developer.mozilla.org/en-US/docs/Web/CSS/text-rendering)\n  +  [word-spacing](https://developer.mozilla.org/en-US/docs/Web/CSS/word-spacing)\n  +  [white-space](https://developer.mozilla.org/en-US/docs/Web/CSS/white-space)\n  +  [text-indent](https://developer.mozilla.org/en-US/docs/Web/CSS/text-indent)\n  +  [text-transform](https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform)\n  +  [text-shadow](https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow)\n- [line-height](https://developer.mozilla.org/en-US/docs/Web/CSS/line-height)\n- [color](https://developer.mozilla.org/en-US/docs/Web/CSS/color)\n- [visibility](https://developer.mozilla.org/en-US/docs/Web/CSS/visibility)\n- [cursor](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor)\n\n\n\n### IE6浏览器有哪些常见的bug,缺陷或者与标准不一致的地方,如何解决\n\n- IE6不支持min-height，解决办法使用css hack：\n\n```\n.target {\n    min-height: 100px;\n    height: auto !important;\n    height: 100px;   // IE6下内容高度超过会自动扩展高度\n}\n```\n\n- ``ol``内``li``的序号全为1，不递增。解决方法：为li设置样式``display: list-item;``\n\n- 未定位父元素``overflow: auto;``，包含``position: relative;``子元素，子元素高于父元素时会溢出。解决办法：1）子元素去掉``position: relative;``; 2）不能为子元素去掉定位时，父元素``position: relative;``\n\n```\n<style type=\"text/css\">\n.outer {\n    width: 215px;\n    height: 100px;\n    border: 1px solid red;\n    overflow: auto;\n    position: relative;  /* 修复bug */\n}\n.inner {\n    width: 100px;\n    height: 200px;\n    background-color: purple;\n    position: relative;\n}\n</style>\n\n<div class=\"outer\">\n    <div class=\"inner\"></div>\n</div>\n```\n\n- IE6只支持``a``标签的``:hover``伪类，解决方法：使用js为元素监听mouseenter，mouseleave事件，添加类实现效果：\n\n```\n<style type=\"text/css\">\n.p:hover,\n.hover {\n    background: purple;\n}\n</style>\n\n<p class=\"p\" id=\"target\">aaaa bbbbb<span>DDDDDDDDDDDd</span> aaaa lkjlkjdf j</p>\n\n<script type=\"text/javascript\">\nfunction addClass(elem, cls) {\n    if (elem.className) {\n        elem.className += ' ' + cls;\n    } else {\n        elem.className = cls;\n    }\n}\nfunction removeClass(elem, cls) {\n    var className = ' ' + elem.className + ' ';\n    var reg = new RegExp(' +' + cls + ' +', 'g');\n    elem.className = className.replace(reg, ' ').replace(/^ +| +$/, '');\n}\n\nvar target = document.getElementById('target');\nif (target.attachEvent) {\n    target.attachEvent('onmouseenter', function () {\n        addClass(target, 'hover');\n    });\n    target.attachEvent('onmouseleave', function () {\n        removeClass(target, 'hover');\n    })\n}\n</script>\n```\n\n- IE5-8不支持``opacity``，解决办法：\n\n```\n.opacity {\n    opacity: 0.4\n    filter: alpha(opacity=60); /* for IE5-7 */\n    -ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)\"; /* for IE 8*/\n}\n```\n\n- IE6在设置``height``小于``font-size``时高度值为``font-size``，解决办法：``font-size: 0;``\n- IE6不支持PNG透明背景，解决办法: **IE6下使用gif图片**\n- IE6-7不支持``display: inline-block``解决办法：设置inline并触发hasLayout\n\n```\n    display: inline-block;\n    *display: inline;\n    *zoom: 1;\n```\n\n- IE6下浮动元素在浮动方向上与父元素边界接触元素的外边距会加倍。解决办法：\n1）使用padding控制间距。\n2）浮动元素``display: inline;``这样解决问题且无任何副作用：css标准规定浮动元素display:inline会自动调整为block\n- 通过为块级元素设置宽度和左右margin为auto时，IE6不能实现水平居中，解决方法：为父元素设置``text-align: center;``\n\n### 容器包含若干浮动元素时如何清理(包含)浮动\n\n1. 容器元素闭合标签前添加额外元素并设置``clear: both``\n2. 父元素触发块级格式化上下文(见块级可视化上下文部分)\n3. 设置容器元素伪元素进行清理[推荐的清理浮动方法](http://nicolasgallagher.com/micro-clearfix-hack/)\n\n```\n/**\n* 在标准浏览器下使用\n* 1 content内容为空格用于修复opera下文档中出现\n*   contenteditable属性时在清理浮动元素上下的空白\n* 2 使用display使用table而不是block：可以防止容器和\n*   子元素top-margin折叠,这样能使清理效果与BFC，IE6/7\n*   zoom: 1;一致\n**/\n\n.clearfix:before,\n.clearfix:after {\n    content: \" \"; /* 1 */\n    display: table; /* 2 */\n}\n\n.clearfix:after {\n    clear: both;\n}\n\n/**\n* IE 6/7下使用\n* 通过触发hasLayout实现包含浮动\n**/\n.clearfix {\n    *zoom: 1;\n}\n```\n\n### 什么是FOUC?如何避免\nFlash Of Unstyled Content：用户定义样式表加载之前浏览器使用默认样式显示文档，用户样式加载渲染之后再从新显示文档，造成页面闪烁。**解决方法**：把样式表放到文档的`head`\n\n### 如何创建块级格式化上下文(block formatting context),BFC有什么用\n创建规则：\n\n1. 根元素\n2. 浮动元素（``float``不是``none``）\n3. 绝对定位元素（``position``取值为``absolute``或``fixed``）\n4. ``display``取值为``inline-block``,``table-cell``, ``table-caption``,``flex``, ``inline-flex``之一的元素\n5. ``overflow``不是``visible``的元素\n\n\n作用：\n\n1. 可以包含浮动元素\n2. 不被浮动元素覆盖\n3. 阻止父子元素的margin折叠\n\n### display,float,position的关系\n\n1. 如果``display``为none，那么position和float都不起作用，这种情况下元素不产生框\n2. 否则，如果position值为absolute或者fixed，框就是绝对定位的，float的计算值为none，display根据下面的表格进行调整。\n3. 否则，如果float不是none，框是浮动的，display根据下表进行调整\n4. 否则，如果元素是根元素，display根据下表进行调整\n5. 其他情况下display的值为指定值\n总结起来：**绝对定位、浮动、根元素都需要调整``display``**\n![display转换规则](img/display-adjust.png)\n\n### 外边距折叠(collapsing margins)\n毗邻的两个或多个``margin``会合并成一个margin，叫做外边距折叠。规则如下：\n\n1. 两个或多个毗邻的普通流中的块元素垂直方向上的margin会折叠\n2. 浮动元素/inline-block元素/绝对定位元素的margin不会和垂直方向上的其他元素的margin折叠\n3. 创建了块级格式化上下文的元素，不会和它的子元素发生margin折叠\n4. 元素自身的margin-bottom和margin-top相邻时也会折叠\n\n### 如何确定一个元素的包含块(containing block)\n\n1. 根元素的包含块叫做初始包含块，在连续媒体中他的尺寸与viewport相同并且anchored at the canvas origin；对于paged media，它的尺寸等于page area。初始包含块的direction属性与根元素相同。\n2. ``position``为``relative``或者``static``的元素，它的包含块由最近的块级（``display``为``block``,``list-item``, ``table``）祖先元素的**内容框**组成\n3. 如果元素``position``为``fixed``。对于连续媒体，它的包含块为viewport；对于paged media，包含块为page area\n4. 如果元素``position``为``absolute``，它的包含块由祖先元素中最近一个``position``为``relative``,``absolute``或者``fixed``的元素产生，规则如下：\n    - 如果祖先元素为行内元素，the containing block is the bounding box around the **padding boxes** of the first and the last inline boxes generated for that element.\n    - 其他情况下包含块由祖先节点的**padding edge**组成\n\n    如果找不到定位的祖先元素，包含块为**初始包含块**\n\n### stacking context,布局规则\nz轴上的默认层叠顺序如下（从下到上）：\n\n1. 根元素的边界和背景\n2. 常规流中的元素按照html中顺序\n3. 浮动块\n4. positioned元素按照html中出现顺序\n\n如何创建stacking context：\n\n1. 根元素\n2. z-index不为auto的定位元素\n3. a flex item with a z-index value other than 'auto'\n4. opacity小于1的元素\n5. 在移动端webkit和chrome22+，z-index为auto，position: fixed也将创建新的stacking context\n\n### 如何水平居中一个元素\n- 如果需要居中的元素为**常规流中inline元素**，为父元素设置`text-align: center;`即可实现\n- 如果需要居中的元素为**常规流中block元素**，1）为元素设置宽度，2）设置左右margin为auto。3）IE6下需在父元素上设置`text-align: center;`,再给子元素恢复需要的值\n\n```\n<body>\n    <div class=\"content\">\n    aaaaaa aaaaaa a a a a a a a a\n    </div>\n</body>\n\n<style>\n    body {\n        background: #DDD;\n        text-align: center; /* 3 */\n    }\n    .content {\n        width: 500px;      /* 1 */\n        text-align: left;  /* 3 */\n        margin: 0 auto;    /* 2 */\n\n        background: purple;\n    }\n</style>\n```\n\n- 如果需要居中的元素为**浮动元素**，1）为元素设置宽度，2）`position: relative;`，3）浮动方向偏移量（left或者right）设置为50%，4）浮动方向上的margin设置为元素宽度一半乘以-1\n\n```\n<body>\n    <div class=\"content\">\n    aaaaaa aaaaaa a a a a a a a a\n    </div>\n</body>\n\n<style>\n    body {\n        background: #DDD;\n    }\n    .content {\n        width: 500px;         /* 1 */\n        float: left;\n\n        position: relative;   /* 2 */\n        left: 50%;            /* 3 */\n        margin-left: -250px;  /* 4 */\n\n        background-color: purple;\n    }\n</style>\n```\n\n- 如果需要居中的元素为**绝对定位元素**，1）为元素设置宽度，2）偏移量设置为50%，3）偏移方向外边距设置为元素宽度一半乘以-1\n\n```\n<body>\n    <div class=\"content\">\n    aaaaaa aaaaaa a a a a a a a a\n    </div>\n</body>\n\n<style>\n    body {\n        background: #DDD;\n        position: relative;\n    }\n    .content {\n        width: 800px;\n\n        position: absolute;\n        left: 50%;\n        margin-left: -400px;\n\n        background-color: purple;\n    }\n</style>\n```\n\n- 如果需要居中的元素为**绝对定位元素**，1）为元素设置宽度，2）设置左右偏移量都为0,3）设置左右外边距都为auto\n\n```\n<body>\n    <div class=\"content\">\n    aaaaaa aaaaaa a a a a a a a a\n    </div>\n</body>\n\n<style>\n    body {\n        background: #DDD;\n        position: relative;\n    }\n    .content {\n        width: 800px;\n\n        position: absolute;\n        margin: 0 auto;\n        left: 0;\n        right: 0;\n\n        background-color: purple;\n    }\n</style>\n```\n\n### 如何竖直居中一个元素\n参考资料：[6 Methods For Vertical Centering With CSS](http://www.vanseodesign.com/css/vertical-centering/)。 [盘点8种CSS实现垂直居中](http://blog.csdn.net/freshlover/article/details/11579669)\n\n- 需要居中元素为**单行文本**，为包含文本的元素设置大于`font-size`的`line-height`：\n\n```\n<p class=\"text\">center text</p>\n\n<style>\n.text {\n    line-height: 200px;\n}\n</style>\n```\n\n\n## $javascript概念部分\n\n### DOM元素e的e.getAttribute(propName)和e.propName有什么区别和联系\n\n- e.getAttribute()，是标准DOM操作文档元素属性的方法，具有通用性可在任意文档上使用，返回元素在源文件中**设置的属性**\n- e.propName通常是在HTML文档中访问特定元素的**特性**，浏览器解析元素后生成对应对象（如a标签生成HTMLAnchorElement），这些对象的特性会根据特定规则结合属性设置得到，对于没有对应特性的属性，只能使用getAttribute进行访问\n- e.getAttribute()返回值是源文件中设置的值，类型是字符串或者null（有的实现返回\"\"）\n- e.propName返回值可能是字符串、布尔值、对象、undefined等\n- 大部分attribute与property是一一对应关系，修改其中一个会影响另一个，如id，title等属性\n- 一些布尔属性`<input hidden/>`的检测设置需要hasAttribute和removeAttribute来完成，或者设置对应property\n- 像`<a href=\"../index.html\">link</a>`中href属性，转换成property的时候需要通过转换得到完整URL\n- 一些attribute和property不是一一对应如：form控件中`<input value=\"hello\"/>`对应的是defaultValue，修改或设置value property修改的是控件当前值，setAttribute修改value属性不会改变value property\n\n### offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别\n\n- offsetWidth/offsetHeight返回值包含**content + padding + border**，效果与e.getBoundingClientRect()相同\n- clientWidth/clientHeight返回值只包含**content + padding**，如果有滚动条，也**不包含滚动条**\n- scrollWidth/scrollHeight返回值包含**content + padding + 溢出内容的尺寸**\n\n[Measuring Element Dimension and Location with CSSOM in Windows Internet Explorer 9](http://msdn.microsoft.com/en-us/library/ie/hh781509(v=vs.85).aspx)\n\n![元素尺寸](img/element-size.png)\n\n### XMLHttpRequest通用属性和方法\n\n1. `readyState`:表示请求状态的整数，取值：\n  - UNSENT（0）：对象已创建\n  - OPENED（1）：open()成功调用，在这个状态下，可以为xhr设置请求头，或者使用send()发送请求\n  - HEADERS_RECEIVED(2)：所有重定向已经自动完成访问，并且最终响应的HTTP头已经收到\n  - LOADING(3)：响应体正在接收\n  - DONE(4)：数据传输完成或者传输产生错误\n3. `onreadystatechange`：readyState改变时调用的函数\n4. `status`：服务器返回的HTTP状态码（如，200， 404）\n5. `statusText`:服务器返回的HTTP状态信息（如，OK，No Content）\n6. `responseText`:作为字符串形式的来自服务器的完整响应\n6. `responseXML`: Document对象，表示服务器的响应解析成的XML文档\n7. `abort()`:取消异步HTTP请求\n8. `getAllResponseHeaders()`: 返回一个字符串，包含响应中服务器发送的全部HTTP报头。每个报头都是一个用冒号分隔开的名/值对，并且使用一个回车/换行来分隔报头行\n9. `getResponseHeader(headerName)`:返回headName对应的报头值\n10. `open(method, url, asynchronous [, user, password])`:初始化准备发送到服务器上的请求。method是HTTP方法，不区分大小写；url是请求发送的相对或绝对URL；asynchronous表示请求是否异步；user和password提供身份验证\n11. `setRequestHeader(name, value)`:设置HTTP报头\n12. `send(body)`:对服务器请求进行初始化。参数body包含请求的主体部分，对于POST请求为键值对字符串；对于GET请求，为null\n\n### focus/blur与focusin/focusout的区别与联系\n\n1. focus/blur不冒泡，focusin/focusout冒泡\n2. focus/blur兼容性好，focusin/focusout在除FireFox外的浏览器下都保持良好兼容性，如需使用事件托管，可考虑在FireFox下使用事件捕获elem.addEventListener('focus', handler, true)\n3. 可获得焦点的元素：\n    1. window\n    2. 链接被点击或键盘操作\n    3. 表单空间被点击或键盘操作\n    4. 设置`tabindex`属性的元素被点击或键盘操作\n\n### mouseover/mouseout与mouseenter/mouseleave的区别与联系\n\n1. mouseover/mouseout是标准事件，**所有浏览器都支持**；mouseenter/mouseleave是IE5.5引入的特有事件后来被DOM3标准采纳，现代标准浏览器也支持\n2. mouseover/mouseout是**冒泡**事件；mouseenter/mouseleave**不冒泡**。需要为**多个元素监听鼠标移入/出事件时，推荐mouseover/mouseout托管，提高性能**\n3. 标准事件模型中event.target表示发生移入/出的元素,**vent.relatedTarget**对应移出/如元素；在老IE中event.srcElement表示发生移入/出的元素，**event.toElement**表示移出的目标元素，**event.fromElement**表示移入时的来源元素\n\n例子：鼠标从div#target元素移出时进行处理，判断逻辑如下：\n\n    <div id=\"target\"><span>test</span></div>\n\n    <script type=\"text/javascript\">\n    var target = document.getElementById('target');\n    if (target.addEventListener) {\n      target.addEventListener('mouseout', mouseoutHandler, false);\n    } else if (target.attachEvent) {\n      target.attachEvent('onmouseout', mouseoutHandler);\n    }\n\n    function mouseoutHandler(e) {\n      e = e || window.event;\n      var target = e.target || e.srcElement;\n\n      // 判断移出鼠标的元素是否为目标元素\n      if (target.id !== 'target') {\n        return;\n      }\n\n      // 判断鼠标是移出元素还是移到子元素\n      var relatedTarget = event.relatedTarget || e.toElement;\n      while (relatedTarget !== target\n        && relatedTarget.nodeName.toUpperCase() !== 'BODY') {\n        relatedTarget = relatedTarget.parentNode;\n      }\n\n      // 如果相等，说明鼠标在元素内部移动\n      if (relatedTarget === target) {\n        return;\n      }\n\n      // 执行需要操作\n      //alert('鼠标移出');\n\n    }\n    </script>\n\n### sessionStorage,localStorage,cookie区别\n\n1. 都会在浏览器端保存，有大小限制，同源限制\n2. cookie会在请求时发送到服务器，作为会话标识，服务器可修改cookie；web storage不会发送到服务器\n3. cookie有path概念，子路径可以访问父路径cookie，父路径不能访问子路径cookie\n4. 有效期：cookie在设置的有效期内有效，默认为浏览器关闭；sessionStorage在窗口关闭前有效，localStorage长期有效，直到用户删除\n5. 共享：sessionStorage不能共享，localStorage在同源文档之间共享，cookie在同源且符合path规则的文档之间共享\n6. localStorage的修改会促发其他文档窗口的update事件\n7. cookie有secure属性要求HTTPS传输\n8. 浏览器不能保存超过300个cookie，单个服务器不能超过20个，每个cookie不能超过4k。web storage大小支持能达到5M\n\n### javascript跨域通信\n同源：两个文档同源需满足\n\n1. 协议相同\n2. 域名相同\n3. 端口相同\n\n跨域通信：js进行DOM操作、通信时如果目标与当前窗口不满足同源条件，浏览器为了安全会阻止跨域操作。跨域通信通常有以下方法\n\n- 如果是log之类的简单**单项通信**，新建``<img>``,``<script>``,``<link>``,``<iframe>``元素，通过src，href属性设置为目标url。实现跨域请求\n- 如果请求**json数据**，使用``<script>``进行jsonp请求\n- 现代浏览器中**多窗口通信**使用HTML5规范的targetWindow.postMessage(data, origin);其中data是需要发送的对象，origin是目标窗口的origin。window.addEventListener('message', handler, false);handler的event.data是postMessage发送来的数据，event.origin是发送窗口的origin，event.source是发送消息的窗口引用\n- 内部服务器代理请求跨域url，然后返回数据\n- 跨域请求数据，现代浏览器可使用HTML5规范的CORS功能，只要目标服务器返回HTTP头部**``Access-Control-Allow-Origin: *``**即可像普通ajax一样访问跨域资源\n\n### javascript有哪几种数据类型\n六种基本数据类型\n\n- undefined\n- null\n- string\n- boolean\n- number\n- [symbol](https://developer.mozilla.org/en-US/docs/Glossary/Symbol)(ES6)\n\n一种引用类型\n\n- Object\n\n### 什么闭包,闭包有什么用\n**闭包是在某个作用域内定义的函数，它可以访问这个作用域内的所有变量**。闭包作用域链通常包括三个部分：\n\n1. 函数本身作用域。\n2. 闭包定义时的作用域。\n3. 全局作用域。\n\n闭包常见用途：\n\n1. 创建特权方法用于访问控制\n2. 事件处理程序及回调\n\n### javascript有哪几种方法定义函数\n\n1. [函数声明表达式](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)\n2. [function操作符](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function)\n3. [Function 构造函数](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function)\n4. [ES6:arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/arrow_functions)\n\n重要参考资料：[MDN:Functions_and_function_scope](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope)\n\n### 应用程序存储和离线web应用\nHTML5新增应用程序缓存，允许web应用将应用程序自身保存到用户浏览器中，用户离线状态也能访问。\n1.为html元素设置manifest属性:``<html manifest=\"myapp.appcache\">``，其中后缀名只是一个约定，真正识别方式是通过``text/cache-manifest``作为MIME类型。所以需要配置服务器保证设置正确\n2.manifest文件首行为``CACHE MANIFEST``，其余就是要缓存的URL列表，每个一行，相对路径都相对于manifest文件的url。注释以#开头\n3.url分为三种类型：``CACHE``:为默认类型。``NETWORK``：表示资源从不缓存。 ``FALLBACK``:每行包含两个url，第二个URL是指需要加载和存储在缓存中的资源， 第一个URL是一个前缀。任何匹配该前缀的URL都不会缓存，如果从网络中载入这样的URL失败的话，就会用第二个URL指定的缓存资源来替代。以下是一个文件例子：\n\n```\nCACHE MANIFEST\n\nCACHE:\nmyapp.html\nmyapp.css\nmyapp.js\n\nFALLBACK:\nvideos/ offline_help.html\n\nNETWORK:\ncgi/\n```\n\n### 客户端存储localStorage和sessionStorage\n\n- localStorage有效期为永久，sessionStorage有效期为顶层窗口关闭前\n- 同源文档可以读取并修改localStorage数据，sessionStorage只允许同一个窗口下的文档访问，如通过iframe引入的同源文档。\n- Storage对象通常被当做普通javascript对象使用：**通过设置属性来存取字符串值**，也可以通过**setItem(key, value)设置**，**getItem(key)读取**，**removeItem(key)删除**，**clear()删除所有数据**，**length表示已存储的数据项数目**，**key(index)返回对应索引的key**\n\n```\nlocalStorage.setItem('x', 1); // storge x->1\nlocalStorage.getItem('x); // return value of x\n\n// 枚举所有存储的键值对\nfor (var i = 0, len = localStorage.length; i < len; ++i ) {\n    var name = localStorage.key(i);\n    var value = localStorage.getItem(name);\n}\n\nlocalStorage.removeItem('x'); // remove x\nlocalStorage.clear();  // remove all data\n```\n\n### cookie及其操作\n\n- cookie是web浏览器存储的少量数据，最早设计为服务器端使用，作为HTTP协议的扩展实现。cookie数据会自动在浏览器和服务器之间传输。\n- 通过读写cookie检测是否支持\n- cookie属性有**名**，**值**，**max-age**，**path**, **domain**，**secure**；\n- cookie默认有效期为浏览器会话，一旦用户关闭浏览器，数据就丢失，通过设置**max-age=seconds**属性告诉浏览器cookie有效期\n- cookie作用域通过**文档源**和**文档路径**来确定，通过**path**和**domain**进行配置，web页面同目录或子目录文档都可访问\n- 通过cookie保存数据的方法为：为document.cookie设置一个符合目标的字符串如下\n- 读取document.cookie获得'; '分隔的字符串，key=value,解析得到结果\n\n```\ndocument.cookie = 'name=qiu; max-age=9999; path=/; domain=domain; secure';\n\ndocument.cookie = 'name=aaa; path=/; domain=domain; secure';\n// 要改变cookie的值，需要使用相同的名字、路径和域，新的值\n// 来设置cookie，同样的方法可以用来改变有效期\n\n// 设置max-age为0可以删除指定cookie\n\n//读取cookie，访问document.cookie返回键值对组成的字符串，\n//不同键值对之间用'; '分隔。通过解析获得需要的值\n```\n\n[cookieUtil.js](https://github.com/qiu-deqing/google/blob/master/module/js/cookieUtil.js)：自己写的cookie操作工具\n\n### javascript有哪些方法定义对象\n\n1. 对象字面量： `var obj = {};`\n2. 构造函数： `var obj = new Object();`\n3. Object.create(): `var obj = Object.create(Object.prototype);`\n\n### ===运算符判断相等的流程是怎样的\n\n1. 如果两个值不是相同类型，它们不相等\n2. 如果两个值都是null或者都是undefined，它们相等\n3. 如果两个值都是布尔类型true或者都是false，它们相等\n4. 如果其中有一个是**NaN**，它们不相等\n5. 如果都是数值型并且数值相等，他们相等， -0等于0\n6. 如果他们都是字符串并且在相同位置包含相同的16位值，他它们相等；如果在长度或者内容上不等，它们不相等；两个字符串显示结果相同但是编码不同==和===都认为他们不相等\n7. 如果他们指向相同对象、数组、函数，它们相等；如果指向不同对象，他们不相等\n\n### ==运算符判断相等的流程是怎样的\n\n1. 如果两个值类型相同，按照===比较方法进行比较\n2. 如果类型不同，使用如下规则进行比较\n  1. 如果其中一个值是null，另一个是undefined，它们相等\n  2. 如果一个值是**数字**另一个是**字符串**，将**字符串转换为数字**进行比较\n  3. 如果有布尔类型，将**true转换为1，false转换为0**，然后用==规则继续比较\n  4. 如果一个值是对象，另一个是数字或字符串，将对象转换为原始值然后用==规则继续比较\n  5. **其他所有情况都认为不相等**\n\n### 对象到字符串的转换步骤\n\n1. 如果对象有toString()方法，javascript调用它。如果返回一个原始值（primitive value如：string number boolean）,将这个值转换为字符串作为结果\n2. 如果对象没有toString()方法或者返回值不是原始值，javascript寻找对象的valueOf()方法，如果存在就调用它，返回结果是原始值则转为字符串作为结果\n3. 否则，javascript不能从toString()或者valueOf()获得一个原始值，此时throws a TypeError\n\n\n### 对象到数字的转换步骤\n\n    1. 如果对象有valueOf()方法并且返回元素值，javascript将返回值转换为数字作为结果\n    2. 否则，如果对象有toString()并且返回原始值，javascript将返回结果转换为数字作为结果\n    3. 否则，throws a TypeError\n\n### <,>,<=,>=的比较规则\n\n所有比较运算符都支持任意类型，但是**比较只支持数字和字符串**，所以需要执行必要的转换然后进行比较，转换规则如下:\n1. 如果操作数是对象，转换为原始值：如果valueOf方法返回原始值，则使用这个值，否则使用toString方法的结果，如果转换失败则报错\n2. 经过必要的对象到原始值的转换后，如果两个操作数都是字符串，按照字母顺序进行比较（他们的16位unicode值的大小）\n3. 否则，如果有一个操作数不是字符串，**将两个操作数转换为数字**进行比较\n\n### +运算符工作流程\n1. 如果有操作数是对象，转换为原始值\n2. 此时如果有**一个操作数是字符串**，其他的操作数都转换为字符串并执行连接\n3. 否则：**所有操作数都转换为数字并执行加法**\n\n### 函数内部arguments变量有哪些特性,有哪些属性,如何将它转换为数组\n\n- arguments所有函数中都包含的一个局部变量，是一个类数组对象，对应函数调用时的实参。如果函数定义同名参数会在调用时覆盖默认对象\n- arguments[index]分别对应函数调用时的实参，并且通过arguments修改实参时会同时修改实参\n- arguments.length为实参的个数（Function.length表示形参长度）\n- arguments.callee为当前正在执行的函数本身，使用这个属性进行递归调用时需注意this的变化\n- arguments.caller为调用当前函数的函数（已被遗弃）\n- 转换为数组：<code>var args = Array.prototype.slice.call(arguments, 0);</code>\n\n### DOM事件模型是如何的,编写一个EventUtil工具类实现事件管理兼容\n\n- DOM事件包含捕获（capture）和冒泡（bubble）两个阶段：捕获阶段事件从window开始触发事件然后通过祖先节点一次传递到触发事件的DOM元素上；冒泡阶段事件从初始元素依次向祖先节点传递直到window\n- 标准事件监听elem.addEventListener(type, handler, capture)/elem.removeEventListener(type, handler, capture)：handler接收保存事件信息的event对象作为参数，event.target为触发事件的对象，handler调用上下文this为绑定监听器的对象，event.preventDefault()取消事件默认行为，event.stopPropagation()/event.stopImmediatePropagation()取消事件传递\n- 老版本IE事件监听elem.attachEvent('on'+type, handler)/elem.detachEvent('on'+type, handler)：handler不接收event作为参数，事件信息保存在window.event中，触发事件的对象为event.srcElement，handler执行上下文this为window使用闭包中调用handler.call(elem, event)可模仿标准模型，然后返回闭包，保证了监听器的移除。event.returnValue为false时取消事件默认行为，event.cancleBubble为true时取消时间传播\n- 通常利用事件冒泡机制托管事件处理程序提高程序性能。\n\n```\n/**\n * 跨浏览器事件处理工具。只支持冒泡。不支持捕获\n * @author  (qiu_deqing@126.com)\n */\n\nvar EventUtil = {\n    getEvent: function (event) {\n        return event || window.event;\n    },\n    getTarget: function (event) {\n        return event.target || event.srcElement;\n    },\n    // 返回注册成功的监听器，IE中需要使用返回值来移除监听器\n    on: function (elem, type, handler) {\n        if (elem.addEventListener) {\n            elem.addEventListener(type, handler, false);\n            return handler;\n        } else if (elem.attachEvent) {\n            var wrapper = function () {\n              var event = window.event;\n              event.target = event.srcElement;\n              handler.call(elem, event);\n            };\n            elem.attachEvent('on' + type, wrapper);\n            return wrapper;\n        }\n    },\n    off: function (elem, type, handler) {\n        if (elem.removeEventListener) {\n            elem.removeEventListener(type, handler, false);\n        } else if (elem.detachEvent) {\n            elem.detachEvent('on' + type, handler);\n        }\n    },\n    preventDefault: function (event) {\n        if (event.preventDefault) {\n            event.preventDefault();\n        } else if ('returnValue' in event) {\n            event.returnValue = false;\n        }\n    },\n    stopPropagation: function (event) {\n        if (event.stopPropagation) {\n            event.stopPropagation();\n        } else if ('cancelBubble' in event) {\n            event.cancelBubble = true;\n        }\n    },\n    /**\n     * keypress事件跨浏览器获取输入字符\n     * 某些浏览器在一些特殊键上也触发keypress，此时返回null\n     **/\n     getChar: function (event) {\n        if (event.which == null) {\n            return String.fromCharCode(event.keyCode);  // IE\n        }\n        else if (event.which != 0 && event.charCode != 0) {\n            return String.fromCharCode(event.which);    // the rest\n        }\n        else {\n            return null;    // special key\n        }\n     }\n};\n```\n\n### 评价一下三种方法实现继承的优缺点,并改进\n\n```\nfunction Shape() {}\n\nfunction Rect() {}\n\n// 方法1\nRect.prototype = new Shape();\n\n// 方法2\nRect.prototype = Shape.prototype;\n\n// 方法3\nRect.prototype = Object.create(Shape.prototype);\n\nRect.prototype.area = function () {\n  // do something\n};\n```\n\n方法1：\n\n1. 优点：正确设置原型链实现继承\n2. 优点：父类实例属性得到继承，原型链查找效率提高，也能为一些属性提供合理的默认值\n3. 缺点：父类实例属性为引用类型时，不恰当地修改会导致所有子类被修改\n4. 缺点：创建父类实例作为子类原型时，可能无法确定构造函数需要的合理参数，这样提供的参数继承给子类没有实际意义，当子类需要这些参数时应该在构造函数中进行初始化和设置\n5. 总结：继承应该是继承方法而不是属性，为子类设置父类实例属性应该是通过在子类构造函数中调用父类构造函数进行初始化\n\n方法2：\n\n1. 优点：正确设置原型链实现继承\n2. 缺点：父类构造函数原型与子类相同。修改子类原型添加方法会修改父类\n\n方法3：\n\n1. 优点：正确设置原型链且避免方法1.2中的缺点\n2. 缺点：ES5方法需要注意兼容性\n\n改进：\n\n1. 所有三种方法应该在子类构造函数中调用父类构造函数实现实例属性初始化\n\n```\nfunction Rect() {\n    Shape.call(this);\n}\n```\n\n\n2. 用新创建的对象替代子类默认原型，设置``Rect.prototype.constructor = Rect;``保证一致性\n3. 第三种方法的polyfill：\n\n```\nfunction create(obj) {\n    if (Object.create) {\n        return Object.create(obj);\n    }\n\n    function f() {};\n    f.prototype = obj;\n    return new f();\n}\n```\n\n## $javascript编程部分\n\n### 请用原生js实现一个函数,给页面制定的任意一个元素添加一个透明遮罩(透明度可变,默认0.2),使这个区域点击无效,要求兼容IE8+及各主流浏览器,遮罩层效果如下图所示:\n![遮罩效果](img/element-mask.jpg)\n\n```\n<style>\n#target {\n    width: 200px;\n    height: 300px;\n    margin: 40px;\n    background-color: tomato;\n}\n</style>\n\n<div id=\"target\"></div>\n\n<script>\nfunction addMask(elem, opacity) {\n    opacity = opacity || 0.2;\n\n    var rect = elem.getBoundingClientRect();\n    var style = getComputedStyle(elem, null);\n\n    var mask = document.createElement('div');\n    mask.style.position = 'absolute';\n    var marginLeft = parseFloat(style.marginLeft);\n    mask.style.left = (elem.offsetLeft - marginLeft) + 'px';\n    var marginTop = parseFloat(style.marginTop);\n    mask.style.top = (elem.offsetTop - marginTop) + 'px';\n    mask.style.zIndex = 9999;\n    mask.style.opacity = '' + opacity;\n    mask.style.backgroundColor = '#000';\n\n    mask.style.width = (parseFloat(style.marginLeft) +\n        parseFloat(style.marginRight) + rect.width) + 'px';\n    mask.style.height = (parseFloat(style.marginTop) +\n        parseFloat(style.marginBottom) + rect.height) + 'px';\n\n    elem.parentNode.appendChild(mask);\n}\n\nvar target = document.getElementById('target');\naddMask(target);\n\ntarget.addEventListener('click', function () {\n    console.log('click');\n}, false);\n</script>\n```\n\n### 请用代码写出(今天是星期x)其中x表示当天是星期几,如果当天是星期一,输出应该是\"今天是星期一\"\n\n```\nvar days = ['日','一','二','三','四','五','六'];\nvar date = new Date();\n\nconsole.log('今天是星期' + days[date.getDay()]);\n```\n\n### 下面这段代码想要循环延时输出结果0 1 2 3 4,请问输出结果是否正确,如果不正确,请说明为什么,并修改循环内的代码使其输出正确结果\n\n```\nfor (var i = 0; i < 5; ++i) {\n  setTimeout(function () {\n    console.log(i + ' ');\n  }, 100);\n}\n```\n\n不能输出正确结果，因为循环中setTimeout接受的参数函数通过闭包访问变量i。javascript运行环境为单线程，setTimeout注册的函数需要等待线程空闲才能执行，此时for循环已经结束，i值为5.五个定时输出都是5\n修改方法：将setTimeout放在函数立即调用表达式中，将i值作为参数传递给包裹函数，创建新闭包\n\n```\nfor (var i = 0; i < 5; ++i) {\n  (function (i) {\n    setTimeout(function () {\n      console.log(i + ' ');\n    }, 100);\n  }(i));\n}\n```\n\n\n\n### 现有一个Page类,其原型对象上有许多以post开头的方法(如postMsg);另有一拦截函数chekc,只返回ture或false.请设计一个函数,该函数应批量改造原Page的postXXX方法,在保留其原有功能的同时,为每个postXXX方法增加拦截验证功能,当chekc返回true时继续执行原postXXX方法,返回false时不再执行原postXXX方法\n\n```\nfunction Page() {}\n\nPage.prototype = {\n  constructor: Page,\n\n  postA: function (a) {\n    console.log('a:' + a);\n  },\n  postB: function (b) {\n    console.log('b:' + b);\n  },\n  postC: function (c) {\n    console.log('c:' + c);\n  },\n  check: function () {\n    return Math.random() > 0.5;\n  }\n}\n\nfunction checkfy(obj) {\n  for (var key in obj) {\n    if (key.indexOf('post') === 0 && typeof obj[key] === 'function') {\n      (function (key) {\n        var fn = obj[key];\n        obj[key] = function () {\n          if (obj.check()) {\n            fn.apply(obj, arguments);\n          }\n        };\n      }(key));\n    }\n  }\n} // end checkfy()\n\ncheckfy(Page.prototype);\n\nvar obj = new Page();\n\nobj.postA('checkfy');\nobj.postB('checkfy');\nobj.postC('checkfy');\n```\n\n### 完成下面的tool-tip\n![xxx](img/tip-box.jpg)\n\n### 编写javascript深度克隆函数deepClone\n\n    function deepClone(obj) {\n        var _toString = Object.prototype.toString;\n\n        // null, undefined, non-object, function\n        if (!obj || typeof obj !== 'object') {\n            return obj;\n        }\n\n        // DOM Node\n        if (obj.nodeType && 'cloneNode' in obj) {\n            return obj.cloneNode(true);\n        }\n\n        // Date\n        if (_toString.call(obj) === '[object Date]') {\n            return new Date(obj.getTime());\n        }\n\n        // RegExp\n        if (_toString.call(obj) === '[object RegExp]') {\n            var flags = [];\n            if (obj.global) { flags.push('g'); }\n            if (obj.multiline) { flags.push('m'); }\n            if (obj.ignoreCase) { flags.push('i'); }\n\n            return new RegExp(obj.source, flags.join(''));\n        }\n\n        var result = Array.isArray(obj) ? [] :\n            obj.constructor ? new obj.constructor() : {};\n\n        for (var key in obj ) {\n            result[key] = deepClone(obj[key]);\n        }\n\n        return result;\n    }\n\n    function A() {\n        this.a = a;\n    }\n\n    var a = {\n        name: 'qiu',\n        birth: new Date(),\n        pattern: /qiu/gim,\n        container: document.body,\n        hobbys: ['book', new Date(), /aaa/gim, 111]\n    };\n\n    var c = new A();\n    var b = deepClone(c);\n    console.log(c.a === b.a);\n    console.log(c, b);\n\n### 补充代码,鼠标单击Button1后将Button1移动到Button2的后面\n    <!doctype html>\n    <html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>TEst</title>\n    </head>\n    <body>\n\n    <div>\n       <input type=\"button\" id =\"button1\" value=\"1\" />\n       <input type=\"button\" id =\"button2\" value=\"2\" />\n    </div>\n\n    <script type=\"text/javascript\">\n        var btn1 = document.getElementById('button1');\n        var btn2 = document.getElementById('button2');\n\n        addListener(btn1, 'click', function (event) {\n            btn1.parentNode.insertBefore(btn2, btn1);\n        });\n\n        function addListener(elem, type, handler) {\n            if (elem.addEventListener) {\n                elem.addEventListener(type, handler, false);\n                return handler;\n            } else if (elem.attachEvent) {\n                function wrapper() {\n                    var event = window.event;\n                    event.target = event.srcElement;\n                    handler.call(elem, event);\n                }\n                elem.attachEvent('on' + type, wrapper);\n                return wrapper;\n            }\n        }\n\n    </script>\n    </body>\n    </html>\n\n### 网页中实现一个计算当年还剩多少时间的倒数计时程序,要求网页上实时动态显示\"××年还剩××天××时××分××秒\"\n\n    <!doctype html>\n    <html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>TEst</title>\n    </head>\n    <body>\n\n        <span id=\"target\"></span>\n\n\n    <script type=\"text/javascript\">\n        // 为了简化。每月默认30天\n        function getTimeString() {\n            var start = new Date();\n            var end = new Date(start.getFullYear() + 1, 0, 1);\n            var elapse = Math.floor((end - start) / 1000);\n\n            var seconds = elapse % 60 ;\n            var minutes = Math.floor(elapse / 60) % 60;\n            var hours = Math.floor(elapse / (60 * 60)) % 24;\n            var days = Math.floor(elapse / (60 * 60 * 24)) % 30;\n            var months = Math.floor(elapse / (60 * 60 * 24 * 30)) % 12;\n            var years = Math.floor(elapse / (60 * 60 * 24 * 30 * 12));\n\n            return start.getFullYear() + '年还剩' + years + '年' + months + '月' + days + '日'\n                + hours + '小时' + minutes + '分' + seconds + '秒';\n        }\n\n        function domText(elem, text) {\n            if (text == undefined) {\n\n                if (elem.textContent) {\n                    return elem.textContent;\n                } else if (elem.innerText) {\n                    return elem.innerText;\n                }\n            } else {\n                if (elem.textContent) {\n                    elem.textContent = text;\n                } else if (elem.innerText) {\n                    elem.innerText = text;\n                } else {\n                    elem.innerHTML = text;\n                }\n            }\n        }\n\n        var target = document.getElementById('target');\n\n        setInterval(function () {\n            domText(target, getTimeString());\n        }, 1000)\n    </script>\n\n    </body>\n    </html>\n\n### 完成一个函数,接受数组作为参数,数组元素为整数或者数组,数组元素包含整数或数组,函数返回扁平化后的数组\n如：[1, [2, [ [3, 4], 5], 6]] => [1, 2, 3, 4, 5, 6]\n\n```\n    var data =  [1, [2, [ [3, 4], 5], 6]];\n\n    function flat(data, result) {\n        var i, d, len;\n        for (i = 0, len = data.length; i < len; ++i) {\n            d = data[i];\n            if (typeof d === 'number') {\n                result.push(d);\n            } else {\n                flat(d, result);\n            }\n        }\n    }\n\n    var result = [];\n    flat(data, result);\n\n    console.log(result);\n```\n\n### 如何判断一个对象是否为数组\n如果浏览器支持Array.isArray()可以直接判断否则需进行必要判断\n\n```\n/**\n * 判断一个对象是否是数组，参数不是对象或者不是数组，返回false\n *\n * @param {Object} arg 需要测试是否为数组的对象\n * @return {Boolean} 传入参数是数组返回true，否则返回false\n */\nfunction isArray(arg) {\n    if (typeof arg === 'object') {\n        return Object.prototype.toString.call(arg) === '[object Array]';\n    }\n    return false;\n}\n```\n\n### 请评价以下事件监听器代码并给出改进意见\n\n```\nif (window.addEventListener) {\n  var addListener = function (el, type, listener, useCapture) {\n    el.addEventListener(type, listener, useCapture);\n  };\n}\nelse if (document.all) {\n  addListener = function (el, type, listener) {\n    el.attachEvent('on' + type, function () {\n      listener.apply(el);\n    });\n  };\n}\n```\n\n作用：浏览器功能检测实现跨浏览器DOM事件绑定\n\n优点：\n\n1. 测试代码只运行一次，根据浏览器确定绑定方法\n2. 通过``listener.apply(el)``解决IE下监听器this与标准不一致的地方\n3. 在浏览器不支持的情况下提供简单的功能，在标准浏览器中提供捕获功能\n\n缺点：\n\n1. document.all作为IE检测不可靠，应该使用if(el.attachEvent)\n2. addListener在不同浏览器下API不一样\n3. ``listener.apply``使this与标准一致但监听器无法移除\n4. 未解决IE下listener参数event。 target问题\n\n改进:\n\n```\nvar addListener;\n\nif (window.addEventListener) {\n  addListener = function (el, type, listener, useCapture) {\n    el.addEventListener(type, listener, useCapture);\n    return listener;\n  };\n}\nelse if (window.attachEvent) {\n  addListener = function (el, type, listener) {\n    // 标准化this，event，target\n    var wrapper = function () {\n      var event = window.event;\n      event.target = event.srcElement;\n      listener.call(el, event);\n    };\n\n    el.attachEvent('on' + type, wrapper);\n    return wrapper;\n    // 返回wrapper。调用者可以保存，以后remove\n  };\n}\n```\n\n### 如何判断一个对象是否为函数\n\n```\n/**\n * 判断对象是否为函数，如果当前运行环境对可调用对象（如正则表达式）\n * 的typeof返回'function'，采用通用方法，否则采用优化方法\n *\n * @param {Any} arg 需要检测是否为函数的对象\n * @return {boolean} 如果参数是函数，返回true，否则false\n */\nfunction isFunction(arg) {\n    if (arg) {\n        if (typeof (/./) !== 'function') {\n            return typeof arg === 'function';\n        } else {\n            return Object.prototype.toString.call(arg) === '[object Function]';\n        }\n    } // end if\n    return false;\n}\n```\n\n### 编写一个函数接受url中query string为参数,返回解析后的Object,query string使用application/x-www-form-urlencoded编码\n\n```\n/**\n * 解析query string转换为对象，一个key有多个值时生成数组\n *\n * @param {String} query 需要解析的query字符串，开头可以是?，\n * 按照application/x-www-form-urlencoded编码\n * @return {Object} 参数解析后的对象\n */\nfunction parseQuery(query) {\n    var result = {};\n\n    // 如果不是字符串返回空对象\n    if (typeof query !== 'string') {\n        return result;\n    }\n\n    // 去掉字符串开头可能带的?\n    if (query.charAt(0) === '?') {\n        query = query.substring(1);\n    }\n\n    var pairs = query.split('&');\n    var pair;\n    var key, value;\n    var i, len;\n\n    for (i = 0, len = pairs.length; i < len; ++i) {\n        pair = pairs[i].split('=');\n        // application/x-www-form-urlencoded编码会将' '转换为+\n        key = decodeURIComponent(pair[0]).replace(/\\+/g, ' ');\n        value = decodeURIComponent(pair[1]).replace(/\\+/g, ' ');\n\n        // 如果是新key，直接添加\n        if (!(key in result)) {\n            result[key] = value;\n        }\n        // 如果key已经出现一次以上，直接向数组添加value\n        else if (isArray(result[key])) {\n            result[key].push(value);\n        }\n        // key第二次出现，将结果改为数组\n        else {\n            var arr = [result[key]];\n            arr.push(value);\n            result[key] = arr;\n        } // end if-else\n    } // end for\n\n    return result;\n}\n\nfunction isArray(arg) {\n    if (arg && typeof arg === 'object') {\n        return Object.prototype.toString.call(arg) === '[object Array]';\n    }\n    return false;\n}\n/**\nconsole.log(parseQuery('sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8'));\n */\n```\n\n### 解析一个完整的url,返回Object包含域与window.location相同\n\n```\n/**\n * 解析一个url并生成window.location对象中包含的域\n * location:\n * {\n *      href: '包含完整的url',\n *      origin: '包含协议到pathname之前的内容',\n *      protocol: 'url使用的协议，包含末尾的:',\n *      username: '用户名', // 暂时不支持\n *      password: '密码',  // 暂时不支持\n *      host: '完整主机名，包含:和端口',\n *      hostname: '主机名，不包含端口'\n *      port: '端口号',\n *      pathname: '服务器上访问资源的路径/开头',\n *      search: 'query string，?开头',\n *      hash: '#开头的fragment identifier'\n * }\n *\n * @param {string} url 需要解析的url\n * @return {Object} 包含url信息的对象\n */\nfunction parseUrl(url) {\n    var result = {};\n    var keys = ['href', 'origin', 'protocol', 'host',\n                'hostname', 'port', 'pathname', 'search', 'hash'];\n    var i, len;\n    var regexp = /(([^:]+:)\\/\\/(([^:\\/\\?#]+)(:\\d+)?))(\\/[^?#]*)?(\\?[^#]*)?(#.*)?/;\n\n    var match = regexp.exec(url);\n\n    if (match) {\n        for (i = keys.length - 1; i >= 0; --i) {\n            result[keys[i]] = match[i] ? match[i] : '';\n        }\n    }\n\n    return result;\n}\n```\n\n### 完成函数getViewportSize返回指定窗口的视口尺寸\n\n```\n/**\n* 查询指定窗口的视口尺寸，如果不指定窗口，查询当前窗口尺寸\n**/\nfunction getViewportSize(w) {\n    w = w || window;\n\n    // IE9及标准浏览器中可使用此标准方法\n    if ('innerHeight' in w) {\n        return {\n            width: w.innerWidth,\n            height: w.innerHeight\n        };\n    }\n\n    var d = w.document;\n    // IE 8及以下浏览器在标准模式下\n    if (document.compatMode === 'CSS1Compat') {\n        return {\n            width: d.documentElement.clientWidth,\n            height: d.documentElement.clientHeight\n        };\n    }\n\n    // IE8及以下浏览器在怪癖模式下\n    return {\n        width: d.body.clientWidth,\n        height: d.body.clientHeight\n    };\n}\n```\n\n### 完成函数getScrollOffset返回窗口滚动条偏移量\n\n    /**\n     * 获取指定window中滚动条的偏移量，如未指定则获取当前window\n     * 滚动条偏移量\n     *\n     * @param {window} w 需要获取滚动条偏移量的窗口\n     * @return {Object} obj.x为水平滚动条偏移量,obj.y为竖直滚动条偏移量\n     */\n    function getScrollOffset(w) {\n        w =  w || window;\n        // 如果是标准浏览器\n        if (w.pageXOffset != null) {\n            return {\n                x: w.pageXOffset,\n                y: w.pageYOffset\n            };\n        }\n\n        // 老版本IE，根据兼容性不同访问不同元素\n        var d = w.document;\n        if (d.compatMode === 'CSS1Compat') {\n            return {\n                x: d.documentElement.scrollLeft,\n                y: d.documentElement.scrollTop\n            }\n        }\n\n        return {\n            x: d.body.scrollLeft,\n            y: d.body.scrollTop\n        };\n    }\n\n\n### 现有一个字符串richText,是一段富文本,需要显示在页面上.有个要求,需要给其中只包含一个img元素的p标签增加一个叫pic的class.请编写代码实现.可以使用jQuery或KISSY.\n\n    function richText(text) {\n        var div = document.createElement('div');\n        div.innerHTML = text;\n        var p = div.getElementsByTagName('p');\n        var i, len;\n\n        for (i = 0, len = p.length; i < len; ++i) {\n            if (p[i].getElementsByTagName('img').length === 1) {\n                p[i].classList.add('pic');\n            }\n        }\n\n        return div.innerHTML;\n    }\n\n### 请实现一个Event类,继承自此类的对象都会拥有两个方法on,off,once和trigger\n\n\n    function Event() {\n        if (!(this instanceof Event)) {\n            return new Event();\n        }\n        this._callbacks = {};\n    }\n    Event.prototype.on = function (type, handler) {\n        this_callbacks = this._callbacks || {};\n        this._callbacks[type] = this.callbacks[type] || [];\n        this._callbacks[type].push(handler);\n\n        return this;\n    };\n\n    Event.prototype.off = function (type, handler) {\n        var list = this._callbacks[type];\n\n        if (list) {\n            for (var i = list.length; i >= 0; --i) {\n                if (list[i] === handler) {\n                    list.splice(i, 1);\n                }\n            }\n        }\n\n        return this;\n    };\n\n    Event.prototype.trigger = function (type, data) {\n        var list = this._callbacks[type];\n\n        if (list) {\n            for (var i = 0, len = list.length; i < len; ++i) {\n                list[i].call(this, data);\n            }\n        }\n    };\n\n    Event.prototype.once = function (type, handler) {\n        var self = this;\n\n        function wrapper() {\n            handler.apply(self, arguments);\n            self.off(type, wrapper);\n        }\n        this.on(type, wrapper);\n        return this;\n    };\n\n### 编写一个函数将列表子元素顺序反转\n\n```\n<ul id=\"target\">\n    <li>1</li>\n    <li>2</li>\n    <li>3</li>\n    <li>4</li>\n</ul>\n\n<script>\n    var target = document.getElementById('target');\n    var i;\n    var frag = document.createDocumentFragment();\n\n    for (i = target.children.length - 1; i &gt;= 0; --i) {\n        frag.appendChild(target.children[i]);\n    }\n    target.appendChild(frag);\n</script>\n```\n\n### 以下函数的作用是?空白区域应该填写什么\n\n```\n// define\n(function (window) {\n    function fn(str) {\n        this.str = str;\n    }\n\n    fn.prototype.format = function () {\n        var arg = __1__;\n        return this.str.replace(__2__, function (a, b) {\n            return arg[b] || '';\n        });\n    };\n\n    window.fn = fn;\n})(window);\n\n// use\n(function () {\n    var t = new fn('<p><a href=\"{0}\">{1}</a><span>{2}</span></p>');\n    console.log(t.format('http://www.alibaba.com', 'Alibaba', 'Welcome'));\n})();\n```\n\ndefine部分定义一个简单的模板类，使用{}作为转义标记，中间的数字表示替换目标，format实参用来替换模板内标记\n横线处填：\n\n1. ``Array.prototype.slice.call(arguments, 0)``\n2. ``/\\{\\s*(\\d+)\\s*\\}/g``\n\n### 编写一个函数实现form的序列化(即将一个表单中的键值序列化为可提交的字符串)\n\n\n    <form id=\"target\">\n        <select name=\"age\">\n            <option value=\"aaa\">aaa</option>\n            <option value=\"bbb\" selected>bbb</option>\n        </select>\n        <select name=\"friends\" multiple>\n            <option value=\"qiu\" selected>qiu</option>\n            <option value=\"de\">de</option>\n            <option value=\"qing\" selected>qing</option>\n        </select>\n        <input name=\"name\" value=\"qiudeqing\">\n        <input type=\"password\" name=\"password\" value=\"11111\">\n        <input type=\"hidden\" name=\"salery\" value=\"3333\">\n        <textarea name=\"description\">description</textarea>\n        <input type=\"checkbox\" name=\"hobby\" checked value=\"football\">Football\n        <input type=\"checkbox\" name=\"hobby\" value=\"basketball\">Basketball\n        <input type=\"radio\" name=\"sex\" checked value=\"Female\">Female\n        <input type=\"radio\" name=\"sex\" value=\"Male\">Male\n    </form>\n\n\n    <script>\n\n    /**\n     * 将一个表单元素序列化为可提交的字符串\n     *\n     * @param {FormElement} form 需要序列化的表单元素\n     * @return {string} 表单序列化后的字符串\n     */\n    function serializeForm(form) {\n      if (!form || form.nodeName.toUpperCase() !== 'FORM') {\n        return;\n      }\n\n      var result = [];\n\n      var i, len;\n      var field, fieldName, fieldType;\n\n      for (i = 0, len = form.length; i < len; ++i) {\n        field = form.elements[i];\n        fieldName = field.name;\n        fieldType = field.type;\n\n        if (field.disabled || !fieldName) {\n          continue;\n        } // enf if\n\n        switch (fieldType) {\n          case 'text':\n          case 'password':\n          case 'hidden':\n          case 'textarea':\n            result.push(encodeURIComponent(fieldName) + '=' +\n                encodeURIComponent(field.value));\n            break;\n\n          case 'radio':\n          case 'checkbox':\n            if (field.checked) {\n              result.push(encodeURIComponent(fieldName) + '=' +\n                encodeURIComponent(field.value));\n            }\n            break;\n\n          case 'select-one':\n          case 'select-multiple':\n            for (var j = 0, jLen = field.options.length; j < jLen; ++j) {\n              if (field.options[j].selected) {\n                result.push(encodeURIComponent(fieldName) + '=' +\n                  encodeURIComponent(field.options[j].value || field.options[j].text));\n              }\n            } // end for\n            break;\n\n          case 'file':\n          case 'submit':\n            break; // 是否处理？\n\n          default:\n            break;\n        } // end switch\n      } // end for\n\n        return result.join('&');\n    }\n\n    var form = document.getElementById('target');\n    console.log(serializeForm(form));\n    </script>\n\n### 使用原生javascript给下面列表中的li节点绑定点击事件,点击时创建一个Object对象,兼容IE和标准浏览器\n\n```\n<ul id=\"nav\">\n    <li><a href=\"http://11111\">111</a></li>\n    <li><a href=\"http://2222\">222</a></li>\n    <li><a href=\"http://333\">333</a></li>\n    <li><a href=\"http://444\">444</a></li>\n</ul>\n\nObject:\n{\n    \"index\": 1,\n    \"name\": \"111\",\n    \"link\": \"http://1111\"\n}\n```\n\nscript:\n\n```\nvar EventUtil = {\n    getEvent: function (event) {\n        return event || window.event;\n    },\n    getTarget: function (event) {\n        return event.target || event.srcElement;\n    },\n    // 返回注册成功的监听器，IE中需要使用返回值来移除监听器\n    on: function (elem, type, handler) {\n        if (elem.addEventListener) {\n            elem.addEventListener(type, handler, false);\n            return handler;\n        } else if (elem.attachEvent) {\n            function wrapper(event) {\n                return handler.call(elem, event);\n            };\n            elem.attachEvent('on' + type, wrapper);\n            return wrapper;\n        }\n    },\n    off: function (elem, type, handler) {\n        if (elem.removeEventListener) {\n            elem.removeEventListener(type, handler, false);\n        } else if (elem.detachEvent) {\n            elem.detachEvent('on' + type, handler);\n        }\n    },\n    preventDefault: function (event) {\n        if (event.preventDefault) {\n            event.preventDefault();\n        } else if ('returnValue' in event) {\n            event.returnValue = false;\n        }\n    },\n    stopPropagation: function (event) {\n        if (event.stopPropagation) {\n            event.stopPropagation();\n        } else if ('cancelBubble' in event) {\n            event.cancelBubble = true;\n        }\n    }\n};\nvar DOMUtil = {\n    text: function (elem) {\n        if ('textContent' in elem) {\n            return elem.textContent;\n        } else if ('innerText' in elem) {\n            return elem.innerText;\n        }\n    },\n    prop: function (elem, propName) {\n        return elem.getAttribute(propName);\n    }\n};\n\nvar nav = document.getElementById('nav');\n\nEventUtil.on(nav, 'click', function (event) {\n    var event = EventUtil.getEvent(event);\n    var target = EventUtil.getTarget(event);\n\n    var children = this.children;\n    var i, len;\n    var anchor;\n    var obj = {};\n\n    for (i = 0, len = children.length; i < len; ++i) {\n        if (children[i] === target) {\n            obj.index = i + 1;\n            anchor = target.getElementsByTagName('a')[0];\n            obj.name = DOMUtil.text(anchor);\n            obj.link = DOMUtil.prop(anchor, 'href');\n        }\n    }\n\n    alert('index: ' + obj.index + ' name: ' + obj.name +\n        ' link: ' + obj.link);\n});\n```\n\n### 有一个大数组,var a = ['1', '2', '3', ...];a的长度是100,内容填充随机整数的字符串.请先构造此数组a,然后设计一个算法将其内容去重\n\n```\n    /**\n    * 数组去重\n    **/\n    function normalize(arr) {\n        if (arr && Array.isArray(arr)) {\n            var i, len, map = {};\n            for (i = arr.length; i >= 0; --i) {\n                if (arr[i] in map) {\n                    arr.splice(i, 1);\n                } else {\n                    map[arr[i]] = true;\n                }\n            }\n        }\n        return arr;\n    }\n\n    /**\n    * 用100个随机整数对应的字符串填充数组。\n    **/\n    function fillArray(arr, start, end) {\n        start = start == undefined ? 1 : start;\n        end = end == undefined ?  100 : end;\n\n        if (end <= start) {\n            end = start + 100;\n        }\n\n        var width = end - start;\n        var i;\n        for (i = 100; i >= 1; --i) {\n            arr.push('' + (Math.floor(Math.random() * width) + start));\n        }\n        return arr;\n    }\n\n    var input = [];\n    fillArray(input, 1, 100);\n    input.sort(function (a, b) {\n        return a - b;\n    });\n    console.log(input);\n\n    normalize(input);\n    console.log(input);\n```\n"
  },
  {
    "path": "24-100+Web-Development-Tools-and-Resources/README.md",
    "content": "# 100+ 超全的web开发工具和资源\n\n> 整合 WEB 开发包含的 JavaScript 库，前端框架，Web 应用框架，任务批处理工具 / 包管理器，编程语言 / 开发平台，数据库，icon 图标，本地开发环境搭建，协作工具，Web 开发社区，未能一一整合，欢迎评论提交哦。\n\n![](http://ww4.sinaimg.cn/large/66101050jw1f7axgo2hbtj20l808cjss.jpg)\n\n**英文原文：** [https://www.keycdn.com/blog/web-development-tools/](https://www.keycdn.com/blog/web-development-tools/)\n\n**转载出处：** https://xituqu.com/170.html\n\n**译者：** 稀土区\n\n作为Web开发者，这是好的时代，也是坏的时代。Web开发技术也在不断变化。虽然很令人兴奋，但是这也意味着Web开发人员需要要积极主动的学习新技术和新的[编程语言](https://xituqu.com/tag/programing-language)，并愿意和渴望接受新的挑战，以适应变化。新的挑战可能会包括一些开发上的要求，如利用适应现有的[框架](https://xituqu.com/tag/framework)来满足业务需求。测试一个网站，能从中知道出了哪些技术上的问题，并且我们针对这些问题进行优化和消除。便于后端的开发进程加快和测试。所以我们列出了完整的[web](https://xituqu.com/tag/web)开发所需要的工具和资源，助力开发者提高开发效率！学不止步，让我们努力成为一个优秀的开发者！\n\n### Web开发工具和资源整合\n在这里说声抱歉，对于开发者开发使用的工具，我们无法一一囊括，这里是选取较为热门的工具和资源作为范例。我们希望能从中找到适合自己的工具助力自己的开发！\n\n注：工具和资源排序不分先后。\n\n### JavaScript库\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/javascript-libraries.webp)](https://ww4.sinaimg.cn/large/72f96cbagw1f49ehwz03lj20k506e74o)\n\n我敢说JavaScript语言是目前web开发最流行的编程语言。JavaScript库又称JavaScript框架，封装了很多预定义的对象和使用函数。是网站更容易兼容各式各样的浏览器。那么您就可以使用以下JavaScript库来帮助你的开发更好进行。\n\n[jQuery](http://jquery.com/)：快y速，小巧，功能丰富的[JavaScript库](https://xituqu.com/tag/javascript-library)。\n\n[BackBoneJS](http://backbonejs.org/)：为复杂Javascript应用程序提供模型(models)、集合(collections)、视图(views)的结构。\n\n[D3.js](http://d3js.org/)：*D3*是基于数据的文档操作javascript库,*D3*能够把数据和HTML、SVG、CSS结合起来,创造出可交互的数据图表。\n\n[React:](https://facebook.github.io/react/)：Facebook的Javascript库为构建用户界面而开发。\n\n[jQ](http://jqueryui.com/)[uery](http://jqueryui.com/)[ UI](http://jqueryui.com/)：*jQuery UI* 是以 jQuery 为基础的开源 JavaScript 网页用户界面代码库。包含底层用户交互、动画、特效和可更换主题的可视控件。\n\n[jQuery Mobile](http://jquerymobile.com/)：基于HTML5用于创建移动 web 应用程序的框架。\n\n[Underscore.js](http://underscorejs.org/)：JavaScript实用库,提供了类似Prototype.js的一些功能,但是没有继承任何JavaScript内置对象。\n\n[Moment.js](http://momentjs.com/)：一个 JavaScript 日期处理类库，用于解析、检验、操作、以及显示日期。\n\n[Lodash](https://lodash.com/)：一个 JavaScript 实用工具库,提供一致性,模块化,性能和配件等功能。\n\n### [前端框架](https://xituqu.com/tag/front-end-framework)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/front-end-frameworks.webp)](https://ww1.sinaimg.cn/large/72f96cbagw1f49eh9fjvhj20k506eaab)\n\n通俗的前端由HTML，CSS，JavasScript等构成。当然为了适应Web开发日益增长的需求，应运而生许多独立的前端框架，例如Bootstrap。一个优秀的框架可以为前端开发人员在开发过程中增益，减小开发压力。\n\n[Bootstrap](http://getbootstrap.com/)： *Bootstrap* 是基于 HTML、CSS、JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加快捷。\n\n[Foundation](http://foundation.zurb.com/)： 迄今为止最好的响应式前端框架，更快、更轻、更多功能、更灵活、更强大！\n\n[Semantic UI](http://semantic-ui.com/)：*Semantic* *UI* 是一款语义化设计的前端开源框架,其功能强大,使用简单,为设计师和开发师提供可复用的完美设计方案。\n\n[uikit](http://getuikit.com/)：*UIKit*使用的变量基于LESS,具有体积小、模块化、可轻松地自定义主题及响应式界面。\n\n### [Web应用框架](https://xituqu.com/tag/web-framework)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/web-application-frameworks.webp)](https://ww3.sinaimg.cn/large/72f96cbagw1f49ei86hctj20k506edg4)\n\nWeb应用框架作为一个软件框架，意在帮助和缓解开发者在进行Web应用的开发与维护时遇见的开发问题。例如：AngularJS，您可以在您的项目完全免费使用它，详细文档请您参见 [angularcdn.com](https://angularcdn.com/).\n\n[Ruby](http://rubyonrails.org/)：Ruby on Rails 是使用 Ruby 语言编写的网页程序开发框架，目的是为开发者提供常用组件，简化网页程序的开发。\n\n[React](http://facebook.github.io/react/)：React 起源于 Facebook 的内部项目，React 的设计思想极其独特，属于革命性创新，性能出众，代码逻辑却非常简单。是现在非长热门的框架。\n\n[Vue](http://cn.vuejs.org/)：Vue.js 是用于构建交互式的 Web  界面的库。它提供了 MVVM 数据绑定和一个可组合的组件系统，具有简单、灵活的 API。从技术上讲， Vue.js 集中在 MVVM 模式上的视图模型层，并通过双向数据绑定连接视图和模型。\n\n[AngularJS](https://angularjs.org/)：AngularJS 通过新的属性和表达式扩展了 HTML，可以构建一个单一页面应用程序。AngularJS有着诸多特性，最为核心的是：MVVM、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。\n\n[Ember.js](http://emberjs.com/)：一个用于创建 web 应用的 JavaScript MVC 框架，采用基于字符串的Handlebars模板，支持双向绑定、观察者模式、计算属性（依赖其他属性动态变化）、自动更新模板、路由控制、状态机等。\n\n[Express](http://expressjs.com/)：基于 Node.js 平台的 web 应用开发框架 基于Node.js 平台,快速、开放、极简的 web 开发框架。\n\n[Meteor](https://www.meteor.com/)：Meteor 是一个构建在 Node.js 之上的平台，用来开发实时网页程序。Meteor 位于程序[数据库](https://xituqu.com/tag/database)和用户界面之间，保持二者之间的数据同步更新。\n\n[Django](https://www.djangoproject.com/)：*Django*是一个开放源代码的Web应用框架,由Python写成。采用了MVC的软件设计模式,即模型M,视图V和控制器C。\n\n[ASP.net](https://www.microsoft.com/web/platform/framework.aspx)：ASP.NET是免费，高兼容的WEB应用框架，能够提供标准化WEB应用构建时所需的解决方案。\n\n[Laravel](https://laravel.com/)：一个免费，开源的PHP Web应用程序框架，可以基于MVC模式来创建Web应用程序。\n\n[Zend Framework 2](http://framework.zend.com/)：一款的Web应用框架，基于PHP来创建Web应用和服务端应用。\n\n[Phalcon](https://phalconphp.com/en/)：*Phalcon* 是开源、全功能栈、使用 C 扩展编写、针对高性能优化的 PHP 5 框架。\n\n[Symfony](http://symfony.com/)：*Symfony*是一个基于MVC模式的面向对象的PHP5框架。*Symfony*允许在一个web应用中分离事务控制，服务逻辑和表示层。\n\n[CakePHP](http://cakephp.org/)：*CakePHP*是一个运用了诸如ActiveRecord、Association Data Mapping、Front Controller和MVC等著名设计模式的快速开发框架。主要目标是提供一个可以让各种层次的PHP开发人员快速地开发出健壮的Web应用，而 又不失灵活性。\n\n[Flask](http://flask.pocoo.org/)：*Flask*是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ，模板引擎则使用 Jinja2\n\n[CodeIgniter](https://www.codeigniter.com/)：CodeIgniter 是一个简单快速的PHP MVC框架。它为团队提供了足够的自由支持，允许开发人员更迅速地工作。\n\n### [任务批处理工具](https://xituqu.com/tag/task-runner)/[包管理器](https://xituqu.com/tag/package-manager)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/build-systems-task-runners.webp)](https://ww1.sinaimg.cn/large/72f96cbagw1f49eifxrl5j20k506ejru)\n\n任务批量处理工具可将你的工作流程全自动化.例如你可以创建一个任务，使用JavaScript语言编写的工具来进行自动化的处理。 然后打包，这样会大大提高开发效率。 包管理器它能跟踪所有已安装的软件、自动化进行安装和删除应用程序、以及确保所有软件都保持更新以获得最新的增强功能和错误修复。\n\n[Grunt](http://gruntjs.com/)：*Grunt*是基于Node.js的项目构建工具。它可以自动运行你所设定的任务。\n\n[Gulp](http://gulpjs.com/)：*Gulp*.js 是基于 Node.js 构建的一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务。\n\n[npm](https://www.npmjs.com/)：NPM（node package manager），通常称为node包管理器。顾名思义，它的主要功能就是管理node包，包括：安装、卸载、更新、查看、搜索、发布等。\n\n[Bower](http://bower.io/)：Bower是一个客户端技术的软件包管理器，它可用于搜索、安装和卸载如JavaScript、HTML、CSS之类的网络资源。\n\n### 编程语言 / 开发平台\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/programming-languages.webp)](https://ww2.sinaimg.cn/large/72f96cbagw1f49eimuqt3j20k506ewew)\n\n所有Web开发都需要编程语言的支持.*编程语言*（programming language），是用来定义计算机程序的形式语言。它是一种被标准化的交流技巧，用来向计算机发出指令。一种计算机语言让程序员能够准确地定义计算机所需要使用的数据，并精确地定义在不同情况下所应当采取的行动。.当然进行Web开发不仅仅只有一门语言来进开发。\n\n[PHP](http://php.net/)：PHP（外文名:PHP: Hypertext Preprocessor，中文名：“超文本预处理器”）是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点，利于学习，使用广泛，主要适用于Web开发领域\n\n[NodeJS](https://nodejs.org/en/)：*Node*.*js* 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。*Node*.*js* 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。\n\n[Javascript](https://en.wikipedia.org/wiki/JavaScript)：JavaScript一种直译式脚本语言，是一种动态类型、弱类型、基于原型的语言，内置支持类型。它的解释器被称为JavaScript引擎，为浏览器的一部分，广泛用于客户端的脚本语言\n\n[HTML5](https://www.w3.org/TR/html5/)：标记语言，是HTML和XHTML的最新版本。\n\n[Python](https://www.python.org/)：Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。\n\n[Ruby](https://www.ruby-lang.org/en/)：*Ruby*，一种为简单快捷的面向对象编程（面向对象程序设计）而创的脚本语言\n\n[Scala](http://www.scala-lang.org/)：*Scala*是一门多范式的编程语言，一种类似java的编程语言，设计初衷是实现可伸缩的语言、并集成面向对象编程和函数式编程的各种特性。\n\n[CSS3](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS3)：*CSS*即层叠*样式表*（Cascading StyleSheet）。 在网页制作时采用层叠*样式表*技术，可以有效地对页面的布局、字体、颜色、背景和其它效果实现更加精确的控制。CSS3是CSS的最新版本。\n\n[SQL](https://en.wikipedia.org/wiki/SQL)：结构化查询语言(Structured Query Language)简称*SQL，*是一种特殊目的的编程语言，是一种数据库查询和程序设计语言，用于存取数据以及查询、更新和管理关系数据库系统；同时也是数据库脚本文件的扩展名。\n\n[Golang](https://golang.org/)：Go是Google开发的一种编译型，可平行化，并具有垃圾回收功能的编程语言。\n\n[Rust](https://www.rust-lang.org/)：Rust是Mozilla开发的注重安全、性能和并发性的编程语言。\n\n[Elixir](http://elixir-lang.org/)：Elixir 是一种函数式编程语言,建立在Erlang虚拟机之上。它是一种动态语言,灵活的语法与宏支持,利用Erlang的能力来构建并发、分布式、容错应用程序与热代码升级。\n\n### 数据库\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/databases.webp)](https://ww1.sinaimg.cn/large/72f96cbagw1f49eiztykmj20k506eweu)\n\n*数据库*（Database）是按照数据结构来组织、存储和管理数据的仓库。\n\n[MySQL](https://www.mysql.com/)：MySQL是一种关联数据库管理系统，关联数据库将数据保存在不同的表中，而不是将所有数据放在一个大仓库内，这样就增加了速度并提高了灵活性。\n\n[MariaDB](https://mariadb.org/)：*MariaDB*数据库管理系统是MySQL的一个分支，主要由开源社区在维护，采用GPL授权许可 *MariaDB*的目的是完全兼容MySQL，包括API和命令行，使之能轻松成为MySQL的代替品。\n\n[MongoDB](https://www.mongodb.org/)：*MongoDB* 教程 *MongoDB* 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。\n\n[Redis](http://redis.io/)：*Redis*是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库，并提供多种语言的API。\n\n[PostgreSQL](http://www.postgresql.org/)：ostgreSQL支持大部分 SQL标准并且提供了许多其他现代特性：复杂查询、外键、触发器、视图、事务完整性、MVCC。\n\n### CSS 预处理器\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/css-preprocessors.webp)](https://ww3.sinaimg.cn/large/72f96cbagw1f49ej7q1o7j20k506edga)\n\nCSS 预处理器定义了一种新的语言，其基本思想是，用一种专门的编程语言，为 CSS 增加了一些编程的特性，将 CSS 作为目标生成文件，然后开发者就只要使用这种语言进行编码工作。\n\n通俗的说，“CSS 预处理器用一种专门的编程语言，进行 Web 页面样式设计，然后再编译成正常的 CSS 文件，以供项目使用。CSS 预处理器为 CSS 增加一些编程的特性，无需考虑浏览器的兼容性问题”，例如你可以在 CSS 中使用变量、简单的逻辑程序、函数等等在编程语言中的一些基本特性，可以让你的 CSS 更加简洁、适应性更强、可读性更佳，更易于代码的维护等诸多好处。例如：Sass，Less，Stylus。\n\n[Sass](http://sass-lang.com/)： Sass是一种CSS的开发工具，提供了许多便利的写法，大大节省了设计者的时间，使得CSS的开发，变得简单和可维护。\n\n[Less](http://lesscss.org/)：*Lesscss*是一种动态样式语言,属于CSS预处理语言的一种,它使用类似CSS的语法,为CSS的赋予了动态语言的特性,如变量、继承、运算、函数等,更方便CSS的编写和维护。\n\n[Stylus](http://stylus-lang.com/)：Stylus 是一个CSS的预处理框架，2010年产生，来自Node.js社区，主要用来给Node项目进行CSS预处理支持，所以Stylus 是一种新型语言，可以创建健壮的、动态的、富有表现力的CSS。\n\n如果你是刚刚开始使用CSS的预处理器，你可能要先使用第三方编译器进行开发，如下所示。\n\n### [文本编辑器](https://xituqu.com/tag/text-editor) / [代码编辑器](https://xituqu.com/tag/code-editor)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/text-editors-code-editors.webp)](https://ww2.sinaimg.cn/large/72f96cbagw1f49ejgpwtjj20k506eglx)\n\n无论你是做笔记，敲代码，或者Markdown文档编写，一个好的文本编辑器都是必须拥有的！\n\n[Atom](https://atom.io/)：*Atom* 更为先进的文本代码编辑器 - 由 Github 打造的下一代编程开发利器在代码编辑器、文本编辑器领域,有着不少的「神器」级的产品。\n\n[Sublime Text](http://www.sublimetext.com/)：Sublime Text 是一个代码编辑器（Sublime Text 2和3是收费软件，但可以无限期试用），也是HTML和散文先进的文本编辑器。\n\n[Notepad++](https://notepad-plus-plus.org/)：*Notepad++*是 Windows操作系统下的一套文本编辑器(软件版权许可证: GPL)，有完整的中文化接口及支持多国语言编写的功能。\n\n[Visual Studio Code ](https://www.visualstudio.com/products/code-vs)：微软推出，一个运行于 Mac OS X、Windows和 Linux 之上的，针对于编写现代 Web 和云应用的跨平台源代码编辑器。\n\n[TextMate](https://macromates.com/)：TextMate是Mac下的著名的文本编辑器软件，与BBedit一起并称苹果机上的emacs和vim。\n\n[Coda 2](https://panic.com/coda/):  OS X下快速，简洁，功能强大的编辑器【需要付费】.\n\n[WebStorm](https://www.jetbrains.com/webstorm/)：jetbrains公司旗下一款JavaScript 开发工具。被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。\n\n[Vim](http://www.vim.org/)：Vim是一个类似于Vi的著名的功能强大、高度可定制的文本编辑器，在Vi的基础上改进和增加了很多特性。\n\n[Brackets](http://brackets.io/)：Brackets 是一个免费、开源且跨平台的 HTML/CSS/JavaScript 前端 WEB 集成开发环境 (IDE工具)。\n\n[Emacs](https://www.gnu.org/software/emacs/)：著名的集成开发环境和文本编辑器。*Emacs*被公认为是最受专业程序员喜爱的代码编辑器之一。\n\n### [Markdown 编辑器](https://xituqu.com/tag/markdown-editor)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/markdown-editors.webp)](https://ww4.sinaimg.cn/large/72f96cbagw1f49ejo6wj1j20k506edg1)\n\n*Markdown* 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用。*Markdown* 十分轻量,学习成本也不高。\n\n[MWeb](http://zh.mweb.im/)：专业的 Markdown 写作、记笔记、静态博客生成软件 【付费】\n\n[Markeditor](http://markeditor.com/app/markeditor)：MarkEditor 是最新的一款 Markdown 编辑器，除了基本功能外，还包含了诸如表格编辑、图表、高亮、公式等等丰富的功能！【付费】\n\n[StackEdit](https://stackedit.io/)：一个开放源码免费使用的 MarkDown 编辑器, 基于 PageDown,使用了 Stack Overflow 和其他 Stack Exchange 网站的 MarkDown 库\n\n[Dillinger](http://dillinger.io/)：Dillinger 是一款在线的 Markdown 编辑器,支持更换主题,字数统计,云服务保存,导出 HTML、PDF 等功能。\n\n[Mou](http://25.io/mou/): Mac OS X下的免费Markdown编辑器【作者貌似已经跑路了】\n\n[Texts](http://www.texts.io/)：Windows和Mac OS X下纯文本编辑器。\n\n表示有些付费的Markdown编辑器宝宝买不起。\n\n### [icon图标](https://xituqu.com/tag/icon)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/icons.webp)](https://ww3.sinaimg.cn/large/72f96cbagw1f49ejvaf9zj20k506emxi)\n\n几乎每一个Web开发者，尤其是前端开发人员都会需要icon图标来增色项目。\n\n[Font Awesome](http://fontawesome.io/)：Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小、颜色、阴影或者其它任何支持的效果。\n\n[IconMonster](http://iconmonstr.com/)：免费，高质量, 庞大且资源不断增长的简洁的icon图标库。\n\n[IconFinder](https://www.iconfinder.com/)：*Iconfinder*提供美丽的图标,服务数以百万计的设计师,开发商和其他有创意的专业人员。\n\n[Fontello](http://fontello.com/)：一个目测有200+个图标（数量还在增加）的 Web-font 图标市场，对于广大设计师、前端开发者来说是很棒的资源。\n\n### Git 代理 / 服务\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/git-clients.webp)](https://ww2.sinaimg.cn/large/72f96cbagw1f49ek4s93zj20k506eq3e)\n\nGit是一款免费、开源的分布式版本控制系统，用于敏捷高效地处理任何或小或大的项目。Git是一个开源的分布式版本控制系统，可以有效、高速的处理从很小到非常大的项目版本管。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。\n\n[SourceTree](https://www.sourcetreeapp.com/)：SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端。支持创建、克隆、提交、push、pull 和合并等操作。\n\n[GitKraken](http://www.gitkraken.com/) (Beta)：一款自由、直观、快捷、美观的跨平台Git客户端。\n\n[Tower 2](https://www.git-tower.com/)：一款美丽，高效，强大的Git管理，让Git版本控制变得容易。\n\n[GitHub Client](https://desktop.github.com/)：有助于无缝连接GitHub和GitHub的企业的项目。\n\n[Gogs](https://gogs.io/)：Gogs (Go Git Service) 是一款极易搭建的自助 Git 服务。 开发目的 *Gogs* 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。\n\n[GitLab](https://about.gitlab.com/gitlab-com/):  GitLab是利用 Ruby on Rails 一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。\n\n[Coding](http://ww1.sinaimg.cn/large/72f96cbajw1f4chvmh9hqj206t03ywei)：Coding 的代码托管功能除了基本的 Git 仓库以外，还有保护分支，分屏对比， Code Review 等高级功能。并且整合了 Pages 服务，质量管理，演示平台等开发工具，提升研发效率。\n\n### [本地开发环境搭建](https://xituqu.com/tag/local-development-environment)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/local-dev-environment.webp)](https://ww1.sinaimg.cn/large/72f96cbagw1f49ekcv2vqj20k506emxn)\n\n根据您运行的是什么操作系统和计算机配置，有时候进行测试的时候就有可能需要搭建一个快速的本地开发环境。自己搭建很是蛮烦，不用担心，有很多将Apache，Nginx，MySQL和phpMyAdmin进行打包一体化的软件。这些软件很是方便我们来进行本地测试。\n\n[XAMPP](https://www.apachefriends.org/index.html)：XAMPP（Apache+MySQL+PHP+PERL）是一个功能强大的建站集成软件包。\n\n[MAMP PRO](https://www.mamp.info/en/)：*MAMP* *Pro* for mac是Mac OS平台搭建本地服务器环境的组合软件套装,包含 Macintosh、Apache、MySQL和PHP 四大开发环境。\n\n[WampServer](http://www.wampserver.com/en/)：Wamp就是Windows Apache Mysql PHP集成安装环境，即在window下的apache、php和mysql的服务器软件。\n\n[Vagrant](https://www.vagrantup.com/)：*Vagrant*是一个基于Ruby的工具，用于创建和部署虚拟化开发环境。它 使用Oracle的开源VirtualBox虚拟化系统，使用 Chef创建自动化虚拟环境。\n\n[Laragon](https://laragon.org/)：Laragon工具就是Laravel的一键安装工具吧，还集成了一整套wamp工具，除去Laravel安装外，它也是一款不错的wamp工具，干净简单，便捷迅速。Diff Checkers\n[Wnmp](https://www.getwnmp.org/)：WNMP是Windows下便捷，安全的Nginx+MariaDB+PHP开发环境环境集成套件包。\n\n### 文本对比检查\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/diff-checkers.webp)](https://ww3.sinaimg.cn/large/72f96cbagw1f49ekq3tfpj20k506eaaa)\n\nDiff checkers 可以帮助您比较文件之间的差异，然后合并更改。帮助我们更直观的看见文本之间的差异。\n\n[Diffchecker](https://www.diffchecker.com/)：Diffchecker 是一款非常好用的在线文本对比工具,能够高亮显示有差异的行和字符。*Diffchecker* 提供了文件上传对比功能,还可以选择对比的存储时间。\n\n[Beyond Compare](http://www.scootersoftware.com/)：Beyond Compare是一套由Scooter Software推出的软件，主要用途是对比两个文件夹或者文件，并将差异以颜色标示。\n\n当然有很多免费的文本编辑器，包括我们上面提到的也有插件和扩展，可以协助开发者方便的进行文件比较。\n\n### 代码共享 / 代码测试\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/code-sharing.webp)](https://ww2.sinaimg.cn/large/72f96cbagw1f49ekurukwj20k506eq3a)\n\n前端开发者在公司内或者团体间需要进行协作，共享代码，那么一下工具很值得开发者一试。\n\n[JS Bin](http://jsbin.com/)：*JS* *Bin*能够让你编辑和测试JavaScript和HTML代码。你还可以将编辑后的代码保存到本地,或将URL地址发给其他人,让其协助调试代码。\n\n[JSfiddle](https://jsfiddle.net/)：jsFiddle是一个在线的shell编辑器,通过流行的JS框架创建自定义的环境,以简化JS代码。可以用于测试示例代码。\n\n[codeshare](https://codeshare.io/)：与其他开发者实时共享代码。\n\n[Dabblet](http://dabblet.com/)：Dabblet是一个开源互动测试工具,用于测试CSS和HTML。*Dabblet*支持实时更新、匿名备份、嵌入网站、与他人共享或者存储到GitHub。\n\n### [协作工具](https://xituqu.com/tag/collaboration-tools)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/dev-collaboration-tools.webp)](https://ww3.sinaimg.cn/large/72f96cbagw1f49el0a4oxj20k506ejrq)\n每一个很棒的开发团队需要一种方式来保持联系，协作，来帮助提高生产力。\n\n[Slack](https://slack.com/)：Slack 是聊天群组 + 大规模工具集成 + 文件整合 + 统一搜索。\n\n[Trello](https://trello.com/)：Trello的目标是提供简洁清晰的团队协作工具。不过弥缝在这里将介绍如果将*Trello*用来建立自己的时间管理系统。\n\n[Glip](https://glip.com/)：Glip:在线团队办公协作平台是一个类似于Slack网站的网络办公集合体,内置了邮箱、网盘、即时通讯应用、协作服务等,把所有和网络办公有关的服务和工具都整合在了一起。\n\n[Asana](https://asana.com/)：Asana是一款团队任务管理软件 方便人们去制定和跟踪团队的项目任务的完成情况\n\n[Jira](https://www.atlassian.com/software/jira)：JIRA是Atlassian公司出品的项目与事务跟踪工具，被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域。\n\n### 灵感创意\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/developers-inspiration.webp)](https://ww3.sinaimg.cn/large/72f96cbagw1f49ela424oj20k506e74e)\n\n当我们进行开发时，偶尔迸发的灵感会使我们的项目或者产品增色不少。当然不仅仅依靠自我的灵感，我们也需要从别人的作品中得到灵感来保证我们的Web设计界面或者产品不落后这个时代。\n\n[CodePen](http://codepen.io/)：全球web前端开发人员的圣地！可以展示个人的创意和建立一个测试实例来解决bug。 来寻找你的项目设计方式和灵感吧。\n\n[Dribble](https://dribbble.com/)：Dribbble是一个面向创作家、艺术工作者、设计师等创意类作品的人群，提供作品在线服务，供网友在线查看已经完成的作品或者正在创作的作品的交流网站。\n\n### [网站测速工具](https://xituqu.com/tag/web-test)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/website-speed-test-tools.webp)](https://ww1.sinaimg.cn/large/72f96cbagw1f49elhl774j20k506eglw)\n网站的速度是用户体验关键因素。网站速度快与慢决定是否能更高的搜索引擎排名，更高的转换率，更低的跳出率，以及更好的整体用户体验和。值得高兴的是很多免费软件可以用于测试网站速度，帮助我们找出加载缓慢的问题，方便我们去解决。\n\n[Google PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/)：PageSpeed Insights是一款可以分析网页速度瓶颈,让网页设计人员开发出速度更快的网站的*谷歌*浏览器插件。\n\n[Google Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/?hl=en)：Chrome DevTools 是公认的优秀的前端调试工具，功能强大，使用起来有一定的学习门槛。\n\n[WebPageTest](http://www.webpagetest.org/)：*WebPagetest*是一款Web应用程序,它将一个URL以及一系列配置参数作为输入,并对那个URL运行性能测试。\n\n[Pingdom](http://tools.pingdom.com/fpt/)：pingdom全面的网站监测服务网站,可测速和ping跟踪路由,可以免费监测1个站点,最短1分钟监测一次。\n\n[GTmetrix](https://gtmetrix.com/)：主要优点在于提供了丰富的详细的测量结果，并建议如何来优化网页中每个元素的，最重要的是会根据网站的具体情况，直接告诉你导致网站加载速度变慢的根源在哪里\n\n### [Web开发社区](https://xituqu.com/tag/web-community)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/web-development-communities.webp)](https://ww2.sinaimg.cn/large/72f96cbagw1f49elwu9q7j20k506edg4)\n\n当开发者在开发的过程中有遇到问题时，除了询问他人以外，还可以使用搜索引擎搜索。社区的重要性就显而易见了，大部分开发者会在开发社区分享他们经验，如何避过不必要踩的坑。\n\n**国内：**\n \n[谷歌开发者社区(GDG)](http://chinagdg.org/)：开放 · 分享 · 创新\n\n[segmentfault](https://segmentfault.com/)：是中国领先的*开发*者技术*社区*。 为编程爱好者提供一个纯粹、高质的技术交流的平台, 与*开发*者一起学习、交流与成长。【老实话我觉得这名字不好记】\n\n[全栈社区](http://www.fullstackspace.com/)：中国最大的全栈*开发者社区*,致力于打造一个问题解答,技术文章分享,全栈人员创业的服务平台,让开发更容易,让创业更简单.\n\n**国外：**\n\n[Stack Overflow](http://stackoverflow.com/)：Stack Overflow是一个与程序相关的IT技术问答网站。用户可以在网站免费提交问题，浏览问题，索引相关内容，在创建主页的时候使用简单的HTML。\n\n[Front-end Front](https://frontendfront.com/)：在Front-end Front，前端开发者可以提出问题，分享有趣的链接，并展示他们的项目作品。\n\n[Hashnode](https://hashnode.com/)：Hashnode是开发者讨论技术问题，分享解决方案，与世界各地的开发者共享资源的聚集地。\n\n[Refind](https://refind.com/)：有着开发者, 黑客, 设计师收集和分享最好的资源的社区。\n\n[Google+ Web Developers Group](https://plus.google.com/u/0/communities/114175980151299757659)：Web 开发者,Web设计师和Web开发.\n\n[Google+ Web Developers Group](https://plus.google.com/communities/114947356043496560984)：Java, PHP, Ruby, JavaScript and Python 资源。\n\n[Facebook WordPress Front-end Developers Group](https://www.facebook.com/groups/wpfrontenddevs/)：WordPress 前端开发者的分享社区，可以提问题，分享开发者的项目作品，还有讨论WP未来发展趋势。\n\n[LinkedIn Web Design and Development Professionals Group](https://www.linkedin.com/groups/139851/profile)：与专业网页设计师，网页开发者共享Web开发资源\n\n[LinkedIn Web Site Development Group](https://www.linkedin.com/groups/2192521/profile): 网站设计和开发。\n\n[LinkedIn PHP Developer Group](https://www.linkedin.com/groups/2195403/profile): PHP, Mysql, Drupal, Joomla, Zend, Cake, MVC.\n\n[LinkedIn WordPress Developers Group](https://www.linkedin.com/groups/3722491): WordPress 开发. 使用WP来创建CMS和CMF.\n\n[Webdeveloper.com](http://www.webdeveloper.com/forum/)：帮助Web开发者和设计师学习使用HTML，java和javascript开发网站。\n\n[Sitepoint Forums](https://www.sitepoint.com/community/): Web开发者论坛。\n\n[/r/perfmatters](https://www.reddit.com/r/perfmatters/): 讨论关于 web 性能\n\n[/r/webdev](https://www.reddit.com/r/webdev): 关于Web开发和开发者的新闻\n\n### [Web开发新闻聚合](https://xituqu.com/tag/web-news)\n[![100+ 超全的web开发工具和资源-稀土区](https://blog.keycdn.com/blog/wp-content/uploads/2016/02/web-development-newsletters.webp)](https://ww1.sinaimg.cn/large/72f96cbagw1f49em7ogivj20k506e74n)阅读开发和设计的技术干货，及时的知道技术圈内更新了什么，保持信息流新鲜，有助于我们更好的开发！\n\n**国内：**\n[掘金](http://gold.xitu.io/#/)：掘金是中国质量最高的技术分享社区，邀请稀土用户作为Co-Editor 来分享优质的技术干货，从前端到后端开发，从设计到产品，让每一个*掘金*用户都能挖掘到有价值的干货。\n\n[开发者头条](http://toutiao.io/)：一个以程序员为中心，基于学习和分享的开发者社区。你可以阅读头条新闻、分享技术文章、发布开源项目，订阅技术极客们创建的学习主题和关注编程牛人。\n\n[推酷](http://www.tuicool.com/)：以技术为驱动，以聚合挖掘为核心，打造个性推荐和订阅，给你一站式的阅读。 更汇聚优质公开课和线下活动，让信息知识获取更便捷。\n\n**国外：**\n[wdrl.info](https://wdrl.info/)：精心挑选的Web开发相关资源，每星期进行整合报道。\n\n[webopsweekly.com](http://webopsweekly.com/)： 每周进行报道关于网络运营，应用部署，网站性能和工具分享类的文章。\n\n[web tools weekly](http://webtoolsweekly.com/)：专注于前端开发和网页设计工具分享。每一个问题都有一个简短的提示或教程，另外每周都会分享的各种应用程序、脚本、插件和其他有用的资源。\n\n[freshbrewed.co](https://freshbrewed.co/)：每周为前端开发者和设计师提供开发和设计类的阅读摘要。\n\n[smashingmagazine.com](https://www.smashingmagazine.com/)： Smashing Magazine是一款专门为个人前端开发者和设计师提供的在线报纸，每周二都会定时的更新有用的资源。\n\n[front-end dev weekly](http://frontenddevweekly.com/): 每周为前端开发者提供新闻, 包含工具资源，还有灵感。\n\n[friday front-end](http://fridayfrontend.com/)：邮件订阅，每日为前端开发者发关于开发资源的邮件。\n\n[dev tips](https://umaar.com/dev-tips/): 收集开发者的问题和建议, 用gif呈现，会每周发邮件通知。\n\n当然, 你也可以关注稀土区，来找到你需要的文章，顺便解决你的问题。\n\n**备注**\n如你所见，有数以百计的网络开发工具和资源，可以帮助简化你的开发工作流程，帮助开发更高效。我们无法一一列出所有工具或资源，如果有重要的工具或资源有遗漏，那就要麻烦小伙伴们在下面的评论里进行补充，谢谢！\n\n**版权归原作者所有！**"
  },
  {
    "path": "25-web-develop-standard-master/README.md",
    "content": "Web前端开发规范文档\n===================\n\n### 规范目的：\n-------------------\n> - 使开发流程更加规范化。\n\n### 通用规范：\n-------------------\n> - TAB键用两个空格代替（`WINDOWS`下TAB键占四个空格，`LINUX`下TAB键占八个空格）。\n> - `CSS`样式属性或者`JAVASCRIPT`代码后加“;”方便压缩工具“断句”。\n> - 文件内容编码均统一为`UTF-8`。\n> - `CSS`、`JAVASCRIPT`中的非注释类中文字符须转换成unicode编码使用,以避免编码错误时乱码显示。\n\n### 文件规范：\n-------------------\n> - 文件名用英文单词，多个单词用驼峰命名法。\n> - 一些浏览器会将含有这些词的作为广告拦截，文件命名、ID、CLASS等所有命名避免以上词汇。\n>  `ad`、`ads`、`adv`、`banner`、`sponsor`、`gg`、`guangg`、`guanggao`等。\n\n### html书写规范：\n-------------------\n> -   为每个`HTML`页面的第一行添加标准模式（standard mode）的声明，确保在每个浏览器中拥有一致的展现。\n>\t\t\n\t\t<!DOCTYPE html>\t\t\n>     `文档类型声明`统一为HTML5声明类型，`编码`统一为UTF-8。\n>\n\t\t<meta charset=\"UTF-8\">\n>     `<HEAD>`中添加信息。\n>\n\t\t<meta name=\"author\" content=\"smile@kang.cool\">//作者\n\t\t<meta name=\"description\" content=\"hello\">//网页描述\n\t\t<meta name=\"keywords\" content=\"a,b,c\">//关键字,“，”分隔\n\t\t<meta http-equiv=\"expires\" content=\"Wed, 26 Feb 1997 08：21：57 GMT\">//设定网页的到期时间。一旦网页过期，必须到服务器上重新调阅\n\t\t<meta http-equiv=\"Pragma\" content=\"no-cache\">//禁止浏览器从本地机的缓存中调阅页面内容\n\t\t<meta http-equiv=\"Window-target\" content=\"_top\">//用来防止别人在框架里调用你的页面\n\t\t<meta http-equiv=\"Refresh\" content=\"5;URL=http://kahn1990.com/\">//跳转页面，5指时间停留5秒 网页搜索机器人向导。用来告诉搜索机器人哪些页面需要索引，哪些页面不需要索引\n\t\t<meta name=\"robots\" content=\"none\">//content的参数有all,none,index,noindex,follow,nofollow，默认是all\n\t\t<link rel=\"Shortcut Icon\" href=\"favicon.ico\">//收藏图标\n\t\t<meta http-equiv=\"Cache-Control\" content=\"no-cache, must-revalidate\">//网页不会被缓存\n>     `IE`支持通过特定&lt;meta&gt;标签来确定绘制当前页面所应该采用的`IE`版本。除非有强烈的特殊需求，否则最好是设置为`edge mode` ，从而通知`IE`采用其所支持的最新的模式。\n>\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\">\n> -   非特殊情况下`CSS`样式文件外链至HEAD之间，`JAVASCRIPT`文件外链至页面底部。\n>\n\t\t<!DOCTYPE html>\n\t\t<html>\n\t\t<head>\n\t\t\t<link rel=\"stylesheet\" href=\"css/main.css\">\n\t\t</head>\n\t\t<body>\n\t\t\t<!-- 逻辑代码 -->\n\t\t\t<!-- 逻辑代码底部 -->\n\t\t\t<script src=\"lib/jquery/jquery-2.1.1.min.js\"></script>\n\t\t</body>\n\t\t</html>\n>     引入`JAVASCRIPT`库文件，文件名须包含库名称及版本号及是否为压缩版。\n>\n\t\tjQuery-1.8.3.min.js\n>     引入`JAVASCRIPT`插件, 文件名格式为库名称+`.`+插件名称。\n>\n\t\tjQuery.cookie.js\n> -   `HTML`属性应当按照以下给出的顺序依次排列，来确保代码的易读性。\n>\n\t\tclass\n\t\tid 、 name\n\t\tdata-*\n\t\tsrc、for、 type、 href\n\t\ttitle、alt\n\t\taria-*、 role\n>     编码均遵循`XHTML`标准,\n>     标签、属性、属性命名由小写英文、数字和\\_组成，且所有标签必须闭合，属性值必须用双引号`\"\"`,\n>     避免使用中文拼音尽量简易并要求语义化。\n>\n\t\tCLASS --> nHeadTitle --> CLASS遵循小驼峰命名法（little camel-case）\n\t\tID --> n_head_title --> ID遵循名称+_\n\t\tNAME --> N_Head_Title --> NAME属性命名遵循首个字母大写+_\n\t\t<div class=\"nHeadTitle\" id=\"n_head_title\" name=\"N_Head_Title\"></div>\n>     当`JAVASCRIPT`获取单个元素时，通常使用document.getElementById来获取dom元素，document.getElementById兼容所有浏览器，但IE浏览器会混淆元素的ID和NAME属性，所以要区分ID和NAME命名。\n>\n\t\t<input type=\"text\" name=\"test\">\n\t\t<div id=\"test\"></div>\n\t\t<button onclick=\"alert(document.getElementById('test').tagName)\"></button>\n\t\t<!-- ie6下为INPUT -->\n> -   特殊符号应使用转意符。\n>\n\t\t<    -->    &lt;\n\t\t>    -->    &gt;\n\t\t空格  -->    &nbsp;\n> -   含有描述性表单元素（`INPUT`，`TEXTAREA`）添加`LABEL`。\n>\n\t\t<p>\n\t\t\t<label for=\"test\">测试</label>\n\t\t\t<input type=\"text\" id=\"test\" />\n\t\t</p>\n> -   多用无兼容性问题的`HTML`内置标签,比如SPAN、EM、STRONG、OPTGROUP、LABEL等,需要自定义`HTML`标签属性时，首先考虑是否存在已有的合适标签可替换，如果没有,可使用须以“`data-`”为前缀来添加自定义属性，避免使用其他命名方式。\n> -   语义化`HTML`。\n> -   尽可能减少`<DIV>`嵌套。\n> -   书写链接地址时避免重定向。\n>\n\t\thref=\"http://www.kahn1990.com/\" //即在URL地址后面加“/”\n> -   `HTML`中对于属性的定义，确保全部使用双引号，绝不要使用单引号\n\n### css书写规范：\n-------------------\n> -   为了欺骗`W3C`的验证工具,可将代码分为两个文件，一个是针对所有浏览器,一个只针对IE。即将所有符合`W3C`的代码写到一个文件中,而一些IE中必须而又不能通过`W3C`验证的代码（如:`cursor:hand;`）放到另一个文件中，再用下面的方法导入。\n>\n\t\t<!-- 放置所有浏览器样式-->\n\t\t<link rel=\"stylesheet\" type=\"text/css\" href=\"\">\n\t\t<!-- 只放置IE必须，而不能通过w3c的-->\n\t\t<!--[if IE]\n\t\t\t<link rel=\"stylesheet\" href=\"\">\n\t\t<![endif]-->\n> -   `CSS`样式新建或修改尽量遵循以下原则。\n>\n\t\t根据新建样式的适用范围分为三级：全站级、产品级、页面级。\n\t\t尽量通过继承和层叠重用已有样式。\n\t\t不要轻易改动全站级CSS。改动后，要经过全面测试。\n> -   `CSS`属性显示顺序。\n>\n\t\t显示属性\n\t\t元素位置\n\t\t元素属性\n\t\t元素内容属性\n>\n> -   `CSS`书写顺序。\n>\n\t\t.header {\n\t\t/* 显示属性 */\n\t\t\tdisplay || visibility\n\t\t\tlist-style\n\t\t\tposition top || right || bottom || left\n\t\t\tz-index\n\t\t\tclear\n\t\t\tfloat\n\t\t/* 自身属性 */\n\t\t\twidth max-width || min-width\n\t\t\theight max-height || min-height\n\t\t\toverflow || clip\n\t\t\tmargin\n\t\t\tpadding\n\t\t\toutline\n\t\t\tborder\n\t\t\tbackground\n\t\t/* 文本属性 */\n\t\t\tcolor\n\t\t\tfont\n\t\t\ttext-overflow\n\t\t\ttext-align\n\t\t\ttext-indent\n\t\t\tline-height\n\t\t\twhite-space\n\t\t\tvertical-align\n\t\t\tcursor\n\t\t\tcontent\n\t\t};\n>\n>     兼容多个浏览器时，将标准属性写在底部。\n>\n\t\t-moz-border-radius: 15px; /* Firefox */\n\t\t-webkit-border-radius: 15px; /* Safari和Chrome */\n\t\t-o-border-radius: 15px; \n\t\tborder-radius: 15px; /* Opera 10.5+, 以及使用了IE-CSS3的IE浏览器 *//标准属性\n> -   使用选择器时，命名比较短的词汇或者缩写的不允许直接定义样式。\n>\n\t\t.hd,.bd,.td{};//如这些命名\n>     可用上级节点进行限定。\n>\n\t\t.recommend-mod .hd\n>     多选择器规则之间换行，即当样式针对多个选择器时每个选择器占一行。\n>\n\t\tbutton.btn,\n\t\tinput.btn,\n\t\tinput[type=\"button\"] {…};\n>     优化`CSS`选择器。\n>\n\t\t#header a { color: #444; };/*CSS选择器是从右边到左边进行匹配*/\n>     浏览器将检查整个文档中的所有链接和每个链接的父元素，并遍历文档树去查找ID为header的祖先元素，如果找不到header将追溯到文档的根节点，解决方法如下。\n>\n\t\t避免使用通配规则和相邻兄弟选择符、子选择符,、后代选择符、属性选择符等选择器\n\t\t不要限定id选择符，如div#header（提权的除外）\n\t\t不要限定类选择器，如ul.recommend（提权的除外）\n\t\t不要使用 ul li a 这样长的选择符\n\t\t避免使用标签子选择符，如#header > li > a\n> -   使用`z-index`属性尽量`z-index`的值不要超过150（通用组的除外），页面中的元素内容的`z-index`不能超过10（提示框等模块除外但维持在150以下），不允许直接使用（999\\~9999）之间大值。\n> -   尽量避免使用CSS Hack。\n>\n\t\tproperty:value; /* 所有浏览器 */\n\t\t+property:value; /* IE7 */\n\t\t_property:value; /* IE6 */\n\t\t*property:value; /* IE6/7 */\n\t\tproperty:value\\9; /* IE6/7/8/9，即所有IE浏览器 */\n>\n\t\t* html selector { … }; /* IE6 */\n\t\t*:first-child+html selector { … }; /* IE7 */\n\t\thtml>body selector { … }; /* 非IE6 */\n\t\t@-moz-document url-prefix() { … }; /* firefox */\n\t\t@media all and (-webkit-min-device-pixel-ratio:0) { … }; /* saf3+/chrome1+ */\n\t\t@media all and (-webkit-min-device-pixel-ratio:10000),not all and (-webkit-min-device-pixel-ratio:0) { … }; /* opera */\n\t\t@media screen and (max-device-width: 480px) { … }; /* iPhone/mobile webkit */\n>     避免使用低效的选择器。\n>\n\t\tbody > * {…};\n\t\tul > li > a {…};\n\t\t#footer > h3 {…};\n\t\tul#top_blue_nav {…};\n\t\tsearbar span.submit a { … }; /* 反面示例 */\n>\n> -   六个不要三个避免一个使用。\n>\n\t\t不要在标签上直接写样式\n\t\t不要在CSS中使用expression\n\t\t不要在CSS中使用@import\n\t\t不要在CSS中使用!important\n\t\t不要在CSS中使用“*”选择符\n\t\t不要将CSS样式写为单行\n\t\t避免使用filter\n\t\t避免使用行内（inline）样式\n\t\t避免使用“*”设置{margin: 0; padding: 0;}\n\t\t使用after或overflow的方式清浮动\n> -   减少使用影响性能的属性。\n>\n\t\tposition:absolute;\n\t\tfloat:left;//如这些定位或浮动属性\n>\n\t\t减少在`CSS`中使用滤镜表达式和图片repeat,\n\t\t尤其在body当中,渲染性能极差, 如果需要用repeat的话,\n\t\t图片的宽或高不能少于8px。\n\n### javaScript书写规范：\n-------------------\n> -   命名规范。\n>\n\t\t常量名\n\t\t\t全部大写并单词间用下划线分隔\n\t\t\t如：CSS_BTN_CLOSE、TXT_LOADING\n>\n\t\t对象的属性或方法名\n\t\t\t小驼峰式（little camel-case）\n\t\t\t如：init、bindEvent、updatePosition\n\t\t\t示例：Dialog.prototype = {\n\t\t\t\t\tinit: function () {},\n\t\t\t\t\tbindEvent: function () {},\n\t\t\t\t\tupdatePosition: function () {}\n\t\t\t\t\t …\n\t\t\t\t};\n\t\t类名（构造器）\n\t\t\t-->小驼峰式但首字母大写\n\t\t\t-->如：Current、DefaultConfig\n\t\t函数名\n\t\t\t-->小驼峰式\n\t\t\t-->如：current()、defaultConfig()\n\t\t变量名\n\t\t\t-->小驼峰式\n\t\t\t-->如：current、defaultConfig\n\t\t私有变量名\n\t\t\t-->小驼峰式但需要用_开头\n\t\t\t-->如：_current、_defaultConfig\n\t\t变量名的前缀\n\t\t\t-->续\n> -   代码格式。\n>\n\t\t\"()\"前后需要跟空格\n\t\t\"=\"前后需要跟空格\n\t\t\",\"后面需要跟空格\n\t\tJSON对象需格式化对象参数\n\t\tif、while、for、do语句的执行体用\"{}\"括起来\n>     \"{}\"格式如下。\n>\n\t\tif (a==1) {\n\t\t\t//代码\n\t\t};\n>     避免额外的逗号。\n>\n\t\tvar arr = [1,2,3,];\n>     `for-in`循环体中必须用`hasOwnProperty`方法检查成员是否为自身成员，避免来自原型链上的污染。\n> -   长语句可考虑断行。\n>\n\t\tTEMPL_SONGLIST.replace('{TABLE}', da['results'])\n\t\t\t.replace('{PREV_NUM}', prev)\n\t\t\t.replace('{NEXT_NUM}', next)\n\t\t\t.replace('{CURRENT_NUM}', current)\n\t\t\t.replace('{TOTAL_NUM}', da.page_total);\n>     为了避免和`JSLint`的检验机制冲突，“.”或“+”这类操作符放在行尾。\n>\n\t\tTEMPL_SONGLIST.replace('{TABLE}', da['results']).\n\t\t\treplace('{PREV_NUM}', prev).\n\t\t\treplace('{NEXT_NUM}', next).\n\t\t\treplace('{CURRENT_NUM}', current).\n\t\t\treplace('{TOTAL_NUM}', da.page_total);\n>     如果模块代码中，使用其它全局变量想跳过JSLint的检查，可以在该文件中加入`/*global*/`声明。\n>\n\t\t/*global alert: true, console: true, top: true, setTimeout: true */\n> -   使用严格的条件判断符。用===代替==，用!==代替!=，避免掉入==造成的陷阱\n>     在条件判断时，这样的一些值表示false。\n>\n\t\tnull\n\t\tundefined与null相等\n\t\t字符串''\n\t\t数字0\n\t\tNaN\n>     在==时，则会有一些让人难以理解的陷阱。\n>\n\t\t(function () {\n\t\t\tvar undefined;\n\t\t\tundefined == null; // true\n\t\t\t1 == true; //true\n\t\t\t2 == true; // false\n\t\t\t0 == false; // true\n\t\t\t0 == ''; // true\n\t\t\tNaN == NaN;// false\n\t\t\t[] == false; // true\n\t\t\t[] == ![]; // true\n\t\t})();\n>\n>     对于不同类型的 == 判断，有这样一些规则，顺序自上而下：\n>\n\t\tundefined与null相等\n\t\t一个是number一个是string时，会尝试将string转换为number\n\t\t尝试将boolean转换为number\n\t\t0或1\n\t\t尝试将Object转换成number或string\n>\n>     而这些取决于另外一个对比量，即值的类型，所以对于0、空字符串的判断，建议使用`===`\n>     。`===`会先判断两边的值类型，类型不匹配时为`false`。\n> -   下面类型的对象不建议用new构造。\n>\n\t\tnew Number\n\t\tnew String\n\t\tnew Boolean\n\t\tnew Object //用{}代替\n\t\tnew Array //用[]代替\n>     引用对象成员用`obj.prop`代替`obj[\"prop\"]`，除非属性名是变量。\n> -   从number到string的转换。\n>\n\t\t/** 推荐写法*/\n\t\tvar a = 1;\n\t\ttypeof(a); //\"number\"\n\t\tconsole.log(a); //1\n\t\tvar aa=a+'';\n\t\ttypeof(aa); //\"string\"\n\t\tconsole.log(aa); //'1'\n\t\t/** 不推荐写法*/\n\t\tnew String(a)或a.toString()\n>\n>     从string到number的转换，使用parseInt，必须显式指定第二个参数的进制。\n>\n\t\t/** 推荐写法*/\n\t\tvar a = '1';\n\t\tvar aa = parseInt(a,10);\n\t\ttypeof(a); //\"string\"\n\t\tconsole.log(a); //'1'\n\t\ttypeof(aa); //\"number\"\n\t\tconsole.log(aa); //1\n>\n>     从float到integer的转换。\n>\n\t\t/** 推荐写法*/\n\t\tMath.floor/Math.round/Math.ceil\n\t\t/** 不推荐写法*/\n\t\tparseInt\n>\n>     字符串拼接应使用数组保存字符串片段，使用时调用join方法。避免使用+或+=的方式拼接较长的字符串，每个字符串都会使用一个小的内存片段，过多的内存片段会影响性能。\n>\n\t\t/**推荐的拼接方式array的push、join*/\n\t\tvar str=[],\n\t\t\tlist=['测试A','测试B'];\n\t\tfor (var i=0 , len=list.length; i < len; i++) {\n\t\t\tstr.push( '<div>'+ list[i] + '</div>');\n\t\t};\n\t\tconsole.log(str.join('')); //<div>测试A</div><div>测试B</div>\n\t\t/** 不推荐的拼接方式+=*/\n\t\tvar str = '',\n\t\t\tlist=['测试A','测试B'];\n\t\tfor (var i = 0, len = list.length; i< len; i++) {\n\t\t\tstr+='<div>' + list[i] + '</div>';\n\t\t};\n\t\tconsole.log(str); //<div>测试A</div><div>测试B</div>\n> -   尽量避免使用存在兼容性及消耗资源的方法或属性。\n>\n\t\t不要使用with，void，evil，eval_r，innerText\n> -   注重`HTML`分离, 减小`reflow`, 注重性能。\n\n### 图片规范：\n-------------------\n> -   命名应用`小写英文`、`数字`、`_`组合，便于团队其他成员理解。\n>\n\t\theader_btn.gif\n\t\theader_btn2.gif\n> -   页面元素类图片均放入`img`文件夹,测试用图片放于`img/testimg`文件夹，psd源图放入`img/psdimg`文件夹。\n> -   图片格式仅限于`gif`、`png`、`jpg`等。\n> -   用`png`图片做图片时,\n>     要求图片格式为`png-8`格式,若`png-8`实在影响图片质量或其中有半透明效果,请为`ie-6`单独定义背景，并尽量避免使用半透明的png图片。\n> -   背景图片请尽可能使用`sprite`技术, 减小`http`请求。\n>\n\n### 注释规范：\n-------------------\n> -   `JAVASCRIPT`、`CSS`文件注释需要标明作者、文件版本、创建/修改时间、重大版本修改记录、函数描述、文件版本、创建或者修改时间、功能、作者等信息。\n>\n\t\t/* * 注释块 */\n>     中间可添加如下信息。\n>\n\t\t @file 文件名\n\t\t@addon 把一个函数标记为另一个函数的扩张，另一个函数的定义不在源文件中\n\t\t@argument 用大括号中的自变量类型描述一个自变量\n\t\t@author 函数/类作者的姓名\n\t\t@base 如果类是继承得来，定义提供的类名称\n\t\t@class 用来给一个类提供描述，不能用于构造器的文档中\n\t\t@constructor 描述一个类的构造器\n\t\t@deprecated 表示函数/类已被忽略\n\t\t@exception 描述函数/类产生的一个错误\n\t\t@exec @extends 表示派生出当前类的另一个类\n\t\t@fileoverview 表示文档块将用于描述当前文件，这个标签应该放在其它任何标签之前\n\t\t@final 指出函数/类\n\t\t@ignore 让jsdoc忽视随后的代码\n\t\t@link 类似于@link标签，用于连接许多其它页面\n\t\t@member 定义随后的函数为提供的类名称的一个成员\n\t\t@param 用大括号中的参数类型描述一个参数\n\t\t@private 表示函数/类为私有，不应包含在生成的文档中\n\t\t@requires 表示需要另一个函数/类\n\t\t@return 描述一个函数的返回值\n\t\t@see 连接到另一个函数/类\n\t\t@throws 描述函数/类可能产生的错误\n\t\t@type 指定函数/成员的返回类型\n\t\t@version 函数/类的版本号\n\n### 开发及测试工具约定：\n-------------------\n> -   编码格式化，三码统一。\n> -   测试工具: 前期开发仅测试FireFox & IE6 & IE7 & IE8 & IE9 & Opera &\n>     Chrome & Safari\n\n### 参考和借鉴了大家的经验，收集整理了这一篇开发规范，感谢所有的原作者，众人拾柴火焰高，技术无国界，持续更新中。\n\n\n"
  },
  {
    "path": "26-front-end-learning-path/README.MD",
    "content": "# 前端学习路径\n\n## 什么是前端工程师？\n\n![](https://pic3.zhimg.com/e63ca0895a3c783f0792148dadd82a46_b.png)\n\n> 总而言之前端工程师就是运用HTML/CSS/JavaScript等Web技术，在工作中配合设计师实现用户界面，和后端工程师进行数据对接，完成Web应用开发的职位。\n\n- [阅读更多有关前端工程师](https://www.h5jun.com/post/to-be-a-good-frontend-engineer)\n\n**作者：** 余博伦 https://github.com/discountry\n\n链接：https://zhuanlan.zhihu.com/p/21935921\n\n来源：知乎 著作权归作者所有\n\n## 开发工具\n### 设计软件\n\n> 前端工程师最首要的任务就是把设计师的设计图切好并翻译成代码，所以我们要学习一些设计软件的基础操作和切图方法。\n\n- Photoshop 运用最广泛的设计软件，大部分人都在用它，很有必要学习一下[**前端工程师必备的PS技能——切图篇**](https://www.imooc.com/learn/506)\n\n- Sketch 轻量且功能强大，切图迅速高效，为UI设计而生的Mac App[**Sketch切图教程**](https://www.sketchs.cn/tutorials/detail/257.html)\n\n### 编辑器\n> 工欲善其事，必先利其器。可以用的编辑器和IDE有很多，在这里我只推荐最棒的两个。\n\n[**Sublime text**](https://www.sublimetext.com/) 最性感的编辑器，搭配插件各种好用[**配置和使用方法**](https://www.zybuluo.com/king/note/47271)\n\n[**Webstorm**](https://www.jetbrains.com/webstorm/) 功能强大，学生可以免费用的前端开发IDE\n\n### 代码管理\n> 不光要学会写代码，也要学会管理你的代码。在工作中你可能会遇到需要自己部署代码的情况；不停地修改迭代重构，当然也需要你掌握版本控制软件。\n\n- Linux 你需要学会在命令行打开移动复制文件等最基本的操作[**Linux最常用的20条命令**](https://blog.csdn.net/ljianhui/article/details/11100625)\n[**鸟哥的linux私房菜——基础篇**](https://wizardforcel.gitbooks.io/vbird-linux-basic-4e/content/)\n\n- Git 写代码一定会用到的版本控制软件，入门很快就能学会[**猴子都能懂的Git入门**](https://backlogtool.com/git-guide/cn/)\n\n### 测试工具\n> 预览和调试必不可少，编写前端代码的大部分时间都是在编辑器和浏览器之间切来切去。\n\n- [**Chrome Dev Tools**](https://wiki.jikexueyuan.com/project/chrome-devtools/overview.html) 谷歌浏览器开发工具，想要预览调试你的前端页面必须在这里啦\n\n## 基础知识\n### HTML\n* [**MDN的HTML入门**](https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/Introduction)\n\n- [**HTML30分钟快速入门**](http://deerchao.net/tutorials/html/html.htm)\n\n### CSS\n- [**MDN的CSS入门教程**](https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Getting_started)\n\n- [**学习CSS布局**](https://zh.learnlayout.com/)\n\n### JavaScript\n- [**JavaScript菜鸟教程**](https://www.runoob.com/js/js-tutorial.html)\n\n- [**慕课网JavaScript入门篇**](https://www.imooc.com/view/36)\n\n### Web\n- [**当你在浏览器中输入google.com并按下回车后发生了什么**](https://github.com/skyline75489/what-happens-when-zh_CN)\n\n- [**互联网协议入门**](https://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html)\n\n## 中级知识\n### HTML5\n- [**MDN的HTML5入门教程**](https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/HTML5/Introduction_to_HTML5)\n\n- [**网易云课堂HTML5入门**](https://study.163.com/course/introduction/171001.htm%23/courseDetail)\n\n### CSS3\n- [**CSS3菜鸟教程**](https://www.runoob.com/css3/css3-tutorial.html)\n\n- [**Gitbook的CSS3教程**](https://www.gitbook.com/book/waylau/css3-tutorial/)\n\n### Style Guide\n- [**腾讯alloteam前端代码规范**](https://alloyteam.github.io/CodeGuide/)\n\n- [**百度ecomfe前端代码规范**](https://github.com/ecomfe/spec)\n\n- [**Google HTML/CSS Style Guide**](https://google.github.io/styleguide/htmlcssguide.xml)\n\n- [**Google JavaScript Style Guide**](https://google.github.io/styleguide/javascriptguide.xml)\n\n### Responsive Design\n- [**响应式设计指南**](https://geekplux.com/grid/)\n\n- [**自适应网页设计——阮一峰**](https://www.ruanyifeng.com/blog/2012/05/responsive_web_design.html)\n\n- [**什么是响应式web设计？怎样进行？**](https://beforweb.com/node/6)\n\n### Web Animation\n- [**CSS动画**](https://www.ruanyifeng.com/blog/2014/02/css_transition_and_animation.html)\n\n- [**Canvas动画教程**](https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial)\n\n- [**Learn to Create Animations in JavaScript**](https://www.kirupa.com/javascript_animations/index.htm)\n\n- [**Bootstrap**](https://www.bootcss.com/)[**Bootstrap菜鸟教程**](https://www.runoob.com/bootstrap/bootstrap-tutorial.html)\n\n- [**慕课网玩转Bootstrap**](https://www.imooc.com/view/141)\n\n- jQuery[**jQuery菜鸟教程**](https://www.runoob.com/jquery/jquery-tutorial.html)\n\n- [**慕课网jQuery基础**](https://www.imooc.com/course/list%3Fc%3Djquery%26is_easy%3D1)\n\n### Ajax\n- [**jQuery Ajax快速入门**](https://blog.qiubio.com%3A8080/archives/1467)\n\n- [**jQuery Ajax全解析**](https://www.cnblogs.com/qleelulu/archive/2008/04/21/1163021.html)\n\n## 高级知识\n- [**w3c标准**](https://www.w3.org/standards/)\n\n- [**Web Platform Docs**](https://docs.webplatform.org/wiki/Main_Page)\n\n### ECMA6\n- [**阮一峰ECMAScript6入门**](https://es6.ruanyifeng.com/)\n\n### 测试\n- [**FEX前端自动化测试探索**](https://fex.baidu.com/blog/2015/07/front-end-test/)\n\n- [**测试框架Mocha实例教程**](https://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html)\n\n- [**Karma和Jasmine自动化单元测试**](https://blog.fens.me/nodejs-karma-jasmine/)\n\n### 自动化构建\n- [**流式自动化构建工具Gulp**](https://www.gulpjs.com.cn/)\n\n- [**前端工程构建工具fis**](https://fex-team.github.io/fis3/)\n\n- [**Web项目脚手架生成工具Yeoman**](https://yeoman.io/)[**用Yeoman和AngularJS做Web应用**](https://blog.jobbole.com/65399/)\n\n### 模块/包管理\n\n- [**npm**](https://www.npmjs.com/)\n\n  - [**npm使用介绍**](https://www.runoob.com/nodejs/nodejs-npm.html)\n\n  - [**快速搭建 Node.js 开发环境以及加速 npm**](https://cnodejs.org/topic/5338c5db7cbade005b023c98)\n\n- [**Sea.js**](https://seajs.org/docs/)\n  - [**5分钟上手Sea.js**](https://seajs.org/docs/%23quick-start)\n\n- [**RequireJS**](https://www.requirejs.cn/)\n\n- [**ES6模块**](https://www.infoq.com/cn/articles/es6-in-depth-modules)\n\n### 预处理器\n- [**Haml**](https://haml.info/)\n\n  -[**Tutorial**](https://haml.info/tutorial.html)\n\n  - [**HTML代码简写法：Emmet和Haml**](https://www.ruanyifeng.com/blog/2013/06/emmet_and_haml.html)\n\n- [**Sass**](https://www.sasschina.com/)\n\n  - [**Sass入门**](https://www.w3cplus.com/sassguide/)\n\n- [**TypeScript**](https://www.typescriptlang.org/)\n\n  - [**TypeScript Handbook（中文版）**](https://www.gitbook.com/book/zhongsp/typescript-handbook/details)\n\n### [**框架**](https://github.com/showcases/front-end-javascript-frameworks)\n\n- [**React**](https://reactjs.cn/)\n\n  - [**入门实例教程**](https://www.ruanyifeng.com/blog/2015/03/react.html)\n\n- [**Vue**](https://vuejs.org.cn/)\n\n  - [**vue.js教程**](https://wiki.jikexueyuan.com/project/vue-js/)\n\n- [**Angular**](https://www.runoob.com/angularjs/angularjs-tutorial.html)\n\n## 服务器端\n- [**Nodejs**](https://nodejs.org/zh-cn/)\n\n  - [**Node入门**](https://www.nodebeginner.org/index-zh-cn.html)\n\n  - [**7天学会NodeJS**](https://nqdeng.github.io/7-days-nodejs/)\n\n- [**MongoDB**](https://www.mongodb.com/)\n  - [**NodeJS与MongoDB交互**](https://www.cnblogs.com/zhongweiv/p/node_mongodb.html)\n\n## 技能图谱\n[**StuQ技能图谱**](https://skill-map.stuq.org/)\n\n[**Frontend Knowledge Structure**](https://html5ify.com/fks/)\n\n## 在线资源\n[**大前端导航**](https://www.daqianduan.com/nav)\n\n[**Frontend Stuff**](https://github.com/moklick/frontend-stuff)\n\n[**Frontend directory**](https://frontend.directory/)\n\n[**Frontend Interview Questions**](https://github.com/h5bp/Front-end-Developer-Interview-Questions)\n\n## 在线教程\n[**菜鸟教程**](https://www.runoob.com/)\n\n[**极客学院Wiki**](https://wiki.jikexueyuan.com/)\n\n[**Mozilla开发者网络**](https://developer.mozilla.org/zh-CN/docs/Learn)\n\n[**front-end-web-development on Treehouse**](https://teamtreehouse.com/tracks/front-end-web-development)\n\n[**Learn to Code Advanced HTML/CSS**](https://learn.shayhowe.com/advanced-html-css/)\n\n## 在线书籍\n[**Front-end Developer HandBook**](https://www.gitbook.com/book/dwqs/frontenddevhandbook/)\n\n[**Front-end Database**](https://leohxj.gitbooks.io/front-end-database/)\n\n[**Frontend Notebook**](https://li-xinyang.gitbooks.io/frontend-notebook/)\n\n## 推荐书目\n\n### 基础\n[**深入浅出HTML与CSS、XHTML**](https://book.douban.com/subject/1799652/)\n\n[**HTML & CSS设计与构建网站**](https://book.douban.com/subject/21338365/)\n\n[**Pro Git中文版**](https://iissnan.com/progit/)\n\n[**鸟哥的linux私房菜**](https://book.douban.com/subject/4889838/)\n\n\n### 中级\n\n[**Head First HTML5 Programming**](https://book.douban.com/subject/19894872/)\n\n[**JavaScript权威指南**](https://book.douban.com/subject/10546125/)\n\n[**JavaScript语言精粹**](https://book.douban.com/subject/3590768/)\n\n\n[**JavaScript & jQuery交互式Web前端开发**](https://www.amazon.cn/JavaScript-jQuery%25E4%25BA%25A4%25E4%25BA%2592%25E5%25BC%258FWeb%25E5%2589%258D%25E7%25AB%25AF%25E5%25BC%2580%25E5%258F%2591-%25E8%25BE%25BE%25E5%2585%258B%25E7%2589%25B9/dp/B010L41T5O/)\n\n[**深入浅出Ajax**](https://book.douban.com/subject/3136781/)\n\n### 高级\n[**JavaScript高级程序设计**](https://book.douban.com/subject/10546125/)\n\n[**HTML5高级程序设计**](https://book.douban.com/subject/5402708/)\n\n[**CSS权威指南**](https://book.douban.com/subject/2308234/)\n\n[**深入浅出Node.js**](https://book.douban.com/subject/25768396/)\n"
  },
  {
    "path": "27-front-end-style-guide/README.md",
    "content": "# 前端开发规范手册\n\n##### Github： [仓库地址](https://github.com/Aaaaaashu/Front-End-Style-Guide)\n##### 知笔墨：[手册地址](http://zhibimo.com/read/Ashu/front-end-style-guide/)\n\n此手册主要实现的目标：**代码一致性**和**最佳实践**。通过代码风格的一致性，降低维护代码的成本以及改善多人协作的效率。同时遵守最佳实践，确保页面性能得到最佳优化和高效的代码。\n\n此手册是在开发中积累下来的经验和参考其它规范/指南制定的，它只是起指导作用，除个别条目强制之外，大多数为非强制约束，开发者可根据自己的实际情况自行决定是否要遵守\n该指南只是保证大方向一致性和最佳实践的阶段性总结，不是最后结论，它会随着时间而变化。\n\n## 目录\n* [Introduction](http://zhibimo.com/read/Ashu/front-end-style-guide/)\n* [基本原则](http://zhibimo.com/read/Ashu/front-end-style-guide/basic/index.html)\n* HTML\n   * [通用约定](http://zhibimo.com/read/Ashu/front-end-style-guide/html/general.html)\n   * [语义化](http://zhibimo.com/read/Ashu/front-end-style-guide/html/semantic.html)\n   * [HEAD](http://zhibimo.com/read/Ashu/front-end-style-guide/html/head.html)\n* CSS\n   * [通用约定](http://zhibimo.com/read/Ashu/front-end-style-guide/css/general.html)\n   * [字体排印](http://zhibimo.com/read/Ashu/front-end-style-guide/css/typography.html)\n   * [模块组织](http://zhibimo.com/read/Ashu/front-end-style-guide/css/structure.html)\n   * [Less 规范](http://zhibimo.com/read/Ashu/front-end-style-guide/css/less.html)\n   * [性能优化](http://zhibimo.com/read/Ashu/front-end-style-guide/css/performance.html)\n* JavaScript\n   * [通用约定](http://zhibimo.com/read/Ashu/front-end-style-guide/javascript/general.html)\n   * [jQuery 规范](http://zhibimo.com/read/Ashu/front-end-style-guide/javascript/jquery.html)\n   * [性能优化](http://zhibimo.com/read/Ashu/front-end-style-guide/javascript/performance.html)\n* [移动端优化](http://zhibimo.com/read/Ashu/front-end-style-guide/mobile-optimize/index.html)\n* [工具箱](http://zhibimo.com/read/Ashu/front-end-style-guide/tool/index.html)\n* [参考](http://zhibimo.com/read/Ashu/front-end-style-guide/reference/index.html)\n\n![](https://raw.githubusercontent.com/Aaaaaashu/Front-End-Style-Guide/master/img/husky.png)\n"
  },
  {
    "path": "28-fetool-master/README.md",
    "content": "# 大前端工具集 [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)\n\n这个项目的定位是 **大前端程序猿的百宝箱**。主要针对 前端方向和 Node 方向；主要内容是国内外优秀的库、工具、套路、设计/交互或关注的前端组织/博客等等，反正用 **瑞士军刀** 来总结这篇文章再合适不过了。\n\n对于列在这里的几乎所有项目，我都有去实践与了解，所以我会尽量给出中肯的建议和理解，也希望大家能多关注我的评语:)\n\n> 感谢和期待大家的 PR，我会及时回复的~\n\n---\n\n<h2 id=\"catalog\">目录</h2>\n\n- [前端组织/前端博客](#blogs)\n- [博客搭建](#blog_build)\n- [HTML](#html)\n- [CSS](#css)\n- [浏览端 JS](#javascript)\n- [Project Build](#project_build)\n- [Node Package](#node_package)\n- [Node Project](#node_project)\n- [精选阅读](#read)\n  - [前端技术](#fedev)\n  - [Node 学习资料](#node_read)\n  - [前端面试](#interview)\n  - [其他技术](#otherdev)\n- [工具/软件](#tools)\n  - [Web](#web)\n  - [APP](#app)\n  - [Mac 软件篇](#mac_soft)\n  - [Linux](#linux)\n- [Chrome Plugins](#BrowserPlugins)\n- [Git](#git)\n- [服务端](#servers)\n- [数据端](#backend)\n- [客户端](#client)\n- [设计/交互](#ux)\n- [速查手册](#handbook)\n- [杂七杂八](#other)\n- [前端炫技-炫酷狂拽叼炸天的 Web](#cool)\n- [小结](#summary)\n- [TODO](#todo)\n\n## 正文\n\n<h3 id=\"blogs\">前端组织/前端博客</h3>\n\n> 虽混过外企俩家，但劳资英文这项的技能点还是灰色的...so，俺关注的站点主要以中文为主\n\n- [GitHub](https://github.com) - 没 ```Github``` 都不好意思面基有木有！！！\n- [MDN](https://developer.mozilla.org/zh-CN/) - 无数的资源再等着你探索，追标准和新特性肯定得关注的网站\n- [Awesomes.cn](https://www.awesomes.cn/) - 国人维护的前端资源库，深度对接到 ```Github```，分类和展现清晰，值得收藏\n- [如何跟上前端开发的最新前沿](https://uptodate.frontendrescue.org/zh/) - RT，不解释\n- [慕课](http://www.imooc.com/) - 大量的在线计算机课程。 虽然初、中级居多，但是不乏有巨作值得细细品尝\n- [阮一峰](http://javascript.ruanyifeng.com/) - 关注多年，拜读其 [ES6](http://es6.ruanyifeng.com/) 系列。虽网传靠写书进鸟阿里，但博客内容确实够丰富\n- [W3Cplus](http://www.w3cplus.com/) - 大漠(《图解 CSS3》作者)在国内的影响力杠杠的，```Sass``` 专家级\n- [淘宝前端团队](http://taobaofed.org/) - 内容涵盖 ```Web``` 和 ```Node```，要深度游深度，要广度有广度\n- [奇舞团博客](http://www.75team.com/) - 坚持是最宝贵的，别人的奇舞周刊早已经过百期了\n- [大搜车前端](http://f2e.souche.com/blog/) - 前端网红 [小芋头君](http://weibo.com/676588498) 所在的团队，文章质量高，尤其是 Node 方向的\n- [百度 FEX](http://fex.baidu.com/) - 代表作 ```FIS```、```UEditor```、```WebUploader```、```KityMinder```\n- [腾讯全端 AlloyTeam](http://www.alloyteam.com/) - 腾讯 Web 前端团队，博客真的有点丑...\n- [粉丝日志 for 张丹](http://blog.fens.me/) - 大爱作者写的 ```Node``` 系列\n- [张鑫旭](http://www.zhangxinxu.com/wordpress/) - 成名多年的、高产的前端大湿，```CSS```猛人\n\n\n<h3 id=\"blog_build\">博客搭建</h3>\n\n- [Hexo](https://hexo.io/zh-cn/) - 快速、简洁且高效的博客框架，照着文档分分钟就可以在本地跑起来。```Github``` 地址:[Hexo](https://github.com/hexojs/hexo)\n- [Jekyll](http://jekyll.bootcss.com/) - 将纯文本转化为静态网站和博客。由于环境依赖的问题，所以安装起来可能稍费劲那么一点。```Github``` 地址：[Jekyll](https://github.com/jekyll/jekyll)\n- [GithubPages](https://pages.github.com/) - 免费的静态站点。配合着 ```Hexo``` 或 ```Jekyll``` 的模板，分分搭建出一套炫酷的个人博客\n- [Tumblr](https://www.tumblr.com/) - 轻博客的祖师爷，各种各样的主题感觉不错\n- [Wordpress](https://zh-cn.wordpress.com/) - 这玩意古老到都不想介绍\n\n> 使用 ```Hexo/Jekyll + GitPage```，前端搭建静态博客那是相当 easy。用 ```Markdown``` 写文章做记录，再 ```push``` 到 ```Github``` 上，分分钟高大上有木有\n\n再推荐三款视觉效果极佳的 ```Hexo``` 主题，且在 ```Github``` 上的 ```star``` 都很不错：\n- [NexT](https://github.com/iissnan/hexo-theme-next)\n- [Yilia](https://github.com/litten/hexo-theme-yilia)\n- [Tranquilpeak](https://github.com/LouisBarranqueiro/hexo-theme-tranquilpeak)\n\n不能偏心，所以也推荐三款 ```Jekyll``` 的好主题：\n- [So Simple](https://github.com/mmistakes/so-simple-theme) 如果你看过俺的博客，对这个主题就肯定不会陌生啦\n- [HPSTR](https://github.com/mmistakes/hpstr-jekyll-theme) 当初 [fefork](http://www.fefork.com/) 差点选这个主题:)\n- [beautiful](https://github.com/daattali/beautiful-jekyll#readme)\n\n<h3 id=\"html\">HTML</h3>\n\n纯 ```HTML``` 相关其实没有好玩的项目，所以这儿展示的内容主要都是一些模板，而且以下列出来的都是免费的，方便拿取搭架后台或者博客\n\n- [HEAD](https://github.com/joshbuchea/HEAD) - 最全的 ```<head>``` 列表，真心佩服这种偏执的整理能力\n- [blur-admin](https://github.com/akveo/blur-admin) - 视觉冲击极强的管理后台，各种动画效果。PS：因为团队有[ant-design](https://github.com/ant-design/ant-design)的使用经验，感觉使用起来不是很顺畅，这套后台又是基于```AngularJS```，所以再三权限之后还是没实际使用，劳资还是别给团队添乱了，囧...\n- [AdminLTE](https://github.com/almasaeed2010/AdminLTE) - 很小清新的后台模板，每次看[preview](https://almsaeedstudio.com/preview) 页面都觉得很有视觉冲击\n- [gentelella](https://github.com/puikinsh/gentelella) - 刚用这个搭建了我司内部用的的数据平台，效果喜人。模板实现的功能比较全，比如登录、注册甚至各种 ```widget```，所以最终交付的时候，自己几乎没写几行CSS。\n- [material-design-lite](https://github.com/google/material-design-lite) - ```Star``` 数超过2W的开源模板项目，包含了多套简洁的 ```templates```，可以用于博客、后台或者企业首页。\n\n\n<h3 id=\"css\">CSS</h3>\n\n- [MetroUI](http://metroui.org.ua/) - 好看好用，重点是样式特别、个性\n- [Font-Awesome](http://fontawesome.io/) - 图标字体库。相类似的库有不少，大厂都喜欢造轮子嘛:)\n- [LoadersCSS](https://connoratherton.com/loaders) - 用 CSS 技术实现 loading 动画； 补一句，想熟悉、理解 ```keyframes、animation、transform、transition``` 的童鞋可以直接去读其源码(只有千把行代码)，读完就算出师鸟:)\n- [WeUI](https://github.com/weui/weui) - 一套同微信原生视觉体验一致的基础样式库 为微信 Web 开发量身设计，令用户的使用感知更加统一\n- [PostCSS](https://github.com/postcss/postcss) - 最近才知道大名鼎鼎[Autoprefixer](https://github.com/postcss/autoprefixer)是其插件 推荐大漠的文章[《PostCSS深入学习》](http://www.w3cplus.com/PostCSS/postcss-deep-dive-what-you-need-to-know.html)，有关 PostCSS 不是什么？PostCSS 是什么？PostCSS 可以做什么等等问题，文章里面有答案\n- [CSSgram](https://github.com/una/CSSgram) - 图片滤镜库，终于可以用 CSS 在 web 上实现滤镜的效果鸟 IE不支持，不过新的移动设备支持没问题 [Can I Use](http://caniuse.com/#search=CSS%20Blend%20Modes)\n- [HINT.css](https://github.com/chinchang/hint.css) - 一款非常小巧的提示框效果\n- [Balloon.css](http://kazzkiq.github.io/balloon.css/) - 同上，一款非常小巧的提示框效果\n- [Hover.css](http://ianlunn.github.io/Hover/) - 很多鼠标 Hover 态的效果，可以给产品学习一下:)\n- [Cursor](http://css-cursor.techstream.org/) - 记录各浏览器对Cursor的支持情况\n- [csscss](https://github.com/zmoazeni/csscss) - 用于检查 CSS 代码冗余\n- [purecss](http://purecss.io/) - 小巧的响应式 CSS 库，Yahoo!出品\n- [hamburgers](https://jonsuh.com/hamburgers/) - 简单的动画库，让 Click(or Tap) 变得美妙\n- [cssmatic](http://www.cssmatic.com) - 一个帮忙调试CSS效果的工具\n\n\n<h3 id=\"javascript\">浏览端 JS</h3>\n\n- [requirejs](https://github.com/requirejs/requirejs) - JS模块化是构建复杂项目的第一步 中文学习文档奉上：[RequireJS 中文网](http://www.requirejs.cn/)\n- [three.js](https://github.com/mrdoob/three.js) - JavaScript 3D 库。超多的 [examples](http://threejs.org/examples/) 等着你去发现，你只需要关注内存和风扇就行了\n- [ECharts](http://echarts.baidu.com/index.html) - 好用，最关键的是支持的图表展示非常之多，强烈推荐\n- [Swiper](http://www.swiper.com.cn) - 强大的 Slider 库 其实这类效果库非常多，但文档能那么专业的就很少鸟\n- [babel](https://babeljs.io/) - ```ES6``` 用起来。这个插件可以让我们用新的 **标准/提案** 写 ```JavaScript``` 代码，然后再向下 **转换编译**，最终生成随处可用的 ```JavaScript``` 代码。中文文档奉上[《babel-handbook》](https://github.com/thejameskyle/babel-handbook/blob/master/translations/zh-Hans/README.md)\n- [fullPage](http://alvarotrigo.com/fullPage/) - 非常好用的全屏滑动库，看 Demo 就明白\n- [PhotoSwipe](http://photoswipe.com/) - 偶常用的 js 库 官网上有这么一句很关键、重要\"no dependencies\"\n- [Vuejs](http://cn.vuejs.org) - 比较喜欢其作者... 所以劳资正在看源码学习学习\n- [mixitup](https://github.com/patrickkunka/mixitup) 一款基于 ```jQuery``` 的 **排序/过滤** 的JS库，最关键是有着美妙的动画效果\n- [favico.js](http://lab.ejci.net/favico.js/) - 动态改变浏览器标签栏中的网站图标，非常好玩\n- [ant.design](http://ant.design) - 蚂蚁金服搞的良心项目，文档美好的令人发指 样式优雅，强烈推荐内部系统尝试此库\n- [highlightjs](https://highlightjs.org/) - 代码高亮库，支持非常多的语言\n- [daterangepicker](http://www.daterangepicker.com) - 时间选择插件的不二选择，基于 ```Bootstrap``` 和 [Moment.js](http://momentjs.com/)\n- [nodePPT](https://github.com/ksky521/nodePPT) - 前同事三水的大作，好用必须得支持:) 用 Markdown 写 PPT，还可以 HTML 混排，上手飞快\n- [excellentexport](https://github.com/jmaister/excellentexport) - 纯前端的 Excel 导出，非常之方便\n- [Sortable](https://github.com/RubaXa/Sortable) - 拖拽神器，用了就知道\n- [toastr](https://github.com/CodeSeven/toastr) - 信息提示的库，推荐的原因是卖相好、功能强大  [demo](http://codeseven.github.io/toastr/demo.html)\n- [peity.js](http://benpickles.github.io/peity/) - jQuery的图表插件，特别cute，感觉萌萌哒 将HTML转换成一个小的```<svg>```饼图、圆环图、折线图等等\n- [emojify.js](https://github.com/Ranks/emojify.js) - 能够将```emoji```关键词转换为```emoji```图片的```JS```插件 可以快速的为你的网站提供```emoji```表情支持\n- [Push.js](https://github.com/Nickersoft/push.js) - 基于 ```Notification API``` 实现的桌面效果的提示栏。浏览器支持情况不错，如[http://caniuse.com/#search=Notification](http://caniuse.com/#search=Notification)\n- [Highcharts](http://www.hcharts.cn/) - Highcharts 中文网，又是一个图表库 确实功能强大，但是觉得不好看... PS：官网就做的不好看，脏脏的赶脚\n- [NProgress](https://github.com/rstacruz/nprogress/) - 使页面加载时有更好的loading效果\n- [Noticejs](https://github.com/jaredreich/notie.js) - 一个简单的通知库，木有依赖\n- [onepage-scroll](https://github.com/peachananr/onepage-scroll) - 依赖 jQuery 的单页滚动库，和 [fullPage](http://alvarotrigo.com/fullPage/) 类似\n- [videojs](http://videojs.com/) - 当下视频需求都用上```<video>```鸟 样式和交互统一的问题交给 videojs 搞定:)\n- [clipboard](http://zenorocha.github.io/clipboard.js/) - 仅 2KB 大小，搞定剪贴板功能，屌不屌~ 但是，Safari 不支持...\n- [impress.js](https://github.com/impress/impress.js) -  用来写 PPT 不错，偶也曾为其写过一篇[impress.js 初体验](http://www.cnblogs.com/Darren_code/archive/2013/01/04/impressjs.html)\n- [Cropper](http://fengyuanchen.github.io/cropper/) - 国人开发的图片裁剪库\n\n> ___```Swiper/PhotoSwipe/fullPage``` 有这仨库，微信里常见的 H5 页完全不是问题哒___\n\n\n<h3 id=\"project_build\">Project Build</h3>\n\n- [pm2](https://www.npmjs.com/package/pm2) - 是一个带有负载均衡功能的 Node 应用的进程管理器； 是 [Forever](https://www.npmjs.com/package/forever) 的进阶库，想了解的可以看这篇文章[《拥抱PM2》](http://se77en.cc/2013/06/27/goodbye-node-forever-hello-pm2-translation/)\n- [Webpack](http://webpack.github.io/) - 项目构建工具，由于过于复杂和太强大，所以劳资还没去深入研究。推荐篇教程：[webpack 教程资源收集](https://github.com/naraku666/webpack-tutorial-collection)\n- [Gulp](https://github.com/gulpjs/gulp/) - Gulp 是基于 Node 实现 Web 前端自动化开发的工具。 俺总结了篇[《gulp使用小结》](http://www.fefork.com/gulp_1/)，推荐您阅读:)\n- [Bower](http://bower.io/) - 前端项目的包管理其实是件复杂的事 谁谁谁依赖谁谁谁，谁谁谁依赖谁谁谁的某个版本...卧槽 Bower 就是搞定这件事儿的，亲爹是 Twitter 推荐篇 Bower 的中文文章：[《bower 解决 js 的依赖管理》](http://blog.fens.me/nodejs-bower-intro/)\n- [Grunt](http://gruntjs.com/) - 和 Gulp 类似，都是项目构建的常见选择 对比这俩的文章可谓不少，推荐篇[《Gulp vs Grunt》](http://www.benben.cc/blog/?p=407) 英盲又想看文档，可以去[Grunt 中文网](http://www.gruntjs.net/)\n- [FIS](http://fex-team.github.io/fis3/) - 度厂出品的前端构建工具 文档清晰，功能强大，推荐了解和使用\n- [Gitlab CI](https://ci.gitlab.org/) - 一套基于[Gitlab](https://about.gitlab.com/)的持续集成服务\n- [Travis CI](https://travis-ci.org/) - 为 Github 上的项目打造的 CI 服务。记得 2013年 开始陆续看到文章介绍，刚在官网上看到，目前已经有 30W 开源项目和 23.5W 用户在使用。大概看了一下 [getting started](https://travis-ci.org/getting_started)，简单几步就可以实现开源项目的持续集成。\n\n> Gulp + Webpack 的使用__套路__参考: [learning-gulp](https://github.com/demohi/learning-gulp)\n\n> Gulp 资料收集：[use-gulp](https://github.com/Platform-CUF/use-gulp)\n\n> 推荐篇与 Webpack 相关的文章《[CSS Modules](http://boke.io/tan-tan-css-modules/)》\n\n> Webpack 用起来吼吼：[webpack-howto](https://github.com/petehunt/webpack-howto)\n\n\n<h3 id=\"node_package\">Node Package</h3>\n\n> 作为一名大前端甚至是多端，```Node``` 绝逼是必备的一块\n\n> 有关 ```Node``` 的学习资料，请访问 [Node 学习资料](https://github.com/nieweidong/fetool#node_read)\n\n##### 这里介绍些有特色且前端有必要知道的包\n\n- [anywhere](https://www.npmjs.com/package/anywhere) - 随时随地将你的当前目录变成一个静态文件服务器的根目录\n- [supervisor](https://www.npmjs.com/package/supervisor) - 监控 Node 代码，自动重启。 A supervisor program for running nodejs programs\n- [nodemon](https://github.com/remy/nodemon) - 监控 Node 代码，自动重启。 Nodemon is a utility that will monitor for any changes in your source and automatically restart your server.\n- [pm2](https://www.npmjs.com/package/pm2) - 是一个带有负载均衡功能的 Node 应用的进程管理器； 是 [Forever](https://www.npmjs.com/package/forever) 的进阶库，想了解的可以看这篇文章[《拥抱PM2》](http://se77en.cc/2013/06/27/goodbye-node-forever-hello-pm2-translation/)\n- [async](https://www.npmjs.com/package/async) - 一个流程控制工具包，提供直接而强大的异步功能\n- [optimist](https://www.npmjs.com/package/optimist) - 当需要处理 ```CLI``` 中的 ```argv``` 时(即命令行传参)，用它就行了\n- [lodash](https://www.npmjs.com/package/lodash) - JS 工具库 ```Underscore.js```的一个 fork 发展而来\n- [socket.io](https://github.com/socketio/socket.io) - 预计 Node 的实时框架 聊天室、页游等对实时性有高要求的较适用\n- [Inquirer.js](https://github.com/SBoudrias/Inquirer.js) - 实现的效果比 [Commander](https://github.com/tj/commander.js) 简单、有趣，贴个 GIF供大家参考：[loc](https://raw.githubusercontent.com/nieweidong/local-info/master/img/loc.gif)\n- [Commander](https://github.com/tj/commander.js) - 用 Commander.js 可以方便的创建基于 Node 的命令行工具，比如 [vue-cli](https://github.com/vuejs/vue-cli) 这类，瞬间觉得自己又高大上了呢~\n- [Mongoose](https://github.com/Automattic/mongoose) - 让 NodeJS 更容易操作 Mongodb 数据库；  附上一篇[Mongoose 学习参考文档](https://cnodejs.org/topic/504b4924e2b84515770103dd)\n- [CNPM](http://npm.taobao.org/) - 淘宝 NPM 镜像，提供了 NPM 同步的服务 当然可不仅仅这样，利用 CNPM 可以打造__企业/个人__私有的 NPM 服务 推荐篇搭建私有NPM的文章：[《CNPM搭建私有的NPM服务》](http://blog.fens.me/nodejs-cnpm-npm/)\n- [koa](http://koajs.com/) - 玩 Node 都知道 express，但使用 koa 的就少很多，门槛比 Ex 稍高 通过 generator 避免繁琐的回调函数嵌套，强烈推崇 [官方的文章教程](https://github.com/guo-yu/koa-guide)\n- [Shipit](https://github.com/shipitjs/shipit) - 一个强大的自动化部署工具。 shipit 很多地方非常类似 gulp，他们的核心都是任务系统。\n- [node-inspector](https://www.npmjs.com/package/node-inspector) - Node 调试工具，使用起来跟 Chrome 的 JS 调试器很相似\n- [winston](https://www.npmjs.com/package/winston) - Node 服务最流行的日志库之一\n- [co](https://www.npmjs.com/package/co) - 用 generator 写法让异步代码同步\n- [thenify-all](https://www.npmjs.com/package/thenify-all) - 把异步的方法变成 Promise 的 Promisifies all the selected functions in an object\n- [PhantomJS](http://phantomjs.org/) - 一般用来做抓取截图和无界面测试 也可以用来操作 DOM 和网络监测，很好玩的库 [Quick Start](http://phantomjs.org/quick-start.html)\n- [ava](https://www.npmjs.com/package/ava) - 偶是应TJ大神推荐而得之的 ```ava``` 未来的测试运行器\n- [Mocha](https://github.com/mochajs/mocha) - Node 里最常用的测试框架； 它支持多种 Node 的 Assert libs； 同时支持异步和同步的测试，同时支持多种方式导出结果； 也支持直接在 browser 上跑 JS 代码测试。\n- [koa-validate](https://www.npmjs.com/package/koa-validate) - ```koa``` 的校验库 可以非常方便的对 ```queryString``` 或 ```postBody``` 的信息进行验证\n- [line-reader](https://www.npmjs.com/package/line-reader) - 基于```steam```的按行读文件，偶处理日志时用哒 要不实现一个按行读文件，又得 ```steam```、 又得 ```chunk```，还是比较麻烦的\n- [binary](https://github.com/substack/node-binary) 作者是大神 [substack](https://github.com/substack)，对应的处理 ```PHP/Python``` 中的 ```unpack``` 方法。英文解释：Unpack multibyte binary values from buffers and streams.\n- [everyauth](https://www.npmjs.com/package/everyauth) - OAuth 的集成解决方案\n- [shelljs](http://documentup.com/shelljs/shelljs) - 写 Node 时难免需要用 shell 去操作些神马 shelljs 是基于 Node 的 shell 工具，API 及其简单\n- [hashids](https://www.npmjs.com/package/hashids) - 看名称就懂，给 userid 加解密用的\n- [node-pool](https://github.com/coopernurse/node-pool) - 让 ```Node``` 有连接池的概念\n- [colors](https://www.npmjs.com/package/colors) - 花俏的小工具 让打印```console.log```时有更好的展示样式\n- [n](https://www.npmjs.com/package/n) - 控制Node的版本，想升级一行代码搞定\n\n> ```supervisor``` 和 ```nodemon``` 这俩都是监控 Node 代码，使得每次修改代码后会，开发 Node 程序必备\n\n> 以上库俺都有使用过，甚至有不少都是项目开发中、各种特定场景下必用的，有任何使用问题欢迎沟通哈:)\n\n\n<h3 id=\"node_project\">Node Project</h3>\n\n_暂无_\n\n\n<h2 id=\"read\">精选阅读</h2>\n\n<h3 id=\"fedev\">前端技术</h3>\n\n- [2015D2前端论坛](http://www.imooc.com/learn/590) - Node方向非常值得看，有干货，相信东哥推荐哈\n- [前端开发规范手册](http://zhibimo.com/read/Ashu/front-end-style-guide/index.html) -  此手册主要实现的目标：代码一致性和最佳实践\n- [《babel-handbook》](https://github.com/thejameskyle/babel-handbook/blob/master/translations/zh-Hans/README.md) - 可以用新的规范(如 ```ES6```)写代码，经过 ```babel``` 编译后生成没有兼容问题的代码\n- [JavaScript Standard Style](http://standardjs.com/) - 强烈推荐，尤其适合技术 Leader。优秀的 JS 编码规范是好前端团队的开始\n- [ECMAScript 6入门](http://es6.ruanyifeng.com/) - 阮一峰大神所著，一本开源的JS教程 全面介绍 ECMAScript 6新引入的语法特性\n- [ReactNative 中文版](http://wiki.jikexueyuan.com/project/react-native/) - 翻译自官方的中文文档\n- [ReactWebpackCookBook](https://fakefish.github.io/react-webpack-cookbook/index.html) - 此书会引导读者是进入```React```和```Webpack```的世界。 俩都是非常前沿的技术，同时使用会更有趣。\n- [ReactNative 学习指南](https://github.com/ele828/react-native-guide) - 新玩意层出不穷... 对于能持续学习的童鞋，这是个美好的时代\n- [HTML/CSS 编码规范](http://www.css88.com/doc/codeguide/) - 编写灵活、稳定、高质量的```HTML```和```CSS```代码的规范\n- [移动前端入门](http://gold.xitu.io/entry/56c29abfa34131005b8cb1f3) - 入门价值高，移动方向常见问题的较好总结\n- [GulpBook](https://github.com/nimojs/gulp-book) - Gulp 是基于 Node 实现 Web 前端自动化开发的工具\n\n\n<h3 id=\"node_read\">Node 学习资料</h3>\n\n- [Node.js 中文资料导航](https://github.com/youyudehexie/node123) - Node 的中文资料导航，```start1300+```\n- [从零开始 NodeJS 系列文章](http://blog.fens.me/series-nodejs/) - 基本上每一篇都看过，强烈推荐\n- [Node.js 包教不包会](http://nqdeng.github.io/7-days-nodejs/) - 值得阅读，看完绝不用买书鸟\n- [七天学会 NodeJS](https://github.com/alsotang/node-lessons) - 劳资还没看，不过看目录还不错:)\n- [Style Guide](https://github.com/dead-horse/node-style-guide) - 这是一份关于如何写出一致且美观的 ```Node``` 代码的风格指南\n- [koa实战](http://book.apebook.org/minghe/koa-action/index.html) - “[明河](https://github.com/minghe)出品”这四字已经说明一切。PS：正在连载中\n- [stream-handbook](https://github.com/jabez128/stream-handbook) - 如果学习 NodeJS，那么流一定是需要掌握的概念\n\n\n<h3 id=\"interview\">前端面试</h3>\n\n- [笔试面试知识整理](https://github.com/HIT-Alibaba/interview) - 打开其 Gitbook 上的地址我都惊呆了。虽然有部分内容待完善，但是光浏览目录都是享受。\n- [在 LinkedIn 做面试官的故事](http://dongfei.baijia.baidu.com/article/52449) - 非面试题，介绍 LinkedIn 的面试过程 文章有很多中肯的建议和想法，推荐阅读\n- [大漠：写给前端面试者](http://www.w3cplus.com/css/write-to-front-end-developer-interview.html) - 这篇文章不涉及任何的面试题 大漠与大家聊聊面试者与被面者之间的感受...\n- [前端面试题](https://github.com/h5bp/Front-end-Developer-Interview-Questions/tree/master/Translations/Chinese) - Git 上非常火的前端面试题，```start17k+```\n- [前端面经](https://github.com/paddingme/Front-end-Web-Development-Interview-Question) - 主要内容是些前端面试笔试题和面试套路，值得阅读\n\n\n<h3 id=\"otherdev\">其他技术</h3>\n\n- [命令行的艺术](https://github.com/jlevy/the-art-of-command-line/blob/master/README-zh.md) - 熟练使用命令行是优秀工程师的基础\n- [MongoDB 极简实践入门](https://github.com/StevenSLXie/Tutorials-for-Web-Developers/blob/master/MongoDB%20%E6%9E%81%E7%AE%80%E5%AE%9E%E8%B7%B5%E5%85%A5%E9%97%A8.md) - 入门推荐的套路，非常浅显易懂\n- [Mac 设置指南](https://github.com/macdao/ocds-guide-to-setting-up-mac) - Mac 使用必看 尤其适合 偏执狂/强迫症 患者:)\n- [Markdown 资料](https://github.com/xirong/my-markdown) - 简单看些语法入门，快速用起来\n\n\n<h2 id=\"tools\">工具/软件</h2>\n\n<h3 id=\"web\">Web</h3>\n\n- [百度脑图](http://naotu.baidu.com) - 非常方便的思维导图工具。功能强、样式佳、无广告，算百度出的良心产品之一。除了 Evernote，脑图是我非常依赖的记录工具\n- [CanIuse](http://caniuse.com/) - __前端必备__；查看浏览器对各种新特性的兼容情况\n- [overapi](http://overapi.com/) - 最全的开发人员在线速查手册\n- [ProcessOn](https://www.processon.com/) - 和百度脑图的功能类似，脑图工具。但是还有社交、通讯的功能，提倡 **协作绘图** 的理念。感觉网页跳转的时候有点慢，模板样式比百度脑图好看(个人观点)，而且团队协作的功能真的相当好用。\n- [Slides](https://slides.com/) - 一个所见即所得的 WebPPT 编辑器。虽然装X效果一般，但是比较推荐，因为无论懂不懂 UI，做出来的效果不会太难看\n- [faviconer.co](http://www.faviconer.co/) - 一个所见即所得的icon生成器，很好用\n- [smallpdf](http://smallpdf.com/cn) - 提供各种格式和 PDF 互相转换\n- [Cmd Markdown](https://www.zybuluo.com/mdeditor) - 好用的 Web 版 Markdown 编辑器\n- [VimAwesome](http://vimawesome.com/) - Vim 插件集合，__Vim 党必备__\n- [Tower](https://tower.im) - 小而美的多人协同工具。 不光只有 Web 版，还有 iPhone、iPad、Android、微信版。\n- [StackEdit](https://stackedit.io/editor) - 又是一款 Web 版 Markdown 编辑器\n- [墨刀](https://modao.cc/) - 一个在线移动应用原型制作工具。 旨在帮助产品经理快速制作可在手机端展示的移动应用原型。\n- [htm2pdf](http://www.htm2pdf.co.uk) - HTML to PDF\n- [Speaker Deck](https://speakerdeck.com/p/featured) - 在线的演讲稿展示平台\n- [RunJS](http://runjs.cn/) - 在线编辑、展示、分享、交流你的 ```JavaScript``` 代码\n- [Bootswatch](https://bootswatch.com/) - ```Bootstrap``` 的免费模板\n- [AdminLTE](https://github.com/almasaeed2010/AdminLTE/) -  又是一个 ```Bootstrap``` 的免费管理后台\n\n\n<h3 id=\"app\">APP</h3>\n\n> 以下列表中的 APP 都是不区分系统平台的\n\n- [印象笔记](https://www.yinxiang.com/) - 免费账号完全够用，跨平台跨终端的记录软件\n- [365日历](http://www.365rili.com/) - 首先肯定比系统自带的日历强大，要不推荐个蛋蛋 俺一般用来搞目标管理，比如学习计划和工作计划 生活中会订阅演唱会、电影首映的信息\n- [多看阅读](http://www.duokan.com/) - kindle 确实好，但是懒得随身带着 多看还算不错，书较多且偶尔有特价比较爽\n- [Surge](https://itunes.apple.com/cn/app/surge-web-developer-tool-proxy/id1040100637?mt=8&v0=WWW-GCCN-ITSTOP100-PAIDAPPS&l=&ign-mpt=uo%3D4) - 非免费 牛逼的网络开发与调试工具，前端必备\n- [Monkey](https://github.com/coderyi/Monkey) - Monkey 是 iPhone 上一个 GitHub 第三方客户端。 展示 GitHub 上的开发者的排名，以及仓库的排名\n\n\n<h3 id=\"mac_soft\">Mac 软件篇</h3>\n\n> 对于美好事务的追求无论何时都不算晚。\n\nMac 下的软件那么多，又是免费又是付费，应该怎么选呢？我来分享下我的推荐列表，推荐的优先级老规矩，从上往下依次降低。\n\n- [Alfred](https://www.alfredapp.com/) - **免费**，绝对的推荐Top1，很提效率，高级版 ```Powerpack``` 售价 ```£17```。除了能快速搜索和打开应用程序之外，查找文本文件、全文检索、调起浏览器搜索和计数器都是俺经常使用的功能。如果想知道具体咋用，推荐阅读老池(池建强)的文章：[《神兵利器—Alfred》](http://www.cnblogs.com/chijianqiang/p/alfred.html)\n- [iTerm2](http://www.iterm2.com/) - **免费**。```Mac``` 终端功能少又不好看，```iTerm2``` 可以解救你~  推荐篇文章：[《让你的命令行丰富多彩》](http://swiftcafe.io/2015/07/25/iterm/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io)\n- [HyperDock](https://bahoom.com/hyperdock/) - 售价 ```￥68```，感觉还是很值的(特么我还想说，```Windows``` 数年前就自带的功能，在 ```Mac``` 上还收费，略忧伤)。预览和快速切换窗口太有必要了，能用快捷键控制窗口，能让拖拽到边缘的窗口自动调整大小(window早就有的功能)，真心能提高效率。推荐篇中文的文章：[让Mac的窗口飞](http://www.cnblogs.com/ider/p/let-mac-window-fly-with-hyperdock.html)\n- [ATOM](https://atom.io) - **免费**。2015/7 之前，在桌面环境下偶最喜欢的编辑器是 ```Sublime```，但之后就是 ```ATOM```，俺也专门为它写了篇___[使用纪要](https://github.com/nieweidong/learn-atom)___\n- [Surge](https://itunes.apple.com/us/app/surge-web-developer-tool-proxy/id1040100637) - ```$99.99```。关注 ```IOS``` 开发或者常备梯子的同学，肯定都知道这大名鼎鼎的软件。价钱从 ```￥68``` 涨到 ```$99``` 也让偶咋舌，背后的故事就不细说了，感兴趣可自行去谷歌百度一下。PS：翻墙软件 [小飞机ShadowsocksX](https://shadowsocks.com/) 也非常棒，同样推荐：“轻量级科学上网姿势，改变您的生活体验！”\n- [1Password](https://1password.com/) - **免费** 试用一个月，售价不便宜 ```$64.99```。如果觉得对各种账号的密码管理心累，那么推荐你使用，这个钱肯定值，```Mac``` 和 ```iPhone``` 通用，爽歪歪。如果账号密码都是那种一、俩个套路，而且被盗也随意，那么用不用就无所谓啦\n- [Sequel Pro](http://www.sequelpro.com) - **免费**。好用的Mysql工具\n- [Manico](http://manico.im/) - **免费** 版已经很好用了，全功能版售价 ```￥25```。快捷启动和切换 ```APP``` 的工具，高效的第一步\n- [Moom](http://manytricks.com/moom/) - 售价 **$10**，有试用版。个人觉得这钱花的值，设置快捷键之后可以方便的调整每个窗口的位置。我不管在家还是公司都是开双屏，外接屏幕三分之一 ```iTerm```，三分之二 ```ATOM```，日常使用时各种全屏、居中、靠左、靠右等用快捷键来回着换，辛福感满满的。\n- [CheatSheet](https://www.mediaatelier.com/CheatSheet/) - **免费**。能够显示当前程序的快捷键列表，默认的快捷键是长按 ⌘\n- [马克鳗](http://www.getmarkman.com/) - **免费** 版已经够用啦，收费版是 ```60/年```。英文名 ```MarkMan```，非常强大好用的标注、测量工具，__强烈推荐__\n- [BrowseShot](https://itunes.apple.com/cn/app/browseshot/id615916400) - **免费**。偶正在使用的网页截图工具，强烈推荐\n- [Wireshark](https://www.wireshark.org/) - **免费**。说实话，```Mac``` 下木有 ```Fiddler``` 挺不习惯，不过在有更强大的替代品，虽然有点复杂...还好后来下载到便宜(```￥68```)的 ```Surge``` 做替代品\n- [LICEcap](http://www.cockos.com/licecap/) - **免费**。屏幕录制工具，支持导出 GIF 动画图片格式 轻量级、使用简单，录制过程中可以改变录屏范围\n- [Bartender 2](https://www.macbartender.com/) - 售价 ```$20.97```，但是可 **免费** 试用四周。Mac右上角菜单的管理工具，试用之后右上角的菜单瞬间清爽了，反正试用下也不花钱:)\n- [BeyondCompare](http://www.scootersoftware.com) - **免费**。在Windows下就开始用了 比对文件和文件夹杠杠好使，Merge必备工具\n- [SourceTree](https://www.sourcetreeapp.com/) - **免费**。属于大名鼎鼎的 ```Atlassian```，一款好用的的 ```Git``` 客户端工具，重点是 **支持中文**，哈哈:)\n- [focus booster](https://www.focusboosterapp.com/) - **免费** 已经够用，当然还有更高级的 ```INDIVIDUAL/PROFESSIONAL```，售价分别是 ```$3/$5```。因为比较在意时间管理，所以当工作压力较大时，这软件是俺的必备之物\n- [WebTorrent](https://webtorrent.io/) - **免费**。直接播放种子，你懂得。年轻的斯坦福大神 [Feross](http://feross.org/) 开发，Git上的开源项目哦。\n- [WebStorm](http://www.jetbrains.com/webstorm/) - **$129**，可试用一个月。功能超强的前端 ```IDE```，谁用谁知道 PS：貌似俺插件装多了，用着卡卡的，风扇呼呼转...然后俺就卸载装了，装了 ```ATOM```...\n- [MindNode](http://mindnode.com/) - 售价 **$29.99**，有免费试用版。这是款漂亮的思维导图工具。其实 [百度脑图](http://naotu.baidu.com/) 这类 Web 上的工具绝对够用了，不太推荐...\n- [Mou](http://25.io/mou/) - 我曾使用过的 Markdown 编辑器，不推荐使用。原本已经准备去掉，但是偶还是想让大家了解下这个有意思的事情：[《一年了，那个闻名遐迩的 Mou 你还记得吗？》](http://matrix.sspai.com/p/c7a3c9c0)\n\n以上列出来的都是偶觉得比较有意思、有特点的软件。当然，类似 ```Docker```、```Polarr(泼辣修图)``` 等这类都太小众；```有道翻译 ```、```Evernote```、```Foxmail``` 等这类又太大众；然后有些软件买了觉得有点“亏”，比如刚出手买入的 ```Final Cut Pro```，其实机器自带的 ```iMovie``` 就挺好了（完美诠释《Final从入手到放弃》）。所以，这几类就不一一往这列举啦~\n\n\n<h3 id=\"linux\">Linux</h3>\n\n> 作为一名程序员兼工具控，我期待自己无比高效\n\n首先，都是免费哒；然后，所列项目都是针对 ```CLI(命令行界面)``` 哒；最后，探索无止境\n\n- [oh-my-zsh](http://ohmyz.sh/) - ___终端党___ 必备，好处太多太多，比如炫酷的外观，超强的易用性...推荐大家阅读知乎的问题：[《为什么说 zsh 是 shell 中的极品？》](https://www.zhihu.com/question/21418449)\n- [spf13-vim](https://github.com/spf13/spf13-vim) - 对于 Vim 偶之前做了好多文档和记录，但是自从了解有这个套路，那些记录都可以丢掉了。不过建议想了解的去看看 .vimrc 中的 Plugin，确实足够大而全。PS：如果遇见 ```neocomplete does not work``` 之类的错误，可以参考 [Problems with Vim and lua?](http://stackoverflow.com/questions/26724859/problems-with-vim-and-lua)\n- [Vundle](https://github.com/VundleVim/Vundle.vim) - Vim 党必备。用于管理各种 Vim 插件，有 Git 就可以安装 ```$ git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle```\n- [tree](http://mama.indstate.edu/users/ice/tree/) - linux 以树状图逐级列出目录的内容，装逼效果和实用功能都不错\n- [cloc](http://cloc.sourceforge.net/) - 可用来计算 文件夹中各种语言的代码占比情况。展示内容非常直观，如某目录下 ```JavaScript``` 有多少个文件，共多少空格行数、注释行数、代码行数，就这些简单粗暴的内容。常见的安装方式可通过 ```npm``` 来进行安装。\n- [oneapm](http://www.oneapm.com/) - 强大的运维工具，提供多种监控客户端； 有采集、分析、展示等一套功能； PS：我这用了服务器监控(免费哦)\n- [httpie](https://github.com/jkbrzt/httpie) - 一个 CLI 中的 HTTP 客户端，用法简单，非常适合用来搞调试、测试\n- [ESLint](http://eslint.org/) - 前端大神[Nicholas C. Zakas](http://nczonline.net/)创建。JavaScript 辅助编码的规范工具，有效控制偶们的代码质量\n- [Lucario](https://github.com/raphamorim/lucario) 暗色系主题，支持 Vim, Atom, Sublime Text, TextMate, Terminal.app, iTerm, Xcode and XTerm\n- [cmatrix](http://www.asty.org/cmatrix/) - 作用就是装逼，可以在屏幕上显示经典的黑客帝国的数码雨效果(看官方文档上也有其他效果，俺就不往细研究了)。在 Mac 下安装非常简单，一步搞定：`$ brew install cmatrix`\n\n**Mac**\n- [Homebrew](http://brew.sh/) - 有了他 ```OS X``` 程序猿能更好的专注代码层面。最近在看《七周七语言》，里面出现各种语言环境，用 ```brew``` 来安装、管理各种解释器和编译器，省心省力！\n- [Xcode](https://developer.apple.com/xcode/) - 因为玩 ```Swift``` 所以早早就下载了，后来才知道原来 ```Mac``` 下如果不安装 ```Xcode```，部分常用的指令都不支持，囧\n\n<h3 id=\"BrowserPlugins\">Chrome 浏览器插件</h3>\n\n> ```Chrome``` 应用商店必定是需要翻墙的哈。\n\n以下插件都是俺多年积累淘出来的，数量不多，所以就不区分 ```Github``` 插件和非 ```Github``` 插件了。按照俺推荐的强度自上向下展示，且大多数插件就是偶工作和生活必备，希望能对大家有用。后续如有新发现好插件，偶也会及时更新哒。\n\n- [Postman](https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop) - ```POST``` 接口调试终结者，异常强大的接口调试工具。稍稍有一点学习成本，推荐之\n- [JSONView](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc) - 就是个 ```JSON``` 格式的查看工具，可以很方便的展示数据，麻麻再也不用担心偶调试接口啦。PS：同类插件有不少，所以用的开心就行\n- [二维码生成器](https://chrome.google.com/webstore/detail/%E4%BA%8C%E7%BB%B4%E7%A0%81qr%E7%A0%81%E7%94%9F%E6%88%90%E5%99%A8/pflgjjogbmmcmfhfcnlohagkablhbpmg) - RT。PS：这FF早已经自带生成二维码工具了，```Chrome``` 还得装插件才行，任性...\n- [WEB前端助手(FeHelper)](https://chrome.google.com/webstore/detail/web%E5%89%8D%E7%AB%AF%E5%8A%A9%E6%89%8Bfehelper/pkgccpejnmalmdinmhkkfafefagiiiad) - [百度FE](https://www.baidufe.com/)出品，功能超全的 Chrome 插件。简单列一下其功能：QR码生成器、字符串编解码工具、JSON格式化查看器、前端编码规范检测、代码压缩工具、页面取色工具、统计并分析网页加载性能等等\n- [Eye Dropper](https://chrome.google.com/webstore/detail/eye-dropper/hmdcmlfkchdmnmnmheododdhjedfccka) - 前端必备的颜色提取神器，操作简单容易上手\n- [Vimium](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb) 和 ```Vim``` 快捷键一样，浏览网站时不需要鼠标咯\n- [Page Ruler](https://chrome.google.com/webstore/detail/page-ruler/jlpkojjdgbllmedoapgfodplfhcbnbpn) - 前端必备的尺子。计算页面元素间距、位置等信息的时候，你就知道它的好了，无脑上手，你值得拥有\n- [FireShot](https://chrome.google.com/webstore/detail/capture-webpage-screensho/mcbpblocgmgfnpjjppndjkmgjaogfceg) - 可以截取整个网页、部分页面，然后支持导出为各种格式。俺微博上发的网页全景图都是靠这个插件截取的\n- [Infinity](https://chrome.google.com/webstore/detail/infinity-new-tab/dbfmnekepjoapopniengjbcpnbljalfg) - 好不好用有点见仁见智了，但是我个人比较喜欢。使用后会让你的 **新标签页** 耳目一新，有漂亮的背景和各种常用的功能，比如地图、天气、```Gmail```、```Chrome```商店等等。当然，在这个插件的设置中还可以设置壁纸、动画效果等等\n- [Momentum](https://chrome.google.com/webstore/detail/momentum/laookkfknpbbblfpciffpaejjkokdgca) - 同样也是 **新标签页** 的插件，但是不管是视觉上(高清大图)还是功能上，都比 [Infinity](https://chrome.google.com/webstore/detail/infinity-new-tab/dbfmnekepjoapopniengjbcpnbljalfg) 高大上不少，```Setting``` 里面有不少设置和快捷键，都很好上手的。[Infinity](https://chrome.google.com/webstore/detail/infinity-new-tab/dbfmnekepjoapopniengjbcpnbljalfg)胜在中文和直观，[Momentum](https://chrome.google.com/webstore/detail/momentum/laookkfknpbbblfpciffpaejjkokdgca)胜在视觉冲击。俺基本上这俩款看心情换着用，所以希望你也都能喜欢:)\n- [Google翻译](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb) - 英文不好又得经常浏览英文资料的，一般都准备好了翻译工具。不过能在浏览器里达到划词翻译的方案就不多了，偶推荐这个Google翻译(PS：如不能翻墙，有道词典的扩展也同样支持划词翻译)。\n- [Octotree](https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc) - 在浏览器左侧展示 ```Github``` 项目的文件导航，使目录结构一目了然，而且我们国内 ```Github``` 的访问速度又不稳定，用这个工具也就很提效率了。对经常使用 ```Github``` 的同学强烈推荐\n- [BuiltWith](https://chrome.google.com/webstore/detail/builtwith-technology-prof/dapjbgnjinbpoindlpdmhochffioedbn) / [wappalyzer](https://chrome.google.com/webstore/detail/wappalyzer/gppongmhjkpfnbhagpmjfkannfbllamg) / [Chrome Sniffer Plus](https://chrome.google.com/webstore/detail/chrome-sniffer-plus/fhhdlnnepfjhlhilgmeepgkhjmhhhjkh) - 几款超强的网站分析工具，可以给出网站非常多的技术栈信息。大到 ```Web Servers```、服务端的 ```Frameworks``` 或 ```JS``` 框架，小到 ```meta```、编码格式甚至 ```Analytics```，非常推荐\n- [Adblock Plus](https://chrome.google.com/webstore/detail/adblock-plus/cfhdojbkjhnklbpkdaibdccddilifddb/related) - 非常非常有名的免费的过滤广告的插件。PS：广告屏蔽这个见仁见智，其实俺个人还是比较接受一些个性化推荐的广告\n- [Wide Github](https://chrome.google.com/webstore/detail/wide-github/kaalofacklcidaampbokdplbklpeldpj/related) - 无聊又实用的 ```Github``` 插件。无聊是因为这个插件就特么一个功能，**加宽**，能让 ```Github``` 页面变宽，每行展示更多的内容，尤其配合着[Octotree](https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc)，展示效果极佳。非常推荐 ```Mac``` 用户实用，因为屏幕比较不大，变宽后阅读感觉更好\n- [Gmail](https://chrome.google.com/webstore/detail/google-mail-checker/mihcahmgecmbnbcchbopgniflfhgnkff) - 方便查看自己的 ```Gmail``` 邮件\n- [Imagus](https://chrome.google.com/webstore/detail/imagus/immpkjjlgappgfkkfieppnmlhakdmaab) 鼠标指针悬停在链接或缩略图上时直接在当前页面的弹出视图上显示这些图片、HTML5 视频/音频和内容专辑...看新浪微博时贼有用:)\n- [DevTools Author](https://chrome.google.com/webstore/detail/devtools-author/egfhcfdfnajldliefpdoaojgahefjhhi) - 纯装逼的插件，可以选择你的 ```Chrome``` 开发者工具的主题，且支持的主题超过25种，视觉装逼控必备。设置分大概三步，官网有文字说明，```youtube``` 上的视频教程奉上(Customization With DevTools Author)[https://www.youtube.com/watch?v=AUZagMLMAJc]\n- [GitPlug](https://chrome.google.com/webstore/detail/porter-plug/lngoojfoglemfpbeiomhgheccpdheilp) - 在 ```Github``` 项目页中嵌入有关的图表信息，直观的展示当前项目的 ```Star Trend```，能方便看到当前这个开源项目的发起时间，火爆趋势；对比较知名的项目还有相关的 ```News``` 展示\n- [OctoLinker](https://chrome.google.com/webstore/detail/octolinker/jlmafbaeoofdegohdhinkhilhclaklkp) - 在 ```package.json``` 或任意 ```.js``` 文件中，可以方便的对 ```require()``` 的 ```package``` 进去点击，跳转去对应的 ```Github``` 页面。PS：特么不太好表达，建议你去这个插件的概述页，里面有个十来秒的视频，看完就明白鸟\n\n补充：\n\n1. 翻墙代理的插件偶没使用，偶手机和电脑的翻墙都是配的 ```Surge``` 无脑搞定，不过翻墙代理插件推荐[Proxy SwitchySharp](https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm)，熊掌公司里大多用的都是它\n2. 日常开发相关的插件就以上这些，还有几款如知乎的插件、购物插件等这类与开发效率不沾边的，俺就不这上头列了哈\n\n\n<h3 id=\"git\">Git</h3>\n\n- [Git 教程-廖雪峰](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) - 俺有看过不少 Git 的文章，确实这个系列是最通俗易懂的\n- [GitAwards](http://github-awards.com/) - Git 工具，可以查看 Git 排名\n- [Git 速查](https://github.com/flyhigher139/Git-Cheat-Sheet/blob/master/Git%20Cheat%20Sheet-Zh.md) - 分类清晰的速查表\n- [Git 简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) - 入门```Github```的简明指南，木有高深内容:)\n- [Git 学习资料整理](https://github.com/xirong/my-git) - 内容包括很多 Git 的相关资料，```star 1200+```\n- [GitHub 漫游指南](https://github.com/phodal/github-roam) - 一篇还算不错的 Git 学习总结，就是乱了点... 我理解作者___漫游___的意思是漫无目的想到哪写到哪~ 看到作者为鸟达成 Git 连击的成就，也是蛮拼的:)\n\n\n<h3 id=\"servers\">服务端</h3>\n\n如 ```Ruby、Python、Perl``` 等相似的服务端语言的学习资源。\n\n_暂无_\n\n\n<h3 id=\"backend\">数据端</h3>\n\n- [Mongoose](https://github.com/Automattic/mongoose) - 让 NodeJS 更容易操作 Mongodb 数据库。  附上一篇[Mongoose 学习参考文档](https://cnodejs.org/topic/504b4924e2b84515770103dd)\n\n\n<h3 id=\"client\">客户端</h3>\n\n面对大名鼎鼎的 Electron，我懵逼了。犹豫了一会儿，不知道把其放在哪个分类中，于是我单开了一个 **客户端** 的类目。\n\n- [Electron](http://electron.atom.io/) - 如果你想利用 web 技术构建跨平台的桌面程序，那么赶紧来了解 Electron。\n\n<h3 id=\"ux\">设计/交互</h3>\n\n> 作为负责最终效果呈现的前端工程师，多少得了解些 __设计和交互__ 的，这也是为什么 fetool 会单独的存在这一章...当然话又说回来了，偶毕业的第一份工作是设计:)\n\n- [站酷](http://www.zcool.com.cn/works/) - 里面好东西太多，俺当年真没少再上面淘素材\n- [UI中国](http://www.ui.cn/list.html) - 光听名字就知道有多高大上鸟:)\n\n\n<h3 id=\"handbook\">速查手册</h3>\n\n> RT，这篇都是些文档或者API，一般这类东西都在大家浏览器的书签内，偶这也列一下大前端常用的手册地址\n\n- [JavaScript Standard Style](http://standardjs.com/) - 强烈推荐，尤其适合技术 Leader。优秀的 JS 编码规范是好前端团队的开始\n- [HEAD](https://github.com/joshbuchea/HEAD) - 最全的 ```<head>``` 列表，真心佩服这种偏执的整理能力\n- [百度CDN公共库](http://cdn.code.baidu.com/) - 基本常见的库都收录拉，搞 demo 的时候特方便\n- [HTML 和 CSS 代码规范](http://codeguide.bootcss.com/) - 编写灵活、稳定、高质量的 HTML 和 CSS 代码的规范\n- [Linux命令中文手册](http://linux.51yip.com) - 木有系统的好好学习 Linux，所以命令更不熟悉 真羡慕那些CLI玩的飞起的:)\n- [Git 速查](https://github.com/flyhigher139/Git-Cheat-Sheet/blob/master/Git%20Cheat%20Sheet-Zh.md) - 分类清晰的速查表\n- [jQueryAPI 1.11.3](http://jquery.cuishifeng.cn/) - ZeptoAPI 基本和 jQuery 一样，所以看一份就好\n- [CSS](http://www.css88.com/book/css/) - CSS 在线参考手册\n- [Redux 中文文档](http://cn.redux.js.org/index.html) - 作为个前端，React 还是得尝试下的。英文文档就不给大家推荐了~\n- [Express API](http://www.expressjs.com.cn/4x/api.html) - 中文手册:) 4.x和3.x都有\n- [CI用户指南](http://codeigniter.org.cn/user_guide/index.html) - 一个轻量级的 PHP 框架用户指南 推荐指数低的原因是劳资PHP比较弱，囧\n- [Yaf](http://www.laruence.com/manual/) - 鸟哥(惠新宸)所写的 PHP 框架 推荐指数低的原因同上...\n\n\n<h3 id=\"other\">杂七杂八</h3>\n\n> 放些开发中较有用的杂物在这儿\n\n- [提問的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way) - RT，[简体版](https://github.com/FredWe/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)。“當你拋出一個技術問題時，最終是否能得到有用的回答，往往取決於你所提問和追問的方式。本指南將教你如何正確的提問以獲得你滿意的答案。”——摘自原文\n- [租房要点](https://github.com/soulteary/tenant-point) - 适用于北上广深杭，大城市打拼__租房__确实是硬伤\n- [QQ 群规](https://github.com/jsfront/src/blob/master/qq.md) - 突然某天，有个 QQ 群让我加群 原本我是拒绝的，但当我看完这篇 QQ 群规后... 劳资真的被感动到了，太牛逼、够专业！ 最后，我默默加群鸟:)\n- [.gitignore 文件](https://github.com/github/gitignore) - 介绍不同语言项目的 gitignore 模板\n- [程序员如何优雅的挣零花钱？](https://github.com/easychen/howto-make-more-money) - 中肯的文章，如果读完能有些许收获，那么恭喜你\n- [git-draw](https://github.com/ben174/git-draw) - 黑魔法，可以修改自己 Git 上的 Contributions\n- [GitBook](https://www.gitbook.com) - 写记录的好地方\n- [Codebabes](https://codebabes.com/) - 学编程的网站。 重点是每通过一个测试，尼玛对应的妞会脱一件衣服... PS：要翻墙哦~\n- [emailframe](http://emailframe.work/) - 邮件展示确实比较坑，建议有需要的收藏\n- [ReadmeSample](https://github.com/nieweidong/ReadmeSample) - 项目高大上的第一步就是__包装__，所以来看看 ```README``` 的书写套路吧 PS：劳资怎么这么无聊...\n\n\n<h3 id=\"cool\">前端炫技-_炫酷狂拽叼炸天站点_</h3>\n\n- [three.js](https://github.com/mrdoob/three.js) - JavaScript 3D 库。超多的 [examples](http://threejs.org/examples/) 等着你去发现，你只需要关注内存和风扇就行了\n- [windows93](http://www.windows93.net/) - 模拟 Win93 桌面，思路、体验和整体效果比较有意思\n- [GeekTyper](http://geektyper.com/) - 好玩又具有 Geek 精神的网站，虽然创建的目的是个恶作剧 PS：网站需要翻墙\n- [2016.makemepulse.com](http://2016.makemepulse.com/) - 帅哭了。请使用现代浏览器打开\n- [前端技能栈](http://skill.phodal.com/) - 好玩的前端技能栈展示\n- [Mapbox](https://www.mapbox.com/) - 非常叼的开源项目，有方便的 JSAPI(还有 SDK)。 不过免费版只能浅尝，流量有限。 PS：网站需要翻墙\n- [mixitup](https://mixitup.kunkalabs.com/) 一款基于 ```jQuery``` 的 **排序/过滤** 的JS库，最关键是有着美妙的动画效果\n- [Clark Duvall](http://www.clarkduvall.com/) - 一枚歪果仁的个人 blog，范儿叼叼的\n- [earth](https://github.com/cambecc/earth) - 全球天气的可视化项目\n- [SuperScrollorama](http://johnpolacek.github.io/superscrollorama/) - 好玩好看的动画库，链接是 SuperScrollorama 的展示页\n- [parallax.js](http://matthew.wagerfield.com/parallax/) - 一个视差引擎的官网，在电脑和手机上都有很好的体验\n- [CSS字母](http://yusugomori.com/projects/css-sans/fonts) - 用 CSS 实现英文字母，叼叼的\n- [墨刀](https://modao.cc/) - 一个在线移动应用原型制作工具。 旨在帮助产品经理快速制作可在手机端展示的移动应用原型。\n\n<h3 id=\"summary\">小结</h3>\n\n##### 背景\n  俺算个比较能自我总结的码农，所以偶尔喜欢写点东西做些记录或者自我熏陶陶醉一下。\n  可写着写着发现```Evernote```里面的东西太尼玛多(乱)了，于是想着把一些技术相关的资料都整理整理，都丢到```Github```上沉淀下来。 这样Evernote就可以只需要记录些偏生活方便的，看着清爽一些...\n\n  所以，这篇记录其实只是为偶自己而写，确信以后也一直会这样~~~\n\n##### 说说目标\n  其实与这篇记录类似的文章太多鸟，俺也不愿意成为一个单纯的收集资料，分享资料的这么个东西。\n  我希望 fetool 能更生动、更个性，最好能更另类点，对于每样工具的思考和解析更多点，吐槽也必须有理有据，然后再配上劳资收集的 low 图，完美！\n  __希望通过不停的完善这篇记录，能Push劳资多了解业内的新玩具和新创意，然后围绕这些新东西，客观的再写点好东西，比如文章、资料、开源项目这些，让其他伙伴们少走弯路或学的更顺畅点儿__\n\n> 所以劳资对自己的要求是：这篇记录里列出的每样东西，自己都得的去了解、去尝试，然后再列出来。 能举一反三最好，如果达不到至少也能清楚的认识：列出来的这玩意对程序员有没有卵用，解决了啥痛点。\n\n\n<h3 id=\"todo\">TODO</h3>\n\n1. 继续完善和扩充内容\n\n2. “备注/说明”这一栏不够犀利，希望再多加入自己的理解、点评、吐槽，让这篇记录更犀利和生动\n\n3. 支持导出多种格式，如```.pdf```、```.epub```、```.mobi```等\n\n4. 后续看看如果有必要，可以单独搞个页面，优化下阅读和展示效果\n\n---\n\n以下是 [@拔赤](http://weibo.com/jayli) 总结的前端技能图：\n![拔赤总结的前端技能图](https://raw.githubusercontent.com/nieweidong/fetool/master/img/fe.jpg)\n\n---\n\n完善 ing，慢慢把 __Evernote__ 和 __浏览器书签__ 里面的好东西慢慢捣腾到这儿，更欢迎 PR，谢谢。\n\n<img src=\"https://raw.githubusercontent.com/nieweidong/fetool/master/img/me.jpg\" width=\"120\" height=\"120\" style=\"border-radius: 60px;\" />\n\n用自己青涩时的照片镇楼，哇哈哈~\n\n#### 您可以通过以下方式联系到我：\n- 微博 [@聂微东](http://weibo.com/darrencode \"Darren 聂微东\")\n- 个人 Blog [fefork.com](http://www.fefork.com/ \"一枚 Web 技术领域的手艺人\")\n- 博客园 [犀利的东哥](http://www.cnblogs.com/Darren_code/ \"关注前端技术\")\n- QQ 群 **214199415**，群名__前端 Club__。PS：入群务必请提供 __有内容的 git 或 blog 地址__，否则进不去哈:)\n\n## License\n\n[![CC0](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)](https://creativecommons.org/publicdomain/zero/1.0/)\n\n---\n\n**[⬆ 返回顶部](#catalog)**\n\n[opensource_icon]: http://nieweidong.github.com/images/open_source.svg\n[free_icon]: http://nieweidong.github.com/images/freeware.svg\n[hot_icon]: http://nieweidong.github.com/images/hot.svg\n[rec_icon]: http://nieweidong.github.com/images/rec.svg\n[must_icon]: http://nieweidong.github.com/images/must.svg\n"
  },
  {
    "path": "29-google-interview-university/LICENSE.txt",
    "content": "Attribution-ShareAlike 4.0 International\n\n=======================================================================\n\nCreative Commons Corporation (\"Creative Commons\") is not a law firm and\ndoes not provide legal services or legal advice. Distribution of\nCreative Commons public licenses does not create a lawyer-client or\nother relationship. Creative Commons makes its licenses and related\ninformation available on an \"as-is\" basis. Creative Commons gives no\nwarranties regarding its licenses, any material licensed under their\nterms and conditions, or any related information. Creative Commons\ndisclaims all liability for damages resulting from their use to the\nfullest extent possible.\n\nUsing Creative Commons Public Licenses\n\nCreative Commons public licenses provide a standard set of terms and\nconditions that creators and other rights holders may use to share\noriginal works of authorship and other material subject to copyright\nand certain other rights specified in the public license below. The\nfollowing considerations are for informational purposes only, are not\nexhaustive, and do not form part of our licenses.\n\n     Considerations for licensors: Our public licenses are\n     intended for use by those authorized to give the public\n     permission to use material in ways otherwise restricted by\n     copyright and certain other rights. Our licenses are\n     irrevocable. Licensors should read and understand the terms\n     and conditions of the license they choose before applying it.\n     Licensors should also secure all rights necessary before\n     applying our licenses so that the public can reuse the\n     material as expected. Licensors should clearly mark any\n     material not subject to the license. This includes other CC-\n     licensed material, or material used under an exception or\n     limitation to copyright. More considerations for licensors:\n\twiki.creativecommons.org/Considerations_for_licensors\n\n     Considerations for the public: By using one of our public\n     licenses, a licensor grants the public permission to use the\n     licensed material under specified terms and conditions. If\n     the licensor's permission is not necessary for any reason--for\n     example, because of any applicable exception or limitation to\n     copyright--then that use is not regulated by the license. Our\n     licenses grant only permissions under copyright and certain\n     other rights that a licensor has authority to grant. Use of\n     the licensed material may still be restricted for other\n     reasons, including because others have copyright or other\n     rights in the material. A licensor may make special requests,\n     such as asking that all changes be marked or described.\n     Although not required by our licenses, you are encouraged to\n     respect those requests where reasonable. More_considerations\n     for the public:\n\twiki.creativecommons.org/Considerations_for_licensees\n\n=======================================================================\n\nCreative Commons Attribution-ShareAlike 4.0 International Public\nLicense\n\nBy exercising the Licensed Rights (defined below), You accept and agree\nto be bound by the terms and conditions of this Creative Commons\nAttribution-ShareAlike 4.0 International Public License (\"Public\nLicense\"). To the extent this Public License may be interpreted as a\ncontract, You are granted the Licensed Rights in consideration of Your\nacceptance of these terms and conditions, and the Licensor grants You\nsuch rights in consideration of benefits the Licensor receives from\nmaking the Licensed Material available under these terms and\nconditions.\n\n\nSection 1 -- Definitions.\n\n  a. Adapted Material means material subject to Copyright and Similar\n     Rights that is derived from or based upon the Licensed Material\n     and in which the Licensed Material is translated, altered,\n     arranged, transformed, or otherwise modified in a manner requiring\n     permission under the Copyright and Similar Rights held by the\n     Licensor. For purposes of this Public License, where the Licensed\n     Material is a musical work, performance, or sound recording,\n     Adapted Material is always produced where the Licensed Material is\n     synched in timed relation with a moving image.\n\n  b. Adapter's License means the license You apply to Your Copyright\n     and Similar Rights in Your contributions to Adapted Material in\n     accordance with the terms and conditions of this Public License.\n\n  c. BY-SA Compatible License means a license listed at\n     creativecommons.org/compatiblelicenses, approved by Creative\n     Commons as essentially the equivalent of this Public License.\n\n  d. Copyright and Similar Rights means copyright and/or similar rights\n     closely related to copyright including, without limitation,\n     performance, broadcast, sound recording, and Sui Generis Database\n     Rights, without regard to how the rights are labeled or\n     categorized. For purposes of this Public License, the rights\n     specified in Section 2(b)(1)-(2) are not Copyright and Similar\n     Rights.\n\n  e. Effective Technological Measures means those measures that, in the\n     absence of proper authority, may not be circumvented under laws\n     fulfilling obligations under Article 11 of the WIPO Copyright\n     Treaty adopted on December 20, 1996, and/or similar international\n     agreements.\n\n  f. Exceptions and Limitations means fair use, fair dealing, and/or\n     any other exception or limitation to Copyright and Similar Rights\n     that applies to Your use of the Licensed Material.\n\n  g. License Elements means the license attributes listed in the name\n     of a Creative Commons Public License. The License Elements of this\n     Public License are Attribution and ShareAlike.\n\n  h. Licensed Material means the artistic or literary work, database,\n     or other material to which the Licensor applied this Public\n     License.\n\n  i. Licensed Rights means the rights granted to You subject to the\n     terms and conditions of this Public License, which are limited to\n     all Copyright and Similar Rights that apply to Your use of the\n     Licensed Material and that the Licensor has authority to license.\n\n  j. Licensor means the individual(s) or entity(ies) granting rights\n     under this Public License.\n\n  k. Share means to provide material to the public by any means or\n     process that requires permission under the Licensed Rights, such\n     as reproduction, public display, public performance, distribution,\n     dissemination, communication, or importation, and to make material\n     available to the public including in ways that members of the\n     public may access the material from a place and at a time\n     individually chosen by them.\n\n  l. Sui Generis Database Rights means rights other than copyright\n     resulting from Directive 96/9/EC of the European Parliament and of\n     the Council of 11 March 1996 on the legal protection of databases,\n     as amended and/or succeeded, as well as other essentially\n     equivalent rights anywhere in the world.\n\n  m. You means the individual or entity exercising the Licensed Rights\n     under this Public License. Your has a corresponding meaning.\n\n\nSection 2 -- Scope.\n\n  a. License grant.\n\n       1. Subject to the terms and conditions of this Public License,\n          the Licensor hereby grants You a worldwide, royalty-free,\n          non-sublicensable, non-exclusive, irrevocable license to\n          exercise the Licensed Rights in the Licensed Material to:\n\n            a. reproduce and Share the Licensed Material, in whole or\n               in part; and\n\n            b. produce, reproduce, and Share Adapted Material.\n\n       2. Exceptions and Limitations. For the avoidance of doubt, where\n          Exceptions and Limitations apply to Your use, this Public\n          License does not apply, and You do not need to comply with\n          its terms and conditions.\n\n       3. Term. The term of this Public License is specified in Section\n          6(a).\n\n       4. Media and formats; technical modifications allowed. The\n          Licensor authorizes You to exercise the Licensed Rights in\n          all media and formats whether now known or hereafter created,\n          and to make technical modifications necessary to do so. The\n          Licensor waives and/or agrees not to assert any right or\n          authority to forbid You from making technical modifications\n          necessary to exercise the Licensed Rights, including\n          technical modifications necessary to circumvent Effective\n          Technological Measures. For purposes of this Public License,\n          simply making modifications authorized by this Section 2(a)\n          (4) never produces Adapted Material.\n\n       5. Downstream recipients.\n\n            a. Offer from the Licensor -- Licensed Material. Every\n               recipient of the Licensed Material automatically\n               receives an offer from the Licensor to exercise the\n               Licensed Rights under the terms and conditions of this\n               Public License.\n\n            b. Additional offer from the Licensor -- Adapted Material.\n               Every recipient of Adapted Material from You\n               automatically receives an offer from the Licensor to\n               exercise the Licensed Rights in the Adapted Material\n               under the conditions of the Adapter's License You apply.\n\n            c. No downstream restrictions. You may not offer or impose\n               any additional or different terms or conditions on, or\n               apply any Effective Technological Measures to, the\n               Licensed Material if doing so restricts exercise of the\n               Licensed Rights by any recipient of the Licensed\n               Material.\n\n       6. No endorsement. Nothing in this Public License constitutes or\n          may be construed as permission to assert or imply that You\n          are, or that Your use of the Licensed Material is, connected\n          with, or sponsored, endorsed, or granted official status by,\n          the Licensor or others designated to receive attribution as\n          provided in Section 3(a)(1)(A)(i).\n\n  b. Other rights.\n\n       1. Moral rights, such as the right of integrity, are not\n          licensed under this Public License, nor are publicity,\n          privacy, and/or other similar personality rights; however, to\n          the extent possible, the Licensor waives and/or agrees not to\n          assert any such rights held by the Licensor to the limited\n          extent necessary to allow You to exercise the Licensed\n          Rights, but not otherwise.\n\n       2. Patent and trademark rights are not licensed under this\n          Public License.\n\n       3. To the extent possible, the Licensor waives any right to\n          collect royalties from You for the exercise of the Licensed\n          Rights, whether directly or through a collecting society\n          under any voluntary or waivable statutory or compulsory\n          licensing scheme. In all other cases the Licensor expressly\n          reserves any right to collect such royalties.\n\n\nSection 3 -- License Conditions.\n\nYour exercise of the Licensed Rights is expressly made subject to the\nfollowing conditions.\n\n  a. Attribution.\n\n       1. If You Share the Licensed Material (including in modified\n          form), You must:\n\n            a. retain the following if it is supplied by the Licensor\n               with the Licensed Material:\n\n                 i. identification of the creator(s) of the Licensed\n                    Material and any others designated to receive\n                    attribution, in any reasonable manner requested by\n                    the Licensor (including by pseudonym if\n                    designated);\n\n                ii. a copyright notice;\n\n               iii. a notice that refers to this Public License;\n\n                iv. a notice that refers to the disclaimer of\n                    warranties;\n\n                 v. a URI or hyperlink to the Licensed Material to the\n                    extent reasonably practicable;\n\n            b. indicate if You modified the Licensed Material and\n               retain an indication of any previous modifications; and\n\n            c. indicate the Licensed Material is licensed under this\n               Public License, and include the text of, or the URI or\n               hyperlink to, this Public License.\n\n       2. You may satisfy the conditions in Section 3(a)(1) in any\n          reasonable manner based on the medium, means, and context in\n          which You Share the Licensed Material. For example, it may be\n          reasonable to satisfy the conditions by providing a URI or\n          hyperlink to a resource that includes the required\n          information.\n\n       3. If requested by the Licensor, You must remove any of the\n          information required by Section 3(a)(1)(A) to the extent\n          reasonably practicable.\n\n  b. ShareAlike.\n\n     In addition to the conditions in Section 3(a), if You Share\n     Adapted Material You produce, the following conditions also apply.\n\n       1. The Adapter's License You apply must be a Creative Commons\n          license with the same License Elements, this version or\n          later, or a BY-SA Compatible License.\n\n       2. You must include the text of, or the URI or hyperlink to, the\n          Adapter's License You apply. You may satisfy this condition\n          in any reasonable manner based on the medium, means, and\n          context in which You Share Adapted Material.\n\n       3. You may not offer or impose any additional or different terms\n          or conditions on, or apply any Effective Technological\n          Measures to, Adapted Material that restrict exercise of the\n          rights granted under the Adapter's License You apply.\n\n\nSection 4 -- Sui Generis Database Rights.\n\nWhere the Licensed Rights include Sui Generis Database Rights that\napply to Your use of the Licensed Material:\n\n  a. for the avoidance of doubt, Section 2(a)(1) grants You the right\n     to extract, reuse, reproduce, and Share all or a substantial\n     portion of the contents of the database;\n\n  b. if You include all or a substantial portion of the database\n     contents in a database in which You have Sui Generis Database\n     Rights, then the database in which You have Sui Generis Database\n     Rights (but not its individual contents) is Adapted Material,\n\n     including for purposes of Section 3(b); and\n  c. You must comply with the conditions in Section 3(a) if You Share\n     all or a substantial portion of the contents of the database.\n\nFor the avoidance of doubt, this Section 4 supplements and does not\nreplace Your obligations under this Public License where the Licensed\nRights include other Copyright and Similar Rights.\n\n\nSection 5 -- Disclaimer of Warranties and Limitation of Liability.\n\n  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE\n     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS\n     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF\n     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,\n     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,\n     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR\n     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,\n     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT\n     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT\n     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.\n\n  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE\n     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,\n     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,\n     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,\n     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR\n     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN\n     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR\n     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR\n     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.\n\n  c. The disclaimer of warranties and limitation of liability provided\n     above shall be interpreted in a manner that, to the extent\n     possible, most closely approximates an absolute disclaimer and\n     waiver of all liability.\n\n\nSection 6 -- Term and Termination.\n\n  a. This Public License applies for the term of the Copyright and\n     Similar Rights licensed here. However, if You fail to comply with\n     this Public License, then Your rights under this Public License\n     terminate automatically.\n\n  b. Where Your right to use the Licensed Material has terminated under\n     Section 6(a), it reinstates:\n\n       1. automatically as of the date the violation is cured, provided\n          it is cured within 30 days of Your discovery of the\n          violation; or\n\n       2. upon express reinstatement by the Licensor.\n\n     For the avoidance of doubt, this Section 6(b) does not affect any\n     right the Licensor may have to seek remedies for Your violations\n     of this Public License.\n\n  c. For the avoidance of doubt, the Licensor may also offer the\n     Licensed Material under separate terms or conditions or stop\n     distributing the Licensed Material at any time; however, doing so\n     will not terminate this Public License.\n\n  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public\n     License.\n\n\nSection 7 -- Other Terms and Conditions.\n\n  a. The Licensor shall not be bound by any additional or different\n     terms or conditions communicated by You unless expressly agreed.\n\n  b. Any arrangements, understandings, or agreements regarding the\n     Licensed Material not stated herein are separate from and\n     independent of the terms and conditions of this Public License.\n\n\nSection 8 -- Interpretation.\n\n  a. For the avoidance of doubt, this Public License does not, and\n     shall not be interpreted to, reduce, limit, restrict, or impose\n     conditions on any use of the Licensed Material that could lawfully\n     be made without permission under this Public License.\n\n  b. To the extent possible, if any provision of this Public License is\n     deemed unenforceable, it shall be automatically reformed to the\n     minimum extent necessary to make it enforceable. If the provision\n     cannot be reformed, it shall be severed from this Public License\n     without affecting the enforceability of the remaining terms and\n     conditions.\n\n  c. No term or condition of this Public License will be waived and no\n     failure to comply consented to unless expressly agreed to by the\n     Licensor.\n\n  d. Nothing in this Public License constitutes or may be interpreted\n     as a limitation upon, or waiver of, any privileges and immunities\n     that apply to the Licensor or You, including from the legal\n     processes of any jurisdiction or authority.\n\n\n=======================================================================\n\nCreative Commons is not a party to its public\nlicenses. Notwithstanding, Creative Commons may elect to apply one of\nits public licenses to material it publishes and in those instances\nwill be considered the “Licensor.” The text of the Creative Commons\npublic licenses is dedicated to the public domain under the CC0 Public\nDomain Dedication. Except for the limited purpose of indicating that\nmaterial is shared under a Creative Commons public license or as\notherwise permitted by the Creative Commons policies published at\ncreativecommons.org/policies, Creative Commons does not authorize the\nuse of the trademark \"Creative Commons\" or any other trademark or logo\nof Creative Commons without its prior written consent including,\nwithout limitation, in connection with any unauthorized modifications\nto any of its public licenses or any other arrangements,\nunderstandings, or agreements concerning use of licensed material. For\nthe avoidance of doubt, this paragraph does not form part of the\npublic licenses.\n\nCreative Commons may be contacted at creativecommons.org."
  },
  {
    "path": "29-google-interview-university/README-en.md",
    "content": "# Google Interview University\n\nTranslations:\n\n- [中文版本](https://github.com/jwasham/google-interview-university/blob/master/README-cn.md)\n\n## What is it?\n\nThis is my multi-month study plan for going from web developer (self-taught, no CS degree) to Google software engineer.\n\n![Coding at the whiteboard - from HBO's Silicon Valley](https://dng5l3qzreal6.cloudfront.net/2016/Aug/coding_board_small-1470866369118.jpg)\n\nThis long list has been extracted and expanded from **Google's coaching notes**, so these are the things you need to know. \nThere are extra items I added at the bottom that may come up in the interview or be helpful in solving a problem. Many items are from \nSteve Yegge's \"[Get that job at Google](http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html)\" and are reflected \nsometimes word-for-word in Google's coaching notes.\n\n---\n\n## Table of Contents\n\n- [What is it?](#what-is-it)\n- [Why use it?](#why-use-it)\n- [How to use it](#how-to-use-it)\n- [Get in a Googley Mood](#get-in-a-googley-mood)\n- [Did I Get the Job?](#did-i-get-the-job)\n- [Follow Along with Me](#follow-along-with-me)\n- [Don't feel you aren't smart enough](#dont-feel-you-arent-smart-enough)\n- [About Google](#about-google)\n- [About Video Resources](#about-video-resources)\n- [Interview Process & General Interview Prep](#interview-process--general-interview-prep)\n- [Pick One Language for the Interview](#pick-one-language-for-the-interview)\n- [Before you Get Started](#before-you-get-started)\n- [What you Won't See Covered](#what-you-wont-see-covered)\n- [Prerequisite Knowledge](#prerequisite-knowledge)\n- [The Daily Plan](#the-daily-plan)\n- [Algorithmic complexity / Big-O / Asymptotic analysis](#algorithmic-complexity--big-o--asymptotic-analysis)\n- [Data Structures](#data-structures)\n    - [Arrays](#arrays)\n    - [Linked Lists](#linked-lists)\n    - [Stack](#stack)\n    - [Queue](#queue)\n    - [Hash table](#hash-table)\n- [More Knowledge](#more-knowledge)\n    - [Binary search](#binary-search)\n    - [Bitwise operations](#bitwise-operations)\n- [Trees](#trees)\n    - [Trees - Notes & Background](#trees---notes--background)\n    - [Binary search trees: BSTs](#binary-search-trees-bsts)\n    - [Heap / Priority Queue / Binary Heap](#heap--priority-queue--binary-heap)\n    - [Tries](#tries)\n    - [Balanced search trees](#balanced-search-trees)\n    - [N-ary (K-ary, M-ary) trees](#n-ary-k-ary-m-ary-trees)\n- [Sorting](#sorting)\n- [Graphs](#graphs)\n- [Even More Knowledge](#even-more-knowledge)\n    - [Recursion](#recursion)\n    - [Dynamic Programming](#dynamic-programming)\n    - [Combinatorics (n choose k) & Probability](#combinatorics-n-choose-k--probability)\n    - [NP, NP-Complete and Approximation Algorithms](#np-np-complete-and-approximation-algorithms)\n    - [Caches](#caches)\n    - [Processes and Threads](#processes-and-threads)\n    - [System Design, Scalability, Data Handling](#system-design-scalability-data-handling)\n    - [Papers](#papers)\n    - [Testing](#testing)\n    - [Scheduling](#scheduling)\n    - [Implement system routines](#implement-system-routines)\n    - [String searching & manipulations](#string-searching--manipulations)\n- [Final Review](#final-review)\n- [Coding Question Practice](#coding-question-practice)\n- [Coding exercises/challenges](#coding-exerciseschallenges)\n- [Once you're closer to the interview](#once-youre-closer-to-the-interview)\n- [Your Resume](#your-resume)\n- [Be thinking of for when the interview comes](#be-thinking-of-for-when-the-interview-comes)\n- [Have questions for the interviewer](#have-questions-for-the-interviewer)\n- [Once You've Got The Job](#once-youve-got-the-job)\n\n---------------- Everything below this point is optional ----------------\n\n- [Additional Books](#additional-books)\n- [Additional Learning](#additional-learning)\n    - [Unicode](#unicode)\n    - [Endianness](#endianness)\n    - [Emacs and vi(m)](#emacs-and-vim)\n    - [Unix command line tools](#unix-command-line-tools)\n    - [Information theory](#information-theory)\n    - [Parity & Hamming Code](#parity--hamming-code)\n    - [Entropy](#entropy)\n    - [Cryptography](#cryptography)\n    - [Compression](#compression)\n    - [Networking](#networking)\n    - [Computer Security](#computer-security)\n    - [Garbage collection](#garbage-collection)\n    - [Parallel Programming](#parallel-programming)\n    - [Design patterns](#design-patterns)\n    - [Messaging, Serialization, and Queueing Systems](#messaging-serialization-and-queueing-systems)\n    - [Fast Fourier Transform](#fast-fourier-transform)\n    - [Bloom Filter](#bloom-filter)\n    - [van Emde Boas Trees](#van-emde-boas-trees)\n    - [Augmented Data Structures](#augmented-data-structures)\n    - [Skip lists](#skip-lists)\n    - [Network Flows](#network-flows)\n    - [Disjoint Sets & Union Find](#disjoint-sets--union-find)\n    - [Math for Fast Processing](#math-for-fast-processing)\n    - [Treap](#treap)\n    - [Linear Programming](#linear-programming)\n    - [Geometry, Convex hull](#geometry-convex-hull)\n    - [Discrete math](#discrete-math)\n    - [Machine Learning](#machine-learning)\n    - [Go](#go)\n- [Additional Detail on Some Subjects](#additional-detail-on-some-subjects)\n- [Video Series](#video-series)\n- [Computer Science Courses](#computer-science-courses)\n\n---\n\n## Why use it?\n\nI'm following this plan to prepare for my Google interview. I've been building the web, building\nservices, and launching startups since 1997. I have an economics degree, not a CS degree.  I've\nbeen very successful in my career, but I want to work at Google. I want to progress into larger systems\nand get a real understanding of computer systems, algorithmic efficiency, data structure performance,\nlow-level languages, and how it all works. And if you don't know any of it, Google won't hire you.\n\nWhen I started this project, I didn't know a stack from a heap, didn't know Big-O anything, anything about trees, or how to\ntraverse a graph. If I had to code a sorting algorithm, I can tell ya it wouldn't have been very good.\nEvery data structure I've ever used was built into the language, and I didn't know how they worked\nunder the hood at all. I've never had to manage memory, unless a process I was running would give an \"out of\nmemory\" error, and then I'd have to find a workaround. I've used a few multi-dimensional arrays in my life and\nthousands of associative arrays, but I've never created data structures from scratch.\n\nBut after going through this study plan I have high confidence I'll be hired. It's a long plan. It's going to take me\nmonths. If you are familiar with a lot of this already it will take you a lot less time.\n\n## How to use it\n\nEverything below is an outline, and you should tackle the items in order from top to bottom.\n\nI'm using Github's special markdown flavor, including tasks lists to check progress.\n\n- [x] Create a new branch so you can check items like this, just put an x in the brackets: [x]\n\n[More about Github-flavored markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)\n\n## Get in a Googley Mood\n\nPrint out a \"[future Googler](https://github.com/jwasham/google-interview-university/blob/master/extras/future-googler.pdf)\" sign (or two) and keep your eyes on the prize.\n\n[![future Googler sign](https://dng5l3qzreal6.cloudfront.net/2016/Oct/Screen_Shot_2016_10_04_at_10_13_24_AM-1475601104364.png)](https://github.com/jwasham/google-interview-university/blob/master/extras/future-googler.pdf)\n\n## Did I Get the Job?\n\nI haven't applied yet.\n\nI still have a few days in the learning phase (finishing up this crazy list), and starting next week all \nI'll be doing is programming questions all day long. That will continue for a few weeks, and then I'll\napply through a referral I've been holding onto since February (yes, February).\n\n    Thanks for the referral, JP.\n\n## Follow Along with Me\n\nI'm on the journey, too. Follow along on my blog at [GoogleyAsHeck.com](https://googleyasheck.com/)\n\n- Twitter: [@googleyasheck](https://twitter.com/googleyasheck)\n- Twitter: [@StartupNextDoor](https://twitter.com/StartupNextDoor)\n- Google+: [+Googleyasheck](https://plus.google.com/+Googleyasheck)\n- LinkedIn: [johnawasham](https://www.linkedin.com/in/johnawasham)\n\n![John Washam - Google Interview University](https://dng5l3qzreal6.cloudfront.net/2016/Aug/book_stack_photo_resized_18_1469302751157-1472661280368.png)\n\n## Don't feel you aren't smart enough\n- Google engineers are smart, but many have an insecurity that they aren't smart enough, even though they work at Google.\n- [The myth of the Genius Programmer](https://www.youtube.com/watch?v=0SARbwvhupQ)\n\n## About Google\n\n- [ ] For students - [Google Careers: Technical Development Guide](https://www.google.com/about/careers/students/guide-to-technical-development.html)\n- [ ] How Search Works:\n    - [ ] [The Evolution of Search (video)](https://www.youtube.com/watch?v=mTBShTwCnD4)\n    - [ ] [How Search Works - the story](https://www.google.com/insidesearch/howsearchworks/thestory/)\n    - [ ] [How Search Works](https://www.google.com/insidesearch/howsearchworks/)\n    - [ ] [How Search Works - Matt Cutts (video)](https://www.youtube.com/watch?v=BNHR6IQJGZs)\n    - [ ] [How Google makes improvements to its search algorithm (video)](https://www.youtube.com/watch?v=J5RZOU6vK4Q)\n- [ ] Series:\n    - [ ] [How Google Search Dealt With Mobile](https://backchannel.com/how-google-search-dealt-with-mobile-33bc09852dc9)\n    - [ ] [Google's Secret Study To Find Out Our Needs](https://backchannel.com/googles-secret-study-to-find-out-our-needs-eba8700263bf)\n    - [ ] [Google Search Will Be Your Next Brain](https://backchannel.com/google-search-will-be-your-next-brain-5207c26e4523)\n    - [ ] [The Deep Mind Of Demis Hassabis](https://backchannel.com/the-deep-mind-of-demis-hassabis-156112890d8a)\n- [ ] [Book: How Google Works](https://www.amazon.com/How-Google-Works-Eric-Schmidt/dp/1455582344)\n- [ ] [Made by Google announcement - Oct 2016 (video)](https://www.youtube.com/watch?v=q4y0KOeXViI)\n\n## About Video Resources\n\nSome videos are available only by enrolling in a Coursera, EdX, or Lynda.com class. These are called MOOCs.\nIt is free to do so, but sometimes the classes are not in session so you have to wait a couple of months, so you have no access. \n\n    I'd appreciate your help converting the MOOC video links to public sources to replace the online course videos over time. I like using university lectures.\n\n\n## Interview Process & General Interview Prep\n\n- [ ] Videos:\n    - [ ] [How to Work at Google - Candidate Coaching Session (video)](https://www.youtube.com/watch?v=oWbUtlUhwa8&feature=youtu.be)\n    - [ ] [Google Recruiters Share Technical Interview Tips (video)](https://www.youtube.com/watch?v=qc1owf2-220&feature=youtu.be)\n    - [ ] [How to Work at Google: Tech Resume Preparation (video)](https://www.youtube.com/watch?v=8npJLXkcmu8)\n\n- [ ] Articles:\n    - [ ] [Becoming a Googler in Three Steps](http://www.google.com/about/careers/lifeatgoogle/hiringprocess/)\n    - [ ] [Get That Job at Google](http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html)\n        - all the things he mentions that you need to know are listed below\n    - [ ] _(very dated)_ [How To Get A Job At Google, Interview Questions, Hiring Process](http://dondodge.typepad.com/the_next_big_thing/2010/09/how-to-get-a-job-at-google-interview-questions-hiring-process.html)\n    - [ ] [Phone Screen Questions](http://sites.google.com/site/steveyegge2/five-essential-phone-screen-questions)\n\n- [ ] Additional (not suggested by Google but I added):\n    - [ ] [ABC: Always Be Coding](https://medium.com/always-be-coding/abc-always-be-coding-d5f8051afce2#.4heg8zvm4)\n    - [ ] [Four Steps To Google Without A Degree](https://medium.com/always-be-coding/four-steps-to-google-without-a-degree-8f381aa6bd5e#.asalo1vfx)\n    - [ ] [Whiteboarding](https://medium.com/@dpup/whiteboarding-4df873dbba2e#.hf6jn45g1)\n    - [ ] [How Google Thinks About Hiring, Management And Culture](http://www.kpcb.com/blog/lessons-learned-how-google-thinks-about-hiring-management-and-culture)\n    - [ ] [Effective Whiteboarding during Programming Interviews](http://www.coderust.com/blog/2014/04/10/effective-whiteboarding-during-programming-interviews/)\n    - [ ] Cracking The Coding Interview Set 1:\n        - [ ] [Gayle L McDowell - Cracking The Coding Interview (video)](https://www.youtube.com/watch?v=rEJzOhC5ZtQ)\n        - [ ] [Cracking the Coding Interview with Author Gayle Laakmann McDowell (video)](https://www.youtube.com/watch?v=aClxtDcdpsQ)\n    - [ ] How to Get a Job at the Big 4:\n        - [ ] ['How to Get a Job at the Big 4 - Amazon, Facebook, Google & Microsoft' (video)](https://www.youtube.com/watch?v=YJZCUhxNCv8)\n    - [ ] [Failing at Google Interviews](http://alexbowe.com/failing-at-google-interviews/)\n\n## Pick One Language for the Interview\n\nI wrote this short article about it: [Important: Pick One Language for the Google Interview](https://googleyasheck.com/important-pick-one-language-for-the-google-interview/)\n\nYou can use a language you are comfortable in to do the coding part of the interview, but for Google, these are solid choices:\n\n- C++\n- Java\n- Python\n\nYou could also use these, but read around first. There may be caveats:\n\n- JavaScript\n- Ruby\n\nYou need to be very comfortable in the language, and be knowledgeable. \n\nRead more about choices:\n- http://www.byte-by-byte.com/choose-the-right-language-for-your-coding-interview/\n- http://blog.codingforinterviews.com/best-programming-language-jobs/\n- https://www.quora.com/What-is-the-best-language-to-program-in-for-an-in-person-Google-interview\n\n[See language resources here](programming-language-resources.md)\n\nYou'll see some C, C++, and Python learning included below, because I'm learning. There are a few books involved, see the bottom.\n\n## Before you Get Started\n\nThis list grew over many months, and yes, it kind of got out of hand. \n\nHere are some mistakes I made so you'll have a better experience.\n\n### 1. You Won't Remember it All\n\nI watched hours of videos and took copious notes, and months later there was much I didn't remember. I spent 3 days going \nthrough my notes and making flashcards so I could review (see below). \n\n### 2. Use Flashcards\n\nTo solve the problem, I made a little flashcards site where I could add flashcards of 2 types: general and code.\nEach card has different formatting.\n\nI made a mobile-first website so I could review on my phone and tablet, whereever I am.\n\nMake your own for free:\n\n- [Flashcards site repo](https://github.com/jwasham/computer-science-flash-cards)\n- [My flash cards database](https://github.com/jwasham/computer-science-flash-cards/blob/master/cards-jwasham.db): Keep in mind I went overboard and have cards covering everything from assembly language and Python trivia to machine learning and statistics. It's way too much for what's required by Google.\n\n**Note on flashcards:** The first time you recognize you know the answer, don't mark it as known. You have to see the \nsame card and answer it several times correctly before you really know it. Repetition will put that knowledge deeper in \nyour brain.\n\n### 3. Review, review, review\n\nI keep a set of cheatsheets on ASCII, OSI stack, Big-O notations, and more. I study them when I have some spare time.\n\nTake a break from programming problems for a half hour and go through your flashcards.\n\n### 4. Focus\n\nThere are a lot of distractions that can take up valuable time. Focus and concentration is hard.\n\n## What you won't see covered\n\nThis big list all started as a personal to-do list made from Google interview coaching notes. These are prevalent \ntechnologies but were not mentioned in those notes:\n\n- SQL\n- Javascript\n- HTML, CSS, and other front-end technologies\n\n## The Daily Plan\n\nSome subjects take one day, and some will take multiple days. Some are just learning with nothing to implement.\n\nEach day I take one subject from the list below, watch videos about that subject, and write an implementation in:\n    C - using structs and functions that take a struct * and something else as args.\n    C++ - without using built-in types\n    C++ - using built-in types, like STL's std::list for a linked list\n    Python - using built-in types (to keep practicing Python)\n    and write tests to ensure I'm doing it right, sometimes just using simple assert() statements\n    You may do Java or something else, this is just my thing.\n\nWhy code in all of these?\n    Practice, practice, practice, until I'm sick of it, and can do it with no problem (some have many edge cases and bookkeeping details to remember)\n    Work within the raw constraints (allocating/freeing memory without help of garbage collection (except Python))\n    Make use of built-in types so I have experience using the built-in tools for real-world use (not going to write my own linked list implementation in production)\n\nI may not have time to do all of these for every subject, but I'll try.\n\nYou can see my code here:\n - [C] (https://github.com/jwasham/practice-c)\n - [C++] (https://github.com/jwasham/practice-cpp)\n - [Python] (https://github.com/jwasham/practice-python)\n\nYou don't need to memorize the guts of every algorithm.\n\nWrite code on a whiteboard or paper, not a computer. Test with some sample inputs. Then test it out on a computer.\n\n## Prerequisite Knowledge\n\n- [ ] **How computers process a program:**\n    - [ ] [How does CPU execute program (video)](https://www.youtube.com/watch?v=42KTvGYQYnA)\n    - [ ] [Machine Code Instructions (video)](https://www.youtube.com/watch?v=Mv2XQgpbTNE)\n\n- [ ] **Compilers**\n    - [ ] [How a Compiler Works in ~1 minute (video)](https://www.youtube.com/watch?v=IhC7sdYe-Jg)\n    - [ ] [Harvard CS50 - Compilers (video)](https://www.youtube.com/watch?v=CSZLNYF4Klo)\n    - [ ] [C++ (video)](https://www.youtube.com/watch?v=twodd1KFfGk)\n    - [ ] [Understanding Compiler Optimization (C++) (video)](https://www.youtube.com/watch?v=FnGCDLhaxKU)\n\n- [ ] **How floating point numbers are stored:**\n    - [ ] simple 8-bit: [Representation of Floating Point Numbers - 1 (video - there is an error in calculations - see video description)](https://www.youtube.com/watch?v=ji3SfClm8TU)\n    - [ ] 32 bit: [IEEE754 32-bit floating point binary (video)](https://www.youtube.com/watch?v=50ZYcZebIec)\n\n## Algorithmic complexity / Big-O / Asymptotic analysis\n- nothing to implement\n- [ ] [Harvard CS50 - Asymptotic Notation (video)](https://www.youtube.com/watch?v=iOq5kSKqeR4)\n- [ ] [Big O Notations (general quick tutorial) (video)](https://www.youtube.com/watch?v=V6mKVRU1evU)\n- [ ] [Big O Notation (and Omega and Theta) - best mathematical explanation (video)](https://www.youtube.com/watch?v=ei-A_wy5Yxw&index=2&list=PL1BaGV1cIH4UhkL8a9bJGG356covJ76qN)\n- [ ] Skiena:\n    - [video](https://www.youtube.com/watch?v=gSyDMtdPNpU&index=2&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [slides](http://www3.cs.stonybrook.edu/~algorith/video-lectures/2007/lecture2.pdf)\n- [ ] [A Gentle Introduction to Algorithm Complexity Analysis](http://discrete.gr/complexity/)\n- [ ] [Orders of Growth (video)](https://class.coursera.org/algorithmicthink1-004/lecture/59)\n- [ ] [Asymptotics (video)](https://class.coursera.org/algorithmicthink1-004/lecture/61)\n- [ ] [UC Berkeley Big O (video)](https://youtu.be/VIS4YDpuP98)\n- [ ] [UC Berkeley Big Omega (video)](https://youtu.be/ca3e7UVmeUc)\n- [ ] [Amortized Analysis (video)](https://www.youtube.com/watch?v=B3SpQZaAZP4&index=10&list=PL1BaGV1cIH4UhkL8a9bJGG356covJ76qN)\n- [ ] [Illustrating \"Big O\" (video)](https://class.coursera.org/algorithmicthink1-004/lecture/63)\n- [ ] TopCoder (includes recurrence relations and master theorem):\n    - [Computational Complexity: Section 1](https://www.topcoder.com/community/data-science/data-science-tutorials/computational-complexity-section-1/)\n    - [Computational Complexity: Section 2](https://www.topcoder.com/community/data-science/data-science-tutorials/computational-complexity-section-2/)\n- [ ] [Cheat sheet](http://bigocheatsheet.com/)\n\n\n    If some of the lectures are too mathy, you can jump down to the bottom and\n    watch the discrete mathematics videos to get the background knowledge.\n\n## Data Structures\n\n- ### Arrays\n    - Implement an automatically resizing vector.\n    - [ ] Description:\n        - [Arrays (video)](https://www.coursera.org/learn/data-structures/lecture/OsBSF/arrays)\n        - [Basic Arrays (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Basic-arrays/149042/177104-4.html)\n        - [Multi-dim (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Multidimensional-arrays/149042/177105-4.html)\n        - [Dynamic Arrays (video)](https://www.coursera.org/learn/data-structures/lecture/EwbnV/dynamic-arrays)\n        - [Jagged Arrays (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Jagged-arrays/149042/177106-4.html)\n        - [Resizing arrays (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Resizable-arrays/149042/177108-4.html)\n    - [ ] Implement a vector (mutable array with automatic resizing):\n        - [ ] Practice coding using arrays and pointers, and pointer math to jump to an index instead of using indexing.\n        - [ ] new raw data array with allocated memory\n            - can allocate int array under the hood, just not use its features\n            - start with 16, or if starting number is greater, use power of 2 - 16, 32, 64, 128\n        - [ ] size() - number of items\n        - [ ] capacity() - number of items it can hold\n        - [ ] is_empty()\n        - [ ] at(index) - returns item at given index, blows up if index out of bounds\n        - [ ] push(item)\n        - [ ] insert(index, item) - inserts item at index, shifts that index's value and trailing elements to the right\n        - [ ] prepend(item) - can use insert above at index 0\n        - [ ] pop() - remove from end, return value\n        - [ ] delete(index) - delete item at index, shifting all trailing elements left\n        - [ ] remove(item) - looks for value and removes index holding it (even if in multiple places)\n        - [ ] find(item) - looks for value and returns first index with that value, -1 if not found\n        - [ ] resize(new_capacity) // private function\n            - when you reach capacity, resize to double the size\n            - when popping an item, if size is 1/4 of capacity, resize to half\n    - [ ] Time\n        - O(1) to add/remove at end (amortized for allocations for more space), index, or update\n        - O(n) to insert/remove elsewhere\n    - [ ] Space\n        - contiguous in memory, so proximity helps performance\n        - space needed = (array capacity, which is >= n) * size of item, but even if 2n, still O(n)\n\n- ### Linked Lists\n    - [ ] Description:\n        - [ ] [Singly Linked Lists (video)](https://www.coursera.org/learn/data-structures/lecture/kHhgK/singly-linked-lists)\n        - [ ] [CS 61B - Linked Lists (video)](https://www.youtube.com/watch?v=sJtJOtXCW_M&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=5)\n    - [ ] [C Code (video)](https://www.youtube.com/watch?v=QN6FPiD0Gzo)\n            - not the whole video, just portions about Node struct and memory allocation.\n    - [ ] Linked List vs Arrays:\n        - [Core Linked Lists Vs Arrays (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/rjBs9/core-linked-lists-vs-arrays)\n        - [In The Real World Linked Lists Vs Arrays (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/QUaUd/in-the-real-world-lists-vs-arrays)\n    - [ ] [why you should avoid linked lists (video)](https://www.youtube.com/watch?v=YQs6IC-vgmo)\n    - [ ] Gotcha: you need pointer to pointer knowledge:\n        (for when you pass a pointer to a function that may change the address where that pointer points)\n        This page is just to get a grasp on ptr to ptr. I don't recommend this list traversal style. Readability and maintainability suffer due to cleverness.\n        - [Pointers to Pointers](https://www.eskimo.com/~scs/cclass/int/sx8.html)\n    - [ ] implement (I did with tail pointer & without):\n        - [ ] size() - returns number of data elements in list\n        - [ ] empty() - bool returns true if empty\n        - [ ] value_at(index) - returns the value of the nth item (starting at 0 for first)\n        - [ ] push_front(value) - adds an item to the front of the list\n        - [ ] pop_front() - remove front item and return its value\n        - [ ] push_back(value) - adds an item at the end\n        - [ ] pop_back() - removes end item and returns its value\n        - [ ] front() - get value of front item\n        - [ ] back() - get value of end item\n        - [ ] insert(index, value) - insert value at index, so current item at that index is pointed to by new item at index\n        - [ ] erase(index) - removes node at given index\n        - [ ] value_n_from_end(n) - returns the value of the node at nth position from the end of the list\n        - [ ] reverse() - reverses the list\n        - [ ] remove_value(value) - removes the first item in the list with this value\n    - [ ] Doubly-linked List\n        - [Description (video)](https://www.coursera.org/learn/data-structures/lecture/jpGKD/doubly-linked-lists)\n        - No need to implement\n\n- ### Stack\n    - [ ] [Stacks (video)](https://www.coursera.org/learn/data-structures/lecture/UdKzQ/stacks)\n    - [ ] [Using Stacks Last-In First-Out (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Using-stacks-last-first-out/149042/177120-4.html)\n    - [ ] Will not implement. Implementing with array is trivial.\n\n- ### Queue\n    - [ ] [Using Queues First-In First-Out(video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Using-queues-first-first-out/149042/177122-4.html)\n    - [ ] [Queue (video)](https://www.coursera.org/learn/data-structures/lecture/EShpq/queue)\n    - [ ] [Circular buffer/FIFO](https://en.wikipedia.org/wiki/Circular_buffer)\n    - [ ] [Priority Queues (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Priority-queues-deques/149042/177123-4.html)\n    - [ ] Implement using linked-list, with tail pointer:\n        - enqueue(value) - adds value at position at tail\n        - dequeue() - returns value and removes least recently added element (front)\n        - empty()\n    - [ ] Implement using fixed-sized array:\n        - enqueue(value) - adds item at end of available storage\n        - dequeue() - returns value and removes least recently added element\n        - empty()\n        - full()\n    - [ ] Cost:\n        - a bad implementation using linked list where you enqueue at head and dequeue at tail would be O(n)\n            because you'd need the next to last element, causing a full traversal each dequeue\n        - enqueue: O(1) (amortized, linked list and array [probing])\n        - dequeue: O(1) (linked list and array)\n        - empty: O(1) (linked list and array)\n    \n- ### Hash table\n    - [ ] Videos:\n        - [ ] [Hashing with Chaining (video)](https://www.youtube.com/watch?v=0M_kIqhwbFo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=8)\n        - [ ] [Table Doubling, Karp-Rabin (video)](https://www.youtube.com/watch?v=BRO7mVIFt08&index=9&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n        - [ ] [Open Addressing, Cryptographic Hashing (video)](https://www.youtube.com/watch?v=rvdJDijO2Ro&index=10&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n        - [ ] [PyCon 2010: The Mighty Dictionary (video)](https://www.youtube.com/watch?v=C4Kc8xzcA68)\n        - [ ] [(Advanced) Randomization: Universal & Perfect Hashing (video)](https://www.youtube.com/watch?v=z0lJ2k0sl1g&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=11)\n        - [ ] [(Advanced) Perfect hashing (video)](https://www.youtube.com/watch?v=N0COwN14gt0&list=PL2B4EEwhKD-NbwZ4ezj7gyc_3yNrojKM9&index=4)\n    \n    - [ ] Online Courses:\n        - [ ] [Understanding Hash Functions (video](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Understanding-hash-functions/149042/177126-4.html)\n        - [ ] [Using Hash Tables (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Using-hash-tables/149042/177127-4.html)\n        - [ ] [Supporting Hashing (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Supporting-hashing/149042/177128-4.html)\n        - [ ] [Language Support Hash Tables (video)](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Language-support-hash-tables/149042/177129-4.html)\n        - [ ] [Core Hash Tables (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/m7UuP/core-hash-tables)\n        - [ ] [Data Structures (video)](https://www.coursera.org/learn/data-structures/home/week/3)\n        - [ ] [Phone Book Problem (video)](https://www.coursera.org/learn/data-structures/lecture/NYZZP/phone-book-problem)\n        - [ ] distributed hash tables:\n            - [Instant Uploads And Storage Optimization In Dropbox (video)](https://www.coursera.org/learn/data-structures/lecture/DvaIb/instant-uploads-and-storage-optimization-in-dropbox)\n            - [Distributed Hash Tables (video)](https://www.coursera.org/learn/data-structures/lecture/tvH8H/distributed-hash-tables)\n    \n    - [ ] implement with array using linear probing\n        - hash(k, m) - m is size of hash table\n        - add(key, value) - if key already exists, update value\n        - exists(key)\n        - get(key)\n        - remove(key)\n\n## More Knowledge\n\n- ### Binary search\n    - [ ] [Binary Search (video)](https://www.youtube.com/watch?v=D5SrAga1pno)\n    - [ ] [Binary Search (video)](https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/binary-search)\n    - [ ] [detail](https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/)\n    - [ ] Implement:\n        - binary search (on sorted array of integers)\n        - binary search using recursion\n\n- ### Bitwise operations\n    - [ ] [Bits cheat sheet](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/bits-cheat-cheet.pdf) - you should know many of the powers of 2 from (2^1 to 2^16 and 2^32)\n    - [ ] Get a really good understanding of manipulating bits with: &, |, ^, ~, >>, <<\n        - [ ] [words](https://en.wikipedia.org/wiki/Word_(computer_architecture))\n        - [ ] Good intro:\n            [Bit Manipulation (video)](https://www.youtube.com/watch?v=7jkIUgLC29I)\n        - [ ] [C Programming Tutorial 2-10: Bitwise Operators (video)](https://www.youtube.com/watch?v=d0AwjSpNXR0)\n        - [ ] [Bit Manipulation](https://en.wikipedia.org/wiki/Bit_manipulation)\n        - [ ] [Bitwise Operation](https://en.wikipedia.org/wiki/Bitwise_operation)\n        - [ ] [Bithacks](https://graphics.stanford.edu/~seander/bithacks.html)\n        - [ ] [The Bit Twiddler](http://bits.stephan-brumme.com/)\n        - [ ] [The Bit Twiddler Interactive](http://bits.stephan-brumme.com/interactive.html)\n    - [ ] 2s and 1s complement\n        - [Binary: Plusses & Minuses (Why We Use Two's Complement) (video)](https://www.youtube.com/watch?v=lKTsv6iVxV4)\n        - [1s Complement](https://en.wikipedia.org/wiki/Ones%27_complement)\n        - [2s Complement](https://en.wikipedia.org/wiki/Two%27s_complement)\n    - [ ] count set bits\n        - [4 ways to count bits in a byte (video)](https://youtu.be/Hzuzo9NJrlc)\n        - [Count Bits](https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan)\n        - [How To Count The Number Of Set Bits In a 32 Bit Integer](http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer)\n    - [ ] round to next power of 2:\n        - [Round Up To Next Power Of Two](http://bits.stephan-brumme.com/roundUpToNextPowerOfTwo.html)\n    - [ ] swap values:\n        - [Swap](http://bits.stephan-brumme.com/swap.html)\n    - [ ] absolute value:\n        - [Absolute Integer](http://bits.stephan-brumme.com/absInteger.html)\n\n## Trees\n\n- ### Trees - Notes & Background\n    - [ ] [Series: Core Trees (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/ovovP/core-trees)\n    - [ ] [Series: Trees (video)](https://www.coursera.org/learn/data-structures/lecture/95qda/trees)\n    - basic tree construction\n    - traversal\n    - manipulation algorithms\n    - BFS (breadth-first search)\n        - [MIT (video)](https://www.youtube.com/watch?v=s-CYnVz-uh4&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=13)\n        - level order (BFS, using queue)\n            time complexity: O(n)\n            space complexity: best: O(1), worst: O(n/2)=O(n)\n    - DFS (depth-first search)\n        - [MIT (video)](https://www.youtube.com/watch?v=AfSk24UTFS8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=14)\n        - notes:\n            time complexity: O(n)\n            space complexity:\n                best: O(log n) - avg. height of tree\n                worst: O(n)\n        - inorder (DFS: left, self, right)\n        - postorder (DFS: left, right, self)\n        - preorder (DFS: self, left, right)\n\n- ### Binary search trees: BSTs\n    - [ ] [Binary Search Tree Review (video)](https://www.youtube.com/watch?v=x6At0nzX92o&index=1&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n    - [ ] [Series (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/p82sw/core-introduction-to-binary-search-trees)\n        - starts with symbol table and goes through BST applications\n    - [ ] [Introduction (video)](https://www.coursera.org/learn/data-structures/lecture/E7cXP/introduction)\n    - [ ] [MIT (video)](https://www.youtube.com/watch?v=9Jry5-82I68)\n    - C/C++:\n        - [ ] [Binary search tree - Implementation in C/C++ (video)](https://www.youtube.com/watch?v=COZK7NATh4k&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=28)\n        - [ ] [BST implementation - memory allocation in stack and heap (video)](https://www.youtube.com/watch?v=hWokyBoo0aI&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=29)\n        - [ ] [Find min and max element in a binary search tree (video)](https://www.youtube.com/watch?v=Ut90klNN264&index=30&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [Find height of a binary tree (video)](https://www.youtube.com/watch?v=_pnqMz5nrRs&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=31)\n        - [ ] [Binary tree traversal - breadth-first and depth-first strategies (video)](https://www.youtube.com/watch?v=9RHO6jU--GU&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=32)\n        - [ ] [Binary tree: Level Order Traversal (video)](https://www.youtube.com/watch?v=86g8jAQug04&index=33&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [Binary tree traversal: Preorder, Inorder, Postorder (video)](https://www.youtube.com/watch?v=gm8DUJJhmY4&index=34&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [Check if a binary tree is binary search tree or not (video)](https://www.youtube.com/watch?v=yEwSGhSsT0U&index=35&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [Delete a node from Binary Search Tree (video)](https://www.youtube.com/watch?v=gcULXE7ViZw&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=36)\n        - [ ] [Inorder Successor in a binary search tree (video)](https://www.youtube.com/watch?v=5cPbNCrdotA&index=37&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n    - [ ] Implement:\n        - [ ] insert    // insert value into tree\n        - [ ] get_node_count // get count of values stored\n        - [ ] print_values // prints the values in the tree, from min to max\n        - [ ] delete_tree\n        - [ ] is_in_tree // returns true if given value exists in the tree\n        - [ ] get_height // returns the height in nodes (single node's height is 1)\n        - [ ] get_min   // returns the minimum value stored in the tree\n        - [ ] get_max   // returns the maximum value stored in the tree\n        - [ ] is_binary_search_tree\n        - [ ] delete_value\n        - [ ] get_successor // returns next-highest value in tree after given value, -1 if none\n\n- ### Heap / Priority Queue / Binary Heap\n    - visualized as a tree, but is usually linear in storage (array, linked list)\n    - [ ] [Heap](https://en.wikipedia.org/wiki/Heap_(data_structure))\n    - [ ] [Introduction (video)](https://www.coursera.org/learn/data-structures/lecture/2OpTs/introduction)\n    - [ ] [Naive Implementations (video)](https://www.coursera.org/learn/data-structures/lecture/z3l9N/naive-implementations)\n    - [ ] [Binary Trees (video)](https://www.coursera.org/learn/data-structures/lecture/GRV2q/binary-trees)\n    - [ ] [Tree Height Remark (video)](https://www.coursera.org/learn/data-structures/supplement/S5xxz/tree-height-remark)\n    - [ ] [Basic Operations (video)](https://www.coursera.org/learn/data-structures/lecture/0g1dl/basic-operations)\n    - [ ] [Complete Binary Trees (video)](https://www.coursera.org/learn/data-structures/lecture/gl5Ni/complete-binary-trees)\n    - [ ] [Pseudocode (video)](https://www.coursera.org/learn/data-structures/lecture/HxQo9/pseudocode)\n    - [ ] [Heap Sort - jumps to start (video)](https://youtu.be/odNJmw5TOEE?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3291)\n    - [ ] [Heap Sort (video)](https://www.coursera.org/learn/data-structures/lecture/hSzMO/heap-sort)\n    - [ ] [Building a heap (video)](https://www.coursera.org/learn/data-structures/lecture/dwrOS/building-a-heap)\n    - [ ] [MIT: Heaps and Heap Sort (video)](https://www.youtube.com/watch?v=B7hVxCmfPtM&index=4&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [CS 61B Lecture 24: Priority Queues (video)](https://www.youtube.com/watch?v=yIUFT6AKBGE&index=24&list=PL4BBB74C7D2A1049C)\n    - [ ] [Linear Time BuildHeap (max-heap)](https://www.youtube.com/watch?v=MiyLo8adrWw)\n    - [ ] Implement a max-heap:\n        - [ ] insert\n        - [ ] sift_up - needed for insert\n        - [ ] get_max - returns the max item, without removing it\n        - [ ] get_size() - return number of elements stored\n        - [ ] is_empty() - returns true if heap contains no elements\n        - [ ] extract_max - returns the max item, removing it\n        - [ ] sift_down - needed for extract_max\n        - [ ] remove(i) - removes item at index x\n        - [ ] heapify - create a heap from an array of elements, needed for heap_sort\n        - [ ] heap_sort() - take an unsorted array and turn it into a sorted array in-place using a max heap\n            - note: using a min heap instead would save operations, but double the space needed (cannot do in-place).\n\n- ### Tries\n    - Note there are different kinds of tries. Some have prefixes, some don't, and some use string instead of bits\n        to track the path.\n    - I read through code, but will not implement.\n    - [ ] [Notes on Data Structures and Programming Techniques](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#Tries)\n    - [ ] Short course videos:\n        - [ ] [Introduction To Tries (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/08Xyf/core-introduction-to-tries)\n        - [ ] [Performance Of Tries (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/PvlZW/core-performance-of-tries)\n        - [ ] [Implementing A Trie (video)](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/DFvd3/core-implementing-a-trie)\n    - [ ] [The Trie: A Neglected Data Structure](https://www.toptal.com/java/the-trie-a-neglected-data-structure)\n    - [ ] [TopCoder - Using Tries](https://www.topcoder.com/community/data-science/data-science-tutorials/using-tries/)\n    - [ ] [Stanford Lecture (real world use case) (video)](https://www.youtube.com/watch?v=TJ8SkcUSdbU)\n    - [ ] [MIT, Advanced Data Structures, Strings (can get pretty obscure about halfway through)](https://www.youtube.com/watch?v=NinWEPPrkDQ&index=16&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf)\n\n- ### Balanced search trees\n    - Know least one type of balanced binary tree (and know how it's implemented):\n    - \"Among balanced search trees, AVL and 2/3 trees are now passé, and red-black trees seem to be more popular.\n        A particularly interesting self-organizing data structure is the splay tree, which uses rotations\n        to move any accessed key to the root.\" - Skiena\n    - Of these, I chose to implement a splay tree. From what I've read, you won't implement a\n        balanced search tree in your interview. But I wanted exposure to coding one up\n        and let's face it, splay trees are the bee's knees. I did read a lot of red-black tree code.\n        - splay tree: insert, search, delete functions\n        If you end up implementing red/black tree try just these:\n        - search and insertion functions, skipping delete\n    - I want to learn more about B-Tree since it's used so widely with very large data sets.\n    - [ ] [Self-balancing binary search tree](https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree)\n\n    - [ ] **AVL trees**\n        - In practice:\n            From what I can tell, these aren't used much in practice, but I could see where they would be:\n            The AVL tree is another structure supporting O(log n) search, insertion, and removal. It is more rigidly\n            balanced than red–black trees, leading to slower insertion and removal but faster retrieval. This makes it\n            attractive for data structures that may be built once and loaded without reconstruction, such as language\n            dictionaries (or program dictionaries, such as the opcodes of an assembler or interpreter).\n        - [ ] [MIT AVL Trees / AVL Sort (video)](https://www.youtube.com/watch?v=FNeL18KsWPc&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=6)\n        - [ ] [AVL Trees (video)](https://www.coursera.org/learn/data-structures/lecture/Qq5E0/avl-trees)\n        - [ ] [AVL Tree Implementation (video)](https://www.coursera.org/learn/data-structures/lecture/PKEBC/avl-tree-implementation)\n        - [ ] [Split And Merge](https://www.coursera.org/learn/data-structures/lecture/22BgE/split-and-merge)\n\n    - [ ] **Splay trees**\n        - In practice:\n            Splay trees are typically used in the implementation of caches, memory allocators, routers, garbage collectors,\n            data compression, ropes (replacement of string used for long text strings), in Windows NT (in the virtual memory,\n            networking, and file system code) etc.\n        - [ ] [CS 61B: Splay Trees (video)](https://www.youtube.com/watch?v=Najzh1rYQTo&index=23&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd)\n        - [ ] MIT Lecture: Splay Trees:\n            - Gets very mathy, but watch the last 10 minutes for sure.\n            - [Video](https://www.youtube.com/watch?v=QnPl_Y6EqMo)\n\n    - [ ] **2-3 search trees**\n        - In practice:\n            2-3 trees have faster inserts at the expense of slower searches (since height is more compared to AVL trees).\n        - You would use 2-3 tree very rarely because its implementation involves different types of nodes. Instead, people use Red Black trees.\n        - [ ] [23-Tree Intuition and Definition (video)](https://www.youtube.com/watch?v=C3SsdUqasD4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=2)\n        - [ ] [Binary View of 23-Tree](https://www.youtube.com/watch?v=iYvBtGKsqSg&index=3&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [2-3 Trees (student recitation) (video)](https://www.youtube.com/watch?v=TOb1tuEZ2X4&index=5&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n\n    - [ ] **2-3-4 Trees (aka 2-4 trees)**\n        - In practice:\n            For every 2-4 tree, there are corresponding red–black trees with data elements in the same order. The insertion and deletion\n            operations on 2-4 trees are also equivalent to color-flipping and rotations in red–black trees. This makes 2-4 trees an\n            important tool for understanding the logic behind red–black trees, and this is why many introductory algorithm texts introduce\n            2-4 trees just before red–black trees, even though **2-4 trees are not often used in practice**.\n        - [ ] [CS 61B Lecture 26: Balanced Search Trees (video)](https://www.youtube.com/watch?v=zqrqYXkth6Q&index=26&list=PL4BBB74C7D2A1049C)\n        - [ ] [Bottom Up 234-Trees (video)](https://www.youtube.com/watch?v=DQdMYevEyE4&index=4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [Top Down 234-Trees (video)](https://www.youtube.com/watch?v=2679VQ26Fp4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=5)\n\n    - [ ] **B-Trees**\n        - fun fact: it's a mystery, but the B could stand for Boeing, Balanced, or Bayer (co-inventor)\n        - In Practice:\n            B-Trees are widely used in databases. Most modern filesystems use B-trees (or Variants). In addition to\n            its use in databases, the B-tree is also used in filesystems to allow quick random access to an arbitrary\n            block in a particular file. The basic problem is turning the file block i address into a disk block\n            (or perhaps to a cylinder-head-sector) address.\n        - [ ] [B-Tree](https://en.wikipedia.org/wiki/B-tree)\n        - [ ] [Introduction to B-Trees (video)](https://www.youtube.com/watch?v=I22wEC1tTGo&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=6)\n        - [ ] [B-Tree Definition and Insertion (video)](https://www.youtube.com/watch?v=s3bCdZGrgpA&index=7&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [B-Tree Deletion (video)](https://www.youtube.com/watch?v=svfnVhJOfMc&index=8&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [MIT 6.851 - Memory Hierarchy Models (video)](https://www.youtube.com/watch?v=V3omVLzI0WE&index=7&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf)\n                - covers cache-oblivious B-Trees, very interesting data structures\n                - the first 37 minutes are very technical, may be skipped (B is block size, cache line size)\n\n    - [ ] **Red/black trees**\n        - In practice:\n            Red–black trees offer worst-case guarantees for insertion time, deletion time, and search time.\n            Not only does this make them valuable in time-sensitive applications such as real-time applications,\n            but it makes them valuable building blocks in other data structures which provide worst-case guarantees;\n            for example, many data structures used in computational geometry can be based on red–black trees, and\n            the Completely Fair Scheduler used in current Linux kernels uses red–black trees. In the version 8 of Java,\n            the Collection HashMap has been modified such that instead of using a LinkedList to store identical elements with poor\n            hashcodes, a Red-Black tree is used.\n        - [ ] [Aduni - Algorithms - Lecture 4 \n            (link jumps to starting point) (video)](https://youtu.be/1W3x0f_RmUo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3871)\n        - [ ] [Aduni - Algorithms - Lecture 5 (video)](https://www.youtube.com/watch?v=hm2GHwyKF1o&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=5)\n        - [ ] [Black Tree](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree)\n        - [ ] [An Introduction To Binary Search And Red Black Tree](https://www.topcoder.com/community/data-science/data-science-tutorials/an-introduction-to-binary-search-and-red-black-trees/)\n\n- ### N-ary (K-ary, M-ary) trees\n    - note: the N or K is the branching factor (max branches)\n        - binary trees are a 2-ary tree, with branching factor = 2\n        - 2-3 trees are 3-ary\n    - [ ] [K-Ary Tree](https://en.wikipedia.org/wiki/K-ary_tree)\n\n## Sorting\n\n- [ ] Notes:\n    - Implement sorts & know best case/worst case, average complexity of each:\n        - no bubble sort - it's terrible - O(n^2), except when n <= 16\n    - [ ] stability in sorting algorithms (\"Is Quicksort stable?\")\n        - [Sorting Algorithm Stability](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability)\n        - [Stability In Sorting Algorithms](http://stackoverflow.com/questions/1517793/stability-in-sorting-algorithms)\n        - [Stability In Sorting Algorithms](http://www.geeksforgeeks.org/stability-in-sorting-algorithms/)\n        - [Sorting Algorithms - Stability](http://homepages.math.uic.edu/~leon/cs-mcs401-s08/handouts/stability.pdf)\n    - [ ] Which algorithms can be used on linked lists? Which on arrays? Which on both?\n        - I wouldn't recommend sorting a linked list, but merge sort is doable.\n        - [Merge Sort For Linked List](http://www.geeksforgeeks.org/merge-sort-for-linked-list/)\n\n- For heapsort, see Heap data structure above. Heap sort is great, but not stable.\n\n- [ ] [Bubble Sort (video)](https://www.youtube.com/watch?v=P00xJgWzz2c&index=1&list=PL89B61F78B552C1AB)\n- [ ] [Analyzing Bubble Sort (video)](https://www.youtube.com/watch?v=ni_zk257Nqo&index=7&list=PL89B61F78B552C1AB)\n- [ ] [Insertion Sort, Merge Sort (video)](https://www.youtube.com/watch?v=Kg4bqzAqRBM&index=3&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n- [ ] [Insertion Sort (video)](https://www.youtube.com/watch?v=c4BRHC7kTaQ&index=2&list=PL89B61F78B552C1AB)\n- [ ] [Merge Sort (video)](https://www.youtube.com/watch?v=GCae1WNvnZM&index=3&list=PL89B61F78B552C1AB)\n- [ ] [Quicksort (video)](https://www.youtube.com/watch?v=y_G9BkAm6B8&index=4&list=PL89B61F78B552C1AB)\n- [ ] [Selection Sort (video)](https://www.youtube.com/watch?v=6nDMgr0-Yyo&index=8&list=PL89B61F78B552C1AB)\n\n- [ ] Stanford lectures on sorting:\n    - [ ] [Lecture 15 | Programming Abstractions (video)](https://www.youtube.com/watch?v=ENp00xylP7c&index=15&list=PLFE6E58F856038C69)\n    - [ ] [Lecture 16 | Programming Abstractions (video)](https://www.youtube.com/watch?v=y4M9IVgrVKo&index=16&list=PLFE6E58F856038C69)\n\n- [ ] Shai Simonson, [Aduni.org](http://www.aduni.org/):\n    - [ ] [Algorithms - Sorting - Lecture 2 (video)](https://www.youtube.com/watch?v=odNJmw5TOEE&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=2)\n    - [ ] [Algorithms - Sorting II - Lecture 3 (video)](https://www.youtube.com/watch?v=hj8YKFTFKEE&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=3)\n\n- [ ] Steven Skiena lectures on sorting:\n    - [ ] [lecture begins at 26:46 (video)](https://youtu.be/ute-pmMkyuk?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=1600)\n    - [ ] [lecture begins at 27:40 (video)](https://www.youtube.com/watch?v=yLvp-pB8mak&index=8&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [lecture begins at 35:00 (video)](https://www.youtube.com/watch?v=q7K9otnzlfE&index=9&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [lecture begins at 23:50 (video)](https://www.youtube.com/watch?v=TvqIGu9Iupw&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=10)\n\n- [ ] UC Berkeley:\n    - [ ] [CS 61B Lecture 29: Sorting I (video)](https://www.youtube.com/watch?v=EiUvYS2DT6I&list=PL4BBB74C7D2A1049C&index=29)\n    - [ ] [CS 61B Lecture 30: Sorting II (video)](https://www.youtube.com/watch?v=2hTY3t80Qsk&list=PL4BBB74C7D2A1049C&index=30)\n    - [ ] [CS 61B Lecture 32: Sorting III (video)](https://www.youtube.com/watch?v=Y6LOLpxg6Dc&index=32&list=PL4BBB74C7D2A1049C)\n    - [ ] [CS 61B Lecture 33: Sorting V (video)](https://www.youtube.com/watch?v=qNMQ4ly43p4&index=33&list=PL4BBB74C7D2A1049C)\n\n- [ ] - Merge sort code:\n    - [ ] [Using output array](http://www.cs.yale.edu/homes/aspnes/classes/223/examples/sorting/mergesort.c)\n    - [ ] [In-place](https://github.com/jwasham/practice-cpp/blob/master/merge_sort/merge_sort.cc)\n- [ ] - Quick sort code:\n    - [ ] [Implementation](http://www.cs.yale.edu/homes/aspnes/classes/223/examples/randomization/quick.c)\n    - [ ] [Implementation](https://github.com/jwasham/practice-c/blob/master/quick_sort/quick_sort.c)\n\n- [ ] Implement:\n    - [ ] Mergesort: O(n log n) average and worst case\n    - [ ] Quicksort O(n log n) average case\n    - Selection sort and insertion sort are both O(n^2) average and worst case\n    - For heapsort, see Heap data structure above.\n\n- [ ] For curiosity - not required:\n    - [ ] [Radix Sort](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#radixSort)\n    - [ ] [Radix Sort (video)](https://www.youtube.com/watch?v=xhr26ia4k38)\n    - [ ] [Radix Sort, Counting Sort (linear time given constraints) (video)](https://www.youtube.com/watch?v=Nz1KZXbghj8&index=7&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [Randomization: Matrix Multiply, Quicksort, Freivalds' algorithm (video)](https://www.youtube.com/watch?v=cNB2lADK3_s&index=8&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [Sorting in Linear Time (video)](https://www.youtube.com/watch?v=pOKy3RZbSws&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf&index=14)\n\n## Graphs\n\nGraphs can be used to represent many problems in computer science, so this section is long, like trees and sorting were.\n\n- Notes from Yegge:\n    - There are three basic ways to represent a graph in memory:\n        - objects and pointers\n        - matrix\n        - adjacency list\n    - Familiarize yourself with each representation and its pros & cons\n    - BFS and DFS - know their computational complexity, their tradeoffs, and how to implement them in real code\n    - When asked a question, look for a graph-based solution first, then move on if none.\n\n- [ ] Skiena Lectures - great intro:\n    - [ ] [CSE373 2012 - Lecture 11 - Graph Data Structures (video)](https://www.youtube.com/watch?v=OiXxhDrFruw&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=11)\n    - [ ] [CSE373 2012 - Lecture 12 - Breadth-First Search (video)](https://www.youtube.com/watch?v=g5vF8jscteo&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=12)\n    - [ ] [CSE373 2012 - Lecture 13 - Graph Algorithms (video)](https://www.youtube.com/watch?v=S23W6eTcqdY&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=13)\n    - [ ] [CSE373 2012 - Lecture 14 - Graph Algorithms (con't) (video)](https://www.youtube.com/watch?v=WitPBKGV0HY&index=14&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [CSE373 2012 - Lecture 15 - Graph Algorithms (con't 2) (video)](https://www.youtube.com/watch?v=ia1L30l7OIg&index=15&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [CSE373 2012 - Lecture 16 - Graph Algorithms (con't 3) (video)](https://www.youtube.com/watch?v=jgDOQq6iWy8&index=16&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n\n- [ ] Graphs (review and more):\n\n    - [ ] [6.006 Single-Source Shortest Paths Problem (video)](https://www.youtube.com/watch?v=Aa2sqUhIn-E&index=15&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [6.006 Dijkstra (video)](https://www.youtube.com/watch?v=2E7MmKv0Y24&index=16&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [6.006 Bellman-Ford (video)](https://www.youtube.com/watch?v=ozsuci5pIso&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=17)\n    - [ ] [6.006 Speeding Up Dijkstra (video)](https://www.youtube.com/watch?v=CHvQ3q_gJ7E&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=18)\n    - [ ] [Aduni: Graph Algorithms I - Topological Sorting, Minimum Spanning Trees, Prim's Algorithm -  Lecture 6 (video)]( https://www.youtube.com/watch?v=i_AQT_XfvD8&index=6&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n    - [ ] [Aduni: Graph Algorithms II - DFS, BFS, Kruskal's Algorithm, Union Find Data Structure - Lecture 7 (video)]( https://www.youtube.com/watch?v=ufj5_bppBsA&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=7)\n    - [ ] [Aduni: Graph Algorithms III: Shortest Path - Lecture 8 (video)](https://www.youtube.com/watch?v=DiedsPsMKXc&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=8)\n    - [ ] [Aduni: Graph Alg. IV: Intro to geometric algorithms - Lecture 9 (video)](https://www.youtube.com/watch?v=XIAQRlNkJAw&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=9)\n    - [ ] [CS 61B 2014 (starting at 58:09) (video)](https://youtu.be/dgjX4HdMI-Q?list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&t=3489)\n    - [ ] [CS 61B 2014: Weighted graphs (video)](https://www.youtube.com/watch?v=aJjlQCFwylA&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=19)\n    - [ ] [Greedy Algorithms: Minimum Spanning Tree (video)](https://www.youtube.com/watch?v=tKwnms5iRBU&index=16&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [Strongly Connected Components Kosaraju's Algorithm Graph Algorithm (video)](https://www.youtube.com/watch?v=RpgcYiky7uw)\n\n- Full Coursera Course:\n    - [ ] [Algorithms on Graphs (video)](https://www.coursera.org/learn/algorithms-on-graphs/home/welcome)\n\n- Yegge: If you get a chance, try to study up on fancier algorithms:\n    - [ ] Dijkstra's algorithm - see above - 6.006\n    - [ ] A*\n        - [ ] [A Search Algorithm](https://en.wikipedia.org/wiki/A*_search_algorithm)\n        - [ ] [A* Pathfinding Tutorial (video)](https://www.youtube.com/watch?v=KNXfSOx4eEE)\n        - [ ] [A* Pathfinding (E01: algorithm explanation) (video)](https://www.youtube.com/watch?v=-L-WgKMFuhE)\n\n- I'll implement:\n    - [ ] DFS with adjacency list (recursive)\n    - [ ] DFS with adjacency list (iterative with stack)\n    - [ ] DFS with adjacency matrix (recursive)\n    - [ ] DFS with adjacency matrix (iterative with stack)\n    - [ ] BFS with adjacency list\n    - [ ] BFS with adjacency matrix\n    - [ ] single-source shortest path (Dijkstra)\n    - [ ] minimum spanning tree\n    - DFS-based algorithms (see Aduni videos above):\n        - [ ] check for cycle (needed for topological sort, since we'll check for cycle before starting)\n        - [ ] topological sort\n        - [ ] count connected components in a graph\n        - [ ] list strongly connected components\n        - [ ] check for bipartite graph\n\nYou'll get more graph practice in Skiena's book (see Books section below) and the interview books\n\n## Even More Knowledge\n\n- ### Recursion\n    - [ ] Stanford lectures on recursion & backtracking:\n        - [ ] [Lecture 8 | Programming Abstractions (video)](https://www.youtube.com/watch?v=gl3emqCuueQ&list=PLFE6E58F856038C69&index=8)\n        - [ ] [Lecture 9 | Programming Abstractions (video)](https://www.youtube.com/watch?v=uFJhEPrbycQ&list=PLFE6E58F856038C69&index=9)\n        - [ ] [Lecture 10 | Programming Abstractions (video)](https://www.youtube.com/watch?v=NdF1QDTRkck&index=10&list=PLFE6E58F856038C69)\n        - [ ] [Lecture 11 | Programming Abstractions (video)](https://www.youtube.com/watch?v=p-gpaIGRCQI&list=PLFE6E58F856038C69&index=11)\n    - when it is appropriate to use it\n    - how is tail recursion better than not?\n        - [ ] [What Is Tail Recursion Why Is It So Bad?](https://www.quora.com/What-is-tail-recursion-Why-is-it-so-bad)\n        - [ ] [Tail Recursion (video)](https://www.youtube.com/watch?v=L1jjXGfxozc)\n \n- ### Dynamic Programming\n    - This subject can be pretty difficult, as each DP soluble problem must be defined as a recursion relation, and coming up with it can be tricky.\n    - I suggest looking at many examples of DP problems until you have a solid understanding of the pattern involved.\n    - [ ] Videos:\n        - the Skiena videos can be hard to follow since he sometimes uses the whiteboard, which is too small to see\n        - [ ] [Skiena: CSE373 2012 - Lecture 19 - Introduction to Dynamic Programming (video)](https://youtu.be/Qc2ieXRgR0k?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=1718)\n        - [ ] [Skiena: CSE373 2012 - Lecture 20 - Edit Distance (video)](https://youtu.be/IsmMhMdyeGY?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=2749)\n        - [ ] [Skiena: CSE373 2012 - Lecture 21 - Dynamic Programming Examples (video)](https://youtu.be/o0V9eYF4UI8?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=406)\n        - [ ] [Skiena: CSE373 2012 - Lecture 22 - Applications of Dynamic Programming (video)](https://www.youtube.com/watch?v=dRbMC1Ltl3A&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=22)\n        - [ ] [Simonson: Dynamic Programming 0 (starts at 59:18) (video)](https://youtu.be/J5aJEcOr6Eo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3558)\n        - [ ] [Simonson: Dynamic Programming I - Lecture 11 (video)](https://www.youtube.com/watch?v=0EzHjQ_SOeU&index=11&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n        - [ ] [Simonson: Dynamic programming II - Lecture 12 (video)](https://www.youtube.com/watch?v=v1qiRwuJU7g&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=12)\n        - [ ] List of individual DP problems (each is short):\n            [Dynamic Programming (video)](https://www.youtube.com/playlist?list=PLrmLmBdmIlpsHaNTPP_jHHDx_os9ItYXr)\n    - [ ] Yale Lecture notes: \n        - [ ] [Dynamic Programming](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#dynamicProgramming)\n    - [ ] Coursera:\n        - [ ] [The RNA secondary structure problem (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/80RrW/the-rna-secondary-structure-problem)\n        - [ ] [A dynamic programming algorithm (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/PSonq/a-dynamic-programming-algorithm)\n        - [ ] [Illustrating the DP algorithm (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/oUEK2/illustrating-the-dp-algorithm)\n        - [ ] [Running time of the DP algorithm (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/nfK2r/running-time-of-the-dp-algorithm)\n        - [ ] [DP vs. recursive implementation (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/M999a/dp-vs-recursive-implementation)\n        - [ ] [Global pairwise sequence alignment (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/UZ7o6/global-pairwise-sequence-alignment)\n        - [ ] [Local pairwise sequence alignment (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/WnNau/local-pairwise-sequence-alignment)\n\n- ### Combinatorics (n choose k) & Probability\n    - [ ] [Math Skills: How to find Factorial, Permutation and Combination (Choose) (video)](https://www.youtube.com/watch?v=8RRo6Ti9d0U)\n    - [ ] [Make School: Probability (video)](https://www.youtube.com/watch?v=sZkAAk9Wwa4)\n    - [ ] [Make School: More Probability and Markov Chains (video)](https://www.youtube.com/watch?v=dNaJg-mLobQ)\n    - [ ] Khan Academy:\n        - Course layout:\n            - [ ] [Basic Theoretical Probability](https://www.khanacademy.org/math/probability/probability-and-combinatorics-topic)\n        - Just the videos - 41 (each are simple and each are short):\n            - [ ] [Probability Explained (video)](https://www.youtube.com/watch?v=uzkc-qNVoOk&list=PLC58778F28211FA19)\n\n- ### NP, NP-Complete and Approximation Algorithms\n    - Know about the most famous classes of NP-complete problems, such as traveling salesman and the knapsack problem,\n        and be able to recognize them when an interviewer asks you them in disguise.\n    - Know what NP-complete means.\n    - [ ] [Computational Complexity (video)](https://www.youtube.com/watch?v=moPtwq_cVH8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=23)\n    - [ ] Simonson:\n        - [ ] [Greedy Algs. II & Intro to NP Completeness (video)](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)\n        - [ ] [NP Completeness II & Reductions (video)](https://www.youtube.com/watch?v=e0tGC6ZQdQE&index=16&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n        - [ ] [NP Completeness III (Video)](https://www.youtube.com/watch?v=fCX1BGT3wjE&index=17&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n        - [ ] [NP Completeness IV (video)](https://www.youtube.com/watch?v=NKLDp3Rch3M&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=18)\n    - [ ] Skiena:\n        - [ ] [CSE373 2012 - Lecture 23 - Introduction to NP-CompletenessNP Completeness IV (video)](https://youtu.be/KiK5TVgXbFg?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=1508)\n        - [ ] [CSE373 2012 - Lecture 24 - NP-Completeness Proofs (video)](https://www.youtube.com/watch?v=27Al52X3hd4&index=24&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n        - [ ] [CSE373 2012 - Lecture 25 - NP-Completeness Challenge (video)](https://www.youtube.com/watch?v=xCPH4gwIIXM&index=25&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [Complexity: P, NP, NP-completeness, Reductions (video)](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n    - [ ] [Complexity: Approximation Algorithms (video)](https://www.youtube.com/watch?v=MEz1J9wY2iM&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=24)\n    - [ ] [Complexity: Fixed-Parameter Algorithms (video)](https://www.youtube.com/watch?v=4q-jmGrmxKs&index=25&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - Peter Norvik discusses near-optimal solutions to traveling salesman problem:\n        - [Jupyter Notebook](http://nbviewer.jupyter.org/url/norvig.com/ipython/TSP.ipynb)\n    - Pages 1048 - 1140 in CLRS if you have it.\n\n- ### Caches\n    - [ ] LRU cache:\n        - [ ] [The Magic of LRU Cache (100 Days of Google Dev) (video)](https://www.youtube.com/watch?v=R5ON3iwx78M)\n        - [ ] [Implementing LRU (video)](https://www.youtube.com/watch?v=bq6N7Ym81iI)\n        - [ ] [LeetCode - 146 LRU Cache (C++) (video)](https://www.youtube.com/watch?v=8-FZRAjR7qU)\n    - [ ] CPU cache:\n        - [ ] [MIT 6.004 L15: The Memory Hierarchy (video)](https://www.youtube.com/watch?v=vjYF_fAZI5E&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-&index=24)\n        - [ ] [MIT 6.004 L16: Cache Issues (video)](https://www.youtube.com/watch?v=ajgC3-pyGlk&index=25&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-)\n\n- ### Processes and Threads\n    - [ ] Computer Science 162 - Operating Systems (25 videos):\n        - for precesses and threads see videos 1-11\n        - [Operating Systems and System Programming (video)](https://www.youtube.com/playlist?list=PL-XXv-cvA_iBDyz-ba4yDskqMDY6A1w_c)\n    - [What Is The Difference Between A Process And A Thread?](https://www.quora.com/What-is-the-difference-between-a-process-and-a-thread)\n    - Covers:\n        - Processes, Threads, Concurrency issues\n            - difference between processes and threads\n            - processes\n            - threads\n            - locks\n            - mutexes\n            - semaphores\n            - monitors\n            - how they work\n            - deadlock\n            - livelock\n        - CPU activity, interrupts, context switching\n        - Modern concurrency constructs with multicore processors\n        - Process resource needs (memory: code, static storage, stack, heap, and also file descriptors, i/o)\n        - Thread resource needs (shares above (minus stack) with other threads in same process but each has its own pc, stack counter, registers and stack)\n        - Forking is really copy on write (read-only) until the new process writes to memory, then it does a full copy.\n        - Context switching\n            - How context switching is initiated by the operating system and underlying hardware\n    - [ ] [threads in C++ (series - 10 videos)](https://www.youtube.com/playlist?list=PL5jc9xFGsL8E12so1wlMS0r0hTQoJL74M)\n    - [ ] concurrency in Python (videos):\n        - [ ] [Short series on threads](https://www.youtube.com/playlist?list=PL1H1sBF1VAKVMONJWJkmUh6_p8g4F2oy1)\n        - [ ] [Python Threads](https://www.youtube.com/watch?v=Bs7vPNbB9JM)\n        - [ ] [Understanding the Python GIL (2010)](https://www.youtube.com/watch?v=Obt-vMVdM8s)\n            - [reference](http://www.dabeaz.com/GIL)\n        - [ ] [David Beazley - Python Concurrency From the Ground Up: LIVE! - PyCon 2015](https://www.youtube.com/watch?v=MCs5OvhV9S4)\n        - [ ] [Keynote David Beazley - Topics of Interest (Python Asyncio)](https://www.youtube.com/watch?v=ZzfHjytDceU)\n        - [ ] [Mutex in Python](https://www.youtube.com/watch?v=0zaPs8OtyKY)\n\n\n    Scalability and System Design are very large topics with many topics and resources, since there is a lot to consider \n    when designing a software/hardware system that can scale. Expect to spend quite a bit of time on this.\n\n- ### System Design, Scalability, Data Handling\n    - Considerations from Yegge:\n        - scalability\n            - Distill large data sets to single values\n            - Transform one data set to another\n            - Handling obscenely large amounts of data\n        - system design\n            - features sets\n            - interfaces\n            - class hierarchies\n            - designing a system under certain constraints\n            - simplicity and robustness\n            - tradeoffs\n            - performance analysis and optimization\n    - [ ] **START HERE**: [System Design from HiredInTech](http://www.hiredintech.com/system-design/)\n    - [ ] [How Do I Prepare To Answer Design Questions In A Technical Inverview?](https://www.quora.com/How-do-I-prepare-to-answer-design-questions-in-a-technical-interview?redirected_qid=1500023)\n    - [ ] [8 Things You Need to Know Before a System Design Interview](http://blog.gainlo.co/index.php/2015/10/22/8-things-you-need-to-know-before-system-design-interviews/)\n    - [ ] [Algorithm design](http://www.hiredintech.com/algorithm-design/)\n    - [ ] [Database Normalization - 1NF, 2NF, 3NF and 4NF (video)](https://www.youtube.com/watch?v=UrYLYV7WSHM)\n    - [ ] [System Design Interview](https://github.com/checkcheckzz/system-design-interview) - There are a lot of resources in this one. Look through the articles and examples. I put some of them below.\n    - [ ] [How to ace a systems design interview](http://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)\n    - [ ] [Numbers Everyone Should Know](http://everythingisdata.wordpress.com/2009/10/17/numbers-everyone-should-know/)\n    - [ ] [How long does it take to make a context switch?](http://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html)\n    - [ ] [Transactions Across Datacenters (video)](https://www.youtube.com/watch?v=srOgpXECblk)\n    - [ ] [A plain english introduction to CAP Theorem](http://ksat.me/a-plain-english-introduction-to-cap-theorem/)\n    - [ ] Paxos Consensus algorithm: \n        - [short video](https://www.youtube.com/watch?v=s8JqcZtvnsM)\n        - [extended video with use case and multi-paxos](https://www.youtube.com/watch?v=JEpsBg0AO6o)\n        - [paper](http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf)\n    - [ ] [Consistent Hashing](http://www.tom-e-white.com/2007/11/consistent-hashing.html)\n    - [ ] [NoSQL Patterns](http://horicky.blogspot.com/2009/11/nosql-patterns.html)\n    - [ ] [Optional: UML 2.0 Series (vido)](https://www.youtube.com/watch?v=OkC7HKtiZC0&list=PLGLfVvz_LVvQ5G-LdJ8RLqe-ndo7QITYc)\n    - [ ] OOSE: Software Dev Using UML and Java (21 videos): \n        - Can skip this if you have a great grasp of OO and OO design practices.\n        - [OOSE: Software Dev Using UML and Java](https://www.youtube.com/playlist?list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n    - [ ] SOLID OOP Principles:\n        - [ ] [Bob Martin SOLID Principles of Object Oriented and Agile Design (video)](https://www.youtube.com/watch?v=TMuno5RZNeE)\n        - [ ] [SOLID Design Patterns in C# (video)](https://www.youtube.com/playlist?list=PL8m4NUhTQU48oiGCSgCP1FiJEcg_xJzyQ)\n        - [ ] [SOLID Principles (video)](https://www.youtube.com/playlist?list=PL4CE9F710017EA77A)\n        - [ ] S - [Single Responsibility Principle](http://www.oodesign.com/single-responsibility-principle.html) | [Single responsibility to each Object](http://www.javacodegeeks.com/2011/11/solid-single-responsibility-principle.html)\n            - [more flavor](https://docs.google.com/open?id=0ByOwmqah_nuGNHEtcU5OekdDMkk)\n        - [ ] O - [Open/Closed Principal](http://www.oodesign.com/open-close-principle.html)  | [On production level Objects are ready for extension for not for modification](https://en.wikipedia.org/wiki/Open/closed_principle)\n            - [more flavor](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgN2M5MTkwM2EtNWFkZC00ZTI3LWFjZTUtNTFhZGZiYmUzODc1&hl=en)\n        - [ ] L - [Liskov Substitution Principal](http://www.oodesign.com/liskov-s-substitution-principle.html) | [Base Class and Derived class follow ‘IS A’ principal](http://stackoverflow.com/questions/56860/what-is-the-liskov-substitution-principle)\n            - [more flavor](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgNzAzZjA5ZmItNjU3NS00MzQ5LTkwYjMtMDJhNDU5ZTM0MTlh&hl=en)\n        - [ ] I - [Interface segregation principle](http://www.oodesign.com/interface-segregation-principle.html) | clients should not be forced to implement interfaces they don't use \n            - [Interface Segregation Principle in 5 minutes (video)](https://www.youtube.com/watch?v=3CtAfl7aXAQ)\n            - [more flavor](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgOTViYjJhYzMtMzYxMC00MzFjLWJjMzYtOGJiMDc5N2JkYmJi&hl=en)\n        - [ ] D -[Dependency Inversion principle](http://www.oodesign.com/dependency-inversion-principle.html) | Reduce the dependency In composition of objects.\n            - [Why Is The Dependency Inversion Principle And Why Is It Important](http://stackoverflow.com/questions/62539/what-is-the-dependency-inversion-principle-and-why-is-it-important)\n            - [more flavor](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgMjdlMWIzNGUtZTQ0NC00ZjQ5LTkwYzQtZjRhMDRlNTQ3ZGMz&hl=en)\n    - [ ] Scalability:\n        - [ ] [Great overview (video)](https://www.youtube.com/watch?v=-W9F__D3oY4)\n        - [ ] Short series: \n            - [Clones](http://www.lecloud.net/post/7295452622/scalability-for-dummies-part-1-clones)\n            - [Database](http://www.lecloud.net/post/7994751381/scalability-for-dummies-part-2-database)\n            - [Cache](http://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)\n            - [Asynchronism](http://www.lecloud.net/post/9699762917/scalability-for-dummies-part-4-asynchronism)\n        - [ ] [Scalable Web Architecture and Distributed Systems](http://www.aosabook.org/en/distsys.html)\n        - [ ] [Fallacies of Distributed Computing Explained](https://pages.cs.wisc.edu/~zuyu/files/fallacies.pdf)\n        - [ ] [Pragmatic Programming Techniques](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)\n            - [extra: Google Pregel Graph Processing](http://horicky.blogspot.com/2010/07/google-pregel-graph-processing.html)\n        - [ ] [Jeff Dean - Building Software Systems At Google and Lessons Learned (video)](https://www.youtube.com/watch?v=modXC5IWTJI)\n        - [ ] [Introduction to Architecting Systems for Scale](http://lethain.com/introduction-to-architecting-systems-for-scale/)\n        - [ ] [Scaling mobile games to a global audience using App Engine and Cloud Datastore (video)](https://www.youtube.com/watch?v=9nWyWwY2Onc)\n        - [ ] [How Google Does Planet-Scale Engineering for Planet-Scale Infra (video)](https://www.youtube.com/watch?v=H4vMcD7zKM0)\n        - [ ] [The Importance of Algorithms](https://www.topcoder.com/community/data-science/data-science-tutorials/the-importance-of-algorithms/)\n        - [ ] [Sharding](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)\n        - [ ] [Scale at Facebook (2009)](https://www.infoq.com/presentations/Scale-at-Facebook)\n        - [ ] [Scale at Facebook (2012), \"Building for a Billion Users\" (video)](https://www.youtube.com/watch?v=oodS71YtkGU)\n        - [ ] [Engineering for the Long Game - Astrid Atkinson Keynote(video)](https://www.youtube.com/watch?v=p0jGmgIrf_M&list=PLRXxvay_m8gqVlExPC5DG3TGWJTaBgqSA&index=4)\n        - [ ] [7 Years Of YouTube Scalability Lessons In 30 Minutes](http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html)\n            - [video](https://www.youtube.com/watch?v=G-lGCC4KKok)\n        - [ ] [How PayPal Scaled To Billions Of Transactions Daily Using Just 8VMs](http://highscalability.com/blog/2016/8/15/how-paypal-scaled-to-billions-of-transactions-daily-using-ju.html)\n        - [ ] [How to Remove Duplicates in Large Datasets](https://blog.clevertap.com/how-to-remove-duplicates-in-large-datasets/)\n        - [ ] [A look inside Etsy's scale and engineering culture with Jon Cowie (video)](https://www.youtube.com/watch?v=3vV4YiqKm1o)\n        - [ ] [What Led Amazon to its Own Microservices Architecture](http://thenewstack.io/led-amazon-microservices-architecture/)\n        - [ ] [To Compress Or Not To Compress, That Was Uber's Question](https://eng.uber.com/trip-data-squeeze/)\n        - [ ] [Asyncio Tarantool Queue, Get In The Queue](http://highscalability.com/blog/2016/3/3/asyncio-tarantool-queue-get-in-the-queue.html)\n        - [ ] [When Should Approximate Query Processing Be Used?](http://highscalability.com/blog/2016/2/25/when-should-approximate-query-processing-be-used.html)\n        - [ ] [Google's Transition From Single Datacenter, To Failover, To A Native Multihomed Architecture]( http://highscalability.com/blog/2016/2/23/googles-transition-from-single-datacenter-to-failover-to-a-n.html)\n        - [ ] [Spanner](http://highscalability.com/blog/2012/9/24/google-spanners-most-surprising-revelation-nosql-is-out-and.html)\n        - [ ] [Egnyte Architecture: Lessons Learned In Building And Scaling A Multi Petabyte Distributed System](http://highscalability.com/blog/2016/2/15/egnyte-architecture-lessons-learned-in-building-and-scaling.html)\n        - [ ] [Machine Learning Driven Programming: A New Programming For A New World](http://highscalability.com/blog/2016/7/6/machine-learning-driven-programming-a-new-programming-for-a.html)\n        - [ ] [The Image Optimization Technology That Serves Millions Of Requests Per Day](http://highscalability.com/blog/2016/6/15/the-image-optimization-technology-that-serves-millions-of-re.html)\n        - [ ] [A Patreon Architecture Short](http://highscalability.com/blog/2016/2/1/a-patreon-architecture-short.html)\n        - [ ] [Tinder: How Does One Of The Largest Recommendation Engines Decide Who You'll See Next?](http://highscalability.com/blog/2016/1/27/tinder-how-does-one-of-the-largest-recommendation-engines-de.html)\n        - [ ] [Design Of A Modern Cache](http://highscalability.com/blog/2016/1/25/design-of-a-modern-cache.html)\n        - [ ] [Live Video Streaming At Facebook Scale](http://highscalability.com/blog/2016/1/13/live-video-streaming-at-facebook-scale.html)\n        - [ ] [A Beginner's Guide To Scaling To 11 Million+ Users On Amazon's AWS](http://highscalability.com/blog/2016/1/11/a-beginners-guide-to-scaling-to-11-million-users-on-amazons.html)\n        - [ ] [How Does The Use Of Docker Effect Latency?](http://highscalability.com/blog/2015/12/16/how-does-the-use-of-docker-effect-latency.html)\n        - [ ] [Does AMP Counter An Existential Threat To Google?](http://highscalability.com/blog/2015/12/14/does-amp-counter-an-existential-threat-to-google.html)\n        - [ ] [A 360 Degree View Of The Entire Netflix Stack](http://highscalability.com/blog/2015/11/9/a-360-degree-view-of-the-entire-netflix-stack.html)\n        - [ ] [Latency Is Everywhere And It Costs You Sales - How To Crush It](http://highscalability.com/latency-everywhere-and-it-costs-you-sales-how-crush-it)\n        - [ ] [Serverless (very long, just need the gist)](http://martinfowler.com/articles/serverless.html)\n        - [ ] [What Powers Instagram: Hundreds of Instances, Dozens of Technologies](http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances)\n        - [ ] [Cinchcast Architecture - Producing 1,500 Hours Of Audio Every Day](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html)\n        - [ ] [Justin.Tv's Live Video Broadcasting Architecture](http://highscalability.com/blog/2010/3/16/justintvs-live-video-broadcasting-architecture.html)\n        - [ ] [Playfish's Social Gaming Architecture - 50 Million Monthly Users And Growing](http://highscalability.com/blog/2010/9/21/playfishs-social-gaming-architecture-50-million-monthly-user.html)\n        - [ ] [TripAdvisor Architecture - 40M Visitors, 200M Dynamic Page Views, 30TB Data](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.html)\n        - [ ] [PlentyOfFish Architecture](http://highscalability.com/plentyoffish-architecture)\n        - [ ] [Salesforce Architecture - How They Handle 1.3 Billion Transactions A Day](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html)\n        - [ ] [ESPN's Architecture At Scale - Operating At 100,000 Duh Nuh Nuhs Per Second](http://highscalability.com/blog/2013/11/4/espns-architecture-at-scale-operating-at-100000-duh-nuh-nuhs.html)\n        - [ ] See \"Messaging, Serialization, and Queueing Systems\" way below for info on some of the technologies that can glue services together\n        - [ ] Twitter:\n            - [O'Reilly MySQL CE 2011: Jeremy Cole, \"Big and Small Data at @Twitter\" (video)](https://www.youtube.com/watch?v=5cKTP36HVgI)\n            - [Timelines at Scale](https://www.infoq.com/presentations/Twitter-Timeline-Scalability)\n        - For even more, see \"Mining Massive Datasets\" video series in the Video Series section.\n    - [ ] Practicing the system design process: Here are some ideas to try working through on paper, each with some documentation on how it was handled in the real world:\n        - review: [System Design from HiredInTech](http://www.hiredintech.com/system-design/)\n        - [cheat sheet](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/system-design.pdf)\n        - flow:\n            1. Understand the problem and scope:\n                - define the use cases, with interviewer's help\n                - suggest additional features\n                - remove items that interviewer deems out of scope\n                - assume high availability is required, add as a use case\n            2. Think about constraints:\n                - ask how many requests per month\n                - ask how many requests per second (they may volunteer it or make you do the math)\n                - estimate reads vs. writes percentage\n                - keep 80/20 rule in mind when estimating\n                - how much data written per second\n                - total storage required over 5 years\n                - how much data read per second\n            3. Abstract design:\n                - layers (service, data, caching)\n                - infrastructure: load balancing, messaging\n                - rough overview of any key algorithm that drives the service\n                - consider bottlenecks and determine solutions\n        - Exercises:\n            - [Design a CDN network: old article](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci)\n            - [Design a random unique ID generation system](https://blog.twitter.com/2010/announcing-snowflake)\n            - [Design an online multiplayer card game](http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer-game.html)\n            - [Design a key-value database](http://www.slideshare.net/dvirsky/introduction-to-redis)\n            - [Design a function to return the top k requests during past time interval]( https://icmi.cs.ucsb.edu/research/tech_reports/reports/2005-23.pdf)\n            - [Design a picture sharing system](http://highscalability.com/blog/2011/12/6/instagram-architecture-14-million-users-terabytes-of-photos.html)\n            - [Design a recommendation system](http://ijcai13.org/files/tutorial_slides/td3.pdf)\n            - [Design a URL-shortener system: copied from above](http://www.hiredintech.com/system-design/the-system-design-process/)\n            - [Design a cache system](https://www.adayinthelifeof.nl/2011/02/06/memcache-internals/)\n\n- ### Papers\n    - These are Google papers and well-known papers.\n    - Reading all from end to end with full comprehension will likely take more time than you have. I recommend being selective on papers and their sections.\n    - [ ] [1978: Communicating Sequential Processes](http://spinroot.com/courses/summer/Papers/hoare_1978.pdf)\n        - [implemented in Go](https://godoc.org/github.com/thomas11/csp)\n        - [Love classic papers?](https://www.cs.cmu.edu/~crary/819-f09/)\n    - [ ] [2003: The Google File System](http://static.googleusercontent.com/media/research.google.com/en//archive/gfs-sosp2003.pdf)\n        - replaced by Colossus in 2012\n    - [ ] [2004: MapReduce: Simplified Data Processing on Large Clusters]( http://static.googleusercontent.com/media/research.google.com/en//archive/mapreduce-osdi04.pdf)\n        - mostly replaced by Cloud Dataflow?\n    - [ ] [2007: What Every Programmer Should Know About Memory (very long, and the author encourages skipping of some sections)](https://www.akkadia.org/drepper/cpumemory.pdf)\n    - [ ] [2012: Google's Colossus](https://www.wired.com/2012/07/google-colossus/)\n        - paper not available\n    - [ ] 2012: AddressSanitizer: A Fast Address Sanity Checker:\n        - [paper](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37752.pdf)\n        - [video](https://www.usenix.org/conference/atc12/technical-sessions/presentation/serebryany)\n    - [ ] 2013: Spanner: Google’s Globally-Distributed Database:\n        - [paper](http://static.googleusercontent.com/media/research.google.com/en//archive/spanner-osdi2012.pdf)\n        - [video](https://www.usenix.org/node/170855)\n    - [ ] [2014: Machine Learning: The High-Interest Credit Card of Technical Debt](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43146.pdf)\n    - [ ] [2015: Continuous Pipelines at Google](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43790.pdf)\n    - [ ] [2015: High-Availability at Massive Scale: Building Google’s Data Infrastructure for Ads](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44686.pdf)\n    - [ ] [2015: TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems](http://download.tensorflow.org/paper/whitepaper2015.pdf )\n    - [ ] [2015: How Developers Search for Code: A Case Study](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43835.pdf)\n    - [ ] [2016: Borg, Omega, and Kubernetes](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44843.pdf)\n\n- ### Testing\n    - To cover:\n        - how unit testing works\n        - what are mock objects\n        - what is integration testing\n        - what is dependency injection\n    - [ ] [Agile Software Testing with James Bach (video)](https://www.youtube.com/watch?v=SAhJf36_u5U)\n    - [ ] [Open Lecture by James Bach on Software Testing (video)](https://www.youtube.com/watch?v=ILkT_HV9DVU)\n    - [ ] [Steve Freeman - Test-Driven Development (that’s not what we meant) (video)](https://vimeo.com/83960706)\n        - [slides](http://gotocon.com/dl/goto-berlin-2013/slides/SteveFreeman_TestDrivenDevelopmentThatsNotWhatWeMeant.pdf)\n    - [ ] [TDD is dead. Long live testing.](http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html)\n    - [ ] [Is TDD dead? (video)](https://www.youtube.com/watch?v=z9quxZsLcfo)\n    - [ ] [Video series (152 videos) - not all are needed (video)](https://www.youtube.com/watch?v=nzJapzxH_rE&list=PLAwxTw4SYaPkWVHeC_8aSIbSxE_NXI76g)\n    - [ ] [Test-Driven Web Development with Python](http://www.obeythetestinggoat.com/pages/book.html#toc)\n    - [ ] Dependency injection:\n        - [ ] [video](https://www.youtube.com/watch?v=IKD2-MAkXyQ)\n        - [ ] [Tao Of Testing](http://jasonpolites.github.io/tao-of-testing/ch3-1.1.html)\n    - [ ] [How to write tests](http://jasonpolites.github.io/tao-of-testing/ch4-1.1.html)\n\n- ### Scheduling\n    - in an OS, how it works\n    - can be gleaned from Operating System videos\n\n- ### Implement system routines\n    - understand what lies beneath the programming APIs you use\n    - can you implement them?\n\n- ### String searching & manipulations\n    - [ ] [Search pattern in text (video)](https://www.coursera.org/learn/data-structures/lecture/tAfHI/search-pattern-in-text)\n    - [ ] Rabin-Karp (videos):\n        - [Rabin Karps Algorithm](https://www.coursera.org/learn/data-structures/lecture/c0Qkw/rabin-karps-algorithm)\n        - [Precomputing](https://www.coursera.org/learn/data-structures/lecture/nYrc8/optimization-precomputation)\n        - [Optimization: Implementation and Analysis](https://www.coursera.org/learn/data-structures/lecture/h4ZLc/optimization-implementation-and-analysis)\n        - [Table Doubling, Karp-Rabin](https://www.youtube.com/watch?v=BRO7mVIFt08&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=9)\n        - [Rolling Hashes, Amortized Analysis](https://www.youtube.com/watch?v=w6nuXg0BISo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=32)\n    - [ ] Knuth-Morris-Pratt (KMP):\n        - [Pratt Algorithm](https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm)\n        - [Tutorial: The Knuth-Morris-Pratt (KMP) String Matching Algorithm](https://www.youtube.com/watch?v=2ogqPWJSftE)\n    - [ ] Boyer–Moore string search algorithm\n        - [Boyer-Moore String Search Algorithm](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm)\n        - [Advanced String Searching Boyer-Moore-Horspool Algorithms (video)](https://www.youtube.com/watch?v=QDZpzctPf10)\n    - [ ] [Coursera: Algorithms on Strings](https://www.coursera.org/learn/algorithms-on-strings/home/week/1)\n\n---\n\n## Final Review \n\n    This section will have shorter videos that can you watch pretty quickly to review most of the important concepts.\n    It's nice if you want a refresher often.\n    (More items will be added here)\n\n#### General:\n\n- [ ] Series of 2-3 minutes short subject videos (23 videos)\n    - [Videos](https://www.youtube.com/watch?v=r4r1DZcx1cM&list=PLmVb1OknmNJuC5POdcDv5oCS7_OUkDgpj&index=22)\n- [ ] Series of 2-5 minutes short subject videos - Michael Sambol (18 videos):\n    - [Videos](https://www.youtube.com/channel/UCzDJwLWoYCUQowF_nG3m5OQ)\n\n#### Sorts:\n\n- [ ] Merge Sort: https://www.youtube.com/watch?v=GCae1WNvnZM\n\n\n---\n\n## Coding Question Practice\n\nNow that you know all the computer science topics above, it's time to practice answering coding problems.\n\n**Coding question practice is not about memorizing answers to programming problems.**\n\nWhy you need to practice doing programming problems:\n- problem recognition, and where the right data structures and algorithms fit in\n- gathering requirements for the problem\n- talking your way through the problem like you will in the interview\n- coding on a whiteboard or paper, not a computer\n- coming up with time and space complexity for your solutions\n- testing your solutions\n\nThere is a great intro for methodical, communicative problem solving in an interview. You'll get this from the programming \ninterview books, too, but I found this outstanding:\n- [ ] [Algorithm design canvas](http://www.hiredintech.com/algorithm-design/)\n\nNo whiteboard at home? That makes sense. I'm a weirdo and have a big whiteboard. Instead of a whiteboard, pick up a \nlarge drawing pad from an art store. You can sit on the couch and practice. This is my \"sofa whiteboard\". \nI added the pen in the photo for scale.\n\n![my sofa whiteboard](https://dng5l3qzreal6.cloudfront.net/2016/Oct/art_board_sm_2-1476233630368.jpg)\n\nSupplemental:\n\n- [Mathematics for Topcoders](https://www.topcoder.com/community/data-science/data-science-tutorials/mathematics-for-topcoders/)\n- [Dynamic Programming – From Novice to Advanced](https://www.topcoder.com/community/data-science/data-science-tutorials/dynamic-programming-from-novice-to-advanced/)\n- [MIT Interview Materials](https://web.archive.org/web/20160906124824/http://courses.csail.mit.edu/iap/interview/materials.php)\n- [Exercises for getting better at a given language](http://exercism.io/languages)\n\n**Read as a review and problem recognition**\n- [ ] [Algorithm Design Manual](http://www.amazon.com/Algorithm-Design-Manual-Steven-Skiena/dp/1849967202) (Skiena)\n    - To quote Yegge: \"More than any other book it helped me understand just how astonishingly commonplace \n        (and important) graph problems are – they should be part of every working programmer's toolkit. The book also \n        covers basic data structures and sorting algorithms, which is a nice bonus. But the gold mine is the second half \n        of the book, which is a sort of encyclopedia of 1-pagers on zillions of useful problems and various ways to solve \n        them, without too much detail. Almost every 1-pager has a simple picture, making it easy to remember. This is a \n        great way to learn how to identify hundreds of problem types.\"\n    - Can rent it on kindle\n    - Half.com is a great resource for textbooks at good prices.\n    - Answers:\n        - [Solutions](http://www.algorithm.cs.sunysb.edu/algowiki/index.php/The_Algorithms_Design_Manual_(Second_Edition))\n        - [Solutions](http://blog.panictank.net/category/algorithmndesignmanualsolutions/page/2/)\n    - [Errata](http://www3.cs.stonybrook.edu/~skiena/algorist/book/errata)\n\n**Read and Do Programming Problems (in this order):**\n- [ ] [Programming Interviews Exposed: Secrets to Landing Your Next Job, 2nd Edition](http://www.wiley.com/WileyCDA/WileyTitle/productCd-047012167X.html)\n    - recommended in Google candidate coaching\n- [ ] [Cracking the Coding Interview, 6th Edition](http://www.amazon.com/Cracking-Coding-Interview-6th-Programming/dp/0984782850/)\n    - recommended on the [Google Careers site](https://www.google.com/about/careers/how-we-hire/interview/)\n    - If you see people reference \"The Google Resume\", it was a book replaced by \"Cracking the Coding Interview\".\n\n**If you have time**\n- [ ] [Programming Pearls](http://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880)\n- [ ] [Algorithms and Programming: Problems and Solutions](http://www.amazon.com/Algorithms-Programming-Solutions-Alexander-Shen/dp/0817638474)\n- [ ] [Introduction to Algorithms](https://www.amazon.com/Introduction-Algorithms-3rd-MIT-Press/dp/0262033844)\n    - To quote Yegge: \"But if you want to come into your interviews *prepped*, then consider deferring your application until you've made your way through that book.\"\n    - Half.com is a great resource for textbooks at good prices.\n    - aka CLR, sometimes CLRS, because Stein was late to the game\n- [ ] [Elements of Programming Interviews](https://www.amazon.com/Elements-Programming-Interviews-Insiders-Guide/dp/1479274836)\n    - all code is in C++, if you're looking to use C++ in your interview\n    - good book on problem solving in general.\n\n## Coding exercises/challenges\n\nOnce you've learned your brains out, put those brains to work.\nTake coding challenges every day, as many as you can.\n\n- [ ] [How to Find a Solution](https://www.topcoder.com/community/data-science/data-science-tutorials/how-to-find-a-solution/)\n- [ ] [How to Dissect a Topcoder Problem Statement](https://www.topcoder.com/community/data-science/data-science-tutorials/how-to-dissect-a-topcoder-problem-statement/)\n\nChallenge sites:\n- [LeetCode](https://leetcode.com/)\n- [TopCoder](https://www.topcoder.com/)\n- [Project Euler (math-focused)](https://projecteuler.net/index.php?section=problems)\n- [Codewars](http://www.codewars.com)\n- [HackerRank](https://www.hackerrank.com/)\n- [Codility](https://codility.com/programmers/)\n- [InterviewCake](https://www.interviewcake.com/)\n- [InterviewBit](https://www.interviewbit.com/invite/icjf)\n\nMaybe:\n- [Mock interviewers from big companies](http://www.gainlo.co/)\n\n## Once you're closer to the interview\n\n- [ ] Cracking The Coding Interview Set 2 (videos):\n    - [Cracking The Code Interview](https://www.youtube.com/watch?v=4NIb9l3imAo)\n    - [Cracking the Coding Interview - Fullstack Speaker Series](https://www.youtube.com/watch?v=Eg5-tdAwclo)\n    - [Ask Me Anything: Gayle Laakmann McDowell (author of Cracking the Coding Interview)](https://www.youtube.com/watch?v=1fqxMuPmGak)\n\n## Your Resume\n\n- [Ten Tips for a (Slightly) Less Awful Resume](http://steve-yegge.blogspot.co.uk/2007_09_01_archive.html)\n- Great stuff at the back of Cracking The Coding Interview\n\n\n## Be thinking of for when the interview comes\n\nThink of about 20 interview questions you'll get, along the lines of the items below. Have 2-3 answers for each.\nHave a story, not just data, about something you accomplished.\n\n- Why do you want this job?\n- What's a tough problem you've solved?\n- Biggest challenges faced?\n- Best/worst designs seen?\n- Ideas for improving an existing Google product.\n- How do you work best, as an individual and as part of a team?\n- Which of your skills or experiences would be assets in the role and why?\n- What did you most enjoy at [job x / project y]?\n- What was the biggest challenge you faced at [job x / project y]?\n- What was the hardest bug you faced at [job x / project y]?\n- What did you learn at [job x / project y]?\n- What would you have done better at [job x / project y]?\n\n## Have questions for the interviewer\n\n    Some of mine (I already may know answer to but want their opinion or team perspective):\n\n- How large is your team?\n- What is your dev cycle look like? Do you do waterfall/sprints/agile?\n- Are rushes to deadlines common? Or is there flexibility?\n- How are decisions made in your team?\n- How many meetings do you have per week?\n- Do you feel your work environment helps you concentrate?\n- What are you working on?\n- What do you like about it?\n- What is the work life like?\n\n## Once You've Got The Job\n\nCongratulations!\n\n- [10 things I wish I knew on my first day at Google](https://medium.com/@moonstorming/10-things-i-wish-i-knew-on-my-first-day-at-google-107581d87286#.livxn7clw)\n\nKeep learning.\n\nYou're never really done.\n\n---\n\n    *****************************************************************************************************\n    *****************************************************************************************************\n    \n    Everything below this point is optional. These are my recommendations, not Google's. \n    By studying these, you'll get greater exposure to more CS concepts, and will be better prepared for \n    any software engineering job. You'll be a much more well-rounded software engineer.\n\n    *****************************************************************************************************\n    *****************************************************************************************************\n\n---\n\n## Additional Books\n\n- [ ] [C Programming Language, Vol 2](https://www.amazon.com/Programming-Language-Brian-W-Kernighan/dp/0131103628)\n    - [answers to questions](https://github.com/lekkas/c-algorithms)\n- [ ] [The Unix Programming Environment](http://product.half.ebay.com/The-UNIX-Programming-Environment-by-Brian-W-Kernighan-and-Rob-Pike-1983-Other/54385&tg=info)\n    - and oldie but a goodie\n- [ ] [The Linux Command Line: A Complete Introduction](https://www.amazon.com/dp/1593273894/)\n    - a modern option\n- [ ] [TCP/IP Illustrated Series](https://en.wikipedia.org/wiki/TCP/IP_Illustrated)\n- [ ] [Head First Design Patterns](https://www.amazon.com/gp/product/0596007124/)\n    - a gentle introduction to design patterns\n- [ ] [Design Patterns: Elements of Reusable Object-Oriente​d Software](https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612)\n    - aka the \"Gang Of Four\" book, or GOF\n    - the canonical design patterns book\n- [ ] [Site Reliability Engineering](https://landing.google.com/sre/book.html)\n    - [Site Reliability Engineering: How Google Runs Production Systems](https://landing.google.com/sre/)\n- [ ] [UNIX and Linux System Administration Handbook, 4th Edition](https://www.amazon.com/UNIX-Linux-System-Administration-Handbook/dp/0131480057/)\n\n## Additional Learning\n\n- ### Unicode\n    - [ ] [The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets]( http://www.joelonsoftware.com/articles/Unicode.html)\n    - [ ] [What Every Programmer Absolutely, Positively Needs To Know About Encodings And Character Sets To Work With Text](http://kunststube.net/encoding/)\n\n- ### Endianness\n    - [ ] [Big And Little Endian](https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html)\n    - [ ] [Big Endian Vs Little Endian (video)](https://www.youtube.com/watch?v=JrNF0KRAlyo)\n    - [ ] [Big And Little Endian Inside/Out (video)](https://www.youtube.com/watch?v=oBSuXP-1Tc0)\n        - Very technical talk for kernel devs. Don't worry if most is over your head.\n        - The first half is enough.\n\n- ### Emacs and vi(m)\n    - suggested by Yegge, from an old Amazon recruiting post: Familiarize yourself with a unix-based code editor\n    - vi(m):\n        - [Editing With vim 01 - Installation, Setup, and The Modes (video)](https://www.youtube.com/watch?v=5givLEMcINQ&index=1&list=PL13bz4SHGmRxlZVmWQ9DvXo1fEg4UdGkr)\n        - [VIM Adventures](http://vim-adventures.com/)\n        - set of 4 videos:\n            - [The vi/vim editor - Lesson 1](https://www.youtube.com/watch?v=SI8TeVMX8pk)\n            - [The vi/vim editor - Lesson 2](https://www.youtube.com/watch?v=F3OO7ZIOaJE)\n            - [The vi/vim editor - Lesson 3](https://www.youtube.com/watch?v=ZYEccA_nMaI)\n            - [The vi/vim editor - Lesson 4](https://www.youtube.com/watch?v=1lYD5gwgZIA)\n        - [Using Vi Instead of Emacs](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#Using_Vi_instead_of_Emacs)\n    - emacs:\n        - [Basics Emacs Tutorial (video)](https://www.youtube.com/watch?v=hbmV1bnQ-i0)\n        - set of 3 (videos):\n            - [Emacs Tutorial (Beginners) -Part 1- File commands, cut/copy/paste, cursor commands](https://www.youtube.com/watch?v=ujODL7MD04Q)\n            - [Emacs Tutorial (Beginners) -Part 2- Buffer management, search, M-x grep and rgrep modes](https://www.youtube.com/watch?v=XWpsRupJ4II)\n            - [Emacs Tutorial (Beginners) -Part 3- Expressions, Statements, ~/.emacs file and packages](https://www.youtube.com/watch?v=paSgzPso-yc)\n        - [Evil Mode: Or, How I Learned to Stop Worrying and Love Emacs (video)](https://www.youtube.com/watch?v=JWD1Fpdd4Pc)\n        - [Writing C Programs With Emacs](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#Writing_C_programs_with_Emacs)\n        - [(maybe) Org Mode In Depth: Managing Structure (video)](https://www.youtube.com/watch?v=nsGYet02bEk)\n\n- ### Unix command line tools\n    - suggested by Yegge, from an old Amazon recruiting post. I filled in the list below from good tools.\n    - [ ] bash\n    - [ ] cat\n    - [ ] grep\n    - [ ] sed\n    - [ ] awk\n    - [ ] curl or wget\n    - [ ] sort\n    - [ ] tr\n    - [ ] uniq\n    - [ ] [strace](https://en.wikipedia.org/wiki/Strace)\n    - [ ] [tcpdump](https://danielmiessler.com/study/tcpdump/)\n\n- ### Information theory (videos)\n    - [ ] [Khan Academy](https://www.khanacademy.org/computing/computer-science/informationtheory)\n    - [ ] more about Markov processes:\n        - [ ] [Core Markov Text Generation](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/waxgx/core-markov-text-generation)\n        - [ ] [Core Implementing Markov Text Generation](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/gZhiC/core-implementing-markov-text-generation)\n        - [ ] [Project = Markov Text Generation Walk Through](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/EUjrq/project-markov-text-generation-walk-through)\n    - See more in MIT 6.050J Information and Entropy series below. \n\n- ### Parity & Hamming Code (videos)\n    - [ ] [Intro](https://www.youtube.com/watch?v=q-3BctoUpHE)\n    - [ ] [Parity](https://www.youtube.com/watch?v=DdMcAUlxh1M)\n    - [ ] Hamming Code:\n        - [Error detection](https://www.youtube.com/watch?v=1A_NcXxdoCc)\n        - [Error correction](https://www.youtube.com/watch?v=JAMLuxdHH8o)\n    - [ ] [Error Checking](https://www.youtube.com/watch?v=wbH2VxzmoZk)\n\n- ### Entropy\n    - also see videos below\n    - make sure to watch information theory videos first\n    - [ ] [Information Theory, Claude Shannon, Entropy, Redundancy, Data Compression & Bits (video)](https://youtu.be/JnJq3Py0dyM?t=176)\n\n- ### Cryptography\n    - also see videos below\n    - make sure to watch information theory videos first\n    - [ ] [Khan Academy Series](https://www.khanacademy.org/computing/computer-science/cryptography)\n    - [ ] [Cryptography: Hash Functions](https://www.youtube.com/watch?v=KqqOXndnvic&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=30)\n    - [ ] [Cryptography: Encryption](https://www.youtube.com/watch?v=9TNI2wHmaeI&index=31&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n\n- ### Compression\n    - make sure to watch information theory videos first\n    - [ ] Computerphile (videos): \n        - [ ] [Compression](https://www.youtube.com/watch?v=Lto-ajuqW3w)\n        - [ ] [Entropy in Compression](https://www.youtube.com/watch?v=M5c_RFKVkko)\n        - [ ] [Upside Down Trees (Huffman Trees)](https://www.youtube.com/watch?v=umTbivyJoiI)\n        - [ ] [EXTRA BITS/TRITS - Huffman Trees](https://www.youtube.com/watch?v=DV8efuB3h2g)\n        - [ ] [Elegant Compression in Text (The LZ 77 Method)](https://www.youtube.com/watch?v=goOa3DGezUA)\n        - [ ] [Text Compression Meets Probabilities](https://www.youtube.com/watch?v=cCDCfoHTsaU)\n    - [ ] [Compressor Head videos](https://www.youtube.com/playlist?list=PLOU2XLYxmsIJGErt5rrCqaSGTMyyqNt2H)\n    - [ ] [(optional) Google Developers Live: GZIP is not enough!](https://www.youtube.com/watch?v=whGwm0Lky2s)\n\n- ### Networking (videos)\n    - [ ] [Khan Academy](https://www.khanacademy.org/computing/computer-science/internet-intro)\n    - [ ] [UDP and TCP: Comparison of Transport Protocols](https://www.youtube.com/watch?v=Vdc8TCESIg8)\n    - [ ] [TCP/IP and the OSI Model Explained!](https://www.youtube.com/watch?v=e5DEVa9eSN0)\n    - [ ] [Packet Transmission across the Internet. Networking & TCP/IP tutorial.](https://www.youtube.com/watch?v=nomyRJehhnM)\n    - [ ] [HTTP](https://www.youtube.com/watch?v=WGJrLqtX7As)\n    - [ ] [SSL and HTTPS](https://www.youtube.com/watch?v=S2iBR2ZlZf0)\n    - [ ] [SSL/TLS](https://www.youtube.com/watch?v=Rp3iZUvXWlM)\n    - [ ] [HTTP 2.0](https://www.youtube.com/watch?v=E9FxNzv1Tr8)\n    - [ ] [Video Series (21 videos)](https://www.youtube.com/playlist?list=PLEbnTDJUr_IegfoqO4iPnPYQui46QqT0j)\n    - [ ] [Subnetting Demystified - Part 5 CIDR Notation](https://www.youtube.com/watch?v=t5xYI0jzOf4)\n\n- ### Computer Security\n    - [MIT (23 videos)](https://www.youtube.com/playlist?list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Introduction, Threat Models](https://www.youtube.com/watch?v=GqmQg-cszw4&index=1&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Control Hijacking Attacks](https://www.youtube.com/watch?v=6bwzNg5qQ0o&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh&index=2)\n        - [ ] [Buffer Overflow Exploits and Defenses](https://www.youtube.com/watch?v=drQyrzRoRiA&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh&index=3)\n        - [ ] [Privilege Separation](https://www.youtube.com/watch?v=6SIJmoE9L9g&index=4&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Capabilities](https://www.youtube.com/watch?v=8VqTSY-11F4&index=5&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Sandboxing Native Code](https://www.youtube.com/watch?v=VEV74hwASeU&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh&index=6)\n        - [ ] [Web Security Model](https://www.youtube.com/watch?v=chkFBigodIw&index=7&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Securing Web Applications](https://www.youtube.com/watch?v=EBQIGy1ROLY&index=8&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Symbolic Execution](https://www.youtube.com/watch?v=yRVZPvHYHzw&index=9&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Network Security](https://www.youtube.com/watch?v=SIEVvk3NVuk&index=11&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Network Protocols](https://www.youtube.com/watch?v=QOtA76ga_fY&index=12&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [Side-Channel Attacks](https://www.youtube.com/watch?v=PuVMkSEcPiI&index=15&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n\n- ### Garbage collection\n    - [ ] [Garbage collection (Java); Augmenting data str (video)](https://www.youtube.com/watch?v=StdfeXaKGEc&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=25)\n    - [ ] [Compilers (video)](https://www.youtube.com/playlist?list=PLO9y7hOkmmSGTy5z6HZ-W4k2y8WXF7Bff)\n    - [ ] [GC in Python (video)](https://www.youtube.com/watch?v=iHVs_HkjdmI)\n    - [ ] [Deep Dive Java: Garbage Collection is Good!](https://www.infoq.com/presentations/garbage-collection-benefits)\n    - [ ] [Deep Dive Python: Garbage Collection in CPython (video)](https://www.youtube.com/watch?v=P-8Z0-MhdQs&list=PLdzf4Clw0VbOEWOS_sLhT_9zaiQDrS5AR&index=3)\n\n- ### Parallel Programming\n    - [ ] [Coursera (Scala)](https://www.coursera.org/learn/parprog1/home/week/1)\n    - [ ] [Efficient Python for High Performance Parallel Computing (video)](https://www.youtube.com/watch?v=uY85GkaYzBk)\n\n- ### Design patterns\n    - [ ] [Quick UML review (video)](https://www.youtube.com/watch?v=3cmzqZzwNDM&list=PLGLfVvz_LVvQ5G-LdJ8RLqe-ndo7QITYc&index=3)\n    - [ ] Learn these patterns:\n        - [ ] strategy\n        - [ ] singleton\n        - [ ] adapter\n        - [ ] prototype\n        - [ ] decorator\n        - [ ] visitor\n        - [ ] factory, abstract factory\n        - [ ] facade\n        - [ ] observer\n        - [ ] proxy\n        - [ ] delegate\n        - [ ] command\n        - [ ] state\n        - [ ] memento\n        - [ ] iterator\n        - [ ] composite\n        - [ ] flyweight\n    - [ ] [Chapter 6 (Part 1) - Patterns (video)](https://youtu.be/LAP2A80Ajrg?list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO&t=3344)\n    - [ ] [Chapter 6 (Part 2) - Abstraction-Occurrence, General Hierarchy, Player-Role, Singleton, Observer, Delegation (video)](https://www.youtube.com/watch?v=U8-PGsjvZc4&index=12&list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n    - [ ] [Chapter 6 (Part 3) - Adapter, Facade, Immutable, Read-Only Interface, Proxy (video)](https://www.youtube.com/watch?v=7sduBHuex4c&index=13&list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n    - [ ] [Series of videos (27 videos)](https://www.youtube.com/playlist?list=PLF206E906175C7E07)\n    - [ ] [Head First Design Patterns](https://www.amazon.com/Head-First-Design-Patterns-Freeman/dp/0596007124)\n        - I know the canonical book is \"Design Patterns: Elements of Reusable Object-Oriented Software\", but Head First is great for beginners to OO.\n    - [ ] [Handy reference: 101 Design Patterns & Tips for Developers](https://sourcemaking.com/design-patterns-and-tips)\n\n- ### Messaging, Serialization, and Queueing Systems\n    - [ ] [Thrift](https://thrift.apache.org/)\n        - [Tutorial](http://thrift-tutorial.readthedocs.io/en/latest/intro.html)\n    - [ ] [Protocol Buffers](https://developers.google.com/protocol-buffers/)\n        - [Tutorials](https://developers.google.com/protocol-buffers/docs/tutorials)\n    - [ ] [gRPC](http://www.grpc.io/)\n        - [gRPC 101 for Java Developers (video)](https://www.youtube.com/watch?v=5tmPvSe7xXQ&list=PLcTqM9n_dieN0k1nSeN36Z_ppKnvMJoly&index=1)\n    - [ ] [Redis](http://redis.io/)\n        - [Tutorial](http://try.redis.io/)\n    - [ ] [Amazon SQS (queue)](https://aws.amazon.com/sqs/)\n    - [ ] [Amazon SNS (pub-sub)](https://aws.amazon.com/sns/)\n    - [ ] [RabbitMQ](https://www.rabbitmq.com/)\n        - [Get Startet](https://www.rabbitmq.com/getstarted.html)\n    - [ ] [Celery](http://www.celeryproject.org/)\n        - [First Steps With Celery](http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html)\n    - [ ] [ZeroMQ](http://zeromq.org/)\n        - [Intro - Read The Manual](http://zeromq.org/intro:read-the-manual)\n    - [ ] [ActiveMQ](http://activemq.apache.org/)\n    - [ ] [Kafka](http://kafka.apache.org/documentation.html#introduction)\n    - [ ] [MessagePack](http://msgpack.org/index.html)\n    - [ ] [Avro](https://avro.apache.org/)\n\n- ### Fast Fourier Transform\n    - [ ] [What is a Fourier transform? What is it used for?](http://www.askamathematician.com/2012/09/q-what-is-a-fourier-transform-what-is-it-used-for/)\n    - [ ] [What is the Fourier Transform? (video)](https://www.youtube.com/watch?v=Xxut2PN-V8Q)\n    - [ ] [Divide & Conquer: FFT (video)](https://www.youtube.com/watch?v=iTMn0Kt18tg&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=4)\n    - [ ] [Understanding The FFT](http://jakevdp.github.io/blog/2013/08/28/understanding-the-fft/)\n\n- ### Bloom Filter\n    - Given a Bloom filter with m bits and k hashing functions, both insertion and membership testing are O(k)\n    - [Bloom Filters](https://www.youtube.com/watch?v=-SuTGoFYjZs)\n    - [Bloom Filters | Mining of Massive Datasets | Stanford University](https://www.youtube.com/watch?v=qBTdukbzc78)\n    - [Tutorial](http://billmill.org/bloomfilter-tutorial/)\n    - [How To Write A Bloom Filter App](http://blog.michaelschmatz.com/2016/04/11/how-to-write-a-bloom-filter-cpp/)\n\n- ### van Emde Boas Trees\n    - [ ] [Divide & Conquer: van Emde Boas Trees (video)](https://www.youtube.com/watch?v=hmReJCupbNU&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=6)\n    - [ ] [MIT Lecture Notes](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-design-and-analysis-of-algorithms-spring-2012/lecture-notes/MIT6_046JS12_lec15.pdf)\n\n- ### Augmented Data Structures\n    - [ ] [CS 61B Lecture 39: Augmenting Data Structures](https://youtu.be/zksIj9O8_jc?list=PL4BBB74C7D2A1049C&t=950)\n\n- ### Skip lists\n    - \"These are somewhat of a cult data structure\" - Skiena\n    - [ ] [Randomization: Skip Lists (video)](https://www.youtube.com/watch?v=2g9OSRKJuzM&index=10&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [For animations and a little more detail](https://en.wikipedia.org/wiki/Skip_list)\n\n- ### Network Flows\n    - [ ] [Ford-Fulkerson in 5 minutes (video)](https://www.youtube.com/watch?v=v1VgJmkEJW0)\n    - [ ] [Ford-Fulkerson Algorithm (video)](https://www.youtube.com/watch?v=v1VgJmkEJW0)\n    - [ ] [Network Flows (video)](https://www.youtube.com/watch?v=2vhN4Ice5jI)\n\n- ### Disjoint Sets & Union Find\n    - [ ] [Disjoint Set](https://en.wikipedia.org/wiki/Disjoint-set_data_structure)\n    - [ ] [UCB 61B - Disjoint Sets; Sorting & selection (video)](https://www.youtube.com/watch?v=MAEGXTwmUsI&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=21)\n    - [ ] Coursera (not needed since the above video explains it great):\n        - [ ] [Overview](https://www.coursera.org/learn/data-structures/lecture/JssSY/overview)\n        - [ ] [Naive Implementation](https://www.coursera.org/learn/data-structures/lecture/EM5D0/naive-implementations)\n        - [ ] [Trees](https://www.coursera.org/learn/data-structures/lecture/Mxu0w/trees)\n        - [ ] [Union By Rank](https://www.coursera.org/learn/data-structures/lecture/qb4c2/union-by-rank)\n        - [ ] [Path Compression](https://www.coursera.org/learn/data-structures/lecture/Q9CVI/path-compression)\n        - [ ] [Analysis Options](https://www.coursera.org/learn/data-structures/lecture/GQQLN/analysis-optional)\n\n- ### Math for Fast Processing\n    - [ ] [Integer Arithmetic, Karatsuba Multiplication (video)](https://www.youtube.com/watch?v=eCaXlAaN2uE&index=11&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [The Chinese Remainder Theorem (used in cryptography) (video)](https://www.youtube.com/watch?v=ru7mWZJlRQg)\n    \n- ### Treap\n    - Combination of a binary search tree and a heap\n    - [ ] [Treap](https://en.wikipedia.org/wiki/Treap)\n    - [ ] [Data Structures: Treaps explained (video)](https://www.youtube.com/watch?v=6podLUYinH8)\n    - [ ] [Applications in set operations](https://www.cs.cmu.edu/~scandal/papers/treaps-spaa98.pdf)\n    \n- ### Linear Programming (videos)\n    - [ ] [Linear Programming](https://www.youtube.com/watch?v=M4K6HYLHREQ)\n    - [ ] [Finding minimum cost](https://www.youtube.com/watch?v=2ACJ9ewUC6U)\n    - [ ] [Finding maximum value](https://www.youtube.com/watch?v=8AA_81xI3ik)\n\n- ### Geometry, Convex hull (videos)\n    - [ ] [Graph Alg. IV: Intro to geometric algorithms - Lecture 9](https://youtu.be/XIAQRlNkJAw?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3164)\n    - [ ] [Geometric Algorithms: Graham & Jarvis - Lecture 10](https://www.youtube.com/watch?v=J5aJEcOr6Eo&index=10&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n    - [ ] [Divide & Conquer: Convex Hull, Median Finding](https://www.youtube.com/watch?v=EzeYI7p9MjU&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=2)\n\n- ### Discrete math\n    - see videos below\n\n- ### Machine Learning\n    - [ ] Why ML?\n        - [ ] [How Google Is Remaking Itself As A Machine Learning First Company](https://backchannel.com/how-google-is-remaking-itself-as-a-machine-learning-first-company-ada63defcb70)\n        - [ ] [Large-Scale Deep Learning for Intelligent Computer Systems (video)](https://www.youtube.com/watch?v=QSaZGT4-6EY)\n        - [ ] [Deep Learning and Understandability versus Software Engineering and Verification by Peter Norvig](https://www.youtube.com/watch?v=X769cyzBNVw)\n    - [ ] [Google's Cloud Machine learning tools (video)](https://www.youtube.com/watch?v=Ja2hxBAwG_0)\n    - [ ] [Google Developers' Machine Learning Recipes (Scikit Learn & Tensorflow) (video)](https://www.youtube.com/playlist?list=PLOU2XLYxmsIIuiBfYad6rFYQU_jL2ryal)\n    - [ ] [Tensorflow (video)](https://www.youtube.com/watch?v=oZikw5k_2FM)\n    - [ ] [Tensorflow Tutorials](https://www.tensorflow.org/versions/r0.11/tutorials/index.html)\n    - [ ] [Practical Guide to implementing Neural Networks in Python](using Theano)])http://www.analyticsvidhya.com/blog/2016/04/neural-networks-python-theano/)\n    - Courses:\n        - [Great starter course: Machine Learning](https://www.coursera.org/learn/machine-learning)\n              - [videos only](https://www.youtube.com/playlist?list=PLZ9qNFMHZ-A4rycgrgOYma6zxF4BZGGPW)\n              - see videos 12-18 for a review of linear algebra (14 and 15 are duplicates)\n        - [Neural Networks for Machine Learning](https://www.coursera.org/learn/neural-networks)\n        - [Google's Deep Learning Nanodegree](https://www.udacity.com/course/deep-learning--ud730)\n        - [Google/Kaggle Machine Learning Engineer Nanodegree](https://www.udacity.com/course/machine-learning-engineer-nanodegree-by-google--nd009)\n        - [Self-Driving Car Engineer Nanodegree](https://www.udacity.com/drive)\n        - [Metis Online Course ($99 for 2 months)](http://www.thisismetis.com/explore-data-science)\n    - Resources:\n        - Books:\n            - [Python Machine Learning](https://www.amazon.com/Python-Machine-Learning-Sebastian-Raschka/dp/1783555130/)\n            - [Data Science from Scratch: First Principles with Python](https://www.amazon.com/Data-Science-Scratch-Principles-Python/dp/149190142X)\n            - [Introduction to Machine Learning with Python](https://www.amazon.com/Introduction-Machine-Learning-Python-Scientists/dp/1449369413/)\n        - [Machine Learning for Software Engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers)\n        - Data School: http://www.dataschool.io/\n\n- ### Go\n    - [ ] Videos:\n        - [ ] [Why Learn Go?](https://www.youtube.com/watch?v=FTl0tl9BGdc)\n        - [ ] [Go Programming](https://www.youtube.com/watch?v=CF9S4QZuV30)\n        - [ ] [A Tour of Go](https://www.youtube.com/watch?v=ytEkHepK08c)\n    - [ ] Books:\n        - [ ] [An Introduction to Programming in Go (read free online)](https://www.golang-book.com/books/intro)\n        - [ ] [The Go Programming Language (Donovan & Kernighan)](https://www.amazon.com/Programming-Language-Addison-Wesley-Professional-Computing/dp/0134190440)\n    - [ ] [Bootcamp](https://www.golang-book.com/guides/bootcamp)\n\n--\n\n## Additional Detail on Some Subjects\n\n    I added these to reinforce some ideas already presented above, but didn't want to include them\n    above because it's just too much. It's easy to overdo it on a subject.\n    You want to get hired in this century, right?\n\n- [ ] **More Dynamic Programming** (videos)\n    - [ ] [6.006: Dynamic Programming I: Fibonacci, Shortest Paths](https://www.youtube.com/watch?v=OQ5jsbhAv_M&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=19)\n    - [ ] [6.006: Dynamic Programming II: Text Justification, Blackjack](https://www.youtube.com/watch?v=ENyox7kNKeY&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=20)\n    - [ ] [6.006: DP III: Parenthesization, Edit Distance, Knapsack](https://www.youtube.com/watch?v=ocZMDMZwhCY&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=21)\n    - [ ] [6.006: DP IV: Guitar Fingering, Tetris, Super Mario Bros.](https://www.youtube.com/watch?v=tp4_UXaVyx8&index=22&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [6.046: Dynamic Programming & Advanced DP](https://www.youtube.com/watch?v=Tw1k46ywN6E&index=14&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [6.046: Dynamic Programming: All-Pairs Shortest Paths](https://www.youtube.com/watch?v=NzgFUwOaoIw&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=15)\n    - [ ] [6.046: Dynamic Programming (student recitation)](https://www.youtube.com/watch?v=krZI60lKPek&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=12)\n\n- [ ] **Advanced Graph Processing** (videos)\n    - [ ] [Synchronous Distributed Algorithms: Symmetry-Breaking. Shortest-Paths Spanning Trees](https://www.youtube.com/watch?v=mUBmcbbJNf4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=27)\n    - [ ] [Asynchronous Distributed Algorithms: Shortest-Paths Spanning Trees](https://www.youtube.com/watch?v=kQ-UQAzcnzA&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=28)\n\n- [ ] MIT **Probability** (mathy, and go slowly, which is good for mathy things) (videos):\n    - [ ] [MIT 6.042J - Probability Introduction](https://www.youtube.com/watch?v=SmFwFdESMHI&index=18&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - Conditional Probability](https://www.youtube.com/watch?v=E6FbvM-FGZ8&index=19&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - Independence](https://www.youtube.com/watch?v=l1BCv3qqW4A&index=20&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - Random Variables](https://www.youtube.com/watch?v=MOfhhFaQdjw&list=PLB7540DEDD482705B&index=21)\n    - [ ] [MIT 6.042J - Expectation I](https://www.youtube.com/watch?v=gGlMSe7uEkA&index=22&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - Expectation II](https://www.youtube.com/watch?v=oI9fMUqgfxY&index=23&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - Large Deviations](https://www.youtube.com/watch?v=q4mwO2qS2z4&index=24&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - Random Walks](https://www.youtube.com/watch?v=56iFMY8QW2k&list=PLB7540DEDD482705B&index=25)\n\n- [ ] [Simonson: Approximation Algorithms (video)](https://www.youtube.com/watch?v=oDniZCmNmNw&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=19)\n\n## Video Series\n\nSit back and enjoy. \"netflix and skill\" :P\n\n- [ ] [List of individual Dynamic Programming problems (each is short)](https://www.youtube.com/playlist?list=PLrmLmBdmIlpsHaNTPP_jHHDx_os9ItYXr)\n\n- [ ] [x86 Architecture, Assembly, Applications (11 videos)](https://www.youtube.com/playlist?list=PL038BE01D3BAEFDB0)\n\n- [ ] [MIT 18.06 Linear Algebra, Spring 2005 (35 videos)](https://www.youtube.com/playlist?list=PLE7DDD91010BC51F8)\n\n- [ ] [Excellent - MIT Calculus Revisited: Single Variable Calculus](https://www.youtube.com/playlist?list=PL3B08AE665AB9002A)\n\n- [ ] [Computer Science 70, 001 - Spring 2015 - Discrete Mathematics and Probability Theory](https://www.youtube.com/playlist?list=PL-XXv-cvA_iD8wQm8U0gG_Z1uHjImKXFy)\n\n- [ ] [Discrete Mathematics by Shai Simonson (19 videos)](https://www.youtube.com/playlist?list=PL3o9D4Dl2FJ9q0_gtFXPh_H4POI5dK0yG)\n\n- [ ] CSE373 - Analysis of Algorithms (25 videos)\n    - [Skiena lectures from Algorithm Design Manual](https://www.youtube.com/watch?v=ZFjhkohHdAA&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=1)\n\n- [ ] [UC Berkeley 61B (Spring 2014): Data Structures (25 videos)](https://www.youtube.com/watch?v=mFPmKGIrQs4&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd)\n\n- [ ] [UC Berkeley 61B (Fall 2006): Data Structures (39 videos)]( https://www.youtube.com/playlist?list=PL4BBB74C7D2A1049C)\n\n- [ ] [UC Berkeley 61C: Machine Structures (26 videos)](https://www.youtube.com/watch?v=gJJeUFyuvvg&list=PL-XXv-cvA_iCl2-D-FS5mk0jFF6cYSJs_)\n    \n- [ ] [OOSE: Software Dev Using UML and Java (21 videos)](https://www.youtube.com/playlist?list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n\n- [ ] [UC Berkeley CS 152: Computer Architecture and Engineering (20 videos)](https://www.youtube.com/watch?v=UH0QYvtP7Rk&index=20&list=PLkFD6_40KJIwEiwQx1dACXwh-2Fuo32qr)\n\n- [ ] [MIT 6.004: Computation Structures (49 videos)](https://www.youtube.com/playlist?list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-)\n\n- [ ] [Carnegie Mellon - Computer Architecture Lectures (39 videos)](https://www.youtube.com/playlist?list=PL5PHm2jkkXmi5CxxI7b3JCL1TWybTDtKq)\n\n- [ ] [MIT 6.006: Intro to Algorithms (47 videos)](https://www.youtube.com/watch?v=HtSuA80QTyo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&nohtml5=False)\n\n- [ ] [MIT 6.033: Computer System Engineering (22 videos)](https://www.youtube.com/watch?v=zm2VP0kHl1M&list=PL6535748F59DCA484)\n\n- [ ] [MIT 6.034 Artificial Intelligence, Fall 2010 (30 videos)](https://www.youtube.com/playlist?list=PLUl4u3cNGP63gFHB6xb-kVBiQHYe_4hSi)\n\n- [ ] [MIT 6.042J: Mathematics for Computer Science, Fall 2010 (25 videos)](https://www.youtube.com/watch?v=L3LMbpZIKhQ&list=PLB7540DEDD482705B)\n\n- [ ] [MIT 6.046: Design and Analysis of Algorithms (34 videos)](https://www.youtube.com/watch?v=2P-yW7LQr08&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n\n- [ ] [MIT 6.050J: Information and Entropy, Spring 2008 (19 videos)](https://www.youtube.com/watch?v=phxsQrZQupo&list=PL_2Bwul6T-A7OldmhGODImZL8KEVE38X7)\n\n- [ ] [MIT 6.851: Advanced Data Structures (22 videos)](https://www.youtube.com/watch?v=T0yzrZL1py0&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf&index=1)\n\n- [ ] [MIT 6.854: Advanced Algorithms, Spring 2016 (24 videos)](https://www.youtube.com/playlist?list=PL6ogFv-ieghdoGKGg2Bik3Gl1glBTEu8c)\n\n- [ ] [HARVARD COMPSCI 224: Advanced Algorithms (25 videos)](https://www.youtube.com/playlist?list=PL2SOU6wwxB0uP4rJgf5ayhHWgw7akUWSf)\n\n- [ ] [MIT 6.858 Computer Systems Security, Fall 2014](https://www.youtube.com/watch?v=GqmQg-cszw4&index=1&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n\n- [ ] [Stanford: Programming Paradigms (27 videos)](https://www.youtube.com/view_play_list?p=9D558D49CA734A02)\n    \n- [ ] [Introduction to Cryptography by Christof Paar](https://www.youtube.com/playlist?list=PL6N5qY2nvvJE8X75VkXglSrVhLv1tVcfy)\n    - [Course Website along with Slides and Problem Sets](http://www.crypto-textbook.com/)\n    \n- [ ] [Mining Massive Datasets - Stanford University (94 videos)](https://www.youtube.com/playlist?list=PLLssT5z_DsK9JDLcT8T62VtzwyW9LNepV)\n\n## Computer Science Courses\n\n- [Directory of Online CS Courses](https://github.com/open-source-society/computer-science)\n- [Directory of CS Courses (many with online lectures)](https://github.com/prakhar1989/awesome-courses)\n\n"
  },
  {
    "path": "29-google-interview-university/README.md",
    "content": "# [译] Google Interview University 一套完整的学习手册帮助自己准备 Google 的面试\n\n> 原文地址：[Google Interview University](https://github.com/jwasham/google-interview-university)\n* 原文作者：[John Washam](https://github.com/jwasham)\n* 译文出自：[掘金翻译计划](https://github.com/xitu/gold-miner)\n* 译者：[Aleen](https://github.com/aleen42)，[Newton](https://github.com/Newt0n)，[bobmayuze](https://github.com/bobmayuze)，[Jaeger](https://github.com/laobie)，[sqrthree](https://github.com/sqrthree)\n\n## 这是？\n\n这是我为了从 web 开发者（自学、非计算机科学学位）蜕变至 Google 软件工程师所制定的计划，其内容历时数月。\n\n![白板上编程 ———— 来自 HBO 频道的剧集，“硅谷”](https://dng5l3qzreal6.cloudfront.net/2016/Aug/coding_board_small-1470866369118.jpg)\n\n这一长列表是从 **Google 的指导笔记** 中萃取出来并进行扩展。因此，有些事情你必须去了解一下。我在列表的底部添加了一些额外项，用于解决面试中可能会出现的问题。这些额外项大部分是来自于 Steve Yegge 的“[得到在 Google 工作的机会](http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html)”。而在 Google 指导笔记的逐字间，它们有时也会被反映出来。\n\n---\n\n## 目录\n\n- [这是？](#这是)\n- [为何要用到它？](#为何要用到它)\n- [如何使用它](#如何使用它)\n- [拥有一名 Googler 的心态](#拥有一名-googler-的心态)\n- [我得到了工作吗？](#我得到了工作吗)\n- [跟随着我](#跟随着我)\n- [不要自以为自己足够聪明](#不要自以为自己足够聪明)\n- [关于 Google](#关于-google)\n- [相关视频资源](#相关视频资源)\n- [面试过程 & 通用的面试准备](#面试过程--通用的面试准备)\n- [为你的面试选择一种语言](#为你的面试选择一种语言)\n- [在你开始之前](#在你开始之前)\n- [你所看不到的](#你所看不到的)\n- [日常计划](#日常计划)\n- [必备知识](#必备知识)\n- [算法复杂度 / Big-O / 渐进分析法](#算法复杂度--big-o--渐进分析法)\n- [数据结构](#数据结构)\n    - [数组（Arrays）](#数组arrays)\n    - [链表（Linked Lists）](#链表linked-lists)\n    - [堆栈（Stack）](#堆栈stack)\n    - [队列（Queue）](#队列queue)\n    - [哈希表（Hash table）](#哈希表hash-table)\n- [更多的知识](#更多的知识)\n    - [二分查找（Binary search）](#二分查找binary-search)\n    - [按位运算（Bitwise operations）](#按位运算bitwise-operations)\n- [树（Trees）](#树trees)\n    - [树 —— 笔记 & 背景](#树--笔记--背景)\n    - [二叉查找树（Binary search trees）：BSTs](#二叉查找树binary-search-treesbsts)\n    - [堆（Heap） / 优先级队列（Priority Queue） / 二叉堆（Binary Heap）](#堆heap--优先级队列priority-queue--二叉堆binary-heap)\n    - [字典树（Tries）](#字典树tries)\n    - [平衡查找树（Balanced search trees）](#平衡查找树balanced-search-trees)\n    - [N 叉树（K 叉树、M 叉树）](#n-叉树k-叉树m-叉树)\n- [排序](#排序sorting)\n- [图（Graphs）](#图graphs)\n- [更多知识](#更多知识)\n    - [递归](#递归recursion)\n    - [动态规划](#动态规划dynamic-programming)\n    - [组合 & 概率](#组合combinatorics-n-中选-k-个--概率probability)\n    - [NP, NP-完全和近似算法](#np-np-完全和近似算法)\n    - [缓存](#缓存cache)\n    - [进程和线程](#进程processe和线程thread)\n    - [系统设计、可伸缩性、数据处理](#系统设计可伸缩性数据处理)\n    - [论文](#论文)\n    - [测试](#测试)\n    - [调度](#调度)\n    - [实现系统例程](#实现系统例程)\n    - [字符串搜索和操作](#字符串搜索和操作)\n- [终面](#终面)\n- [书籍](#书籍)\n- [编码练习和挑战](#编码练习和挑战)\n- [当你临近面试时](#当你临近面试时)\n- [你的简历](#你的简历)\n- [当面试来临的时候](#当面试来临的时候)\n- [问面试官的问题](#问面试官的问题)\n- [当你获得了梦想的职位](#当你获得了梦想的职位)\n\n---------------- 下面的内容是可选的 ----------------\n\n- [附加的学习](#附加的学习)\n    - [Unicode](#unicode)\n    - [字节顺序](#字节顺序)\n    - [Emacs and vi(m)](#emacs-and-vim)\n    - [Unix 命令行工具](#unix-命令行工具)\n    - [信息资源 (视频)](#信息资源-视频)\n    - [奇偶校验位 & 汉明码 (视频)](#奇偶校验位--汉明码-视频)\n    - [系统熵值（系统复杂度）](#系统熵值系统复杂度)\n    - [密码学](#密码学)\n    - [压缩](#压缩)\n    - [网络 (视频)](#网络-视频)\n    - [计算机安全](#计算机安全)\n    - [释放缓存](#释放缓存)\n    - [并行/并发编程](#并行并发编程)\n    - [设计模式](#设计模式)\n    - [信息传输, 序列化, 和队列化的系统](#信息传输-序列化和队列化的系统)\n    - [快速傅里叶变换](#快速傅里叶变换)\n    - [布隆过滤器](#布隆过滤器)\n    - [van Emde Boas 树](#van-emde-boas-树)\n    - [更深入的数据结构](#更深入的数据结构)\n    - [跳表](#跳表)\n    - [网络流](#网络流)\n    - [不相交集 & 联合查找](#不相交集--联合查找)\n    - [快速处理数学](#math-for-fast-processing)\n    - [树堆 (Treap)](#树堆-treap)\n    - [线性规划](#线性规划linear-programming视频)\n    - [几何：凸包（Geometry, Convex hull）](#几何凸包geometry-convex-hull视频)\n    - [离散数学](#离散数学)\n    - [机器学习](#机器学习machine-learning)\n    - [Go 语言](#go-语言)\n- [一些主题的额外内容](#一些主题的额外内容)\n- [视频系列](#视频系列)\n- [计算机科学课程](#计算机科学课程)\n\n---\n\n## 为何要用到它？\n\n我一直都是遵循该计划去准备 Google 的面试。自 1997 年以来，我一直从事于 web 程序的构建、服务器的构建及创业型公司的创办。对于只有着一个经济学学位，而不是计算机科学学位（CS degree）的我来说，在职业生涯中所取得的都非常成功。然而，我想在 Google 工作，并进入大型系统中，真正地去理解计算机系统、算法效率、数据结构性能、低级别编程语言及其工作原理。可一项都不了解的我，怎么会被 Google 所应聘呢？\n\n当我创建该项目时，我从一个堆栈到一个堆都不了解。那时的我，完全不了解 Big-O 、树，或如何去遍历一个图。如果非要我去编写一个排序算法的话，我只能说我所写的肯定是很糟糕。一直以来，我所用的任何数据结构都是内建于编程语言当中。至于它们在背后是如何运作，对此我一概不清楚。此外，以前的我并不需要对内存进行管理，最多就只是在一个正在执行的进程抛出了“内存不足”的错误后，采取一些权变措施。而在我的编程生活中，也甚少使用到多维数组，可关联数组却成千上万。而且，从一开始到现在，我都还未曾自己实现过数据结构。\n\n就是这样的我，在经过该学习计划后，已然对被 Google 所雇佣充满信心。这是一个漫长的计划，以至于花费了我数月的时间。若您早已熟悉大部分的知识，那么也许能节省大量的时间。\n\n## 如何使用它\n\n下面所有的东西都只是一个概述。因此，你需要由上而下逐一地去处理它。\n\n在学习过程中，我是使用 GitHub 特殊的语法特性 markdown flavor 去检查计划的进展，包括使用任务列表。\n\n- [x] 创建一个新的分支，以使得你可以像这样去检查计划的进展。直接往方括号中填写一个字符 x 即可：[x]\n\n[更多关于 Github-flavored markdown 的详情](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)\n\n## 拥有一名 Googler 的心态\n\n把一个（或两个）印有“[future Googler](https://github.com/jwasham/google-interview-university/blob/master/extras/future-googler.pdf)”的图案打印出来，并用你誓要成功的眼神盯着它。\n\n[![future Googler sign](https://dng5l3qzreal6.cloudfront.net/2016/Oct/Screen_Shot_2016_10_04_at_10_13_24_AM-1475601104364.png)](https://github.com/jwasham/google-interview-university/blob/master/extras/future-googler.pdf)\n\n## 我得到了工作吗？\n\n我还没去应聘。\n\n因为我离完成学习（完成该疯狂的计划列表）还需要数天的时间，并打算在下周开始用一整天的时间，以编程的方式去解决问题。当然，这将会持续数周的时间。然后，我才通过使用在二月份所得到的一个介绍资格，去正式应聘 Google（没错，是二月份时就得到的）。\n\n    感谢 JP 的这次介绍。\n\n## 跟随着我\n\n目前我仍在该计划的执行过程中，如果你想跟随我脚步去学习的话，可以登进我在 [GoogleyAsHeck.com](https://googleyasheck.com/) 上所写的博客。\n\n下面是我的联系方式：\n\n- Twitter: [@googleyasheck](https://twitter.com/googleyasheck)\n- Twitter: [@StartupNextDoor](https://twitter.com/StartupNextDoor)\n- Google+: [+Googleyasheck](https://plus.google.com/+Googleyasheck)\n- LinkedIn: [johnawasham](https://www.linkedin.com/in/johnawasham)\n\n![John Washam - Google Interview University](https://dng5l3qzreal6.cloudfront.net/2016/Aug/book_stack_photo_resized_18_1469302751157-1472661280368.png)\n\n## 不要自以为自己足够聪明\n\n- Google 的工程师都是才智过人的。但是，就算是工作在 Google 的他们，仍然会因为自己不够聪明而感到一种不安。\n- [天才程序员的神话](https://www.youtube.com/watch?v=0SARbwvhupQ)\n\n## 关于 Google\n\n- [ ] 面向学生 —— [Google 的职业生涯：技术开发指导](https://www.google.com/about/careers/students/guide-to-technical-development.html)\n- [ ] Google 检索的原理：\n    - [ ] [Google 检索的发展史（视频）](https://www.youtube.com/watch?v=mTBShTwCnD4)\n    - [ ] [Google 检索的原理 —— 故事篇](https://www.google.com/insidesearch/howsearchworks/thestory/)\n    - [ ] [Google 检索的原理](https://www.google.com/insidesearch/howsearchworks/)\n    - [ ] [Google 检索的原理 —— Matt Cutts（视频）](https://www.youtube.com/watch?v=BNHR6IQJGZs)\n    - [ ] [Google 是如何改善其检索算法（视频）](https://www.youtube.com/watch?v=J5RZOU6vK4Q)\n- [ ] 系列文章：\n    - [ ] [Google 检索是如何处理移动设备](https://backchannel.com/how-google-search-dealt-with-mobile-33bc09852dc9)\n    - [ ] [Google 为了寻找大众需求的秘密研究](https://backchannel.com/googles-secret-study-to-find-out-our-needs-eba8700263bf)\n    - [ ] [Google 检索将成为你的下一个大脑](https://backchannel.com/google-search-will-be-your-next-brain-5207c26e4523)\n    - [ ] [Demis Hassabis 的心灵直白](https://backchannel.com/the-deep-mind-of-demis-hassabis-156112890d8a)\n- [ ] [书籍：Google 公司是如何运作的](https://www.amazon.com/How-Google-Works-Eric-Schmidt/dp/1455582344)\n- [ ] [由 Google 通告所制作 —— 2016年10月（视频）](https://www.youtube.com/watch?v=q4y0KOeXViI)\n\n## 相关视频资源\n\n部分视频只能通过在 Coursera、Edx 或 Lynda.com class 上注册登录才能观看。这些视频被称为网络公开课程（MOOC）。即便是免费观看，部分课程可能会由于不在时间段内而无法获取。因此，你需要多等待几个月。\n\n    很感谢您能帮我把网络公开课程的视频链接转换成公开的视频源，以代替那些在线课程的视频。此外，一些大学的讲座视频也是我所青睐的。\n\n## 面试过程 & 通用的面试准备\n\n- [ ] 视频：\n    - [ ] [如何在 Google 工作 —— 考生指导课程（视频）](https://www.youtube.com/watch?v=oWbUtlUhwa8&feature=youtu.be)\n    - [ ] [Google 招聘者所分享的技术面试小窍门（视频）](https://www.youtube.com/watch?v=qc1owf2-220&feature=youtu.be)\n    - [ ] [如何在 Google 工作：技术型简历的准备（视频）](https://www.youtube.com/watch?v=8npJLXkcmu8)\n\n- [ ] 文章：\n    - [ ] [三步成为 Googler](http://www.google.com/about/careers/lifeatgoogle/hiringprocess/)\n    - [ ] [得到在 Google 的工作机会](http://steve-yegge.blogspot.com/2008/03/get-that-job-at-google.html)\n        - 所有他所提及的事情都列在了下面\n    - [ ] _（早已过期）_ [如何得到 Google 的一份工作，面试题，应聘过程](http://dondodge.typepad.com/the_next_big_thing/2010/09/how-to-get-a-job-at-google-interview-questions-hiring-process.html)\n    - [ ] [手机设备屏幕的问题](http://sites.google.com/site/steveyegge2/five-essential-phone-screen-questions)\n\n- [ ] 附加的（虽然 Google 不建议，但我还是添加在此）：\n    - [ ] [ABC：永远都要去编程（Always Be Coding）](https://medium.com/always-be-coding/abc-always-be-coding-d5f8051afce2#.4heg8zvm4)\n    - [ ] [四步成为 Google 里一名没有学位的员工](https://medium.com/always-be-coding/four-steps-to-google-without-a-degree-8f381aa6bd5e#.asalo1vfx)\n    - [ ] [共享白板（Whiteboarding）](https://medium.com/@dpup/whiteboarding-4df873dbba2e#.hf6jn45g1)\n    - [ ] [Google 是如何看待应聘、管理和公司文化](http://www.kpcb.com/blog/lessons-learned-how-google-thinks-about-hiring-management-and-culture)\n    - [ ] [程序开发面试中有效的白板（Whiteboarding）](http://www.coderust.com/blog/2014/04/10/effective-whiteboarding-during-programming-interviews/)\n    - [ ] 震撼开发类面试 第一集：\n        - [ ] [Gayle L McDowell —— 震撼开发类面试（视频）](https://www.youtube.com/watch?v=rEJzOhC5ZtQ)\n        - [ ] [震撼开发类面试 —— 作者 Gayle Laakmann McDowell（视频）](https://www.youtube.com/watch?v=aClxtDcdpsQ)\n    - [ ] 如何在世界四强企业中获得一份工作：\n        - [ ] [“如何在世界四强企业中获得一份工作 —— Amazon、Facebook、Google 和 Microsoft”（视频）](https://www.youtube.com/watch?v=YJZCUhxNCv8)\n    - [ ] [面试 Google 失败](http://alexbowe.com/failing-at-google-interviews/)\n\n## 为你的面试选择一种语言\n\n在这，我就以下话题写一篇短文 —— [重点：为在 Google 的面试选择一种语言](https://googleyasheck.com/important-pick-one-language-for-the-google-interview/)\n\n在大多数公司的面试当中，你可以在编程这一环节，使用一种自己用起来较为舒适的语言去完成编程。但在 Google，你只有三种固定的选择：\n\n- C++\n- Java\n- Python\n\n有时你也可以使用下面两种，但需要事先查阅说明。因为，说明中会有警告：\n\n- JavaScript\n- Ruby\n\n你需要对你所选择的语言感到非常舒适且足够了解。\n\n更多关于语言选择的阅读：\n\n- http://www.byte-by-byte.com/choose-the-right-language-for-your-coding-interview/\n- http://blog.codingforinterviews.com/best-programming-language-jobs/\n- https://www.quora.com/What-is-the-best-language-to-program-in-for-an-in-person-Google-interview\n\n[在此查看相关语言的资源](programming-language-resources.md)\n\n由于，我正在学习C、C++ 和 Python。因此，在下面你会看到部分关于它们的学习资料。相关书籍请看文章的底部。\n\n## 在你开始之前\n\n该列表已经持续更新了很长的一段时间，所以，我们的确很容易会对其失去控制。\n\n这里列出了一些我所犯过的错误，希望您不要重滔覆辙。\n\n### 1. 你不可能把所有的东西都记住\n\n就算我查看了数小时的视频，并记录了大量的笔记。几个月后的我，仍然会忘却其中大部分的东西。所以，我翻阅了我的笔记，并将可回顾的东西制作成抽认卡（flashcard）（请往下看）\n\n### 2. 使用抽认卡\n\n为了解决善忘的问题，我制作了一些关于抽认卡的页面，用于添加两种抽认卡：正常的及带有代码的。每种卡都会有不同的格式设计。\n\n而且，我还以移动设备为先去设计这些网页，以使得在任何地方的我，都能通过我的手机及平板去回顾知识。\n\n你也可以免费制作属于你自己的抽认卡网站：\n\n- [抽认卡页面的代码仓库](https://github.com/jwasham/computer-science-flash-cards)\n- [我的抽认卡数据库](https://github.com/jwasham/computer-science-flash-cards/blob/master/cards-jwasham.db)：有一点需要记住的是，我做事有点过头，以至于把卡片都覆盖到所有的东西上。从汇编语言和 Python 的细枝末节，乃至到机器学习和统计都被覆盖到卡片上。而这种做法，对于 Google 的要求来说，却是多余。\n\n**在抽认卡上做笔记：** 若你第一次发现你知道问题的答案时，先不要急着把其标注成“已懂”。你需要做的，是去查看一下是否有同样的抽认卡，并在你真正懂得如何解决问题之前，多问自己几次。重复地问答可帮助您深刻记住该知识点。\n\n### 3. 回顾，回顾，回顾\n\n我留有一组 ASCII 码表、OSI 堆栈、Big-O 记号及更多的小抄纸，以便在空余的时候可以学习。\n\n每编程半个小时就要休息一下，并去回顾你的抽认卡。\n\n### 4. 专注\n\n在学习的过程中，往往会有许多令人分心的事占据着我们宝贵的时间。因此，专注和集中注意力是非常困难的。\n\n## 你所看不到的\n\n由于，这个巨大的列表一开始是作为我个人从 Google 面试指导笔记所形成的一个事件处理列表。因此，有一些我熟悉且普遍的技术在此都未被谈及到：\n\n- SQL\n- Javascript\n- HTML、CSS 和其他前端技术\n\n## 日常计划\n\n部分问题可能会花费一天的时间去学习，而部分则会花费多天。当然，有些学习并不需要我们懂得如何实现。\n\n因此，每一天我都会在下面所列出的列表中选择一项，并查看相关的视频。然后，使用以下的一种语言去实现：\n\n    C —— 使用结构体和函数，该函数会接受一个结构体指针 * 及其他数据作为参数。\n    C++ —— 不使用内建的数据类型。\n    C++ —— 使用内建的数据类型，如使用 STL 的 std::list 来作为链表。\n    Python ——  使用内建的数据类型（为了持续练习 Python），并编写一些测试去保证自己代码的正确性。有时，只需要使用断言函数 assert() 即可。\n    此外，你也可以使用 Java 或其他语言。以上只是我的个人偏好而已。\n\n为何要在这些语言上分别实现一次？\n\n    因为可以练习，练习，练习，直至我厌倦它，并完美地实现出来。（若有部分边缘条件没想到时，我会用书写的形式记录下来并去记忆）\n    因为可以在纯原生的条件下工作（不需垃圾回收机制的帮助下，分配/释放内存（除了 Python））\n    因为可以利用上内建的数据类型，以使得我拥有在现实中使用内建工具的经验（在生产环境中，我不会去实现自己的链表）\n\n就算我没有时间去每一项都这么做，但我也会尽我所能的。\n\n在这里，你可以查看到我的代码：\n - [C](https://github.com/jwasham/practice-c)\n - [C++](https://github.com/jwasham/practice-cpp)\n - [Python](https://github.com/jwasham/practice-python)\n\n你不需要记住每一个算法的内部原理。\n\n在一个白板上写代码，而不要直接在计算机上编写。在测试完部分简单的输入后，到计算机上再测试一遍。\n\n## 必备知识\n\n- [ ] **计算机是如何处理一段程序：**\n    - [ ] [CPU 是如何执行代码（视频）](https://www.youtube.com/watch?v=42KTvGYQYnA)\n    - [ ] [机器码指令（视频）](https://www.youtube.com/watch?v=Mv2XQgpbTNE)\n\n- [ ] **编译器**\n    - [ ] [编译器是如何在 ~1 分钟内工作（视频）](https://www.youtube.com/watch?v=IhC7sdYe-Jg)\n    - [ ] [Hardvard CS50 —— 编译器（视频）](https://www.youtube.com/watch?v=CSZLNYF4Klo)\n    - [ ] [C++（视频）](https://www.youtube.com/watch?v=twodd1KFfGk)\n    - [ ] [掌握编译器的优化（C++）（视频）](https://www.youtube.com/watch?v=FnGCDLhaxKU)\n\n- [ ] **浮点数是如何存储的：**\n    - [ ] 简单的 8-bit：[浮点数的表达形式　—— 1（视频 —— 在计算上有一个错误 —— 详情请查看视频的介绍）](https://www.youtube.com/watch?v=ji3SfClm8TU)\n    - [ ] 32 bit：[IEEE754 32-bit 浮点二进制（视频）](https://www.youtube.com/watch?v=50ZYcZebIec)\n\n## 算法复杂度 / Big-O / 渐进分析法\n- 并不需要实现\n- [ ] [Harvard CS50 —— 渐进表示（视频）](https://www.youtube.com/watch?v=iOq5kSKqeR4)\n- [ ] [Big O 记号（通用快速教程）（视频）](https://www.youtube.com/watch?v=V6mKVRU1evU)\n- [ ] [Big O 记号（以及 Omega 和 Theta）——  最佳数学解释（视频）](https://www.youtube.com/watch?v=ei-A_wy5Yxw&index=2&list=PL1BaGV1cIH4UhkL8a9bJGG356covJ76qN)\n- [ ] Skiena 算法：\n    - [视频](https://www.youtube.com/watch?v=gSyDMtdPNpU&index=2&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [幻灯片](http://www3.cs.stonybrook.edu/~algorith/video-lectures/2007/lecture2.pdf)\n- [ ] [对于算法复杂度分析的一次详细介绍](http://discrete.gr/complexity/)\n- [ ] [增长阶数（Orders of Growth）（视频）](https://class.coursera.org/algorithmicthink1-004/lecture/59)\n- [ ] [渐进性（Asymptotics）（视频）](https://class.coursera.org/algorithmicthink1-004/lecture/61)\n- [ ] [UC Berkeley Big O（视频）](https://youtu.be/VIS4YDpuP98)\n- [ ] [UC Berkeley Big Omega（视频）](https://youtu.be/ca3e7UVmeUc)\n- [ ] [平摊分析法（Amortized Analysis）（视频）](https://www.youtube.com/watch?v=B3SpQZaAZP4&index=10&list=PL1BaGV1cIH4UhkL8a9bJGG356covJ76qN)\n- [ ] [举证“Big O”（视频）](https://class.coursera.org/algorithmicthink1-004/lecture/63)\n- [ ] 高级编程（包括递归关系和主定理）：\n    - [计算性复杂度：第一部](https://www.topcoder.com/community/data-science/data-science-tutorials/computational-complexity-section-1/)\n    - [计算性复杂度：第二部](https://www.topcoder.com/community/data-science/data-science-tutorials/computational-complexity-section-2/)\n- [ ] [速查表（Cheat sheet）](http://bigocheatsheet.com/)\n\n    如果部分课程过于学术性，你可直接跳到文章底部，去查看离散数学的视频以获取相关背景知识。\n\n## 数据结构\n\n- ### 数组（Arrays）\n    - 实现一个可自动调整大小的动态数组。\n    - [ ] 介绍：\n        - [数组（视频）](https://www.coursera.org/learn/data-structures/lecture/OsBSF/arrays)\n        - [数组的基础知识（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Basic-arrays/149042/177104-4.html)\n        - [多维数组（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Multidimensional-arrays/149042/177105-4.html)\n        - [动态数组（视频）](https://www.coursera.org/learn/data-structures/lecture/EwbnV/dynamic-arrays)\n        - [不规则数组（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Jagged-arrays/149042/177106-4.html)\n        - [调整数组的大小（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Resizable-arrays/149042/177108-4.html)\n    - [ ] 实现一个动态数组（可自动调整大小的可变数组）：\n        - [ ] 练习使用数组和指针去编码，并且指针是通过计算去跳转而不是使用索引\n        - [ ] 通过分配内存来新建一个原生数据型数组\n            - 可以使用 int 类型的数组，但不能使用其语法特性\n            - 从大小为16或更大的数（使用2的倍数 —— 16、32、64、128）开始编写\n        - [ ] size() —— 数组元素的个数\n        - [ ] capacity() —— 可容纳元素的个数\n        - [ ] is_empty()\n        - [ ] at(index) —— 返回对应索引的元素，且若索引越界则愤然报错\n        - [ ] push(item)\n        - [ ] insert(index, item) —— 在指定索引中插入元素，并把后面的元素依次后移\n        - [ ] prepend(item) —— 可以使用上面的 insert 函数，传参 index 为 0\n        - [ ] pop() —— 删除在数组末端的元素，并返回其值\n        - [ ] delete(index) —— 删除指定索引的元素，并把后面的元素依次前移\n        - [ ] remove(item) —— 删除指定值的元素，并返回其索引（即使有多个元素）\n        - [ ] find(item) —— 寻找指定值的元素并返回其中第一个出现的元素其索引，若未找到则返回 -1\n        - [ ] resize(new_capacity) // 私有函数\n            - 若数组的大小到达其容积，则变大一倍\n            - 获取元素后，若数组大小为其容积的1/4，则缩小一半\n    - [ ] 时间复杂度\n        - 在数组末端增加/删除、定位、更新元素，只允许占 O(1) 的时间复杂度（平摊（amortized）去分配内存以获取更多空间）\n        - 在数组任何地方插入/移除元素，只允许 O(n) 的时间复杂度\n    - [ ] 空间复杂度\n        - 因为在内存中分配的空间邻近，所以有助于提高性能\n        - 空间需求 = （大于或等于 n 的数组容积）* 元素的大小。即便空间需求为 2n，其空间复杂度仍然是 O(n)\n\n- ### 链表（Linked Lists）\n    - [ ] 介绍：\n        - [ ] [单向链表（视频）](https://www.coursera.org/learn/data-structures/lecture/kHhgK/singly-linked-lists)\n        - [ ] [CS 61B —— 链表（视频）](https://www.youtube.com/watch?v=sJtJOtXCW_M&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=5)\n    - [ ] [C 代码（视频）](https://www.youtube.com/watch?v=QN6FPiD0Gzo)\n        - 并非看完整个视频，只需要看关于节点结果和内存分配那一部分即可\n    - [ ] 链表 vs 数组：\n        - [基本链表 Vs 数组（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/rjBs9/core-linked-lists-vs-arrays)\n        - [在现实中，链表 Vs 数组（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/QUaUd/in-the-real-world-lists-vs-arrays)\n    - [ ] [为什么你需要避免使用链表（视频）](https://www.youtube.com/watch?v=YQs6IC-vgmo)\n    - [ ] 的确：你需要关于“指向指针的指针”的相关知识：（因为当你传递一个指针到一个函数时，该函数可能会改变指针所指向的地址）该页只是为了让你了解“指向指针的指针”这一概念。但我并不推荐这种链式遍历的风格。因为，这种风格的代码，其可读性和可维护性太低。\n        - [指向指针的指针](https://www.eskimo.com/~scs/cclass/int/sx8.html)\n    - [ ] 实现（我实现了使用尾指针以及没有使用尾指针这两种情况）：\n        - [ ] size() —— 返回链表中数据元素的个数\n        - [ ] empty() —— 若链表为空则返回一个布尔值 true\n        - [ ] value_at(index) —— 返回第 n 个元素的值（从0开始计算）\n        - [ ] push_front(value) —— 添加元素到链表的首部\n        - [ ] pop_front() —— 删除首部元素并返回其值\n        - [ ] push_back(value) —— 添加元素到链表的尾部\n        - [ ] pop_back() —— 删除尾部元素并返回其值\n        - [ ] front() —— 返回首部元素的值\n        - [ ] back() —— 返回尾部元素的值\n        - [ ] insert(index, value) —— 插入值到指定的索引，并把当前索引的元素指向到新的元素\n        - [ ] erase(index) —— 删除指定索引的节点\n        - [ ] value_n_from_end(n) —— 返回倒数第 n 个节点的值\n        - [ ] reverse() —— 逆序链表\n        - [ ] remove_value(value) —— 删除链表中指定值的第一个元素\n    - [ ] 双向链表\n        - [介绍（视频）](https://www.coursera.org/learn/data-structures/lecture/jpGKD/doubly-linked-lists)\n        - 并不需要实现\n\n- ### 堆栈（Stack）\n    - [ ] [堆栈（视频）](https://www.coursera.org/learn/data-structures/lecture/UdKzQ/stacks)\n    - [ ] [使用堆栈 —— 后进先出（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Using-stacks-last-first-out/149042/177120-4.html)\n    - [ ] 可以不实现，因为使用数组来实现并不重要\n\n- ### 队列（Queue）\n    - [ ] [使用队列 —— 先进先出（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Using-queues-first-first-out/149042/177122-4.html)\n    - [ ] [队列（视频）](https://www.coursera.org/learn/data-structures/lecture/EShpq/queue)\n    - [ ] [原型队列/先进先出（FIFO）](https://en.wikipedia.org/wiki/Circular_buffer)\n    - [ ] [优先级队列（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Priority-queues-deques/149042/177123-4.html)\n    - [ ] 使用含有尾部指针的链表来实现:\n        - enqueue(value) —— 在尾部添加值\n        - dequeue() —— 删除最早添加的元素并返回其值（首部元素）\n        - empty()\n    - [ ] 使用固定大小的数组实现：\n        - enqueue(value) —— 在可容的情况下添加元素到尾部\n        - dequeue() —— 删除最早添加的元素并返回其值\n        - empty()\n        - full()\n    - [ ] 花销：\n        - 在糟糕的实现情况下，使用链表所实现的队列，其入列和出列的时间复杂度将会是 O(n)。因为，你需要找到下一个元素，以致循环整个队列\n        - enqueue：O(1)（平摊（amortized）、链表和数组 [探测（probing）]）\n        - dequeue：O(1)（链表和数组）\n        - empty：O(1)（链表和数组）\n\n- ### 哈希表（Hash table）\n    - [ ] 视频：\n        - [ ] [链式哈希表（视频）](https://www.youtube.com/watch?v=0M_kIqhwbFo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=8)\n        - [ ] [Table Doubling 和 Karp-Rabin（视频）](https://www.youtube.com/watch?v=BRO7mVIFt08&index=9&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n        - [ ] [Open Addressing 和密码型哈希（Cryptographic Hashing）（视频）](https://www.youtube.com/watch?v=rvdJDijO2Ro&index=10&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n        - [ ] [PyCon 2010：The Mighty Dictionary（视频）](https://www.youtube.com/watch?v=C4Kc8xzcA68)\n        - [ ] [（进阶）随机取样（Randomization）：全域哈希（Universal Hashing）& 完美哈希（Perfect Hashing）（视频）](https://www.youtube.com/watch?v=z0lJ2k0sl1g&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=11)\n        - [ ] [（进阶）完美哈希（Perfect hashing）（视频）](https://www.youtube.com/watch?v=N0COwN14gt0&list=PL2B4EEwhKD-NbwZ4ezj7gyc_3yNrojKM9&index=4)\n\n    - [ ] 在线课程：\n        - [ ] [哈希函数的掌握（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Understanding-hash-functions/149042/177126-4.html)\n        - [ ] [使用哈希表（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Using-hash-tables/149042/177127-4.html)\n        - [ ] [哈希表的支持（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Supporting-hashing/149042/177128-4.html)\n        - [ ] [哈希表的语言支持（视频）](https://www.lynda.com/Developer-Programming-Foundations-tutorials/Language-support-hash-tables/149042/177129-4.html)\n        - [ ] [基本哈希表（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/m7UuP/core-hash-tables)\n        - [ ] [数据结构（视频）](https://www.coursera.org/learn/data-structures/home/week/3)\n        - [ ] [电话薄问题（Phone Book Problem）（视频）](https://www.coursera.org/learn/data-structures/lecture/NYZZP/phone-book-problem)\n        - [ ] 分布式哈希表：\n            - [Dropbox 中的瞬时上传及存储优化（视频）](https://www.coursera.org/learn/data-structures/lecture/DvaIb/instant-uploads-and-storage-optimization-in-dropbox)\n            - [分布式哈希表（视频）](https://www.coursera.org/learn/data-structures/lecture/tvH8H/distributed-hash-tables)\n\n    - [ ] 使用线性探测的数组去实现\n        - hash(k, m) —— m 是哈希表的大小\n        - add(key, value) —— 如果 key 已存在则更新值\n        - exists(key)\n        - get(key)\n        - remove(key)\n\n## 更多的知识\n\n- ### 二分查找（Binary search）\n    - [ ] [二分查找（视频）](https://www.youtube.com/watch?v=D5SrAga1pno)\n    - [ ] [二分查找（视频）](https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/binary-search)\n    - [ ] [详情](https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/)\n    - [ ] 实现：\n        - 二分查找（在一个已排序好的整型数组中查找）\n        - 迭代式二分查找\n\n- ### 按位运算（Bitwise operations）\n    - [ ] [Bits 速查表](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/bits-cheat-cheet.pdf)\n        - 你需要知道大量2的幂数值（从2^1 到 2^16 及 2^32）\n    - [ ] 好好理解位操作符的含义：&、|、^、~、>>、<<\n        - [ ] [字码（words）](https://en.wikipedia.org/wiki/Word_(computer_architecture))\n        - [ ] 好的介绍：\n            [位操作（视频）](https://www.youtube.com/watch?v=7jkIUgLC29I)\n        - [ ] [C 语言编程教程 2-10：按位运算（视频）](https://www.youtube.com/watch?v=d0AwjSpNXR0)\n        - [ ] [位操作](https://en.wikipedia.org/wiki/Bit_manipulation)\n        - [ ] [按位运算](https://en.wikipedia.org/wiki/Bitwise_operation)\n        - [ ] [Bithacks](https://graphics.stanford.edu/~seander/bithacks.html)\n        - [ ] [位元抚弄者（The Bit Twiddler）](http://bits.stephan-brumme.com/)\n        - [ ] [交互式位元抚弄者（The Bit Twiddler Interactive）](http://bits.stephan-brumme.com/interactive.html)\n    - [ ] 一补数和补码\n        - [二进制：利 & 弊（为什么我们要使用补码）（视频）](https://www.youtube.com/watch?v=lKTsv6iVxV4)\n        - [一补数（1s Complement）](https://en.wikipedia.org/wiki/Ones%27_complement)\n        - [补码（2s Complement）](https://en.wikipedia.org/wiki/Two%27s_complement)\n    - [ ] 计算置位（Set Bits）\n        - [计算一个字节中置位（Set Bits）的四种方式（视频）](https://youtu.be/Hzuzo9NJrlc)\n        - [计算比特位](https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan)\n        - [如何在一个 32 位的整型中计算置位（Set Bits）的数量](http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer)\n    - [ ] 四舍五入2的幂数：\n        - [四舍五入到2的下一幂数](http://bits.stephan-brumme.com/roundUpToNextPowerOfTwo.html)\n    - [ ] 交换值：\n        - [交换（Swap）](http://bits.stephan-brumme.com/swap.html)\n    - [ ] 绝对值：\n        - [绝对整型（Absolute Integer）](http://bits.stephan-brumme.com/absInteger.html)\n\n## 树（Trees）\n\n- ### 树 —— 笔记 & 背景\n    - [ ] [系列：基本树（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/ovovP/core-trees)\n    - [ ] [系列：树（视频）](https://www.coursera.org/learn/data-structures/lecture/95qda/trees)\n    - 基本的树形结构\n    - 遍历\n    - 操作算法\n    - BFS（广度优先检索，breadth-first search）\n        - [MIT（视频）](https://www.youtube.com/watch?v=s-CYnVz-uh4&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=13)\n        - 层序遍历（使用队列的 BFS 算法）\n            - 时间复杂度： O(n)\n            - 空间复杂度：\n                - 最好情况： O(1)\n                - 最坏情况：O(n/2)=O(n)\n    - DFS（深度优先检索，depth-first search）\n        - [MIT（视频）](https://www.youtube.com/watch?v=AfSk24UTFS8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=14)\n        - 笔记：\n            - 时间复杂度：O(n)\n            - 空间复杂度：\n                - 最好情况：O(log n) - 树的平均高度\n                - 最坏情况：O(n)\n        - 中序遍历（DFS：左、节点本身、右）\n        - 后序遍历（DFS：左、右、节点本身）\n        - 先序遍历（DFS：节点本身、左、右）\n\n- ### 二叉查找树（Binary search trees）：BSTs\n    - [ ] [二叉查找树概览（视频）](https://www.youtube.com/watch?v=x6At0nzX92o&index=1&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n    - [ ] [系列（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/p82sw/core-introduction-to-binary-search-trees)\n        - 从符号表开始到 BST 程序\n    - [ ] [介绍（视频）](https://www.coursera.org/learn/data-structures/lecture/E7cXP/introduction)\n    - [ ] [MIT（视频）](https://www.youtube.com/watch?v=9Jry5-82I68)\n    - C/C++:\n        - [ ] [二叉查找树 —— 在 C/C++ 中实现（视频）](https://www.youtube.com/watch?v=COZK7NATh4k&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=28)\n        - [ ] [BST 的实现 —— 在堆栈和堆中的内存分配（视频）](https://www.youtube.com/watch?v=hWokyBoo0aI&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=29)\n        - [ ] [在二叉查找树中找到最小和最大的元素（视频）](https://www.youtube.com/watch?v=Ut90klNN264&index=30&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [寻找二叉树的高度（视频）](https://www.youtube.com/watch?v=_pnqMz5nrRs&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=31)\n        - [ ] [二叉树的遍历 —— 广度优先和深度优先策略（视频）](https://www.youtube.com/watch?v=9RHO6jU--GU&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=32)\n        - [ ] [二叉树：层序遍历（视频）](https://www.youtube.com/watch?v=86g8jAQug04&index=33&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [二叉树的遍历：先序、中序、后序（视频）](https://www.youtube.com/watch?v=gm8DUJJhmY4&index=34&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [判断一棵二叉树是否为二叉查找树（视频）](https://www.youtube.com/watch?v=yEwSGhSsT0U&index=35&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n        - [ ] [从二叉查找树中删除一个节点（视频）](https://www.youtube.com/watch?v=gcULXE7ViZw&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=36)\n        - [ ] [二叉查找树中序遍历的后继者（视频）](https://www.youtube.com/watch?v=5cPbNCrdotA&index=37&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P)\n    - [ ] 实现：\n        - [ ] insert    // 往树上插值\n        - [ ] get_node_count // 查找树上的节点数\n        - [ ] print_values // 从小到大打印树中节点的值\n        - [ ] delete_tree\n        - [ ] is_in_tree // 如果值存在于树中则返回 true\n        - [ ] get_height // 返回节点所在的高度（如果只有一个节点，那么高度则为1）\n        - [ ] get_min   // 返回树上的最小值\n        - [ ] get_max   // 返回树上的最大值\n        - [ ] is_binary_search_tree\n        - [ ] delete_value\n        - [ ] get_successor // 返回给定值的后继者，若没有则返回-1\n\n- ### 堆（Heap） / 优先级队列（Priority Queue） / 二叉堆（Binary Heap）\n    - 可视化是一棵树，但通常是以线性的形式存储（数组、链表）\n    - [ ] [堆](https://en.wikipedia.org/wiki/Heap_(data_structure))\n    - [ ] [介绍（视频）](https://www.coursera.org/learn/data-structures/lecture/2OpTs/introduction)\n    - [ ] [无知的实现（视频）](https://www.coursera.org/learn/data-structures/lecture/z3l9N/naive-implementations)\n    - [ ] [二叉树（视频）](https://www.coursera.org/learn/data-structures/lecture/GRV2q/binary-trees)\n    - [ ] [关于树高的讨论（视频）](https://www.coursera.org/learn/data-structures/supplement/S5xxz/tree-height-remark)\n    - [ ] [基本操作（视频）](https://www.coursera.org/learn/data-structures/lecture/0g1dl/basic-operations)\n    - [ ] [完全二叉树（视频）](https://www.coursera.org/learn/data-structures/lecture/gl5Ni/complete-binary-trees)\n    - [ ] [伪代码（视频）](https://www.coursera.org/learn/data-structures/lecture/HxQo9/pseudocode)\n    - [ ] [堆排序 —— 跳到起点（视频）](https://youtu.be/odNJmw5TOEE?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3291)\n    - [ ] [堆排序（视频）](https://www.coursera.org/learn/data-structures/lecture/hSzMO/heap-sort)\n    - [ ] [构建一个堆（视频）](https://www.coursera.org/learn/data-structures/lecture/dwrOS/building-a-heap)\n    - [ ] [MIT：堆与堆排序（视频）](https://www.youtube.com/watch?v=B7hVxCmfPtM&index=4&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [CS 61B Lecture 24：优先级队列（视频）](https://www.youtube.com/watch?v=yIUFT6AKBGE&index=24&list=PL4BBB74C7D2A1049C)\n    - [ ] [构建线性时间复杂度的堆（大顶堆）](https://www.youtube.com/watch?v=MiyLo8adrWw)\n    - [ ] 实现一个大顶堆：\n        - [ ] insert\n        - [ ] sift_up —— 用于插入元素\n        - [ ] get_max —— 返回最大值但不移除元素\n        - [ ] get_size() —— 返回存储的元素数量\n        - [ ] is_empty() —— 若堆为空则返回 true\n        - [ ] extract_max —— 返回最大值并移除\n        - [ ] sift_down —— 用于获取最大值元素\n        - [ ] remove(i) —— 删除指定索引的元素\n        - [ ] heapify —— 构建堆，用于堆排序\n        - [ ] heap_sort() —— 拿到一个未排序的数组，然后使用大顶堆进行就地排序\n            - 注意：若用小顶堆可节省操作，但导致空间复杂度加倍。（无法做到就地）\n\n- ### 字典树（Tries）\n    - 需要注意的是，字典树各式各样。有些有前缀，而有些则没有。有些使用字符串而不使用比特位来追踪路径。\n    - 阅读代码，但不实现。\n    - [ ] [数据结构笔记及编程技术](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#Tries)\n    - [ ] 短课程视频：\n        - [ ] [对字典树的介绍（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/08Xyf/core-introduction-to-tries)\n        - [ ] [字典树的性能（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/PvlZW/core-performance-of-tries)\n        - [ ] [实现一棵字典树（视频）](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/DFvd3/core-implementing-a-trie)\n    - [ ] [字典树：一个被忽略的数据结构](https://www.toptal.com/java/the-trie-a-neglected-data-structure)\n    - [ ] [高级编程 —— 使用字典树](https://www.topcoder.com/community/data-science/data-science-tutorials/using-tries/)\n    - [ ] [标准教程（现实中的用例）（视频）](https://www.youtube.com/watch?v=TJ8SkcUSdbU)\n    - [ ] [MIT，高阶数据结构，使用字符串追踪路径（可事半功倍）](https://www.youtube.com/watch?v=NinWEPPrkDQ&index=16&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf)\n\n- ### 平衡查找树（Balanced search trees）\n    - 掌握至少一种平衡查找树（并懂得如何实现）：\n    - “在各种平衡查找树当中，AVL 树和2-3树已经成为了过去，而红黑树（red-black trees）看似变得越来越受人青睐。这种令人特别感兴趣的数据结构，亦称伸展树（splay tree）。它可以自我管理，且会使用轮换来移除任何访问过根节点的 key。” —— Skiena\n    - 因此，在各种各样的平衡查找树当中，我选择了伸展树来实现。虽然，通过我的阅读，我发现在 Google 的面试中并不会被要求实现一棵平衡查找树。但是，为了胜人一筹，我们还是应该看看如何去实现。在阅读了大量关于红黑树的代码后，我才发现伸展树的实现确实会使得各方面更为高效。\n        - 伸展树：插入、查找、删除函数的实现，而如果你最终实现了红黑树，那么请尝试一下：\n        - 跳过删除函数，直接实现搜索和插入功能\n    - 我希望能阅读到更多关于 B 树的资料，因为它也被广泛地应用到大型的数据库当中。\n    - [ ] [自平衡二叉查找树](https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree)\n\n    - [ ] **AVL 树**\n        - 实际中：我能告诉你的是，该种树并无太多的用途，但我能看到有用的地方在哪里：AVL 树是另一种平衡查找树结构。其可支持时间复杂度为 O(log n) 的查询、插入及删除。它比红黑树严格意义上更为平衡，从而导致插入和删除更慢，但遍历却更快。正因如此，才彰显其结构的魅力。只需要构建一次，就可以在不重新构造的情况下读取，适合于实现诸如语言字典（或程序字典，如一个汇编程序或解释程序的操作码）。\n        - [ ] [MIT AVL 树 / AVL 树的排序（视频）](https://www.youtube.com/watch?v=FNeL18KsWPc&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=6)\n        - [ ] [AVL 树（视频）](https://www.coursera.org/learn/data-structures/lecture/Qq5E0/avl-trees)\n        - [ ] [AVL 树的实现（视频）](https://www.coursera.org/learn/data-structures/lecture/PKEBC/avl-tree-implementation)\n        - [ ] [分离与合并](https://www.coursera.org/learn/data-structures/lecture/22BgE/split-and-merge)\n\n    - [ ] **伸展树**\n        - 实际中：伸展树一般用于缓存、内存分配者、路由器、垃圾回收者、数据压缩、ropes（字符串的一种替代品，用于存储长串的文本字符）、Windows NT（虚拟内存、网络及文件系统）等的实现。\n        - [ ] [CS 61B：伸展树（Splay trees）（视频）](https://www.youtube.com/watch?v=Najzh1rYQTo&index=23&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd)\n        - [ ] MIT 教程：伸展树（Splay trees）：\n            - 该教程会过于学术，但请观看到最后的10分钟以确保掌握。\n            - [视频](https://www.youtube.com/watch?v=QnPl_Y6EqMo)\n\n    - [ ] **2-3查找树**\n        - 实际中：2-3树的元素插入非常快速，但却有着查询慢的代价（因为相比较 AVL 树来说，其高度更高）。\n        - 你会很少用到2-3树。这是因为，其实现过程中涉及到不同类型的节点。因此，人们更多地会选择红黑树。\n        - [ ] [2-3树的直感与定义（视频）](https://www.youtube.com/watch?v=C3SsdUqasD4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=2)\n        - [ ] [2-3树的二元观点](https://www.youtube.com/watch?v=iYvBtGKsqSg&index=3&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [2-3树（学生叙述）（视频）](https://www.youtube.com/watch?v=TOb1tuEZ2X4&index=5&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n\n    - [ ] **2-3-4树 (亦称2-4树)**\n        - 实际中：对于每一棵2-4树，都有着对应的红黑树来存储同样顺序的数据元素。在2-4树上进行插入及删除操作等同于在红黑树上进行颜色翻转及轮换。这使得2-4树成为一种用于掌握红黑树背后逻辑的重要工具。这就是为什么许多算法引导文章都会在介绍红黑树之前，先介绍2-4树，尽管**2-4树在实际中并不经常使用**。\n        - [ ] [CS 61B Lecture 26：平衡查找树（视频）](https://www.youtube.com/watch?v=zqrqYXkth6Q&index=26&list=PL4BBB74C7D2A1049C)\n        - [ ] [自底向上的2-4树（视频）](https://www.youtube.com/watch?v=DQdMYevEyE4&index=4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [自顶向下的2-4树（视频）](https://www.youtube.com/watch?v=2679VQ26Fp4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=5)\n\n    - [ ] **B 树**\n        - 有趣的是：为啥叫 B 仍然是一个神秘。因为 B 可代表波音（Boeing）、平衡（Balanced）或 Bayer（联合创造者）\n        - 实际中：B 树会被广泛适用于数据库中，而现代大多数的文件系统都会使用到这种树（或变种)。除了运用在数据库中，B 树也会被用于文件系统以快速访问一个文件的任意块。但存在着一个基本的问题，那就是如何将文件块 i 转换成一个硬盘块（或一个柱面-磁头-扇区）上的地址。\n        - [ ] [B 树](https://en.wikipedia.org/wiki/B-tree)\n        - [ ] [B 树的介绍（视频）](https://www.youtube.com/watch?v=I22wEC1tTGo&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=6)\n        - [ ] [B 树的定义及其插入操作（视频）](https://www.youtube.com/watch?v=s3bCdZGrgpA&index=7&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [B 树的删除操作（视频）](https://www.youtube.com/watch?v=svfnVhJOfMc&index=8&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n        - [ ] [MIT 6.851 —— 内存层次模块（Memory Hierarchy Models）（视频）](https://www.youtube.com/watch?v=V3omVLzI0WE&index=7&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf)\n            - 覆盖有高速缓存参数无关型（cache-oblivious）B 树和非常有趣的数据结构\n            - 头37分钟讲述的很专业，或许可以跳过（B 指块的大小、即缓存行的大小）\n\n    - [ ] **红黑树**\n        - 实际中：红黑树提供了在最坏情况下插入操作、删除操作和查找操作的时间保证。这些时间值的保障不仅对时间敏感型应用有用，例如实时应用，还对在其他数据结构中块的构建非常有用，而这些数据结构都提供了最坏情况下的保障；例如，许多用于计算几何学的数据结构都可以基于红黑树，而目前 Linux 系统所采用的完全公平调度器（the Completely Fair Scheduler）也使用到了该种树。在 Java 8中，红黑树也被用于存储哈希列表集合中相同的数据，而不是使用链表及哈希码。\n        - [ ] [Aduni —— 算法 —— 课程4（该链接直接跳到开始部分）（视频）](https://youtu.be/1W3x0f_RmUo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3871)\n        - [ ] [Aduni —— 算法 —— 课程5（视频）](https://www.youtube.com/watch?v=hm2GHwyKF1o&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=5)\n        - [ ] [黑树（Black Tree）](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree)\n        - [ ] [二分查找及红黑树的介绍](https://www.topcoder.com/community/data-science/data-science-tutorials/an-introduction-to-binary-search-and-red-black-trees/)\n\n- ### N 叉树（K 叉树、M 叉树）\n    - 注意：N 或 K 指的是分支系数（即树的最大分支数）：\n        - 二叉树是一种分支系数为2的树\n        - 2-3树是一种分支系数为3的树\n    - [ ] [K 叉树](https://en.wikipedia.org/wiki/K-ary_tree)\n\n## 排序（Sorting）\n\n- [ ] 笔记:\n    - 实现各种排序 & 知道每种排序的最坏、最好和平均的复杂度分别是什么场景:\n        - 不要用冒泡排序 - 大多数情况下效率感人 - 时间复杂度 O(n^2), 除非 n <= 16\n    - [ ] 排序算法的稳定性 (\"快排是稳定的么?\")\n        - [排序算法的稳定性](https://en.wikipedia.org/wiki/Sorting_algorithm#Stability)\n        - [排序算法的稳定性](http://stackoverflow.com/questions/1517793/stability-in-sorting-algorithms)\n        - [排序算法的稳定性](http://stackoverflow.com/questions/1517793/stability-in-sorting-algorithms)\n        - [排序算法的稳定性](http://www.geeksforgeeks.org/stability-in-sorting-algorithms/)\n        - [排序算法 - 稳定性](http://homepages.math.uic.edu/~leon/cs-mcs401-s08/handouts/stability.pdf)\n    - [ ] 哪种排序算法可以用链表？哪种用数组？哪种两者都可？\n        - 并不推荐对一个链表排序，但归并排序是可行的.\n        - [链表的归并排序](http://www.geeksforgeeks.org/merge-sort-for-linked-list/)\n\n- 关于堆排序，请查看前文堆的数据结构部分。堆排序很强大，不过是非稳定排序。\n\n- [ ] [冒泡排序 (video)](https://www.youtube.com/watch?v=P00xJgWzz2c&index=1&list=PL89B61F78B552C1AB)\n- [ ] [冒泡排序分析 (video)](https://www.youtube.com/watch?v=ni_zk257Nqo&index=7&list=PL89B61F78B552C1AB)\n- [ ] [插入排序 & 归并排序 (video)](https://www.youtube.com/watch?v=Kg4bqzAqRBM&index=3&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n- [ ] [插入排序 (video)](https://www.youtube.com/watch?v=c4BRHC7kTaQ&index=2&list=PL89B61F78B552C1AB)\n- [ ] [归并排序 (video)](https://www.youtube.com/watch?v=GCae1WNvnZM&index=3&list=PL89B61F78B552C1AB)\n- [ ] [快排 (video)](https://www.youtube.com/watch?v=y_G9BkAm6B8&index=4&list=PL89B61F78B552C1AB)\n- [ ] [选择排序 (video)](https://www.youtube.com/watch?v=6nDMgr0-Yyo&index=8&list=PL89B61F78B552C1AB)\n\n- [ ] 斯坦福大学关于排序算法的视频:\n    - [ ] [课程 15 | 编程抽象 (video)](https://www.youtube.com/watch?v=ENp00xylP7c&index=15&list=PLFE6E58F856038C69)\n    - [ ] [课程 16 | 编程抽象 (video)](https://www.youtube.com/watch?v=y4M9IVgrVKo&index=16&list=PLFE6E58F856038C69)\n\n- [ ] Shai Simonson 视频, [Aduni.org](http://www.aduni.org/):\n    - [ ] [算法 - 排序 - 第二讲 (video)](https://www.youtube.com/watch?v=odNJmw5TOEE&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=2)\n    - [ ] [算法 - 排序2 - 第三讲 (video)](https://www.youtube.com/watch?v=hj8YKFTFKEE&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=3)\n\n- [ ] Steven Skiena 关于排序的视频:\n    - [ ] [课程从 26:46 开始 (video)](https://youtu.be/ute-pmMkyuk?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=1600)\n    - [ ] [课程从 27:40 开始 (video)](https://www.youtube.com/watch?v=yLvp-pB8mak&index=8&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [课程从 35:00 开始 (video)](https://www.youtube.com/watch?v=q7K9otnzlfE&index=9&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [课程从 23:50 开始 (video)](https://www.youtube.com/watch?v=TvqIGu9Iupw&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=10)\n\n- [ ] 加州大学伯克利分校（UC Berkeley） 大学课程:\n    - [ ] [CS 61B 课程 29: 排序 I (video)](https://www.youtube.com/watch?v=EiUvYS2DT6I&list=PL4BBB74C7D2A1049C&index=29)\n    - [ ] [CS 61B 课程 30: 排序 II (video)](https://www.youtube.com/watch?v=2hTY3t80Qsk&list=PL4BBB74C7D2A1049C&index=30)\n    - [ ] [CS 61B 课程 32: 排序 III (video)](https://www.youtube.com/watch?v=Y6LOLpxg6Dc&index=32&list=PL4BBB74C7D2A1049C)\n    - [ ] [CS 61B 课程 33: 排序 V (video)](https://www.youtube.com/watch?v=qNMQ4ly43p4&index=33&list=PL4BBB74C7D2A1049C)\n\n- [ ] - 归并排序:\n    - [ ] [使用外部数组](http://www.cs.yale.edu/homes/aspnes/classes/223/examples/sorting/mergesort.c)\n    - [ ] [对原数组直接排序](https://github.com/jwasham/practice-cpp/blob/master/merge_sort/merge_sort.cc)\n- [ ] - 快速排序:\n    - [ ] [实现](http://www.cs.yale.edu/homes/aspnes/classes/223/examples/randomization/quick.c)\n    - [ ] [实现](https://github.com/jwasham/practice-c/blob/master/quick_sort/quick_sort.c)\n\n- [ ] 实现:\n    - [ ] 归并：平均和最差情况的时间复杂度为 O(n log n)。\n    - [ ] 快排：平均时间复杂度为 O(n log n)。\n    - 选择排序和插入排序的最坏、平均时间复杂度都是 O(n^2)。\n    - 关于堆排序，请查看前文堆的数据结构部分。\n\n- [ ] 有兴趣的话，还有一些补充 - 但并不是必须的:\n    - [ ] [基数排序](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#radixSort)\n    - [ ] [基数排序 (video)](https://www.youtube.com/watch?v=xhr26ia4k38)\n    - [ ] [基数排序, 计数排序 (线性时间内) (video)](https://www.youtube.com/watch?v=Nz1KZXbghj8&index=7&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [随机算法: 矩阵相乘, 快排, Freivalds' 算法 (video)](https://www.youtube.com/watch?v=cNB2lADK3_s&index=8&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [线性时间内的排序 (video)](https://www.youtube.com/watch?v=pOKy3RZbSws&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf&index=14)\n\n## 图（Graphs）\n\n图论能解决计算机科学里的很多问题，所以这一节会比较长，像树和排序的部分一样。\n\n- Yegge 的笔记:\n    - 有 3 种基本方式在内存里表示一个图:\n        - 对象和指针\n        - 矩阵\n        - 邻接表\n    - 熟悉以上每一种图的表示法，并了解各自的优缺点\n    - 宽度优先搜索和深度优先搜索 - 知道它们的计算复杂度和设计上的权衡以及如何用代码实现它们\n    - 遇到一个问题时，首先尝试基于图的解决方案，如果没有再去尝试其他的。\n\n- [ ] Skiena 教授的课程 - 很不错的介绍:\n    - [ ] [CSE373 2012 - 课程 11 - 图的数据结构 (video)](https://www.youtube.com/watch?v=OiXxhDrFruw&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=11)\n    - [ ] [CSE373 2012 - 课程 12 - 广度优先搜索 (video)](https://www.youtube.com/watch?v=g5vF8jscteo&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=12)\n    - [ ] [CSE373 2012 - 课程 13 - 图的算法 (video)](https://www.youtube.com/watch?v=S23W6eTcqdY&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=13)\n    - [ ] [CSE373 2012 - 课程 14 - 图的算法 (1) (video)](https://www.youtube.com/watch?v=WitPBKGV0HY&index=14&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [CSE373 2012 - 课程 15 - 图的算法 (2) (video)](https://www.youtube.com/watch?v=ia1L30l7OIg&index=15&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [CSE373 2012 - 课程 16 - 图的算法 (3) (video)](https://www.youtube.com/watch?v=jgDOQq6iWy8&index=16&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n\n- [ ] 图 (复习和其他):\n\n    - [ ] [6.006 单源最短路径问题 (video)](https://www.youtube.com/watch?v=Aa2sqUhIn-E&index=15&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [6.006 Dijkstra 算法 (video)](https://www.youtube.com/watch?v=2E7MmKv0Y24&index=16&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [6.006 Bellman-Ford 算法(video)](https://www.youtube.com/watch?v=ozsuci5pIso&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=17)\n    - [ ] [6.006 Dijkstra 效率优化 (video)](https://www.youtube.com/watch?v=CHvQ3q_gJ7E&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=18)\n    - [ ] [Aduni: 图的算法 I - 拓扑排序, 最小生成树, Prim 算法 -  第六课 (video)]( https://www.youtube.com/watch?v=i_AQT_XfvD8&index=6&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n    - [ ] [Aduni: 图的算法 II - 深度优先搜索, 广度优先搜索, Kruskal 算法, 并查集数据结构 - 第七课 (video)]( https://www.youtube.com/watch?v=ufj5_bppBsA&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=7)\n    - [ ] [Aduni: 图的算法 III: 最短路径 - 第八课 (video)](https://www.youtube.com/watch?v=DiedsPsMKXc&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=8)\n    - [ ] [Aduni: 图的算法. IV: 几何算法介绍 - 第九课 (video)](https://www.youtube.com/watch?v=XIAQRlNkJAw&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=9)\n    - [ ] [CS 61B 2014 (从 58:09 开始) (video)](https://youtu.be/dgjX4HdMI-Q?list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&t=3489)\n    - [ ] [CS 61B 2014: 加权图 (video)](https://www.youtube.com/watch?v=aJjlQCFwylA&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=19)\n    - [ ] [贪心算法: 最小生成树 (video)](https://www.youtube.com/watch?v=tKwnms5iRBU&index=16&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [图的算法之强连通分量 Kosaraju 算法 (video)](https://www.youtube.com/watch?v=RpgcYiky7uw)\n\n- 完整的 Coursera 课程:\n    - [ ] [图的算法 (video)](https://www.coursera.org/learn/algorithms-on-graphs/home/welcome)\n\n- Yegge: 如果有机会，可以试试研究更酷炫的算法:\n    - [ ] Dijkstra 算法 - 上文 - 6.006\n    - [ ] A* 算法\n        - [ ] [A* 算法](https://en.wikipedia.org/wiki/A*_search_algorithm)\n        - [ ] [A* 寻路教程 (video)](https://www.youtube.com/watch?v=KNXfSOx4eEE)\n        - [ ] [A* 寻路 (E01: 算法解释) (video)](https://www.youtube.com/watch?v=-L-WgKMFuhE)\n\n- 我会实现:\n    - [ ] DFS 邻接表 (递归)\n    - [ ] DFS 邻接表 (栈迭代)\n    - [ ] DFS 邻接矩阵 (递归)\n    - [ ] DFS 邻接矩阵 (栈迭代)\n    - [ ] BFS 邻接表\n    - [ ] BFS 邻接矩阵\n    - [ ] 单源最短路径问题 (Dijkstra)\n    - [ ] 最小生成树\n    - 基于 DFS 的算法 (根据上文 Aduni 的视频):\n        - [ ] 检查环 (我们会先检查是否有环存在以便做拓扑排序)\n        - [ ] 拓扑排序\n        - [ ] 计算图中的连通分支\n        - [ ] 列出强连通分量\n        - [ ] 检查双向图\n\n可以从 Skiena 的书（参考下面的书推荐小节）和面试书籍中学习更多关于图的实践。\n\n## 更多知识\n\n- ### 递归（Recursion）\n    - [ ] Stanford 大学关于递归 & 回溯的课程:\n        - [ ] [课程 8 | 抽象编程 (video)](https://www.youtube.com/watch?v=gl3emqCuueQ&list=PLFE6E58F856038C69&index=8)\n        - [ ] [课程 9 | 抽象编程 (video)](https://www.youtube.com/watch?v=uFJhEPrbycQ&list=PLFE6E58F856038C69&index=9)\n        - [ ] [课程 10 | 抽象编程 (video)](https://www.youtube.com/watch?v=NdF1QDTRkck&index=10&list=PLFE6E58F856038C69)\n        - [ ] [课程 11 | 抽象编程 (video)](https://www.youtube.com/watch?v=p-gpaIGRCQI&list=PLFE6E58F856038C69&index=11)\n    - 什么时候适合使用\n    - 尾递归会更好么?\n        - [ ] [什么是尾递归以及为什么它如此糟糕?](https://www.quora.com/What-is-tail-recursion-Why-is-it-so-bad)\n        - [ ] [尾递归 (video)](https://www.youtube.com/watch?v=L1jjXGfxozc)\n\n- ### 动态规划（Dynamic Programming）\n    - This subject can be pretty difficult, as each DP soluble problem must be defined as a recursion relation, and coming up with it can be tricky.\n    - 这一部分会有点困难，每个可以用动态规划解决的问题都必须先定义出递推关系，要推导出来可能会有点棘手。\n    - 我建议先阅读和学习足够多的动态规划的例子，以便对解决 DP 问题的一般模式有个扎实的理解。\n\n    - [ ] 视频:\n        - Skiena 的视频可能会有点难跟上，有时候他用白板写的字会比较小，难看清楚。\n        - [ ] [Skiena: CSE373 2012 - 课程 19 - 动态规划介绍 (video)](https://youtu.be/Qc2ieXRgR0k?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=1718)\n        - [ ] [Skiena: CSE373 2012 - 课程 20 - 编辑距离 (video)](https://youtu.be/IsmMhMdyeGY?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=2749)\n        - [ ] [Skiena: CSE373 2012 - 课程 21 - 动态规划举例 (video)](https://youtu.be/o0V9eYF4UI8?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=406)\n        - [ ] [Skiena: CSE373 2012 - 课程 22 - 动态规划应用 (video)](https://www.youtube.com/watch?v=dRbMC1Ltl3A&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=22)\n        - [ ] [Simonson: 动态规划 0 (starts at 59:18) (video)](https://youtu.be/J5aJEcOr6Eo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3558)\n        - [ ] [Simonson: 动态规划 I - 课程 11 (video)](https://www.youtube.com/watch?v=0EzHjQ_SOeU&index=11&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n        - [ ] [Simonson: 动态规划 II - 课程 12 (video)](https://www.youtube.com/watch?v=v1qiRwuJU7g&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=12)\n        - [ ] 单独的 DP 问题 (每一个视频都很短):\n            [动态规划 (video)](https://www.youtube.com/playlist?list=PLrmLmBdmIlpsHaNTPP_jHHDx_os9ItYXr)\n    - [ ] Yale 课程笔记:\n        - [ ] [动态规划](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#dynamicProgramming)\n    - [ ] Coursera 课程:\n        - [ ] [RNA 二级结构问题 (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/80RrW/the-rna-secondary-structure-problem)\n        - [ ] [动态规划算法 (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/PSonq/a-dynamic-programming-algorithm)\n        - [ ] [DP 算法描述 (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/oUEK2/illustrating-the-dp-algorithm)\n        - [ ] [DP 算法的运行时间 (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/nfK2r/running-time-of-the-dp-algorithm)\n        - [ ] [DP vs 递归实现 (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/M999a/dp-vs-recursive-implementation)\n        - [ ] [全局成对序列排列 (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/UZ7o6/global-pairwise-sequence-alignment)\n        - [ ] [本地成对序列排列 (video)](https://www.coursera.org/learn/algorithmic-thinking-2/lecture/WnNau/local-pairwise-sequence-alignment)\n\n- ### 组合（Combinatorics） (n 中选 k 个) & 概率（Probability）\n    - [ ] [数据技巧: 如何找出阶乘、排列和组合(选择) (video)](https://www.youtube.com/watch?v=8RRo6Ti9d0U)\n    - [ ] [来点学校的东西: 概率 (video)](https://www.youtube.com/watch?v=sZkAAk9Wwa4)\n    - [ ] [来点学校的东西: 概率和马尔可夫链 (video)](https://www.youtube.com/watch?v=dNaJg-mLobQ)\n    - [ ] 可汗学院:\n        - 课程设置:\n            - [ ] [概率理论基础](https://www.khanacademy.org/math/probability/probability-and-combinatorics-topic)\n        - 视频 - 41 (每一个都短小精悍):\n            - [ ] [概率解释 (video)](https://www.youtube.com/watch?v=uzkc-qNVoOk&list=PLC58778F28211FA19)\n\n- ### NP, NP-完全和近似算法\n    - 知道最经典的一些 NP 完全问题，比如旅行商问题和背包问题,\n        而且能在面试官试图忽悠你的时候识别出他们。\n    - 知道 NP 完全是什么意思.\n    - [ ] [计算复杂度 (video)](https://www.youtube.com/watch?v=moPtwq_cVH8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=23)\n    - [ ] Simonson:\n        - [ ] [贪心算法. II & 介绍 NP-完全性 (video)](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)\n        - [ ] [NP-完全性 II & 归约 (video)](https://www.youtube.com/watch?v=e0tGC6ZQdQE&index=16&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n        - [ ] [NP-完全性 III (Video)](https://www.youtube.com/watch?v=fCX1BGT3wjE&index=17&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n        - [ ] [NP-完全性 IV (video)](https://www.youtube.com/watch?v=NKLDp3Rch3M&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=18)\n    - [ ] Skiena:\n        - [ ] [CSE373 2012 - 课程 23 - 介绍 NP-完全性 IV (video)](https://youtu.be/KiK5TVgXbFg?list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&t=1508)\n        - [ ] [CSE373 2012 - 课程 24 - NP-完全性证明 (video)](https://www.youtube.com/watch?v=27Al52X3hd4&index=24&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n        - [ ] [CSE373 2012 - 课程 25 - NP-完全性挑战 (video)](https://www.youtube.com/watch?v=xCPH4gwIIXM&index=25&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b)\n    - [ ] [复杂度: P, NP, NP-完全性, 规约 (video)](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n    - [ ] [复杂度: 近视算法 Algorithms (video)](https://www.youtube.com/watch?v=MEz1J9wY2iM&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=24)\n    - [ ] [复杂度: 固定参数算法 (video)](https://www.youtube.com/watch?v=4q-jmGrmxKs&index=25&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - Peter Norvik 讨论旅行商问题的近似最优解:\n        - [Jupyter 笔记本](http://nbviewer.jupyter.org/url/norvig.com/ipython/TSP.ipynb)\n    - 《算法导论》的第 1048 - 1140 页。\n\n- ### 缓存（Cache）\n    - [ ] LRU 缓存:\n        - [ ] [LRU 的魔力 (100 Days of Google Dev) (video)](https://www.youtube.com/watch?v=R5ON3iwx78M)\n        - [ ] [实现 LRU (video)](https://www.youtube.com/watch?v=bq6N7Ym81iI)\n        - [ ] [LeetCode - 146 LRU Cache (C++) (video)](https://www.youtube.com/watch?v=8-FZRAjR7qU)\n    - [ ] CPU 缓存:\n        - [ ] [MIT 6.004 L15: 存储体系 (video)](https://www.youtube.com/watch?v=vjYF_fAZI5E&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-&index=24)\n        - [ ] [MIT 6.004 L16: 缓存的问题 (video)](https://www.youtube.com/watch?v=ajgC3-pyGlk&index=25&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-)\n\n- ### 进程（Processe）和线程（Thread）\n    - [ ] 计算机科学 162 - 操作系统 (25 个视频):\n        - 视频 1-11 是关于进程和线程\n        - [操作系统和系统编程 (video)](https://www.youtube.com/playlist?list=PL-XXv-cvA_iBDyz-ba4yDskqMDY6A1w_c)\n    - [进程和线程的区别是什么?](https://www.quora.com/What-is-the-difference-between-a-process-and-a-thread)\n    - 涵盖了:\n        - 进程、线程、协程\n            - 进程和线程的区别\n            - 进程\n            - 线程\n            - 锁\n            - 互斥\n            - 信号量\n            - 监控\n            - 他们是如何工作的\n            - 死锁\n            - 活锁\n        - CPU 活动, 中断, 上下文切换\n        - 现代多核处理器的并发式结构\n        - 进程资源需要（内存：代码、静态存储器、栈、堆、文件描述符、I/O）\n        - 线程资源需要（在同一个进程内和其他线程共享以上的资源，但是每个线程都有独立的程序计数器、栈计数器、寄存器和栈）\n        - Fork 操作是真正的写时复制（只读），直到新的进程写到内存中，才会生成一份新的拷贝。\n        - 上下文切换\n            - 操作系统和底层硬件是如何初始化上下文切换的。\n    - [ ] [C++ 的线程 (系列 - 10 个视频)](https://www.youtube.com/playlist?list=PL5jc9xFGsL8E12so1wlMS0r0hTQoJL74M)\n    - [ ] Python 的协程 (视频):\n        - [ ] [线程系列](https://www.youtube.com/playlist?list=PL1H1sBF1VAKVMONJWJkmUh6_p8g4F2oy1)\n        - [ ] [Python 线程](https://www.youtube.com/watch?v=Bs7vPNbB9JM)\n        - [ ] [理解 Python 的 GIL (2010)](https://www.youtube.com/watch?v=Obt-vMVdM8s)\n            - [参考](http://www.dabeaz.com/GIL)\n        - [ ] [David Beazley - Python 协程 - PyCon 2015](https://www.youtube.com/watch?v=MCs5OvhV9S4)\n        - [ ] [Keynote David Beazley - 兴趣主题 (Python 异步 I/O)](https://www.youtube.com/watch?v=ZzfHjytDceU)\n        - [ ] [Python 中的互斥](https://www.youtube.com/watch?v=0zaPs8OtyKY)\n\n\n    系统设计以及可伸缩性，要把软硬件的伸缩性设计的足够好有很多的东西要考虑，所以这是个包含非常多内容和资源的大主题。需要花费相当多的时间在这个主题上。\n\n- ### 系统设计、可伸缩性、数据处理\n    - Yegge 的注意事项:\n        - 伸缩性\n            - 把大数据集提取为单一值\n            - 大数据集转换\n            - 处理大量的数据集\n        - 系统\n            - 特征集\n            - 接口\n            - 类层次结构\n            - 在特定的约束下设计系统\n            - 轻量和健壮性\n            - 权衡和折衷\n            - 性能分析和优化\n    - [ ] **从这里开始**: [HiredInTech：系统设计](http://www.hiredintech.com/system-design/)\n    - [ ] [该如何为技术面试里设计方面的问题做准备?](https://www.quora.com/How-do-I-prepare-to-answer-design-questions-in-a-technical-interview?redirected_qid=1500023)\n    - [ ] [在系统设计面试前必须知道的 8 件事](http://blog.gainlo.co/index.php/2015/10/22/8-things-you-need-to-know-before-system-design-interviews/)\n    - [ ] [算法设计](http://www.hiredintech.com/algorithm-design/)\n    - [ ] [数据库范式 - 1NF, 2NF, 3NF and 4NF (video)](https://www.youtube.com/watch?v=UrYLYV7WSHM)\n    - [ ] [系统设计面试](https://github.com/checkcheckzz/system-design-interview) - 这一部分有很多的资源，浏览一下我放在下面的文章和例子。\n    - [ ] [如何在系统设计面试中脱颖而出](http://www.palantir.com/2011/10/how-to-rock-a-systems-design-interview/)\n    - [ ] [每个人都该知道的一些数字](http://everythingisdata.wordpress.com/2009/10/17/numbers-everyone-should-know/)\n    - [ ] [上下文切换操作会耗费多少时间?](http://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html)\n    - [ ] [跨数据中心的事务 (video)](https://www.youtube.com/watch?v=srOgpXECblk)\n    - [ ] [简明 CAP 理论介绍](http://ksat.me/a-plain-english-introduction-to-cap-theorem/)\n    - [ ] Paxos 一致性算法:\n        - [时间很短](https://www.youtube.com/watch?v=s8JqcZtvnsM)\n        - [用例 和 multi-paxos](https://www.youtube.com/watch?v=JEpsBg0AO6o)\n        - [论文](http://research.microsoft.com/en-us/um/people/lamport/pubs/paxos-simple.pdf)\n    - [ ] [一致性哈希](http://www.tom-e-white.com/2007/11/consistent-hashing.html)\n    - [ ] [NoSQL 模式](http://horicky.blogspot.com/2009/11/nosql-patterns.html)\n    - [ ] [OOSE: UML 2.0 系列 (video)](https://www.youtube.com/watch?v=OkC7HKtiZC0&list=PLGLfVvz_LVvQ5G-LdJ8RLqe-ndo7QITYc)\n    - [ ] OOSE: 使用 UML 和 Java 开发软件 (21 videos):\n        - 如果你对 OO 都深刻的理解和实践，可以跳过这部分。\n        - [OOSE: 使用 UML 和 Java 开发软件](https://www.youtube.com/playlist?list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n    - [ ] 面向对象编程的 SOLID 原则:\n        - [ ] [Bob Martin 面向对象的 SOLID 原则和敏捷设计 (video)](https://www.youtube.com/watch?v=TMuno5RZNeE)\n        - [ ] [C# SOLID 设计模式 (video)](https://www.youtube.com/playlist?list=PL8m4NUhTQU48oiGCSgCP1FiJEcg_xJzyQ)\n        - [ ] [SOLID 原则 (video)](https://www.youtube.com/playlist?list=PL4CE9F710017EA77A)\n        - [ ] S - [单一职责原则](http://www.oodesign.com/single-responsibility-principle.html) | [每个对象的单一职责](http://www.javacodegeeks.com/2011/11/solid-single-responsibility-principle.html)\n            - [更多](https://docs.google.com/open?id=0ByOwmqah_nuGNHEtcU5OekdDMkk)\n        - [ ] O - [开闭原则](http://www.oodesign.com/open-close-principle.html)  | [生产环境里的对象应该为扩展做准备而不是为更改](https://en.wikipedia.org/wiki/Open/closed_principle)\n            - [更多](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgN2M5MTkwM2EtNWFkZC00ZTI3LWFjZTUtNTFhZGZiYmUzODc1&hl=en)\n        - [ ] L - [里氏代换原则](http://www.oodesign.com/liskov-s-substitution-principle.html) | [基类和继承类遵循 ‘IS A’ 原则](http://stackoverflow.com/questions/56860/what-is-the-liskov-substitution-principle)\n            - [更多](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgNzAzZjA5ZmItNjU3NS00MzQ5LTkwYjMtMDJhNDU5ZTM0MTlh&hl=en)\n        - [ ] I - [接口隔离原则](http://www.oodesign.com/interface-segregation-principle.html) | 客户端被迫实现用不到的接口\n            - [5 分钟讲解接口隔离原则 (video)](https://www.youtube.com/watch?v=3CtAfl7aXAQ)\n            - [更多](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgOTViYjJhYzMtMzYxMC00MzFjLWJjMzYtOGJiMDc5N2JkYmJi&hl=en)\n        - [ ] D -[依赖反转原则](http://www.oodesign.com/dependency-inversion-principle.html) | 减少对象里的依赖。\n            - [什么是依赖倒置以及它为什么重要](http://stackoverflow.com/questions/62539/what-is-the-dependency-inversion-principle-and-why-is-it-important)\n            - [更多](http://docs.google.com/a/cleancoder.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwhCYaYDn8EgMjdlMWIzNGUtZTQ0NC00ZjQ5LTkwYzQtZjRhMDRlNTQ3ZGMz&hl=en)\n    - [ ] 可伸缩性:\n        - [ ] [很棒的概述 (video)](https://www.youtube.com/watch?v=-W9F__D3oY4)\n        - [ ] 简短系列:\n            - [克隆](http://www.lecloud.net/post/7295452622/scalability-for-dummies-part-1-clones)\n            - [数据库](http://www.lecloud.net/post/7994751381/scalability-for-dummies-part-2-database)\n            - [缓存](http://www.lecloud.net/post/9246290032/scalability-for-dummies-part-3-cache)\n            - [异步](http://www.lecloud.net/post/9699762917/scalability-for-dummies-part-4-asynchronism)\n        - [ ] [可伸缩的 Web 架构和分布式系统](http://www.aosabook.org/en/distsys.html)\n        - [ ] [错误的分布式系统解释](https://pages.cs.wisc.edu/~zuyu/files/fallacies.pdf)\n        - [ ] [实用编程技术](http://horicky.blogspot.com/2010/10/scalable-system-design-patterns.html)\n            - [extra: Google Pregel 图形处理](http://horicky.blogspot.com/2010/07/google-pregel-graph-processing.html)\n        - [ ] [Jeff Dean - 在 Goolge 构建软件系统 (video)](https://www.youtube.com/watch?v=modXC5IWTJI)\n        - [ ] [可伸缩系统架构设计介绍](http://lethain.com/introduction-to-architecting-systems-for-scale/)\n        - [ ] [使用 App Engine 和云存储扩展面向全球用户的手机游戏架构实践(video)](https://www.youtube.com/watch?v=9nWyWwY2Onc)\n        - [ ] [How Google Does Planet-Scale Engineering for Planet-Scale Infra (video)](https://www.youtube.com/watch?v=H4vMcD7zKM0)\n        - [ ] [算法的重要性](https://www.topcoder.com/community/data-science/data-science-tutorials/the-importance-of-algorithms/)\n        - [ ] [分片](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)\n        - [ ] [Facebook 系统规模扩展实践 (2009)](https://www.infoq.com/presentations/Scale-at-Facebook)\n        - [ ] [Facebook 系统规模扩展实践 (2012), \"为 10 亿用户构建\" (video)](https://www.youtube.com/watch?v=oodS71YtkGU)\n        - [ ] [Long Game 工程实践 - Astrid Atkinson Keynote(video)](https://www.youtube.com/watch?v=p0jGmgIrf_M&list=PLRXxvay_m8gqVlExPC5DG3TGWJTaBgqSA&index=4)\n        - [ ] [30 分钟看完 YouTuBe 7 年系统扩展经验](http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html)\n            - [video](https://www.youtube.com/watch?v=G-lGCC4KKok)\n        - [ ] [PayPal 如何用 8 台虚拟机扛住 10 亿日交易量系统](http://highscalability.com/blog/2016/8/15/how-paypal-scaled-to-billions-of-transactions-daily-using-ju.html)\n        - [ ] [如何对大数据集去重](https://blog.clevertap.com/how-to-remove-duplicates-in-large-datasets/)\n        - [ ] [Etsy 的扩展和工程文化探究 Jon Cowie (video)](https://www.youtube.com/watch?v=3vV4YiqKm1o)\n        - [ ] [是什么造就了 Amazon 自己的微服务架构](http://thenewstack.io/led-amazon-microservices-architecture/)\n        - [ ] [压缩还是不压缩，是 Uber 面临的问题](https://eng.uber.com/trip-data-squeeze/)\n        - [ ] [异步 I/O Tarantool 队列](http://highscalability.com/blog/2016/3/3/asyncio-tarantool-queue-get-in-the-queue.html)\n        - [ ] [什么时候应该用近视查询处理?](http://highscalability.com/blog/2016/2/25/when-should-approximate-query-processing-be-used.html)\n        - [ ] [Google 从单数据中心到故障转移, 到本地多宿主架构的演变]( http://highscalability.com/blog/2016/2/23/googles-transition-from-single-datacenter-to-failover-to-a-n.html)\n        - [ ] [Spanner](http://highscalability.com/blog/2012/9/24/google-spanners-most-surprising-revelation-nosql-is-out-and.html)\n        - [ ] [Egnyte: 构建和扩展 PB 级分布式系统架构的经验教训](http://highscalability.com/blog/2016/2/15/egnyte-architecture-lessons-learned-in-building-and-scaling.html)\n        - [ ] [机器学习驱动的编程: 新世界的新编程方式](http://highscalability.com/blog/2016/7/6/machine-learning-driven-programming-a-new-programming-for-a.html)\n        - [ ] [日服务数百万请求的图像优化技术](http://highscalability.com/blog/2016/6/15/the-image-optimization-technology-that-serves-millions-of-re.html)\n        - [ ] [Patreon 架构](http://highscalability.com/blog/2016/2/1/a-patreon-architecture-short.html)\n        - [ ] [Tinder: 推荐引擎是如何决定下一个你将会看到谁的?](http://highscalability.com/blog/2016/1/27/tinder-how-does-one-of-the-largest-recommendation-engines-de.html)\n        - [ ] [现代缓存设计](http://highscalability.com/blog/2016/1/25/design-of-a-modern-cache.html)\n        - [ ] [Facebook 实时视频流扩展](http://highscalability.com/blog/2016/1/13/live-video-streaming-at-facebook-scale.html)\n        - [ ] [在 Amazon AWS 上把服务扩展到 1100 万量级的新手教程](http://highscalability.com/blog/2016/1/11/a-beginners-guide-to-scaling-to-11-million-users-on-amazons.html)\n        - [ ] [对延时敏感的应用是否应该使用 Docker?](http://highscalability.com/blog/2015/12/16/how-does-the-use-of-docker-effect-latency.html)\n        - [ ] [AMP（Accelerated Mobile Pages）的存在是对 Google 的威胁么?](http://highscalability.com/blog/2015/12/14/does-amp-counter-an-existential-threat-to-google.html)\n        - [ ] [360 度解读 Netflix 技术栈](http://highscalability.com/blog/2015/11/9/a-360-degree-view-of-the-entire-netflix-stack.html)\n        - [ ] [延迟无处不在 - 如何搞定它？](http://highscalability.com/latency-everywhere-and-it-costs-you-sales-how-crush-it)\n        - [ ] [无服务器架构](http://martinfowler.com/articles/serverless.html)\n        - [ ] [是什么驱动着 Instagram: 上百个实例、几十种技术](http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances)\n        - [ ] [Cinchcast 架构 - 每天处理 1500 小时的音频](http://highscalability.com/blog/2012/7/16/cinchcast-architecture-producing-1500-hours-of-audio-every-d.html)\n        - [ ] [Justin.Tv 实时视频播放架构](http://highscalability.com/blog/2010/3/16/justintvs-live-video-broadcasting-architecture.html)\n        - [ ] [Playfish's 社交游戏架构 - 每月五千万用户增长](http://highscalability.com/blog/2010/9/21/playfishs-social-gaming-architecture-50-million-monthly-user.html)\n        - [ ] [猫途鹰架构 - 40 万访客, 200 万动态页面访问, 30TB 数据](http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-view.html)\n        - [ ] [PlentyOfFish 架构](http://highscalability.com/plentyoffish-architecture)\n        - [ ] [Salesforce 架构 - 如何扛住 13 亿日交易量](http://highscalability.com/blog/2013/9/23/salesforce-architecture-how-they-handle-13-billion-transacti.html)\n        - [ ] [ESPN's 架构扩展](http://highscalability.com/blog/2013/11/4/espns-architecture-at-scale-operating-at-100000-duh-nuh-nuhs.html)\n        - [ ] 下面 『消息、序列化和消息系统』部分的内容会提到什么样的技术能把各种服务整合到一起\n        - [ ] Twitter:\n            - [O'Reilly MySQL CE 2011: Jeremy Cole, \"Big and Small Data at @Twitter\" (video)](https://www.youtube.com/watch?v=5cKTP36HVgI)\n            - [时间线的扩展](https://www.infoq.com/presentations/Twitter-Timeline-Scalability)\n        - 更多内容可以查看视频部分的『大规模数据挖掘』视频系列。\n    - [ ] 系统设计问题练习：下面有一些指导原则，每一个都有相关文档以及在现实中该如何处理。\n        - 复习: [HiredInTech 的系统设计](http://www.hiredintech.com/system-design/)\n        - [cheat sheet](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/system-design.pdf)\n        - 流程:\n            1. 理解问题和范围:\n                - 在面试官的帮助下定义用例\n                - 提出附加功能的建议\n                - 去掉面试官认定范围以外的内容\n                - 假定高可用是必须的，而且要作为一个用例\n            2. 考虑约束:\n                - 问一下每月请求量\n                - 问一下每秒请求量 (他们可能会主动提到或者让你算一下)\n                - 评估读写所占的百分比\n                - 评估的时候牢记 2/8 原则\n                - 每秒写多少数据\n                - 总的数据存储量要考虑超过 5 年的情况\n                - 每秒读多少数据\n            3. 抽象设计:\n                - 分层 (服务, 数据, 缓存)\n                - 基础设施: 负载均衡, 消息\n                - 粗略的概括任何驱动整个服务的关键算法\n                - 考虑瓶颈并指出解决方案\n        - 练习:\n            - [设计一个 CDN 网络](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2112&context=compsci)\n            - [设计一个随机唯一 ID 生成系统](https://blog.twitter.com/2010/announcing-snowflake)\n            - [设计一个在线多人卡牌游戏](http://www.indieflashblog.com/how-to-create-an-asynchronous-multiplayer-game.html)\n            - [设计一个 key-value 数据库](http://www.slideshare.net/dvirsky/introduction-to-redis)\n            - [设计一个函数获取过去某个时间段内前 K 个最高频访问的请求]( https://icmi.cs.ucsb.edu/research/tech_reports/reports/2005-23.pdf)\n            - [设计一个图片分享系统](http://highscalability.com/blog/2011/12/6/instagram-architecture-14-million-users-terabytes-of-photos.html)\n            - [设计一个推荐系统](http://ijcai13.org/files/tutorial_slides/td3.pdf)\n            - [设计一个短域名生成系统](http://www.hiredintech.com/system-design/the-system-design-process/)\n            - [设计一个缓存系统](https://www.adayinthelifeof.nl/2011/02/06/memcache-internals/)\n\n- ### 论文\n    - 有 Google 的论文和一些知名的论文.\n    - 你很可能实在没时间一篇篇完整的读完他们。我建议可以有选择的读其中一些论文里的核心部分。\n    - [ ] [1978: 通信顺序处理](http://spinroot.com/courses/summer/Papers/hoare_1978.pdf)\n        - [Go 实现](https://godoc.org/github.com/thomas11/csp)\n        - [喜欢经典的论文?](https://www.cs.cmu.edu/~crary/819-f09/)\n    - [ ] [2003: The Google 文件系统](http://static.googleusercontent.com/media/research.google.com/en//archive/gfs-sosp2003.pdf)\n        - 2012 年被 Colossus 取代了\n    - [ ] [2004: MapReduce: Simplified Data Processing on Large Clusters]( http://static.googleusercontent.com/media/research.google.com/en//archive/mapreduce-osdi04.pdf)\n        - 大多被云数据流取代了?\n    - [ ] [2007: 每个程序员都应该知道的内存知识 (非常长，作者建议跳过某些章节来阅读)](https://www.akkadia.org/drepper/cpumemory.pdf)\n    - [ ] [2012: Google 的 Colossus](https://www.wired.com/2012/07/google-colossus/)\n        - 没有论文\n    - [ ] 2012: AddressSanitizer: 快速的内存访问检查器:\n        - [论文](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37752.pdf)\n        - [视频](https://www.usenix.org/conference/atc12/technical-sessions/presentation/serebryany)\n    - [ ] 2013: Spanner: Google 的分布式数据库:\n        - [论文](http://static.googleusercontent.com/media/research.google.com/en//archive/spanner-osdi2012.pdf)\n        - [视频](https://www.usenix.org/node/170855)\n    - [ ] [2014: Machine Learning: The High-Interest Credit Card of Technical Debt](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43146.pdf)\n    - [ ] [2015: Continuous Pipelines at Google](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43790.pdf)\n    - [ ] [2015: 大规模高可用: 构建 Google Ads 的数据基础设施](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44686.pdf)\n    - [ ] [2015: TensorFlow: 异构分布式系统上的大规模机器学习](http://download.tensorflow.org/paper/whitepaper2015.pdf )\n    - [ ] [2015: 开发者应该如何搜索代码：用例学习](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43835.pdf)\n    - [ ] [2016: Borg, Omega, and Kubernetes](http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/44843.pdf)\n\n- ### 测试\n    - 涵盖了:\n        - 单元测试是如何工作的\n        - 什么是模拟对象\n        - 什么是集成测试\n        - 什么是依赖注入\n    - [ ] [James Bach 讲敏捷软件测试 (video)](https://www.youtube.com/watch?v=SAhJf36_u5U)\n    - [ ] [James Bach 软件测试公开课 (video)](https://www.youtube.com/watch?v=ILkT_HV9DVU)\n    - [ ] [Steve Freeman - 测试驱动的开发 (video)](https://vimeo.com/83960706)\n        - [slides](http://gotocon.com/dl/goto-berlin-2013/slides/SteveFreeman_TestDrivenDevelopmentThatsNotWhatWeMeant.pdf)\n    - [ ] [测试驱动的开发已死。测试不朽。](http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html)\n    - [ ] [测试驱动的开发已死? (video)](https://www.youtube.com/watch?v=z9quxZsLcfo)\n    - [ ] [视频系列 (152 个) - 并不都是必须 (video)](https://www.youtube.com/watch?v=nzJapzxH_rE&list=PLAwxTw4SYaPkWVHeC_8aSIbSxE_NXI76g)\n    - [ ] [Python：测试驱动的 Web 开发](http://www.obeythetestinggoat.com/pages/book.html#toc)\n    - [ ] 依赖注入:\n        - [ ] [视频](https://www.youtube.com/watch?v=IKD2-MAkXyQ)\n        - [ ] [测试之道](http://jasonpolites.github.io/tao-of-testing/ch3-1.1.html)\n    - [ ] [如何编写测试](http://jasonpolites.github.io/tao-of-testing/ch4-1.1.html)\n\n- ### 调度\n    - 在操作系统中是如何运作的\n    - 在操作系统部分的视频里有很多资料\n\n- ### 实现系统例程\n    - 理解你使用的系统 API 底层有什么\n    - 你能自己实现它们么?\n\n- ### 字符串搜索和操作\n    - [ ] [文本的搜索模式 (video)](https://www.coursera.org/learn/data-structures/lecture/tAfHI/search-pattern-in-text)\n    - [ ] Rabin-Karp (videos):\n        - [Rabin Karps 算法](https://www.coursera.org/learn/data-structures/lecture/c0Qkw/rabin-karps-algorithm)\n        - [预先计算的优化](https://www.coursera.org/learn/data-structures/lecture/nYrc8/optimization-precomputation)\n        - [优化: 实现和分析](https://www.coursera.org/learn/data-structures/lecture/h4ZLc/optimization-implementation-and-analysis)\n        - [Table Doubling, Karp-Rabin](https://www.youtube.com/watch?v=BRO7mVIFt08&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=9)\n        - [滚动哈希](https://www.youtube.com/watch?v=w6nuXg0BISo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=32)\n    - [ ] Knuth-Morris-Pratt (KMP) 算法:\n        - [Pratt 算法](https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm)\n        - [教程: Knuth-Morris-Pratt (KMP) 字符串匹配算法](https://www.youtube.com/watch?v=2ogqPWJSftE)\n    - [ ] Boyer–Moore 字符串搜索算法\n        - [Boyer-Moore字符串搜索算法](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm)\n        - [Boyer-Moore-Horspool 高级字符串搜索算法 (video)](https://www.youtube.com/watch?v=QDZpzctPf10)\n    - [ ] [Coursera: 字符串的算法](https://www.coursera.org/learn/algorithms-on-strings/home/week/1)\n\n---\n\n## 终面\n\n    这一部分有一些短视频，你可以快速的观看和复习大多数重要概念。\n    这对经常性的巩固很有帮助。\n\n#### 综述:\n\n- [ ] 2-3 分钟的短视频系列 (23 个)\n    - [Videos](https://www.youtube.com/watch?v=r4r1DZcx1cM&list=PLmVb1OknmNJuC5POdcDv5oCS7_OUkDgpj&index=22)\n- [ ] 2-5 分钟的短视频系列 - Michael Sambol (18 个):\n    - [Videos](https://www.youtube.com/channel/UCzDJwLWoYCUQowF_nG3m5OQ)\n\n#### 排序:\n\n- [ ] 归并排序: https://www.youtube.com/watch?v=GCae1WNvnZM\n\n\n## 书籍\n\n### Google Coaching 里提到的\n\n**阅读并做练习:**\n\n- [ ] 算法设计手册 (Skiena)\n    - 书 (Kindle 上可以租到):\n        - [Algorithm Design Manual](http://www.amazon.com/Algorithm-Design-Manual-Steven-Skiena/dp/1849967202)\n    - Half.com 是一个资源丰富且性价比很高的在线书店.\n    - 答案:\n        - [解答](http://www.algorithm.cs.sunysb.edu/algowiki/index.php/The_Algorithms_Design_Manual_(Second_Edition))\n        - [解答](http://blog.panictank.net/category/algorithmndesignmanualsolutions/page/2/)\n    - [勘误表](http://www3.cs.stonybrook.edu/~skiena/algorist/book/errata)\n\n    read and do exercises from the books below. Then move to coding challenges (further down below)\n    一旦你理解了每日计划里的所有内容，就去读上面所列的书并完成练习，然后开始读下面所列的书并做练习，之后就可以开始实战写代码了（本文再往后的部分）\n\n**首先阅读:**\n- [ ] [Programming Interviews Exposed: Secrets to Landing Your Next Job, 2nd Edition](http://www.wiley.com/WileyCDA/WileyTitle/productCd-047012167X.html)\n\n**然后阅读 (这本获得了很多推荐， 但是不在 Google coaching 的文档里):**\n- [ ] [Cracking the Coding Interview, 6th Edition](http://www.amazon.com/Cracking-Coding-Interview-6th-Programming/dp/0984782850/)\n    - 如果你看到有人在看 \"The Google Resume\", 实际上它和 \"Cracking the Coding Interview\" 是同一个作者写的，而且后者是升级版。\n\n### 附加书单\n\n这些没有被 Google 推荐阅读，不过我因为需要这些背景知识所以也把它们列在了这里。\n\n- [ ] C Programming Language, Vol 2\n    - [练习的答案](https://github.com/lekkas/c-algorithms)\n\n- [ ] C++ Primer Plus, 6th Edition\n\n- [ ] [《Unxi 环境高级编程》 The Unix Programming Environment](http://product.half.ebay.com/The-UNIX-Programming-Environment-by-Brian-W-Kernighan-and-Rob-Pike-1983-Other/54385&tg=info)\n\n- [ ] [《编程珠玑》 Programming Pearls](http://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880)\n\n- [ ] [Algorithms and Programming: Problems and Solutions](http://www.amazon.com/Algorithms-Programming-Solutions-Alexander-Shen/dp/0817638474)\n\n### 如果你有时间\n\n- [ ] [Introduction to Algorithms](https://www.amazon.com/Introduction-Algorithms-3rd-MIT-Press/dp/0262033844)\n\n- [ ] [Elements of Programming Interviews](https://www.amazon.com/Elements-Programming-Interviews-Insiders-Guide/dp/1479274836)\n    - 如果你希望在面试里用 C++ 写代码，这本书的代码全都是 C++ 写的\n    - 通常情况下能找到解决方案的好书.\n\n## 编码练习和挑战\n\n一旦你学会了理论基础，就应该把它们拿出来练练。\n尽量坚持每天做编码练习，越多越好。\n\n编程问题预备:\n\n- [ ] [不错的介绍 (摘自 System Design 章节): 算法设计:](http://www.hiredintech.com/algorithm-design/)\n- [ ] [如何找到解决方案](https://www.topcoder.com/community/data-science/data-science-tutorials/how-to-find-a-solution/)\n- [ ] [如何剖析 Topcoder 题目描述](https://www.topcoder.com/community/data-science/data-science-tutorials/how-to-dissect-a-topcoder-problem-statement/)\n- [ ] [Topcoders 里用到的数学](https://www.topcoder.com/community/data-science/data-science-tutorials/mathematics-for-topcoders/)\n- [ ] [动态规划 – 从入门到精通](https://www.topcoder.com/community/data-science/data-science-tutorials/dynamic-programming-from-novice-to-advanced/)\n\n- [MIT 面试材料](https://courses.csail.mit.edu/iap/interview/materials.php)\n\n- [针对编程语言本身的练习](http://exercism.io/languages)\n\n编码练习平台:\n\n- [LeetCode](https://leetcode.com/)\n- [TopCoder](https://www.topcoder.com/)\n- [Project Euler (数学方向为主)](https://projecteuler.net/index.php?section=problems)\n- [Codewars](http://www.codewars.com)\n- [HackerRank](https://www.hackerrank.com/)\n- [Codility](https://codility.com/programmers/)\n- [InterviewCake](https://www.interviewcake.com/)\n- [InterviewBit](https://www.interviewbit.com/invite/icjf)\n\n- [模拟大公司的面试](http://www.gainlo.co/)\n\n## 当你临近面试时\n\n- [ ] 搞定代码面试 (videos):\n    - [Cracking The Code Interview](https://www.youtube.com/watch?v=4NIb9l3imAo)\n    - [Cracking the Coding Interview - 全栈系列](https://www.youtube.com/watch?v=Eg5-tdAwclo)\n    - [Ask Me Anything: Gayle Laakmann McDowell (Cracking the Coding Interview 的作者)](https://www.youtube.com/watch?v=1fqxMuPmGak)\n\n## 你的简历\n\n- [10 条小贴士让你写出一份还算不错的简历](http://steve-yegge.blogspot.co.uk/2007_09_01_archive.html)\n- 这是搞定面试的第一个关键步骤\n\n\n## 当面试来临的时候\n\n    随着下面列举的问题思考下你可能会遇到的 20 个面试问题\n    每个问题准备 2-3 种回答\n    准备点故事，不要只是摆一些你完成的事情的数据，相信我，人人都喜欢听故事\n\n- 你为什么想得到这份工作？\n- 你解决过的最有难度的问题是什么？\n- 面对过的最大挑战是什么?\n- 见过的最好或者最坏的设计是怎么样的?\n- 对某项 Google 产品提出改进建议。\n- 你作为一个个体同时也是团队的一员，如何达到最好的工作状态?\n- 你的什么技能或者经验是你的角色中不可或缺的?为什么？\n- 你在某份工作或某个项目中最享受的是什么?\n- 你在某份工作或某个项目中面临过的最大挑战是什么?\n- 你在某份工作或某个项目中遇到过的最蛋疼的 Bug 是什么样的？\n- 你在某份工作或某个项目中学到了什么？\n- 你在某份工作或某个项目中哪些地方还可以做的更好？\n\n## 问面试官的问题\n\n    我会问的一些：(可能我已经知道了答案但我想听听面试官的看法或者了解团队的前景):\n\n- 团队多大规模?\n- 开发周期是怎样的? 会使用瀑布流/极限编程/敏捷开发么?\n- 经常会为 deadline 加班么? 或者是有弹性的?\n- 团队里怎么做技术选型?\n- 每周平均开多少次会?\n- 你觉得工作环境有助于员工集中精力吗?\n- 目前正在做什么工作?\n- 喜欢这些事情吗?\n- 工作期限是怎么样的?\n\n## 当你获得了梦想的职位\n\n我还能说些什么呢，恭喜你！\n\n- [我希望在 Google 的第一天就知道的 10 件事](https://medium.com/@moonstorming/10-things-i-wish-i-knew-on-my-first-day-at-google-107581d87286#.livxn7clw)\n\n坚持继续学习。\n\n得到这份工作只是一个开始。\n\n---\n\n    *****************************************************************************************************\n    *****************************************************************************************************\n\n    下面的内容都是可选的。这些是我的推荐，不是 Google 的。\n    通过学习这些内容，你将会得到更多的有关 CS 的概念，并将为所有的软件工程工作做更好的准备。\n\n    *****************************************************************************************************\n    *****************************************************************************************************\n\n---\n\n## 附加的学习\n\n- ### Unicode\n    - [ ] [每一个软件开发者的绝对最低限度，必须要知道的关于 Unicode 和字符集知识]( http://www.joelonsoftware.com/articles/Unicode.html)\n    - [ ] [关于处理文本需要的编码和字符集, 每个程序员绝对需要知道的知识](http://kunststube.net/encoding/)\n\n- ### 字节顺序\n    - [ ] [大、小端字节序](https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html)\n    - [ ] [大端字节 Vs 小端字节(视频)](https://www.youtube.com/watch?v=JrNF0KRAlyo)\n    - [ ] [大、小端字节序的里里外外(Big And Little Endian Inside/Out) (视频)](https://www.youtube.com/watch?v=oBSuXP-1Tc0)\n        - 内核开发者的讨论非常技术性，如果大多数都超出了你的理解范围，不要太担心。\n        - 前半段已经足够了。\n\n- ### Emacs and vi(m)\n    - Yegge 的建议，从一个很早以前的亚马逊招聘信息中而来：熟悉基于 unix 的代码编辑器\n    - vi(m):\n        - [使用 vim 进行编辑 01 - 安装, 设置和模式 (视频)](https://www.youtube.com/watch?v=5givLEMcINQ&index=1&list=PL13bz4SHGmRxlZVmWQ9DvXo1fEg4UdGkr)\n        - [VIM 的冒险之旅](http://vim-adventures.com/)\n        - 4 个视频集:\n            - [vi/vim 编辑器 - 课程 1](https://www.youtube.com/watch?v=SI8TeVMX8pk)\n            - [vi/vim 编辑器 - 课程 2](https://www.youtube.com/watch?v=F3OO7ZIOaJE)\n            - [vi/vim 编辑器 - 课程 4](https://www.youtube.com/watch?v=1lYD5gwgZIA)\n            - [vi/vim 编辑器 - 课程 3](https://www.youtube.com/watch?v=ZYEccA_nMaI)\n        - [使用 Vi 而不是 Emacs](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#Using_Vi_instead_of_Emacs)\n    - emacs:\n        - [基础 Emacs 教程 (视频)](https://www.youtube.com/watch?v=hbmV1bnQ-i0)\n        - 3 个视频集:\n            - [Emacs 教程 (初学者) -第 1 部分- 文件命令, 剪切/复制/粘贴,  自定义命令](https://www.youtube.com/watch?v=ujODL7MD04Q)\n            - [Emacs 教程 (初学者 -第 2 部分- Buffer 管理, 搜索, M-x grep 和 rgrep 模式](https://www.youtube.com/watch?v=XWpsRupJ4II)\n            - [Emacs 教程 (初学者 -第 3 部分- 表达式, 声明, ~/.emacs 文件和包机制](https://www.youtube.com/watch?v=paSgzPso-yc)\n        - [Evil 模式: 或许, 我是怎样对 Emacs 路人转粉的 (视频)](https://www.youtube.com/watch?v=JWD1Fpdd4Pc)\n        - [使用 Emacs 开发 C 程序](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#Writing_C_programs_with_Emacs)\n        - [(或许) 深度组织模式:管理结构 (视频)](https://www.youtube.com/watch?v=nsGYet02bEk)\n\n- ### Unix 命令行工具\n    - 下列内容中的优秀工具由的 Yegge 推荐，Yegge 目前致力于 Amazon 人事招聘处。\n    - [ ] bash\n    - [ ] cat\n    - [ ] grep\n    - [ ] sed\n    - [ ] awk\n    - [ ] curl or wget\n    - [ ] sort\n    - [ ] tr\n    - [ ] uniq\n    - [ ] [strace](https://en.wikipedia.org/wiki/Strace)\n    - [ ] [tcpdump](https://danielmiessler.com/study/tcpdump/)\n\n- ### 信息资源 (视频)\n    - [ ] [Khan Academy 可汗学院](https://www.khanacademy.org/computing/computer-science/informationtheory)\n    - [ ] 更多有关马尔可夫的内容:\n        - [ ] [Core Markov Text Generation马尔可夫内容生成](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/waxgx/core-markov-text-generation)\n        - [ ] [Core Implementing Markov Text Generation马尔可夫内容生成补充](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/gZhiC/core-implementing-markov-text-generation)\n        - [ ] [Project = Markov Text Generation Walk Through一个马尔可夫内容生成器的项目](https://www.coursera.org/learn/data-structures-optimizing-performance/lecture/EUjrq/project-markov-text-generation-walk-through)\n    - 关于更多信息，请参照下方 MIT 6.050J 信息和系统复杂度的内容.\n\n- ### 奇偶校验位 & 汉明码 (视频)\n    - [ ] [入门](https://www.youtube.com/watch?v=q-3BctoUpHE)\n    - [ ] [奇偶校验位](https://www.youtube.com/watch?v=DdMcAUlxh1M)\n    - [ ] 汉明码(Hamming Code):\n        - [发现错误](https://www.youtube.com/watch?v=1A_NcXxdoCc)\n        - [修正错误](https://www.youtube.com/watch?v=JAMLuxdHH8o)\n    - [ ] [检查错误](https://www.youtube.com/watch?v=wbH2VxzmoZk)\n\n- ### 系统熵值（系统复杂度）\n    - 请参考下方视频\n    - 观看之前，请先确定观看了信息论的视频\n    - [ ] [信息理论, 克劳德·香农, 熵值, 系统冗余, 数据比特压缩 (视频)](https://youtu.be/JnJq3Py0dyM?t=176)\n\n- ### 密码学\n    - 请参考下方视频\n    - 观看之前，请先确定观看了信息论的视频\n    - [ ] [可汗学院](https://www.khanacademy.org/computing/computer-science/密码学)\n    - [ ] [密码学: 哈希函数](https://www.youtube.com/watch?v=KqqOXndnvic&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=30)\n    - [ ] [密码学: 加密](https://www.youtube.com/watch?v=9TNI2wHmaeI&index=31&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n\n- ### 压缩\n    - 观看之前，请先确定观看了信息论的视频\n    - [ ] 压缩 (视频):\n        - [ ] [压缩](https://www.youtube.com/watch?v=Lto-ajuqW3w)\n        - [ ] [压缩熵值](https://www.youtube.com/watch?v=M5c_RFKVkko)\n        - [ ] [由上而下的树 (霍夫曼编码树)](https://www.youtube.com/watch?v=umTbivyJoiI)\n        - [ ] [额外比特 - 霍夫曼编码树](https://www.youtube.com/watch?v=DV8efuB3h2g)\n        - [ ] [优雅的压缩数据 (无损数据压缩方法)](https://www.youtube.com/watch?v=goOa3DGezUA)\n        - [ ] [Text Compression Meets Probabilities](https://www.youtube.com/watch?v=cCDCfoHTsaU)\n    - [ ] [数据压缩的艺术](https://www.youtube.com/playlist?list=PLOU2XLYxmsIJGErt5rrCqaSGTMyyqNt2H)\n    - [ ] [(可选) 谷歌开发者: GZIP 还差远了呢!](https://www.youtube.com/watch?v=whGwm0Lky2s)\n\n- ### 网络 (视频)\n    - [ ] [可汗学院](https://www.khanacademy.org/computing/computer-science/internet-intro)\n    - [ ] [网络传输协议中的数据压缩](https://www.youtube.com/watch?v=Vdc8TCESIg8)\n    - [ ] [TCP/IP 和 OSI 模型解析!](https://www.youtube.com/watch?v=e5DEVa9eSN0)\n    - [ ] [TCP/IP 教程：传输数据包.](https://www.youtube.com/watch?v=nomyRJehhnM)\n    - [ ] [HTTP](https://www.youtube.com/watch?v=WGJrLqtX7As)\n    - [ ] [SSL 和 HTTPS](https://www.youtube.com/watch?v=S2iBR2ZlZf0)\n    - [ ] [SSL/TLS](https://www.youtube.com/watch?v=Rp3iZUvXWlM)\n    - [ ] [HTTP 2.0](https://www.youtube.com/watch?v=E9FxNzv1Tr8)\n    - [ ] [视频](https://www.youtube.com/playlist?list=PLEbnTDJUr_IegfoqO4iPnPYQui46QqT0j)\n    - [ ] [子网络解密 - 第五部分 经典内部域名指向 CIDR 标记](https://www.youtube.com/watch?v=t5xYI0jzOf4)\n\n- ### 计算机安全\n    - [MIT](https://www.youtube.com/playlist?list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [威胁模型：入门](https://www.youtube.com/watch?v=GqmQg-cszw4&index=1&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [控制攻击](https://www.youtube.com/watch?v=6bwzNg5qQ0o&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh&index=2)\n        - [ ] [缓冲数据注入和防御](https://www.youtube.com/watch?v=drQyrzRoRiA&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh&index=3)\n        - [ ] [优先权区分](https://www.youtube.com/watch?v=6SIJmoE9L9g&index=4&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [能力](https://www.youtube.com/watch?v=8VqTSY-11F4&index=5&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [在沙盒中运行原生代码](https://www.youtube.com/watch?v=VEV74hwASeU&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh&index=6)\n        - [ ] [网络安全模型](https://www.youtube.com/watch?v=chkFBigodIw&index=7&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [网络安全应用](https://www.youtube.com/watch?v=EBQIGy1ROLY&index=8&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [标志化执行](https://www.youtube.com/watch?v=yRVZPvHYHzw&index=9&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [网络安全](https://www.youtube.com/watch?v=SIEVvk3NVuk&index=11&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [网络协议](https://www.youtube.com/watch?v=QOtA76ga_fY&index=12&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n        - [ ] [旁路攻击](https://www.youtube.com/watch?v=PuVMkSEcPiI&index=15&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n\n- ### 释放缓存\n    - [ ] [Java 释放缓存; 片段化数据 (视频)](https://www.youtube.com/watch?v=StdfeXaKGEc&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=25)\n    - [ ] [编译器 (视频)](https://www.youtube.com/playlist?list=PLO9y7hOkmmSGTy5z6HZ-W4k2y8WXF7Bff)\n    - [ ] [Python 释放缓存 (视频)](https://www.youtube.com/watch?v=iHVs_HkjdmI)\n    - [ ] [深度解析：论释放缓存在 JAVA 中的重要性](https://www.infoq.com/presentations/garbage-collection-benefits)\n    - [ ] [深度解析：论释放缓存在 Python 中的重要性(视频)](https://www.youtube.com/watch?v=P-8Z0-MhdQs&list=PLdzf4Clw0VbOEWOS_sLhT_9zaiQDrS5AR&index=3)\n\n- ### 并行/并发编程\n    - [ ] [Coursera (Scala)](https://www.coursera.org/learn/parprog1/home/week/1)\n    - [ ] [论并行/并发编程如何提高 Python 执行效率 (视频)](https://www.youtube.com/watch?v=uY85GkaYzBk)\n\n- ### 设计模式\n    - [ ] [UML统一建模语言概览 (视频)](https://www.youtube.com/watch?v=3cmzqZzwNDM&list=PLGLfVvz_LVvQ5G-LdJ8RLqe-ndo7QITYc&index=3)\n    - [ ] 主要有如下的设计模式:\n        - [ ] s(strategy)\n        - [ ] singleton\n        - [ ] adapter\n        - [ ] prototype\n        - [ ] decorator\n        - [ ] visitor\n        - [ ] factory, abstract factory\n        - [ ] facade\n        - [ ] observer\n        - [ ] proxy\n        - [ ] delegate\n        - [ ] command\n        - [ ] state\n        - [ ] memento\n        - [ ] iterator\n        - [ ] composite\n        - [ ] flyweight\n    - [ ] [第六章 (第 1 部分 ) - 设计模式 (视频)](https://youtu.be/LAP2A80Ajrg?list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO&t=3344)\n    - [ ] [第六章 (第 2 部分 ) - Abstraction-Occurrence, General Hierarchy, Player-Role, Singleton, Observer, Delegation (视频)](https://www.youtube.com/watch?v=U8-PGsjvZc4&index=12&list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n    - [ ] [第六章 (第 3 部分 ) - Adapter, Facade, Immutable, Read-Only Interface, Proxy (video)](https://www.youtube.com/watch?v=7sduBHuex4c&index=13&list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n    - [ ] [视频](https://www.youtube.com/playlist?list=PLF206E906175C7E07)\n    - [ ] [Head Fisrt 设计模型](https://www.amazon.com/Head-First-Design-Patterns-Freeman/dp/0596007124)\n        - 尽管这本书叫做设计模式：重复使用模块，但是我还是认为Head First是对于新手来说很不错的书。\n    - [ ] [基于实际操作对于入门开发者的建议](https://sourcemaking.com/design-patterns-and-tips)\n\n- ### 信息传输, 序列化,和队列化的系统\n    - [ ] [Thrift](https://thrift.apache.org/)\n        - [教程](http://thrift-tutorial.readthedocs.io/en/latest/intro.html)\n    - [ ] [协议缓冲](https://developers.google.com/protocol-buffers/)\n        - [教程](https://developers.google.com/protocol-buffers/docs/tutorials)\n    - [ ] [gRPC](http://www.grpc.io/)\n        - [gRPC 对于JAVA开发者的入门教程（视频）](https://www.youtube.com/watch?v=5tmPvSe7xXQ&list=PLcTqM9n_dieN0k1nSeN36Z_ppKnvMJoly&index=1)\n    - [ ] [Redis](http://redis.io/)\n        - [教程](http://try.redis.io/)\n    - [ ] [Amazon的 SQS 系统 (队列)](https://aws.amazon.com/sqs/)\n    - [ ] [Amazon的 SNS 系统 (pub-sub)](https://aws.amazon.com/sns/)\n    - [ ] [RabbitMQ](https://www.rabbitmq.com/)\n        - [入门教程](https://www.rabbitmq.com/getstarted.html)\n    - [ ] [Celery](http://www.celeryproject.org/)\n        - [Celery入门](http://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html)\n    - [ ] [ZeroMQ](http://zeromq.org/)\n        - [入门教程](http://zeromq.org/intro:read-the-manual)\n    - [ ] [ActiveMQ](http://activemq.apache.org/)\n    - [ ] [Kafka](http://kafka.apache.org/documentation.html#introduction)\n    - [ ] [MessagePack](http://msgpack.org/index.html)\n    - [ ] [Avro](https://avro.apache.org/)\n\n- ### 快速傅里叶变换\n    - [ ] [什么是傅立叶变换？论傅立叶变换的用途](http://www.askamathematician.com/2012/09/q-what-is-a-fourier-transform-what-is-it-used-for/)\n    - [ ] [什么是傅立叶变换？ (视频)](https://www.youtube.com/watch?v=Xxut2PN-V8Q)\n    - [ ] [关于 FFT 的不同观点 (视频)](https://www.youtube.com/watch?v=iTMn0Kt18tg&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=4)\n    - [ ] [FTT 是什么](http://jakevdp.github.io/blog/2013/08/28/understanding-the-fft/)\n\n- ### 布隆过滤器\n    - 给一个布隆过滤器m比特和k个哈希函数，所有的注入和相关测试都会是通过。\n    - [布隆过滤器](https://www.youtube.com/watch?v=-SuTGoFYjZs)\n    - [布隆过滤器 | 数据挖掘 | Stanford University](https://www.youtube.com/watch?v=qBTdukbzc78)\n    - [教程](http://billmill.org/bloomfilter-tutorial/)\n    - [如何写一个布隆过滤器应用](http://blog.michaelschmatz.com/2016/04/11/how-to-write-a-bloom-filter-cpp/)\n\n- ### van Emde Boas 树\n    - [ ] [争论: van Emde Boas 树 (视频)](https://www.youtube.com/watch?v=hmReJCupbNU&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=6)\n    - [ ] [MIT课堂笔记](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-design-and-analysis-of-algorithms-spring-2012/lecture-notes/MIT6_046JS12_lec15.pdf)\n\n- ### 更深入的数据结构\n    - [ ] [CS 61B 第 39 课: 更深入的数据结构](https://youtu.be/zksIj9O8_jc?list=PL4BBB74C7D2A1049C&t=950)\n\n- ### 跳表\n    - \"有一种非常迷幻的数据类型\" - Skiena\n    - [ ] [随机化: 跳表 (视频)](https://www.youtube.com/watch?v=2g9OSRKJuzM&index=10&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [更生动详细的解释](https://en.wikipedia.org/wiki/Skip_list)\n\n- ### 网络流\n    - [ ] [5分钟简析Ford-Fulkerson (视频)](https://www.youtube.com/watch?v=v1VgJmkEJW0)\n    - [ ] [Ford-Fulkerson 算法 (视频)](https://www.youtube.com/watch?v=v1VgJmkEJW0)\n    - [ ] [网络流 (视频)](https://www.youtube.com/watch?v=2vhN4Ice5jI)\n\n- ### 不相交集 & 联合查找\n    - [ ] [不相交集](https://en.wikipedia.org/wiki/Disjoint-set_data_structure)\n    - [ ] [UCB 61B - 不相交集; 排序 & 选择(视频)](https://www.youtube.com/watch?v=MAEGXTwmUsI&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd&index=21)\n    - [ ] Coursera (not needed since the above video explains it great):\n        - [ ] [概览](https://www.coursera.org/learn/data-structures/lecture/JssSY/overview)\n        - [ ] [初级实践](https://www.coursera.org/learn/data-structures/lecture/EM5D0/naive-implementations)\n        - [ ] [树状结构](https://www.coursera.org/learn/data-structures/lecture/Mxu0w/trees)\n        - [ ] [合并树状结构](https://www.coursera.org/learn/data-structures/lecture/qb4c2/union-by-rank)\n        - [ ] [路径压缩](https://www.coursera.org/learn/data-structures/lecture/Q9CVI/path-compression)\n        - [ ] [分析选项](https://www.coursera.org/learn/data-structures/lecture/GQQLN/analysis-optional)\n\n- ### 快速处理数学\n    - [ ] [整数运算, Karatsuba 乘法 (视频)](https://www.youtube.com/watch?v=eCaXlAaN2uE&index=11&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [中国剩余定理 (在密码学中的使用) (视频)](https://www.youtube.com/watch?v=ru7mWZJlRQg)\n\n- ### 树堆 (Treap)\n    - 一个二叉搜索树和一个堆的组合\n    - [ ] [树堆](https://en.wikipedia.org/wiki/Treap)\n    - [ ] [数据结构：树堆的讲解(video)](https://www.youtube.com/watch?v=6podLUYinH8)\n    - [ ] [集合操作的应用(Applications in set operations)](https://www.cs.cmu.edu/~scandal/papers/treaps-spaa98.pdf)\n\n- ### 线性规划（Linear Programming）（视频）\n    - [ ] [线性规划](https://www.youtube.com/watch?v=M4K6HYLHREQ)\n    - [ ] [寻找最小成本](https://www.youtube.com/watch?v=2ACJ9ewUC6U)\n    - [ ] [寻找最大值](https://www.youtube.com/watch?v=8AA_81xI3ik)\n\n- ### 几何：凸包（Geometry, Convex hull）（视频）\n    - [ ] [Graph Alg. IV: 几何算法介绍 - 第 9 课](https://youtu.be/XIAQRlNkJAw?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3164)\n    - [ ] [Graham & Jarvis: 几何算法 - 第 10 课](https://www.youtube.com/watch?v=J5aJEcOr6Eo&index=10&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n    - [ ] [Divide & Conquer: 凸包, 中值查找](https://www.youtube.com/watch?v=EzeYI7p9MjU&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=2)\n\n- ### 离散数学\n    - 查看下面的视频：(这里没看到视频= =）\n\n- ### 机器学习（Machine Learning）\n    - [ ] 为什么学习机器学习？\n        - [ ] [谷歌如何将自己改造成一家「机器学习优先」公司？](https://backchannel.com/how-google-is-remaking-itself-as-a-machine-learning-first-company-ada63defcb70)\n        - [ ] [智能计算机系统的大规模深度学习 (视频)](https://www.youtube.com/watch?v=QSaZGT4-6EY)\n        - [ ] [Peter Norvig：深度学习和理解与软件工程和验证的对比](https://www.youtube.com/watch?v=X769cyzBNVw)\n    - [ ] [谷歌云机器学习工具（视频）](https://www.youtube.com/watch?v=Ja2hxBAwG_0)\n    - [ ] [谷歌开发者机器学习清单 (Scikit Learn 和 Tensorflow) (视频)](https://www.youtube.com/playlist?list=PLOU2XLYxmsIIuiBfYad6rFYQU_jL2ryal)\n    - [ ] [Tensorflow (视频)](https://www.youtube.com/watch?v=oZikw5k_2FM)\n    - [ ] [Tensorflow 教程](https://www.tensorflow.org/versions/r0.11/tutorials/index.html)\n    - [ ] [Python 实现神经网络实例教程（使用 Theano）](http://www.analyticsvidhya.com/blog/2016/04/neural-networks-python-theano/)\n    - 课程:\n        - [ ] [很棒的初级课程：机器学习](https://www.coursera.org/learn/machine-learning)\n              - [视频教程](https://www.youtube.com/playlist?list=PLZ9qNFMHZ-A4rycgrgOYma6zxF4BZGGPW)\n              - 看第 12-18 集复习线性代数（第 14 集和第 15 集是重复的）\n        - [ ] [机器学习中的神经网络](https://www.coursera.org/learn/neural-networks)\n        - [ ] [Google 深度学习微学位](https://www.udacity.com/course/deep-learning--ud730)\n        - [ ] [Google/Kaggle 机器学习工程师微学位](https://www.udacity.com/course/machine-learning-engineer-nanodegree-by-google--nd009)\n        - [ ] [无人驾驶工程师微学位](https://www.udacity.com/drive)\n        - [ ] [Metis 在线课程 (两个月 99 美元)](http://www.thisismetis.com/explore-data-science)\n    - 资源:\n        - 书籍: Data Science from Scratch: First Principles with Python: https://www.amazon.com/Data-Science-Scratch-Principles-Python/dp/149190142X\n        - 网站: Data School: http://www.dataschool.io/\n\n- ### Go 语言\n    - [ ] 视频:\n        - [ ] [为什么学习 Go 语言？](https://www.youtube.com/watch?v=FTl0tl9BGdc)\n        - [ ] [Go 语言编程](https://www.youtube.com/watch?v=CF9S4QZuV30)\n        - [ ] [Go 语言之旅](https://www.youtube.com/watch?v=ytEkHepK08c)\n    - [ ] 书籍:\n        - [ ] [Go 语言编程入门 (免费在线阅读)](https://www.golang-book.com/books/intro)\n        - [ ] [Go 语言圣经 (Donovan & Kernighan)](https://www.amazon.com/Programming-Language-Addison-Wesley-Professional-Computing/dp/0134190440)\n    - [ ] [Go 语言新手训练营](https://www.golang-book.com/guides/bootcamp)\n\n--\n\n## 一些主题的额外内容\n\n    我为前面提到的某些主题增加了一些额外的内容，之所以没有直接添加到前面，是因为这样很容易导致某个主题内容过多。毕竟你想在本世纪找到一份工作，对吧？\n\n- [ ] **动态规划的更多内容** (视频)\n    - [ ] [6.006: 动态规划 I: 斐波那契数列, 最短路径](https://www.youtube.com/watch?v=OQ5jsbhAv_M&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=19)\n    - [ ] [6.006: 动态规划 II: 文本匹配, 二十一点/黑杰克](https://www.youtube.com/watch?v=ENyox7kNKeY&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=20)\n    - [ ] [6.006: 动态规划 III: 最优加括号方式, 最小编辑距离, 背包问题](https://www.youtube.com/watch?v=ocZMDMZwhCY&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=21)\n    - [ ] [6.006: 动态规划 IV: 吉他指法，拓扑，超级马里奥.](https://www.youtube.com/watch?v=tp4_UXaVyx8&index=22&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n    - [ ] [6.046: 动态规划: 动态规划进阶](https://www.youtube.com/watch?v=Tw1k46ywN6E&index=14&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n    - [ ] [6.046: 动态规划: 所有点对最短路径](https://www.youtube.com/watch?v=NzgFUwOaoIw&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=15)\n    - [ ] [6.046: 动态规划: 更多示例](https://www.youtube.com/watch?v=krZI60lKPek&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=12)\n\n- [ ] **图形处理进阶** (视频)\n    - [ ] [异步分布式算法: 对称性破缺，最小生成树](https://www.youtube.com/watch?v=mUBmcbbJNf4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=27)\n    - [ ] [异步分布式算法: 最小生成树](https://www.youtube.com/watch?v=kQ-UQAzcnzA&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=28)\n\n- [ ] MIT **概率论** (mathy, and go slowly, which is good for mathy things) (视频):\n    - [ ] [MIT 6.042J - 概率论概述](https://www.youtube.com/watch?v=SmFwFdESMHI&index=18&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - 条件概率 Probability](https://www.youtube.com/watch?v=E6FbvM-FGZ8&index=19&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - 独立](https://www.youtube.com/watch?v=l1BCv3qqW4A&index=20&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - 随机变量](https://www.youtube.com/watch?v=MOfhhFaQdjw&list=PLB7540DEDD482705B&index=21)\n    - [ ] [MIT 6.042J - 期望 I](https://www.youtube.com/watch?v=gGlMSe7uEkA&index=22&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - 期望 II](https://www.youtube.com/watch?v=oI9fMUqgfxY&index=23&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - 大偏差](https://www.youtube.com/watch?v=q4mwO2qS2z4&index=24&list=PLB7540DEDD482705B)\n    - [ ] [MIT 6.042J - 随机游走](https://www.youtube.com/watch?v=56iFMY8QW2k&list=PLB7540DEDD482705B&index=25)\n\n- [ ] [Simonson: 近似算法 (视频)](https://www.youtube.com/watch?v=oDniZCmNmNw&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=19)\n\n## 视频系列\n\n 坐下来享受一下吧。\"netflix and skill\" :P\n\n- [ ] [个人的动态规划问题列表 (都是短视频哟)](https://www.youtube.com/playlist?list=PLrmLmBdmIlpsHaNTPP_jHHDx_os9ItYXr)\n\n- [ ] [x86 架构，汇编，应用程序 (11 个视频)](https://www.youtube.com/playlist?list=PL038BE01D3BAEFDB0)\n\n- [ ] [MIT 18.06 线性代数，2005 年春季 (35 个视频)](https://www.youtube.com/playlist?list=PLE7DDD91010BC51F8)\n\n- [ ] [绝妙的 MIT 微积分：单变量微积分](https://www.youtube.com/playlist?list=PL3B08AE665AB9002A)\n\n- [ ] [计算机科学 70, 001 - 2015 年春季 - 离散数学和概率理论](https://www.youtube.com/playlist?list=PL-XXv-cvA_iD8wQm8U0gG_Z1uHjImKXFy)\n\n- [ ] [离散数学 (19 个视频)](https://www.youtube.com/playlist?list=PL3o9D4Dl2FJ9q0_gtFXPh_H4POI5dK0yG)\n\n- [ ] CSE373 - 算法分析 (25 个视频)\n    - [Skiena 的算法设计手册讲座](https://www.youtube.com/watch?v=ZFjhkohHdAA&list=PLOtl7M3yp-DV69F32zdK7YJcNXpTunF2b&index=1)\n\n- [ ] [UC Berkeley 61B (2014 年春季): 数据结构 (25 个视频)](https://www.youtube.com/watch?v=mFPmKGIrQs4&list=PL-XXv-cvA_iAlnI-BQr9hjqADPBtujFJd)\n\n- [ ] [UC Berkeley 61B (2006 年秋季): 数据结构 (39 个视频)]( https://www.youtube.com/playlist?list=PL4BBB74C7D2A1049C)\n\n- [ ] [UC Berkeley 61C: 计算机结构 (26 个视频)](https://www.youtube.com/watch?v=gJJeUFyuvvg&list=PL-XXv-cvA_iCl2-D-FS5mk0jFF6cYSJs_)\n\n- [ ] [OOSE: 使用 UML 和 Java 进行软件开发 (21 个视频)](https://www.youtube.com/playlist?list=PLJ9pm_Rc9HesnkwKlal_buSIHA-jTZMpO)\n\n- [ ] [UC Berkeley CS 152: 计算机结构和工程 (20 个视频)](https://www.youtube.com/watch?v=UH0QYvtP7Rk&index=20&list=PLkFD6_40KJIwEiwQx1dACXwh-2Fuo32qr)\n\n- [ ] [MIT 6.004: 计算结构 (49 视频)](https://www.youtube.com/playlist?list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-)\n\n- [ ] [卡內基梅隆大学 - 计算机架构讲座 (39 个视频)](https://www.youtube.com/playlist?list=PL5PHm2jkkXmi5CxxI7b3JCL1TWybTDtKq)\n\n- [ ] [MIT 6.006: 算法介绍 (47 个视频)](https://www.youtube.com/watch?v=HtSuA80QTyo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&nohtml5=False)\n\n- [ ] [MIT 6.033: 计算机系统工程 (22 个视频)](https://www.youtube.com/watch?v=zm2VP0kHl1M&list=PL6535748F59DCA484)\n\n- [ ] [MIT 6.034 人工智能, 2010 年秋季 (30 个视频)](https://www.youtube.com/playlist?list=PLUl4u3cNGP63gFHB6xb-kVBiQHYe_4hSi)\n\n- [ ] [MIT 6.042J: 计算机科学数学, 2010 年秋季 (25 个视频)](https://www.youtube.com/watch?v=L3LMbpZIKhQ&list=PLB7540DEDD482705B)\n\n- [ ] [MIT 6.046: 算法设计与分析 (34 个视频)](https://www.youtube.com/watch?v=2P-yW7LQr08&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n\n- [ ] [MIT 6.050J: 信息和熵, 2008 年春季 (19 个视频)](https://www.youtube.com/watch?v=phxsQrZQupo&list=PL_2Bwul6T-A7OldmhGODImZL8KEVE38X7)\n\n- [ ] [MIT 6.851: 高等数据结构 (22 个视频)](https://www.youtube.com/watch?v=T0yzrZL1py0&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf&index=1)\n\n- [ ] [MIT 6.854: 高等算法, 2016 年春季 (24 个视频)](https://www.youtube.com/playlist?list=PL6ogFv-ieghdoGKGg2Bik3Gl1glBTEu8c)\n\n- [ ] [MIT 6.858计算机系统安全, 2014 年秋季](https://www.youtube.com/watch?v=GqmQg-cszw4&index=1&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n\n- [ ] 斯坦福: 编程范例 (17 个视频)\n    - [C 和 C++ 课程](https://www.youtube.com/watch?v=jTSvthW34GU&list=PLC0B8B318B7394B6F&nohtml5=False)\n\n- [ ] [密码学导论](https://www.youtube.com/watch?v=2aHkqB2-46k&feature=youtu.be)\n    - [本系列更多内容 (不分先后顺序)](https://www.youtube.com/channel/UC1usFRN4LCMcfIV7UjHNuQg)\n\n- [ ] [大数据 - 斯坦福大学 (94 个视频)](https://www.youtube.com/playlist?list=PLLssT5z_DsK9JDLcT8T62VtzwyW9LNepV)\n\n## 计算机科学课程\n\n- [ 在线 CS 课程目录 ](https://github.com/open-source-society/computer-science)\n- [CS 课程目录 (一些是在线讲座)](https://github.com/prakhar1989/awesome-courses)\n"
  },
  {
    "path": "29-google-interview-university/programming-language-resources.md",
    "content": "## Programming Language Resources\n\n- C\n    - [ANSI C Cheat Sheet](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/C%20Reference%20Card%20(ANSI)%202.2.pdf)\n    - K&R C book (ANSI C)\n    - [Make, Clang (video)](https://www.youtube.com/watch?v=U3zCxnj2w8M)\n    - GDB:\n        - [Harvard CS50 - GDB (video)](https://www.youtube.com/watch?v=USPvePv1uzE)\n        - [Harvard CS50 - GDB (video)](https://www.youtube.com/watch?v=y5JmQItfFck)\n      - [Valgrind (video)](https://www.youtube.com/watch?v=fvTsFjDuag8)\n\n- C++\n    - [C++ Cheat Sheet](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/Cpp_reference.pdf)\n    - [STL Cheat Sheet](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/STL%20Quick%20Reference%201.29.pdf)\n    - basics\n    - pointers\n    - functions\n    - references\n    - templates\n    - compilation\n    - scope & linkage\n    - namespaces\n    - OOP\n    - STL\n    - [functors](http://www.cprogramming.com/tutorial/functors-function-objects-in-c++.html)\n    - [C++ at Google (video)](https://www.youtube.com/watch?v=NOCElcMcFik)\n    - [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)\n        - Google uses clang-format (there is a command line \"style\" argument: -style=google)\n    - [Efficiency with Algorithms, Performance with Data Structures (video)](https://youtu.be/fHNmRkzxHWs)\n    - [Review of C++ concepts (video)](https://www.youtube.com/watch?v=Rub-JsjMhWY)\n\n- Python\n    - [Python Cheat Sheet](https://github.com/jwasham/google-interview-university/blob/master/extras/cheat%20sheets/python-cheat-sheet-v1.pdf)\n    - [Python in One Video](https://www.youtube.com/watch?v=N4mEzFDjqtA)\n    - [Series on 3.4 (video)](https://www.youtube.com/playlist?list=PL6gx4Cwl9DGAcbMi1sH6oAMk4JHw91mC_)\n    - [Zero to Hero (video)](https://www.youtube.com/watch?v=emY34tSKXc4)\n    - [Statistics for Hackers (video)](https://www.youtube.com/watch?v=Iq9DzN6mvYA)\n    - [Faster Python (video)](https://www.youtube.com/watch?v=JDSGVvMwNM8)\n    - [CPython Walk (video)](https://www.youtube.com/watch?v=LhadeL7_EIU&list=PLzV58Zm8FuBL6OAv1Yu6AwXZrnsFbbR0S&index=6)\n    - [10 Tips for Pythonic Code (video)](https://www.youtube.com/watch?v=_O23jIXsshs)\n    - [Beyond PEP 8 -- Best practices for beautiful intelligible code (video)](https://www.youtube.com/watch?v=wf-BqAjZb8M)\n    \n- Java\n    - [Stanford CS106A - Programming Methodology (video)](https://see.stanford.edu/Course/CS106A)\n    - [Software Construction In Java (video)](https://www.edx.org/course/software-construction-java-mitx-6-005-1x)\n    - [Introduction To Programming In Java](http://introcs.cs.princeton.edu/java/home/)\n    - [Algorithms 4th Ed - Algorithm Book In Java](http://algs4.cs.princeton.edu/home/)   \n- Go\n    - [The Go programming Language](https://golang.org/)\n    - [The Go programming Language (book)](http://www.gopl.io/)\n    - [A Tour of Go](https://tour.golang.org/)\n    - [Effective Go](https://golang.org/doc/effective_go.html)\n    - [Go Wiki](https://golang.org/wiki)\n    - [Go at Google: Language Design in the Service of Software Engineering](https://talks.golang.org/2012/splash.article)\n    - [Go Proverbs](http://go-proverbs.github.io/)\n    - [Go Proverbs - Rob Pike (video)](https://www.youtube.com/watch?v=PAAkCSZUG1c)\n- Other Language 1\n- Other Language 2\n- etc\n"
  },
  {
    "path": "30-jstraining/README.md",
    "content": "全栈工程师培训材料，帮助学习者掌握全栈开发的基本知识，承担简单 Web 应用的前后端开发。\n\n一共四讲，适合两天的训练营，请先阅读[《培训准备》](docs/preparation.md)。培训时，需要完成[课堂练习](demos)。\n\n## 第一讲：[前端开发的历史和趋势](./docs/history.md)\n\n1. 前端开发的历史演变\n2. 前端MVC框架的兴起\n3. 前后端分离\n4. 全栈工程师\n5. 前端开发的未来\n\n## 第二讲：[React 技术栈](./docs/react.md)\n\n1. React 的基本用法\n2. React 应用的架构\n\n## 第三讲：[Node 应用开发](./docs/node.md)\n\n1. Node 的基本用法\n2. Restful API\n3. Express 框架搭建 Web 应用\n\n## 第四讲：[前端工程简介](./docs/engineering.md)\n\n1. 持续集成\n1. 静态代码检查\n1. 单元测试\n1. 功能测试\n1. 持续集成服务 Travis CI\n\n## License\n\nGPL v3\n"
  },
  {
    "path": "30-jstraining/demos/README.md",
    "content": "# 课堂练习的操作指导\n\n## 目录\n\n- 前端开发的历史和趋势\n  - [Backbone](#backbone)\n  - [Angular](#angular)\n  - [Vue](#vue)\n- React 技术栈\n  - [JSX](#jsx)\n  - [React 组件语法](#react-组件语法)\n  - [React 组件的参数](#react-组件的参数)\n  - [React 组件的状态](#react-组件的状态)\n  - [React 组件实战](#react-组件实战)\n  - [React 组件的生命周期](#react-组件的声明周期)\n  - [ReCharts](#recharts)\n  - [MobX](#mobx)\n  - [Redux](#redux)\n- Node 开发\n  - [Simple App](#simple-app)\n  - [REST API](#rest-api)\n  - [Express](#express)\n- 前端工程简介\n  - [ESLint](#eslint)\n  - [Mocha](#mocha)\n  - [Nightmare](#nightmare)\n  - [Travis CI](#travis-ci)\n\n## Backbone\n\n### 实验目的\n\n1. 理解前端框架的路由组件（`router`）的作用\n\n### 操作步骤\n\n1. 浏览器打开[`demos/backbone-demo/index.html`](./backbone-demo/index.html)\n1. 点击页面上的链接，注意浏览器 URL 的变化\n1. 仔细查看[`js/main.js`](./backbone-demo/js/main.js)的源码，看懂 Router 组件的使用方式\n\n## Angular\n\n### 实验目的\n\n1. 理解 Angular 的双向绑定机制\n\n### 操作步骤\n\n1. 浏览器打开[`demos/angular-demo/index.html`](./angular-demo/index.html)\n1. 在输入框填入内容，注意页面变化\n1. 查看[`index.html`](./angular-demo/index.html)的源码，理解 Angular 对 HTML 标签的增强\n\n## Vue\n\n### 实验目的\n\n1. 理解 Vue 的模板与数据的双向绑定\n\n### 操作步骤\n\n1. 浏览器打开[`demos/vue-demo/index1.html`](./vue-demo/index1.html)\n1. 在输入框填入内容，注意页面变化\n1. 查看[`app1.js`](./vue-demo/app1.js)，理解 Vue 组件的基本写法\n\n### 注意事项\n\n1. [`index2.html`](./vue-demo/index2.html)是一个稍微复杂的例子，模板如何绑定数据对象的一个字段。\n2. [`index3.html`](./vue-demo/index3.html)是事件绑定模板的例子。\n\n## JSX\n\n### 实验目的\n\n1. 掌握 JSX 基本语法\n\n### 操作步骤\n\n1. 浏览器打开`demos/jsx-demo/index.html`，仔细查看源码。\n\n### 注意事项\n\n1. `ReactDOM.render`方法接受两个参数：一个虚拟 DOM 节点和一个真实 DOM 节点，作用是将虚拟 DOM 挂载到真实 DOM。\n\n### 练习\n\n1. 修改源码，将显示文字变为 ”Hello React!“。\n\n## React 组件语法\n\n### 实验目的\n\n1. 掌握 React 组件的基本写法\n\n### 操作步骤\n\n1. 浏览器打开`demos/react-component-demo/index1.html`，仔细查看源码。\n\n### 注意事项\n\n1. `class MyTitle extends React.Component`是 ES6 语法，表示自定义一个`MyTitle`类，该类继承了基类`React.Component`的所有属性和方法。\n1. React 规定，自定义组件的第一个字母必须大写，比如`MyTitle`不能写成`myTitle`，以便与内置的原生类相区分。\n1. 每个组件都必须有`render`方法，定义输出的样式。\n1. `<MyTitle/>`表示生成一个组件类的实例，每个实例一定要有闭合标签，写成`<MyTilte></MyTitle>`也可。\n\n## React 组件的参数\n\n### 实验目的\n\n1. 学会向 React 组件传参数\n\n### 操作步骤\n\n1. 浏览器打开`demos/react-component-demo/index2.html`，仔细查看源码。\n\n### 注意事项\n\n1. 组件内部通过`this.props`对象获取参数。\n\n### 练习\n\n1. 将组件的颜色，从红色（`red`）换成黄色（`yellow`）。\n\n## React 组件的状态\n\n### 实验目的\n\n1. 学会通过状态变动，引发组件的重新渲染。\n\n### 操作步骤\n\n1. 浏览器打开`demos/react-component-demo/index3.html`，仔细查看源码。\n\n### 注意事项\n\n```javascript\n  class MyTitle extends React.Component {\n    constructor(...args) {\n      super(...args);\n      this.state = {\n        name: '访问者'\n      };\n    }\n    // ...\n```\n\n`constructor`是组件的构造函数，会在创建实例时自动调用。`...args`表示组件参数，`super(...args)`是 ES6 规定的写法。`this.state`对象用来存放内部状态，这里是定义初始状态。\n\n```html\n<div>\n  <input\n    type=\"text\"\n    onChange={this.handleChange.bind(this)}\n  />\n  <p>你好，{this.state.name}</p>\n</div>;\n```\n\n`this.state.name`表示读取`this.state`的`name`属性。每当输入框有变动，就会自动调用`onChange`指定的监听函数，这里是`this.handleChange`，`.bind(this)`表示该方法内部的`this`，绑定当前组件。\n\n```javascript\nhandleChange(e) {\n  let name = e.target.value;\n  this.setState({\n    name: name\n  });\n}\n```\n\n`this.setState`方法用来重置`this.state`，每次调用这个方法，就会引发组件的重新渲染。\n\n## React 组件实战\n\n### 实验目的\n\n1. 学会自己写简单的 React 组件。\n\n### 操作步骤\n\n1. 浏览器打开`demos/react-component-demo/index4.html`。\n1. 点击`Hello World`，看看会发生什么。\n\n### 练习\n\n1. 修改源码，使得点击`Hello World`后，会显示当前的日期，比如`Hello 2016年1月1日`。\n\n2. 请在上一步练习的基础上，进一步修改。现在`Hello World`点击一次，会改变内容，再点击就不会有反应了。请将其改成，再点击一次变回原样。\n\n### 提示\n\n 练习一、下面的代码可以得到当前日期。\n\n```javascript\nvar d = new Date();\nd.getFullYear() // 当前年份\nd.getMonth() + 1 // 当前月份\nd.getDate() // 当前是每个月的几号\n```\n\n练习二、可以在`this.state`里面设置一个开关变量`isClicked`。\n\n```javascript\nthis.state = {\n  text: 'World',\n  isClicked: false\n};\n```\n\n然后，在`this.handleClick`方法里面，做一个`toggle`效果。\n\n```javascript\nlet isClicked = !this.state.isClicked;\nthis.setState({\n  isClicked: isClicked,\n  text: isClicked ? 'Clicked' : 'World'\n});\n```\n\n## React 组件的生命周期\n\n### 实验目的\n\n1. 掌握钩子方法的基本用法\n1. 掌握组件如何通过 Ajax 请求获取数据，并对数据进行处理\n\n### 操作步骤\n\n1. 打开`demos/react-lifecycle-demo/index.html`，仔细查看源码。\n\n### 注意事项\n\n```javascript\ncomponentDidMount() {\n  const url = '...';\n  $.getJSON(url)\n    .done()\n    .fail();\n}\n```\n\n- `componentDidMount`方法在组件加载后执行，只执行一次。本例在这个方法里向服务器请求数据，操作结束前，组件都显示`Loading`。\n- `$.getJSON`方法用于向服务器请求 JSON 数据。本例的数据从 Github API 获取，可以打开源码里面的链接，看看原始的数据结构。\n\n### 练习\n\n1. 本例的 JSON 数据是 Github 上面最受欢迎的 JavaScript 项目。请在网页上显示一个列表，列出这些项目。\n\n### 提示\n\n（1） `this.state.loading`记录数据加载是否结束。只要数据请求没有结束，`this.state.loading`就一直是`true`，网页上显示`loading`。\n\n（2） `this.state.error`保存数据请求失败时的错误信息。如果请求失败，`this.state.error`就是返回的错误对象，网页上显示报错信息。\n\n（3） `this.state.data`保存从服务器获取的数据。如果请求成功，可以先用`console.log`方法，将它在控制台里打印出来，看看数据结构。\n\n```javascript\nrender() {\n  // 加一行打印命令，看看数据结构\n  console.log(this.state.data);\n  return {\n  // ...\n```\n\n（4） `this.state.data`里面的`this.state.data.items`应该是一个数组，保存着每个项目的具体信息。可以使用`forEach`方法进行遍历处理。\n\n```javascript\nvar projects = this.state.data.items;\nvar results = [];\nprojects.forEach(p => {\n  var item = <li>{p.name}</li>;\n    results.push(item);\n});\n```\n\n（5）然后，将上一步的`results`插入网页即可。\n\n```javascript\n<div>\n  <ul>{results}</ul>\n</div>\n```\n\n## ReCharts\n\n### 实验目的\n\n1. 了解如何使用第三方组件库。\n\n### 操作步骤\n\n1. 浏览器打开`demos/recharts-demo/index.html`，查看效果。\n\n## MobX\n\n### 实验目的\n\n1. 理解 MobX 框架\n\n### 操作步骤\n\n（1） 命令行进入`demos/mobx-demo/`目录，执行如下的命令。\n\n```bash\n$ npm install\n$ npm start\n```\n\n（2） 打开浏览器，访问 http://localhost:8080，查看结果，并仔细研究代码。\n\n### 注意事项\n\n```javascript\n@observer\nclass App extends React.Component {\n  render() {\n    // ...\n  }\n}\n```\n\n`@observer`是一种新的语法，表示对整个类执行指定的函数。\n\n数据保存在`Store`里面。`Store`的属性分成两种：被观察的属性（`@observable`），和自动计算得到的属性`@computed`。\n\n```javascript\nclass Store {\n  @observable name = 'Bartek';\n  @computed get decorated() {\n    return `${this.name} is awesome!`;\n  }\n}\n```\n\n`Store`的变化由用户引发。组件观察到`Store`的变化，自动重新渲染。\n\n```javascript\n<p>\n  {this.props.store.decorated}\n</p>\n<input\n  defaultValue={this.props.store.name}\n  onChange={\n    (event) =>\n      this.props.store.name = event.currentTarget.value\n  }\n/>\n```\n\n## Redux\n\n### 实验目的\n\n1. 理解 Redux 架构\n\n### 操作步骤\n\n（1） 命令行下进入`demos/redux-demo`目录，执行如下的命令。\n\n```bash\n$ npm install\n$ npm start\n```\n\n（2）打开浏览器，访问 http://localhost:8080，查看结果，并仔细研究代码。\n\n### 注意事项\n\n（1） Redux 要求 UI 的渲染组件都是纯组件，即不包含任何状态（`this.state`）的组件。\n\n```javascript\n<div className=\"index\">\n  <p>{this.props.text}</p>\n  <input\n    defaultValue={this.props.name}\n    onChange={this.props.onChange}\n  />\n</div>\n```\n\n（2） 进行数据处理、并包含状态的组件，称为”容器组件“。Redux 使用`connect`方法，自动生成 UI 组件对应的”容器组件“。\n\n```javascript、\n// MyComponent 是纯的 UI 组件\nconst App = connect(\n  mapStateToProps,\n  mapDispatchToProps\n)(MyComponent);\n```\n\n（3） `mapStateToProps`函数返回一个对象，表示一种映射关系，将 UI 组件的参数映射到`state`。\n\n```javascript\nfunction mapStateToProps(state) {\n  return {\n    text: state.text,\n    name: state.name\n  };\n}\n```\n\n（4） `mapDispatchToProps`函数也是返回一个对象，表示一种映射关系，但定义的是哪些用户的操作应该当作`Action`，传给`Store`。\n\n```javascript\nfunction mapDispatchToProps(dispatch) {\n  return {\n    onChange: (e) => dispatch({\n      type: 'change',\n      payload: e.target.value\n    })\n  }\n}\n```\n\n（5） `reducer`函数用来接收`action`，算出新的`state`。\n\n```javascript\nfunction reducer(state = {\n  text: '你好，访问者',\n  name: '访问者'\n}, action) {\n  switch (action.type) {\n    case 'change':\n      return {\n        name: action.payload,\n        text: '你好，' + action.payload\n      };\n  }\n}\n```\n\n`Store`由 Redux 提供的`createStore`方法生成，该方法接受`reducer`作为参数。\n\n```javascript\nconst store = createStore(reducer);\n\nReactDOM.render(\n  <Provider store={store}>\n    <App />\n  </Provider>,\n  document.body.appendChild(document.createElement('div'))\n);\n```\n\n为了把`Store`传入组件，必须使用 Redux 提供的`Provider`组件在应用的最外面，包裹一层。\n\n## Simple App\n\n### 实验目的\n\n1. 学会使用 Node 编写简单的前端应用。\n\n### 操作步骤\n\n（1）新建一个目录\n\n```bash\n$ mkdir simple-app-demo\n$ cd simple-app-demo\n```\n\n（2）在该目录下，新建一个`package.json`文件。\n\n```bash\n$ npm init -y\n```\n\n`package.json`是项目的配置文件。\n\n（3）安装`jquery`和`webpack`这两个模块。\n\n```bash\n$ npm install -S jquery\n$ npm install -S webpack\n```\n\n打开`package.json`文件，会发现`jquery`和`webpack`都加入了`dependencies`字段，并且带有版本号。\n\n（4）在项目根目录下，新建一个网页文件`index.html`。\n\n```html\n<html>\n  <body>\n    <h1>Hello World</h1>\n    <script src=\"bundle.js\"></script>\n  </body>\n</html>\n```\n\n（5）在项目根目录下，新建一个脚本文件`app.js`。\n\n```javascript\nconst $ = require('jquery');\n$('h1').css({ color: 'red'});\n```\n\n上面代码中，`require`方法是 Node 特有的模块加载命令。\n\n（6）打开`package.json`，在`scripts`字段里面，添加一行。\n\n```javascript\n\"scripts\": {\n  \"build\": \"webpack app.js bundle.js\",\n  \"test\": \"....\"\n},\n```\n\n（7） 在项目根目录下，执行下面的命令，将脚本打包。\n\n```bash\n$ npm run build\n```\n\n执行完成，可以发现项目根目录下，新生成了一个文件`bundle.js`。\n\n（8）浏览器打开`index.html`，可以发现`Hello World`变成了红色。\n\n### 练习\n\n1. 修改样式，将标题变为蓝色，然后重新编译生成打包文件。\n\n## REST API\n\n### 实验目的\n\n1. 熟悉 REST API 的基本用法\n\n### 操作步骤\n\n（1） 命令行进入`rest-api-demo`目录，执行下面的命令。\n\n```bash\n$ npm install -S json-server\n```\n\n（2） 在项目根目录下，新建一个 JSON 文件`db.json`。\n\n```javascript\n{\n  \"posts\": [\n    { \"id\": 1, \"title\": \"json-server\", \"author\": \"typicode\" }\n  ],\n  \"comments\": [\n    { \"id\": 1, \"body\": \"some comment\", \"postId\": 1 }\n  ],\n  \"profile\": { \"name\": \"typicode\" }\n}\n```\n\n（3） 打开`package.json`，在`scripts`字段添加一行。\n\n```javascript\n\"scripts\": {\n  \"server\": \"json-server db.json\",\n  \"test\": \"...\"\n},\n```\n\n（4） 命令行下执行下面的命令，启动服务。\n\n```bash\n$ npm run server\n```\n\n（5）打开 Chrome 浏览器的 Postman 应用。依次向`http://127.0.0.1:3000/posts`、`http://127.0.0.1:3000/posts/1`发出`GET`请求，查看结果。\n\n（6）向`http://127.0.0.1:3000/comments`发出`POST`请求。注意，数据体`Body`要选择`x-www-form-urlencoded`编码，然后依次添加下面两个字段。\n\n```javascript\nbody: \"hello world\"\npostId: 1\n```\n\n发出该请求后，再向`http://127.0.0.1:3000/comments`发出`GET`请求，查看结果。\n\n（7） 向`http://127.0.0.1:3000/comments/2`发出`PUT`请求，数据体`Body`要选择`x-www-form-urlencoded`编码，然后添加下面的字段。\n\n```javascript\nbody: \"hello react\"\n```\n\n发出该请求后，再向`http://127.0.0.1:3000/comments`发出`GET`请求，查看结果。\n\n（8）向`http://127.0.0.1:3000/comments/2`发出`delete`请求。\n\n发出该请求后，再向`http://127.0.0.1:3000/comments`发出`GET`请求，查看结果。\n\n## Express\n\n### 实验目的\n\n1. 学会 Express 搭建 Web 应用的基本用法。\n\n### 操作步骤\n\n（1）进入`demos/express-demo`目录，命令行执行下面的命令，安装依赖。\n\n```bash\n$ cd demos/express-demo\n$ npm install\n```\n\n（2）打开`app1.js`，尝试看懂这个脚本。\n\n```javascript\nvar express    = require('express');\nvar app        = express();\n```\n\n上面代码调用`express`，生成一个 Web 应用的实例。\n\n```javascript\nvar router = express.Router();\n\nrouter.get('/', function(req, res) {\n  res.send('<h1>Hello World</h1>');\n});\n\napp.use('/home', router);\n```\n\n上面代码新建了一个路由对象，该对象指定访问根路由（`/`）时，返回`Hello World`。然后，将该路由加载在`/home`路径，也就是说，访问`/home`会返回`Hello World`。\n\n`router.get`方法的第二个参数是一个回调函数，当符合指定路由的请求进来，会被这个函数处理。该函数的两个参数，`req`和`res`都是Express 内置的对象，分别表示用户的请求和 Web 服务器的回应。`res.send`方法就表示服务器回应所送出的内容。\n\n```javascript\nvar port = process.env.PORT || 8080;\n\napp.listen(port);\nconsole.log('Magic happens on port ' + port);\n```\n\n上面代码指定了外部访问的端口，如果环境变量没有指定，则端口默认为`8080`。最后两行是启动应用，并输出一行提示文字。\n\n（3）在命令行下，启动这个应用。\n\n```bash\n$ node app1.js\n```\n\n浏览器访问`localhost:8080/home`，看看是否输出`Hello World`。\n\n然后，命令行下按 Ctrl + C，退出这个进程。\n\n（4）通过环境变量，自定义启动端口。\n\n假定我们指定必须启动在`7070`端口，命令行可以这样操作。\n\n```bash\n# Linux & Mac\n$ PORT=7070 node app1.js\n\n# windows\n$ set PORT=7070\n$ node app1.js\n```\n\n浏览器就可以访问`localhost:7070/home`了。\n\n然后，命令行下按 Ctrl + C，退出这个进程。\n\n思考题：Node 应用能否直接在`80`端口启动？\n\n（5）打开`app2.js`，查看新增的那个路由。\n\n```javascript\nrouter.get('/:name', function(req, res) {\n  res.send('<h1>Hello ' + req.params.name + '</h1>');\n});\n```\n\n上面代码新增了一个路由，这个路由的路径是一个命名参数`:name`，可以从`req.params.name`拿到这个传入的参数。\n\n在命令行下，启动这个应用。\n\n```bash\n$ node app2.js\n```\n\n浏览器访问`localhost:8080/home/张三`，看看是否输出`Hello 张三`。\n\n然后，命令行下按 Ctrl + C，退出这个进程。\n\n（6）打开`app3.js`，先查看页面头部新增的两行代码。\n\n```javascript\nvar express    = require('express');\nvar app        = express();\n\n// 新增代码...\nvar bodyParser = require('body-parser');\napp.use(bodyParser.urlencoded({ extended: true }));\n\n// ...\n```\n\n上面代码中，`body-parser`模块的作用，是对`POST`、`PUT`、`DELETE`等 HTTP 方法的数据体进行解析。`app.use`用来将这个模块加载到当前应用。有了这两句，就可以处理`POST`、`PUT`、`DELETE`等请求了。\n\n下面查看新增的那个路由。\n\n```javascript\nrouter.post('/', function (req, res) {\n  var name = req.body.name;\n  res.json({message: 'Hello ' + name});\n});\n```\n\n上面代码表示，如果收到了`/`路径（实际上是`/home`路径）的`POST`请求，先从数据体拿到`name`字段，然后返回一段 JSON 信息。\n\n在命令行下，启动这个应用。\n\n```bash\n$ node app3.js\n```\n\n然后，在 Chrome 浏览器的 Postman 插件里面，向`http://127.0.0.1:8080/home`发出一个`POST`请求。数据体的编码方法设为`x-www-form-urlencoded`，里面设置一个`name`字段，值可以随便取，假定设为`Alice`。也就是说，发出这样一个请求。\n\n```\nPOST /home HTTP/1.1\nHost: 127.0.0.1:8080\nContent-Type: application/x-www-form-urlencoded\n\nname=Alice\n```\n\n如果一切正常，服务器会返回一段 JSON 信息。\n\n```javascript\n{\n  \"message\": \"Hello Alice\"\n}\n```\n\n（7）打开`app4.js`，查看在所有路由之前新增的那个函数。\n\n```javascript\nvar router = express.Router();\n\n// 新增的代码\nrouter.use(function(req, res, next) {\n  console.log('Thers is a requesting.');\n  next();\n});\n\nrouter.get('/', function(req, res) {\n  // ...\n```\n\n`router.use`的作用是加载一个函数。这个函数被称为中间件，作用是在请求被路由匹配之前，先进行一些处理。上面这个中间件起到 logging 的作用，每收到一个请求，就在命令行输出一条记录。请特别注意，这个函数内部的`next()`，它代表下一个中间件，表示将处理过的请求传递给下一个中间件。这个例子只有一个中间件，就进入路由匹配处理（实际上，`bodyparser`、`router`本质都是中间件，整个 Express 的设计哲学就是不断对 HTTP 请求加工，然后返回一个 HTTP 回应）。\n\n### 练习\n\n1. 请增加一个中间件，服务器每次收到用户请求，会在服务器的控制台打印出收到请求的时间。\n\n2. URL 的查询字符串，比如`localhost:8080?name=Alice`里面的`name`，可以用`req.query.name`拿到。请修改一个路由，使之可以收到查询字符串，然后输出`'Hello ' + req.query.name`。\n\n## ESLint\n\n### 实验目的\n\n1. 学会使用 ESLint 进行代码检查。\n\n### 操作步骤\n\n（1）进入`demos/eslint-demo`目录，安装 ESLint。\n\n```bash\n$ cd demos/eslint-demo\n$ npm install eslint --save-dev\n```\n\n（2）通常，我们会使用别人已经写好的代码检查规则，这里使用的是 Airbnb 公司的规则。所以，还要安装 ESLint 这个规则模块。\n\n```bash\n$ npm install eslint-plugin-import eslint-config-airbnb-base --save-dev\n```\n\n上面代码中，`eslint-plugin-import`是运行这个规则集必须的，所以也要一起安装。\n\n（3）ESLint 的配置文件是`.eslintrc.json`，放置在项目的根目录下面。新建这个文件，在里面指定使用 Airbnb 的规则。\n\n```javascript\n{\n  \"extends\": \"airbnb-base\"\n}\n```\n\n（4）打开项目的`package.json`，在`scripts`字段里面添加三个脚本。\n\n```javascript\n{\n  // ...\n  \"scripts\" : {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"lint\": \"eslint **/*.js\",\n    \"lint-html\": \"eslint **/*.js -f html -o ./reports/lint-results.html\",\n    \"lint-fix\": \"eslint --fix **/*.js\"\n  },\n  // ...\n}\n```\n\n除了原有的`test`脚本，上面代码新定义了三个脚本，它们的作用如下。\n\n- `lint`：检查所有`js`文件的代码\n- `lint-html`：将检查结果写入一个网页文件`./reports/lint-results.html`\n- `lint-fix`：自动修正某些不规范的代码\n\n（5）运行静态检查命令。\n\n```bash\n$ npm run lint\n\n  1:5  error    Unexpected var, use let or const instead  no-var\n  2:5  warning  Unexpected console statement              no-console\n\n✖ 2 problems (1 error, 1 warning)\n```\n\n正常情况下，该命令会从`index.js`脚本里面，检查出来两个错误：一个是不应该使用`var`命令，另一个是不应该在生产环境使用`console.log`方法。\n\n（6）修正错误。\n\n```bash\n$ npm run lint-fix\n```\n\n运行上面的命令以后，再查看`index.js`，可以看到`var x = 1;`被自动改成了`const x = 1;`。这样就消除了一个错误，但是还留下一个错误。\n\n（7）修改规则。\n\n由于我们想要允许使用`console.log`方法，因此可以修改`.eslintrc.json`，改变`no-console`规则。请将`.eslintrc.json`改成下面的样子。\n\n```javascript\n{\n  \"extends\": \"airbnb-base\",\n\n  \"rules\": {\n    \"no-console\": \"off\"\n  }\n}\n```\n\n再运行`npm run lint`，就不会报错了。\n\n```bash\n$ npm run lint\n```\n\n## Mocha\n\n### 实验目的\n\n1. 学会使用 Mocha 进行单元测试。\n\n### 操作步骤\n\n（1） 进入`demos/mocha-demo`目录，安装 Mocha 和 Chai。\n\n```bash\n$ cd demos/mocha-demo\n$ npm install -D mocha\n$ npm install -D chai\n```\n\n（2）打开`add.js`文件，查看源码，我们要测试的就是这个脚本。\n\n```javascript\nfunction add(x, y) {\n  return x + y;\n}\n\nmodule.exports = add;\n```\n\n（3）编写一个测试脚本`add.test.js`。\n\n```javascript\nvar add = require('./add.js');\nvar expect = require('chai').expect;\n\ndescribe('加法函数的测试', function() {\n  it('1 加 1 应该等于 2', function() {\n    expect(add(1, 1)).to.be.equal(2);\n  });\n});\n```\n\n测试脚本与所要测试的源码脚本同名，但是后缀名为`.test.js`（表示测试）或者`.spec.js`（表示规格）。比如，`add.js`的测试脚本名字就是`add.test.js`。\n\n测试脚本里面应该包括一个或多个`describe`块，每个`describe`块应该包括一个或多个`it`块。\n\n`describe`块称为\"测试套件\"（test suite），表示一组相关的测试。它是一个函数，第一个参数是测试套件的名称（\"加法函数的测试\"），第二个参数是一个实际执行的函数。\n\n`it`块称为\"测试用例\"（test case），表示一个单独的测试，是测试的最小单位。它也是一个函数，第一个参数是测试用例的名称（\"1 加 1 应该等于 2\"），第二个参数是一个实际执行的函数。\n\n上面的测试脚本里面，有一句断言。\n\n```javascript\nexpect(add(1, 1)).to.be.equal(2);\n```\n\n所谓\"断言\"，就是判断源码的实际执行结果与预期结果是否一致，如果不一致就抛出一个错误。上面这句断言的意思是，调用`add(1, 1)`，结果应该等于`2`。\n\n所有的测试用例（`it`块）都应该含有一句或多句的断言。它是编写测试用例的关键。断言功能由断言库来实现，Mocha本身不带断言库，所以必须先引入断言库。\n\n```javascript\nvar expect = require('chai').expect;\n```\n\n断言库有很多种，Mocha并不限制使用哪一种。上面代码引入的断言库是`chai`，并且指定使用它的`expect`断言风格。\n\n（4）打开`package.json`文件，改写`scripts`字段的`test`脚本。\n\n```javascript\n\"scripts\": {\n  \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n},\n\n// 改成\n\n\"scripts\": {\n  \"test\": \"mocha *.test.js\"\n},\n```\n\n（5）命令行下，执行下面的命令，运行测试用例。\n\n```bash\n$ npm test\n```\n\n正常情况下，命令行会有提示，表示测试用例已经通过了。\n\n### 练习\n\n1. 请在`add.test.js`里面添加一个测试用例，测试`3`加上`-3`，`add`函数应该返回`0`。\n\n## Nightmare\n\n### 实验目的\n\n1. 学会使用 Nightmare 完成功能测试。\n\n### 操作步骤\n\n（1）进入`./demos/nightmare-demo`目录，安装依赖。\n\n```bash\n$ cd demos/nightmare-demo\n\n# Linux & Mac\n$ env ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/ npm install\n\n# Windows\n$ set ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/\n$ npm install\n```\n\n注意，Nightmare 会先安装 Electron，而 Electron 的安装需要下载境外的包，有时会连不上，导致安装失败。所以，这里先设置了环境变量，指定使用国内的 Electron 源，然后才执行安装命令。\n\n（2）查看一下浏览器自动化脚本`taobao.test.js`。\n\n```javascript\nvar Nightmare = require('nightmare');\nvar nightmare = Nightmare({ show: true });\n```\n\n上面代码表示新建一个 Nightmare 实例，并且运行功能中，自动打开浏览器窗口。\n\n```javascript\nnightmare\n  .goto('https://www.taobao.com/')\n  .type('#q', '电视机')\n  .click('form[action*=\"/search\"] [type=submit]')\n  .wait('#spulist-grid')\n  .evaluate(function () {\n    return document.querySelector('#spulist-grid .grid-item .info-cont')\n      .textContent.trim();\n  })\n  .end()\n```\n\n上面代码表示，打开淘宝首页，在搜索框键入`电视机`，点击”搜索“按钮，等待`#spulist-grid`元素出现，在页面内注入（`evaluate`）代码，将执行结果返回。\n\n```javascript\n  .then(function (result) {\n    console.log(result);\n  })\n  .catch(function (error) {\n    console.error('Search failed:', error);\n  });\n```\n\nNightmare 会返回一个 Promise 对象，`then`方法指定操作成功的回调函数，`catch`方法指定操作失败的回调函数。\n\n（3）命令行下运行这个示例脚本。\n\n```bash\n$ node taobao.test.js\n```\n\n正常情况下，运行结束后，命令行会显示淘宝”电视机“搜索结果的第一项。\n\n（4）浏览器打开`index.html`文件，这是 React 练习时做过的一个例子，点击`Hello World`，标题会变成`Hello Clicked`。我们就要编写测试脚本，测试这个功能。\n\n（5）打开测试脚本`test.js`。\n\n```javascript\nvar Nightmare = require('nightmare');\nvar expect = require('chai').expect;\nvar fork = require('child_process').fork;\n\ndescribe('test index.html', function() {\n  var child;\n\n  before(function (done) {\n    child = fork('./server.js');\n    child.on('message', function (msg) {\n      if (msg === 'listening') {\n        done();\n      }\n    });\n  });\n\n  after(function () {\n    child.kill();\n  });\n```\n\n上面代码中，`before`和`after`是 Mocha 提供的两个钩子方法，分别在所有测试开始前和结束后运行。这里，我们在`before`方法里面，新建一个子进程，用来启动 HTTP 服务器；测试结束后，再杀掉这个子进程。\n\n注意，`before`方法的参数是一个函数，它接受`done`作为参数。`done`是 Mocha 提供的一个函数，用来表示异步操作完成。如果不调用`done`，Mocha 就会认为异步操作没有结束，一直停在这一步，不往下执行，从而导致超时错误。\n\n子进程脚本`server.js`的代码非常简单，只有四行。\n\n```javascript\nvar httpServer = require('http-server');\nvar server = httpServer.createServer();\nserver.listen(8080);\nprocess.send('listening');\n```\n\n上面代码中，我们在`8080`端口启动 HTTP 服务器，然后向父进程发消息，表示启动完成。\n\n（6）真正的自动化测试脚本如下。\n\n```javascript\n  it('点击后标题改变', function(done) {\n    var nightmare = Nightmare({ show: true });\n    nightmare\n      .goto('http://127.0.0.1:8080/index.html')\n      .click('h1')\n      .wait(1000)\n      .evaluate(function () {\n        return document.querySelector('h1').textContent;\n      })\n      .end()\n      .then(function(text) {\n        expect(text).to.equal('Hello Clicked');\n        done();\n      })\n  });\n```\n\n上面代码中，首先打开网页，点击`h1`元素，然后等待 1 秒钟，注入脚本获取`h1`元素的文本内容。接着，在`then`方法里面，做一个断言，判断获取的文本是否正确。\n\n（7）运行这个测试脚本。\n\n```bash\n$ npm test\n```\n\n如果一切正常，命令行下会显示测试通过。\n\n### 练习\n\n1. 请写一个测试用例，验证`<h1>`的字体颜色是红色。（提示：可以使用`Window.getComputedStyle()`方法，获取元素的最终样式。）\n\n## Travis CI\n\n### 实验目的\n\n1. 了解持续集成的做法，学会使用 Travis CI。\n\n### 操作步骤\n\n（1）注册 [Github](https://github.com) 的账户。如果你已经注册过，跳过这一步。\n\n（2）访问这个代码库[`github.com/ruanyf/travis-ci-demo`](https://github.com/ruanyf/travis-ci-demo)，点击右上角的`Fork`按钮，将它克隆到你自己的空间里面。\n\n（3）将你`fork`的代码库，克隆到本地。注意，要将下面网址之中的`[your_username]`改成你的 Github 用户名。\n\n```bash\n// Linux & Mac\n$ git clone git@github.com:[your_username]/travis-ci-demo.git\n\n// Windows\n$ git clone https://github.com:[your_username]/travis-ci-demo\n```\n\n（4）使用你的 Github 账户，登录 [Travis CI](https://travis-ci.org/auth) 的首页。然后，访问 [Profile](https://travis-ci.org/profile) 页面，选定`travis-ci-demo`代码库运行自动构建。\n\n（5）回到命令行，进入你本地的`travis-ci-demo`目录，切换到`demo01`分支。\n\n```bash\n$ cd travis-ci-demo\n$ git checkout demo01\n```\n\n项目根目录下面有一个`.travis.yml`文件，这是 Travis CI 的配置文件。如果没有这个文件，就不会触发 Travis CI 的自动构建。打开看一下。\n\n```bash\nlanguage: node_js\nnode_js:\n  - \"node\"\n```\n\n上面代码指定，使用 Node 完成构建，版本是最新的稳定版。\n\n指定 Node 的版本号也是可以的。\n\n```javascript\nlanguage: node_js\nnode_js:\n  - \"4.1\"\n```\n\n上面代码指定使用 Node 4.1 版。\n\n（6）Travis CI 默认依次执行以下九个脚本。\n\n- `before_install`\n- `install`\n- `before_script`\n- `script`\n- `after_success` 或者 `after_failure`\n- `after_script`\n- `before_deploy`（可选）\n- `deploy`（可选）\n- `after_deploy`（可选）\n\n用户需要用到哪个脚本，就需要提供该脚本的内容。\n\n对于 Node 项目，以下两个脚本有默认值，可以不用自己设定。\n\n```javascript\n\"install\": \"npm install\",\n\"script\": \"npm test\"\n```\n\n（7）打开当前分支的`package.json`，可以发现它的`test`脚本是一个`lint`命令。\n\n```javascript\n\"scripts\": {\n  \"test\": \"jshint hello.js\"\n},\n```\n\n（8）在项目根目录下，新建一个新文件`NewUser.txt`，内容是你的用户名。提交这个文件，就会触发 Travis CI 的自动构建。\n\n```bash\n$ git add -A\n$ git commit -m 'Testing Travis CI'\n$ git push\n```\n\n（9）等到 Travis CI 完成自动构建，到页面上[检查](https://travis-ci.org/repositories)构建结果。\n\n（10）切换到`demo02`分支，打开`package.json`，可以看到`test`脚本，现在需要完成两步操作了。\n\n```javascript\n  \"scripts\": {\n    \"lint\": \"jshint hello.js hello.test.js\",\n    \"test\": \"npm run lint && mocha hello.test.js\"\n  },\n```\n\n（11）重复上面第 8 步和第 9 步。\n\n### 练习\n\n1. 修改`hello.js`，让其输出`Hello Node`。并修改测试用例`hello.test.js`，使之能够通过 Travis CI 的自动构建。\n\n"
  },
  {
    "path": "30-jstraining/demos/angular-demo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<meta charset=\"UTF-8\"/>\n<script src=\"angular.1.4.8.min.js\"></script>\n<body>\n<div ng-app=\"\">\n  <p>姓名 : <input type=\"text\" ng-model=\"name\" placeholder=\"在这里输入您的大名\"></p>\n  <h1>你好，{{name}}</h1>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/backbone-demo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Backbone Demo</title>\n</head>\n<body>\n\n<h1>Backbone Routing Demo</h1>\n\n  <ul id=\"menu\">\n    <li><a href=\"#\">Index</a></li>\n    <li><a href=\"#show/1\">Show</a></li>\n    <li><a href=\"#download/1\">Download</a></li>\n    <li><a href=\"#search/1\">Search</a></li>\n    <li><a href=\"#other\">Other</a></li>\n  </ul>\n\n<script src=\"js/underscore.js\"></script>\n<script src=\"js/jquery.js\"></script>\n<script src=\"js/backbone.js\"></script>\n<script src=\"js/main.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/backbone-demo/js/backbone.js",
    "content": "// Backbone.js 0.9.2\n\n// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.\n// Backbone may be freely distributed under the MIT license.\n// For all details and documentation:\n// http://backbonejs.org\n(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g=\"undefined\"!==typeof exports?exports:l.Backbone={};g.VERSION=\"0.9.2\";var f=l._;!f&&\"undefined\"!==typeof require&&(f=require(\"underscore\"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks=\n{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g=\nz.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,\"defaults\"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId(\"c\");this.changed={};this._silent=\n{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:\"id\",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null==\nb?\"\":\"\"+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent:\nb)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)};\na.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,\"read\",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger(\"sync\",h,a,c)};c.error=g.wrapError(c.error,\nh,c);b=this.isNew()?\"create\":\"update\";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger(\"destroy\",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger(\"sync\",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,\"delete\",this,a);a.wait||d();return e},url:function(){var a=n(this,\"urlRoot\")||n(this.collection,\"url\")||t();\nreturn this.isNew()?a:a+(\"/\"==a.charAt(a.length-1)?\"\":\"/\")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger(\"change:\"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending=\n{};this.trigger(\"change\",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||\n!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger(\"error\",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator);\nthis._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c<d;c++){if(!(e=a[c]=this._prepareModel(a[c],b)))throw Error(\"Can't add an invalid model to a collection\");g=e.cid;i=e.id;j[g]||this._byCid[g]||null!=i&&(k[i]||this._byId[i])?\nl.push(c):j[g]=k[i]=e}for(c=l.length;c--;)a.splice(l[c],1);c=0;for(d=a.length;c<d;c++)(e=a[c]).on(\"all\",this._onModelEvent,this),this._byCid[e.cid]=e,null!=e.id&&(this._byId[e.id]=e);this.length+=d;A.apply(this.models,[null!=b.at?b.at:this.models.length,0].concat(a));this.comparator&&this.sort({silent:!0});if(b.silent)return this;c=0;for(d=this.models.length;c<d;c++)if(j[(e=this.models[c]).cid])b.index=c,e.trigger(\"add\",e,this,b);return this},remove:function(a,b){var c,d,e,g;b||(b={});a=f.isArray(a)?\na.slice():[a];c=0;for(d=a.length;c<d;c++)if(g=this.getByCid(a[c])||this.get(a[c]))delete this._byId[g.id],delete this._byCid[g.cid],e=this.indexOf(g),this.models.splice(e,1),this.length--,b.silent||(b.index=e,g.trigger(\"remove\",g,this,b)),this._removeReference(g);return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,b);return a},pop:function(a){var b=this.at(this.length-1);this.remove(b,a);return b},unshift:function(a,b){a=this._prepareModel(a,b);this.add(a,f.extend({at:0},b));return a},\nshift:function(a){var b=this.at(0);this.remove(b,a);return b},get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return f.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return!1;return!0})},sort:function(a){a||(a={});if(!this.comparator)throw Error(\"Cannot sort a set without a comparator\");var b=f.bind(this.comparator,this);1==this.comparator.length?\nthis.models=this.sortBy(b):this.models.sort(b);a.silent||this.trigger(\"reset\",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},reset:function(a,b){a||(a=[]);b||(b={});for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);this._reset();this.add(a,f.extend({silent:!0},b));b.silent||this.trigger(\"reset\",this,b);return this},fetch:function(a){a=a?f.clone(a):{};void 0===a.parse&&(a.parse=!0);var b=this,c=a.success;a.success=function(d,\ne,f){b[a.add?\"add\":\"reset\"](b.parse(d,f),a);c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,\"read\",this,a)},create:function(a,b){var c=this,b=b?f.clone(b):{},a=this._prepareModel(a,b);if(!a)return!1;b.wait||c.add(a,b);var d=b.success;b.success=function(e,f){b.wait&&c.add(e,b);d?d(e,f):e.trigger(\"sync\",a,f,b)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId=\n{};this._byCid={}},_prepareModel:function(a,b){b||(b={});a instanceof o?a.collection||(a.collection=this):(b.collection=this,a=new this.model(a,b),a._validate(a.attributes,b)||(a=!1));return a},_removeReference:function(a){this==a.collection&&delete a.collection;a.off(\"all\",this._onModelEvent,this)},_onModelEvent:function(a,b,c,d){(\"add\"==a||\"remove\"==a)&&c!=this||(\"destroy\"==a&&this.remove(b,d),b&&a===\"change:\"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,\narguments))}});f.each(\"forEach,each,map,reduce,reduceRight,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,sortBy,sortedIndex,toArray,size,first,initial,rest,last,without,indexOf,shuffle,lastIndexOf,isEmpty,groupBy\".split(\",\"),function(a){r.prototype[a]=function(){return f[a].apply(f,[this.models].concat(f.toArray(arguments)))}});var u=g.Router=function(a){a||(a={});a.routes&&(this.routes=a.routes);this._bindRoutes();this.initialize.apply(this,arguments)},B=/:\\w+/g,\nC=/\\*\\w+/g,D=/[-[\\]{}()+?.,\\\\^$|#\\s]/g;f.extend(u.prototype,k,{initialize:function(){},route:function(a,b,c){g.history||(g.history=new m);f.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c&&c.apply(this,d);this.trigger.apply(this,[\"route:\"+b].concat(d));g.history.trigger(\"route\",this,b,d)},this));return this},navigate:function(a,b){g.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,\nthis.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(D,\"\\\\$&\").replace(B,\"([^/]+)\").replace(C,\"(.*?)\");return RegExp(\"^\"+a+\"$\")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var m=g.History=function(){this.handlers=[];f.bindAll(this,\"checkUrl\")},s=/^[#\\/]/,E=/msie [\\w.]+/;m.started=!1;f.extend(m.prototype,k,{interval:50,getHash:function(a){return(a=(a?a.location:window.location).href.match(/#(.*)$/))?a[1]:\n\"\"},getFragment:function(a,b){if(null==a)if(this._hasPushState||b){var a=window.location.pathname,c=window.location.search;c&&(a+=c)}else a=this.getHash();a.indexOf(this.options.root)||(a=a.substr(this.options.root.length));return a.replace(s,\"\")},start:function(a){if(m.started)throw Error(\"Backbone.history has already been started\");m.started=!0;this.options=f.extend({},{root:\"/\"},this.options,a);this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=\n!(!this.options.pushState||!window.history||!window.history.pushState);var a=this.getFragment(),b=document.documentMode;if(b=E.exec(navigator.userAgent.toLowerCase())&&(!b||7>=b))this.iframe=i('<iframe src=\"javascript:0\" tabindex=\"-1\" />').hide().appendTo(\"body\")[0].contentWindow,this.navigate(a);this._hasPushState?i(window).bind(\"popstate\",this.checkUrl):this._wantsHashChange&&\"onhashchange\"in window&&!b?i(window).bind(\"hashchange\",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,\nthis.interval));this.fragment=a;a=window.location;b=a.pathname==this.options.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),window.location.replace(this.options.root+\"#\"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&b&&a.hash&&(this.fragment=this.getHash().replace(s,\"\"),window.history.replaceState({},document.title,a.protocol+\"//\"+a.host+this.options.root+this.fragment));if(!this.options.silent)return this.loadUrl()},\nstop:function(){i(window).unbind(\"popstate\",this.checkUrl).unbind(\"hashchange\",this.checkUrl);clearInterval(this._checkUrlInterval);m.started=!1},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe)));if(a==this.fragment)return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(a){var b=this.fragment=this.getFragment(a);return f.any(this.handlers,\nfunction(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){if(!m.started)return!1;if(!b||!0===b)b={trigger:b};var c=(a||\"\").replace(s,\"\");this.fragment!=c&&(this._hasPushState?(0!=c.indexOf(this.options.root)&&(c=this.options.root+c),this.fragment=c,window.history[b.replace?\"replaceState\":\"pushState\"]({},document.title,c)):this._wantsHashChange?(this.fragment=c,this._updateHash(window.location,c,b.replace),this.iframe&&c!=this.getFragment(this.getHash(this.iframe))&&(b.replace||\nthis.iframe.document.open().close(),this._updateHash(this.iframe.location,c,b.replace))):window.location.assign(this.options.root+a),b.trigger&&this.loadUrl(a))},_updateHash:function(a,b,c){c?a.replace(a.toString().replace(/(javascript:|#).*$/,\"\")+\"#\"+b):a.hash=b}});var v=g.View=function(a){this.cid=f.uniqueId(\"view\");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},F=/^(\\S+)\\s*(.*)$/,w=\"model,collection,el,id,attributes,className,tagName\".split(\",\");\nf.extend(v.prototype,k,{tagName:\"div\",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();return this},make:function(a,b,c){a=document.createElement(a);b&&i(a).attr(b);c&&i(a).html(c);return a},setElement:function(a,b){this.$el&&this.undelegateEvents();this.$el=a instanceof i?a:i(a);this.el=this.$el[0];!1!==b&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=n(this,\"events\"))){this.undelegateEvents();\nfor(var b in a){var c=a[b];f.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method \"'+a[b]+'\" does not exist');var d=b.match(F),e=d[1],d=d[2],c=f.bind(c,this),e=e+(\".delegateEvents\"+this.cid);\"\"===d?this.$el.bind(e,c):this.$el.delegate(d,e,c)}}},undelegateEvents:function(){this.$el.unbind(\".delegateEvents\"+this.cid)},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=0,c=w.length;b<c;b++){var d=w[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el)this.setElement(this.el,\n!1);else{var a=n(this,\"attributes\")||{};this.id&&(a.id=this.id);this.className&&(a[\"class\"]=this.className);this.setElement(this.make(this.tagName,a),!1)}}});o.extend=r.extend=u.extend=v.extend=function(a,b){var c=G(this,a,b);c.extend=this.extend;return c};var H={create:\"POST\",update:\"PUT\",\"delete\":\"DELETE\",read:\"GET\"};g.sync=function(a,b,c){var d=H[a];c||(c={});var e={type:d,dataType:\"json\"};c.url||(e.url=n(b,\"url\")||t());if(!c.data&&b&&(\"create\"==a||\"update\"==a))e.contentType=\"application/json\",\ne.data=JSON.stringify(b.toJSON());g.emulateJSON&&(e.contentType=\"application/x-www-form-urlencoded\",e.data=e.data?{model:e.data}:{});if(g.emulateHTTP&&(\"PUT\"===d||\"DELETE\"===d))g.emulateJSON&&(e.data._method=d),e.type=\"POST\",e.beforeSend=function(a){a.setRequestHeader(\"X-HTTP-Method-Override\",d)};\"GET\"!==e.type&&!g.emulateJSON&&(e.processData=!1);return i.ajax(f.extend(e,c))};g.wrapError=function(a,b,c){return function(d,e){e=d===b?e:d;a?a(b,e,c):b.trigger(\"error\",b,e,c)}};var x=function(){},G=function(a,\nb,c){var d;d=b&&b.hasOwnProperty(\"constructor\")?b.constructor:function(){a.apply(this,arguments)};f.extend(d,a);x.prototype=a.prototype;d.prototype=new x;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},n=function(a,b){return!a||!a[b]?null:f.isFunction(a[b])?a[b]():a[b]},t=function(){throw Error('A \"url\" property or function must be specified');}}).call(this);"
  },
  {
    "path": "30-jstraining/demos/backbone-demo/js/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.8.2\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time)\n */\n(function( window, undefined ) {\nvar\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\tlocation = window.location,\n\tnavigator = window.navigator,\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// Save a reference to some core methods\n\tcore_push = Array.prototype.push,\n\tcore_slice = Array.prototype.slice,\n\tcore_indexOf = Array.prototype.indexOf,\n\tcore_toString = Object.prototype.toString,\n\tcore_hasOwn = Object.prototype.hasOwnProperty,\n\tcore_trim = String.prototype.trim,\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Used for matching numbers\n\tcore_pnum = /[\\-+]?(?:\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/.source,\n\n\t// Used for detecting and trimming whitespace\n\tcore_rnotwhite = /\\S/,\n\tcore_rspace = /\\s+/,\n\n\t// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\trquickExpr = /^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d\\d*\\.|)\\d+(?:[eE][\\-+]?\\d+|)/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn ( letter + \"\" ).toUpperCase();\n\t},\n\n\t// The ready event handler and self cleanup method\n\tDOMContentLoaded = function() {\n\t\tif ( document.addEventListener ) {\n\t\t\tdocument.removeEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\t\t\tjQuery.ready();\n\t\t} else if ( document.readyState === \"complete\" ) {\n\t\t\t// we're here because readyState === \"complete\" in oldIE\n\t\t\t// which is good enough for us to call the dom ready!\n\t\t\tdocument.detachEvent( \"onreadystatechange\", DOMContentLoaded );\n\t\t\tjQuery.ready();\n\t\t}\n\t},\n\n\t// [[Class]] -> type pairs\n\tclass2type = {};\n\njQuery.fn = jQuery.prototype = {\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem, ret, doc;\n\n\t\t// Handle $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle $(DOMElement)\n\t\tif ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\t\t\t\t\tdoc = ( context && context.nodeType ? context.ownerDocument || context : document );\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\tselector = jQuery.parseHTML( match[1], doc, true );\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tthis.attr.call( selector, context, true );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.merge( this, selector );\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The current version of jQuery being used\n\tjquery: \"1.8.2\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn core_slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems, name, selector ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\tret.context = this.context;\n\n\t\tif ( name === \"find\" ) {\n\t\t\tret.selector = this.selector + ( this.selector ? \" \" : \"\" ) + selector;\n\t\t} else if ( name ) {\n\t\t\tret.selector = this.selector + \".\" + name + \"(\" + selector + \")\";\n\t\t}\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Add the callback\n\t\tjQuery.ready.promise().done( fn );\n\n\t\treturn this;\n\t},\n\n\teq: function( i ) {\n\t\ti = +i;\n\t\treturn i === -1 ?\n\t\t\tthis.slice( i ) :\n\t\t\tthis.slice( i, i + 1 );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( core_slice.apply( this, arguments ),\n\t\t\t\"slice\", core_slice.call(arguments).join(\",\") );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: core_push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( !document.body ) {\n\t\t\treturn setTimeout( jQuery.ready, 1 );\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.trigger ) {\n\t\t\tjQuery( document ).trigger(\"ready\").off(\"ready\");\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\treturn obj == null ?\n\t\t\tString( obj ) :\n\t\t\tclass2type[ core_toString.call(obj) ] || \"object\";\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!core_hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!core_hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || core_hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\t// data: string of html\n\t// context (optional): If specified, the fragment will be created in this context, defaults to document\n\t// scripts (optional): If true, will include scripts passed in the html string\n\tparseHTML: function( data, context, scripts ) {\n\t\tvar parsed;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( typeof context === \"boolean\" ) {\n\t\t\tscripts = context;\n\t\t\tcontext = 0;\n\t\t}\n\t\tcontext = context || document;\n\n\t\t// Single tag\n\t\tif ( (parsed = rsingleTag.exec( data )) ) {\n\t\t\treturn [ context.createElement( parsed[1] ) ];\n\t\t}\n\n\t\tparsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );\n\t\treturn jQuery.merge( [],\n\t\t\t(parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );\n\t},\n\n\tparseJSON: function( data ) {\n\t\tif ( !data || typeof data !== \"string\") {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\tdata = jQuery.trim( data );\n\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\t// Make sure the incoming data is actual JSON\n\t\t// Logic borrowed from http://json.org/json2.js\n\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\treturn ( new Function( \"return \" + data ) )();\n\n\t\t}\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && core_rnotwhite.test( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar name,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisObj = length === undefined || jQuery.isFunction( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in obj ) {\n\t\t\t\t\tif ( callback.apply( obj[ name ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.apply( obj[ i++ ], args ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isObj ) {\n\t\t\t\tfor ( name in obj ) {\n\t\t\t\t\tif ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( ; i < length; ) {\n\t\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: core_trim && !core_trim.call(\"\\uFEFF\\xA0\") ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\tcore_trim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar type,\n\t\t\tret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\t// The window, strings (and functions) also have 'length'\n\t\t\t// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930\n\t\t\ttype = jQuery.type( arr );\n\n\t\t\tif ( arr.length == null || type === \"string\" || type === \"function\" || type === \"regexp\" || jQuery.isWindow( arr ) ) {\n\t\t\t\tcore_push.call( ret, arr );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( core_indexOf ) {\n\t\t\t\treturn core_indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar l = second.length,\n\t\t\ti = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof l === \"number\" ) {\n\t\t\tfor ( ; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar retVal,\n\t\t\tret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value, key,\n\t\t\tret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\t// jquery objects are treated as arrays\n\t\t\tisArray = elems instanceof jQuery || length !== undefined && typeof length === \"number\" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( key in elems ) {\n\t\t\t\tvalue = callback( elems[ key ], key, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn ret.concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = core_slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context, args.concat( core_slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Multifunctional method to get and set values of a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, pass ) {\n\t\tvar exec,\n\t\t\tbulk = key == null,\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\n\t\t// Sets many values\n\t\tif ( key && typeof key === \"object\" ) {\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], 1, emptyGet, value );\n\t\t\t}\n\t\t\tchainable = 1;\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\t// Optionally, function values get executed if exec is true\n\t\t\texec = pass === undefined && jQuery.isFunction( value );\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations only iterate when executing function values\n\t\t\t\tif ( exec ) {\n\t\t\t\t\texec = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn exec.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\n\t\t\t\t// Otherwise they run against the entire set\n\t\t\t\t} else {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor (; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tchainable = 1;\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t}\n});\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready, 1 );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", DOMContentLoaded, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", jQuery.ready, false );\n\n\t\t// If IE event model is used\n\t\t} else {\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", DOMContentLoaded );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", jQuery.ready );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t(function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll(\"left\");\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\treturn setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.split( core_rspace ), function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" && ( !options.unique || !self.has( arg ) ) ) {\n\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Control if a given callback is in the list\n\t\t\thas: function( fn ) {\n\t\t\t\treturn jQuery.inArray( fn, list ) > -1;\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\targs = args || [];\n\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar action = tuple[ 0 ],\n\t\t\t\t\t\t\t\tfn = fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ]( jQuery.isFunction( fn ) ?\n\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\tvar returned = fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === deferred ? newDefer : this, [ returned ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} :\n\t\t\t\t\t\t\t\tnewDefer[ action ]\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ] = list.fire\n\t\t\tdeferred[ tuple[0] ] = list.fire;\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = core_slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n\t\t\t\t\tif( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\njQuery.support = (function() {\n\n\tvar support,\n\t\tall,\n\t\ta,\n\t\tselect,\n\t\topt,\n\t\tinput,\n\t\tfragment,\n\t\teventName,\n\t\ti,\n\t\tisSupported,\n\t\tclickFn,\n\t\tdiv = document.createElement(\"div\");\n\n\t// Preliminary tests\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\tall = div.getElementsByTagName(\"*\");\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\ta.style.cssText = \"top:1px;float:left;opacity:.5\";\n\n\t// Can't get basic test support\n\tif ( !all || !all.length ) {\n\t\treturn {};\n\t}\n\n\t// First batch of supports tests\n\tselect = document.createElement(\"select\");\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName(\"input\")[ 0 ];\n\n\tsupport = {\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: ( div.firstChild.nodeType === 3 ),\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: ( a.getAttribute(\"href\") === \"/a\" ),\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.5/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Make sure that if no value is specified for a checkbox\n\t\t// that it defaults to \"on\".\n\t\t// (WebKit defaults to \"\" instead)\n\t\tcheckOn: ( input.value === \"on\" ),\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// Tests for enctype support on a form(#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode\n\t\tboxModel: ( document.compatMode === \"CSS1Compat\" ),\n\n\t\t// Will be defined later\n\t\tsubmitBubbles: true,\n\t\tchangeBubbles: true,\n\t\tfocusinBubbles: false,\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tboxSizingReliable: true,\n\t\tpixelPosition: false\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Test to see if it's possible to delete an expando from an element\n\t// Fails in Internet Explorer\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\tif ( !div.addEventListener && div.attachEvent && div.fireEvent ) {\n\t\tdiv.attachEvent( \"onclick\", clickFn = function() {\n\t\t\t// Cloning a node shouldn't copy over any\n\t\t\t// bound event handlers (IE does this)\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\t\tdiv.cloneNode( true ).fireEvent(\"onclick\");\n\t\tdiv.detachEvent( \"onclick\", clickFn );\n\t}\n\n\t// Check if a radio maintains its value\n\t// after being appended to the DOM\n\tinput = document.createElement(\"input\");\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n\n\tinput.setAttribute( \"checked\", \"checked\" );\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( div.lastChild );\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\tfragment.removeChild( input );\n\tfragment.appendChild( div );\n\n\t// Technique from Juriy Zaytsev\n\t// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/\n\t// We only care about the case where non-standard event systems\n\t// are used, namely in IE. Short-circuiting here helps us to\n\t// avoid an eval call (in setAttribute) which can cause CSP\n\t// to go haywire. See: https://developer.mozilla.org/en/Security/CSP\n\tif ( div.attachEvent ) {\n\t\tfor ( i in {\n\t\t\tsubmit: true,\n\t\t\tchange: true,\n\t\t\tfocusin: true\n\t\t}) {\n\t\t\teventName = \"on\" + i;\n\t\t\tisSupported = ( eventName in div );\n\t\t\tif ( !isSupported ) {\n\t\t\t\tdiv.setAttribute( eventName, \"return;\" );\n\t\t\t\tisSupported = ( typeof div[ eventName ] === \"function\" );\n\t\t\t}\n\t\t\tsupport[ i + \"Bubbles\" ] = isSupported;\n\t\t}\n\t}\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, div, tds, marginDiv,\n\t\t\tdivReset = \"padding:0;margin:0;border:0;display:block;overflow:hidden;\",\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = \"visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px\";\n\t\tbody.insertBefore( container, body.firstChild );\n\n\t\t// Construct the test element\n\t\tdiv = document.createElement(\"div\");\n\t\tcontainer.appendChild( div );\n\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\t// (only IE 8 fails this test)\n\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName(\"td\");\n\t\ttds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\t// (IE <= 8 fail this test)\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check box-sizing and margin behavior\n\t\tdiv.innerHTML = \"\";\n\t\tdiv.style.cssText = \"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\";\n\t\tsupport.boxSizing = ( div.offsetWidth === 4 );\n\t\tsupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );\n\n\t\t// NOTE: To any future maintainer, we've window.getComputedStyle\n\t\t// because jsdom on node.js will break without it.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tsupport.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tsupport.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container. For more\n\t\t\t// info see bug #3333\n\t\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tmarginDiv = document.createElement(\"div\");\n\t\t\tmarginDiv.style.cssText = div.style.cssText = divReset;\n\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\t\t\tdiv.appendChild( marginDiv );\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\t// (IE < 8 does this)\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.cssText = divReset + \"width:1px;padding:1px;display:inline;zoom:1\";\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\t// (IE 6 does this)\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.style.overflow = \"visible\";\n\t\t\tdiv.innerHTML = \"<div></div>\";\n\t\t\tdiv.firstChild.style.width = \"5px\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\n\t\t\tcontainer.style.zoom = 1;\n\t\t}\n\n\t\t// Null elements to avoid leaks in IE\n\t\tbody.removeChild( container );\n\t\tcontainer = div = tds = marginDiv = null;\n\t});\n\n\t// Null elements to avoid leaks in IE\n\tfragment.removeChild( div );\n\tall = a = select = opt = input = fragment = div = null;\n\n\treturn support;\n})();\nvar rbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\njQuery.extend({\n\tcache: {},\n\n\tdeletedIds: [],\n\n\t// Remove at next major release (1.9/2.0)\n\tuuid: 0,\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( jQuery.fn.jquery + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, ret,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tgetByName = typeof name === \"string\",\n\n\t\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t\t// can't GC object references properly across the DOM-JS boundary\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t\t// attached directly to the object so GC can occur automatically\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t\t// Avoid doing any more work than we need to when trying to get data on an\n\t\t// object that has no data at all\n\t\tif ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !id ) {\n\t\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t\t// ends up in the global cache\n\t\t\tif ( isNode ) {\n\t\t\t\telem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;\n\t\t\t} else {\n\t\t\t\tid = internalKey;\n\t\t\t}\n\t\t}\n\n\t\tif ( !cache[ id ] ) {\n\t\t\tcache[ id ] = {};\n\n\t\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t\t// is serialized using JSON.stringify\n\t\t\tif ( !isNode ) {\n\t\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t\t}\n\t\t}\n\n\t\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t\t// shallow copied over onto the existing cache\n\t\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\t\tif ( pvt ) {\n\t\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t\t} else {\n\t\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t\t}\n\t\t}\n\n\t\tthisCache = cache[ id ];\n\n\t\t// jQuery data() is stored in a separate object inside the object's internal data\n\t\t// cache in order to avoid key collisions between internal data and user-defined\n\t\t// data.\n\t\tif ( !pvt ) {\n\t\t\tif ( !thisCache.data ) {\n\t\t\t\tthisCache.data = {};\n\t\t\t}\n\n\t\t\tthisCache = thisCache.data;\n\t\t}\n\n\t\tif ( data !== undefined ) {\n\t\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t\t}\n\n\t\t// Check for both converted-to-camel and non-converted data property names\n\t\t// If a data property was specified\n\t\tif ( getByName ) {\n\n\t\t\t// First Try to find as-is property data\n\t\t\tret = thisCache[ name ];\n\n\t\t\t// Test for null|undefined property data\n\t\t\tif ( ret == null ) {\n\n\t\t\t\t// Try to find the camelCased property\n\t\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t\t}\n\t\t} else {\n\t\t\tret = thisCache;\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tremoveData: function( elem, name, pvt /* Internal Use Only */ ) {\n\t\tif ( !jQuery.acceptData( elem ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar thisCache, i, l,\n\n\t\t\tisNode = elem.nodeType,\n\n\t\t\t// See jQuery.data for more information\n\t\t\tcache = isNode ? jQuery.cache : elem,\n\t\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t\t// If there is already no cache entry for this object, there is no\n\t\t// purpose in continuing\n\t\tif ( !cache[ id ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( name ) {\n\n\t\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\t\tif ( thisCache ) {\n\n\t\t\t\t// Support array or space separated string names for data keys\n\t\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tname = name.split(\" \");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t\t}\n\n\t\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t\t// and let the cache object itself get destroyed\n\t\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// See jQuery.data for more information\n\t\tif ( !pvt ) {\n\t\t\tdelete cache[ id ].data;\n\n\t\t\t// Don't destroy the parent cache unless the internal data object\n\t\t\t// had been the only thing left in it\n\t\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Destroy the cache\n\t\tif ( isNode ) {\n\t\t\tjQuery.cleanData( [ elem ], true );\n\n\t\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t\t} else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n\t\t\tdelete cache[ id ];\n\n\t\t// When all else fails, null\n\t\t} else {\n\t\t\tcache[ id ] = null;\n\t\t}\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn jQuery.data( elem, name, data, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\tvar noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t// nodes accept data unless otherwise specified; rejection can be conditional\n\t\treturn !noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar parts, part, attr, name, l,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattr = elem.attributes;\n\t\t\t\t\tfor ( l = attr.length; i < l; i++ ) {\n\t\t\t\t\t\tname = attr[i].name;\n\n\t\t\t\t\t\tif ( !name.indexOf( \"data-\" ) ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.substring(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\tparts = key.split( \".\", 2 );\n\t\tparts[1] = parts[1] ? \".\" + parts[1] : \"\";\n\t\tpart = parts[1] + \"!\";\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\tdata = this.triggerHandler( \"getData\" + part, [ parts[0] ] );\n\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\tif ( data === undefined && elem ) {\n\t\t\t\t\tdata = jQuery.data( elem, key );\n\t\t\t\t\tdata = dataAttr( elem, key, data );\n\t\t\t\t}\n\n\t\t\t\treturn data === undefined && parts[1] ?\n\t\t\t\t\tthis.data( parts[0] ) :\n\t\t\t\t\tdata;\n\t\t\t}\n\n\t\t\tparts[1] = value;\n\t\t\tthis.each(function() {\n\t\t\t\tvar self = jQuery( this );\n\n\t\t\t\tself.triggerHandler( \"setData\" + part, parts );\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t\tself.triggerHandler( \"changeData\" + part, parts );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, false );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\tdata === \"false\" ? false :\n\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray(data) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tjQuery.removeData( elem, type + \"queue\", true );\n\t\t\t\tjQuery.removeData( elem, key, true );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar nodeHook, boolHook, fixSpecified,\n\trclass = /[\\t\\r\\n]/g,\n\trreturn = /\\r/g,\n\trtype = /^(?:button|input)$/i,\n\trfocusable = /^(?:button|input|object|select|textarea)$/i,\n\trclickable = /^a(?:rea|)$/i,\n\trboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classNames, i, l, elem,\n\t\t\tsetClass, c, cl;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\n\t\tif ( value && typeof value === \"string\" ) {\n\t\t\tclassNames = value.split( core_rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !elem.className && classNames.length === 1 ) {\n\t\t\t\t\t\telem.className = value;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetClass = \" \" + elem.className + \" \";\n\n\t\t\t\t\t\tfor ( c = 0, cl = classNames.length; c < cl; c++ ) {\n\t\t\t\t\t\t\tif ( setClass.indexOf( \" \" + classNames[ c ] + \" \" ) < 0 ) {\n\t\t\t\t\t\t\t\tsetClass += classNames[ c ] + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telem.className = jQuery.trim( setClass );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar removes, className, elem, c, cl, i, l;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call(this, j, this.className) );\n\t\t\t});\n\t\t}\n\t\tif ( (value && typeof value === \"string\") || value === undefined ) {\n\t\t\tremoves = ( value || \"\" ).split( core_rspace );\n\n\t\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tif ( elem.nodeType === 1 && elem.className ) {\n\n\t\t\t\t\tclassName = (\" \" + elem.className + \" \").replace( rclass, \" \" );\n\n\t\t\t\t\t// loop over each item in the removal list\n\t\t\t\t\tfor ( c = 0, cl = removes.length; c < cl; c++ ) {\n\t\t\t\t\t\t// Remove until there is nothing to remove,\n\t\t\t\t\t\twhile ( className.indexOf(\" \" + removes[ c ] + \" \") >= 0 ) {\n\t\t\t\t\t\t\tclassName = className.replace( \" \" + removes[ c ] + \" \" , \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = value ? jQuery.trim( className ) : \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.split( core_rspace );\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space separated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t} else if ( type === \"undefined\" || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// toggle whole className\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val,\n\t\t\t\tself = jQuery(this);\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, i, max, option,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tvalues = [],\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tone = elem.type === \"select-one\";\n\n\t\t\t\t// Nothing was selected\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\ti = one ? index : 0;\n\t\t\t\tmax = one ? index + 1 : options.length;\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\tif ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null) &&\n\t\t\t\t\t\t\t(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" )) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fixes Bug #2551 -- select.val() broken in IE after form.reset()\n\t\t\t\tif ( one && !values.length && options.length ) {\n\t\t\t\t\treturn jQuery( options[ index ] ).val();\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\t// Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9\n\tattrFn: {},\n\n\tattr: function( elem, name, value, pass ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {\n\t\t\treturn jQuery( elem )[ name ]( value );\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\n\t\t\t} else if ( hooks && \"set\" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\tret = elem.getAttribute( name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret === null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar propName, attrNames, name, isBool,\n\t\t\ti = 0;\n\n\t\tif ( value && elem.nodeType === 1 ) {\n\n\t\t\tattrNames = value.split( core_rspace );\n\n\t\t\tfor ( ; i < attrNames.length; i++ ) {\n\t\t\t\tname = attrNames[ i ];\n\n\t\t\t\tif ( name ) {\n\t\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\t\t\tisBool = rboolean.test( name );\n\n\t\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t\t// Do not do this for boolean attributes (see #10870)\n\t\t\t\t\tif ( !isBool ) {\n\t\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t\t}\n\t\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\tif ( isBool && propName in elem ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\t// We can't allow the type property to be changed (since it causes problems in IE)\n\t\t\t\tif ( rtype.test( elem.nodeName ) && elem.parentNode ) {\n\t\t\t\t\tjQuery.error( \"type property can't be changed\" );\n\t\t\t\t} else if ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to it's default in case type is set after value\n\t\t\t\t\t// This is for element creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Use the value property for back compat\n\t\t// Use the nodeHook for button elements in IE6/7 (#1954)\n\t\tvalue: {\n\t\t\tget: function( elem, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.get( elem, name );\n\t\t\t\t}\n\t\t\t\treturn name in elem ?\n\t\t\t\t\telem.value :\n\t\t\t\t\tnull;\n\t\t\t},\n\t\t\tset: function( elem, value, name ) {\n\t\t\t\tif ( nodeHook && jQuery.nodeName( elem, \"button\" ) ) {\n\t\t\t\t\treturn nodeHook.set( elem, value, name );\n\t\t\t\t}\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.value = value;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\t// Align boolean attributes with corresponding properties\n\t\t// Fall back to attribute presence where some booleans are not supported\n\t\tvar attrNode,\n\t\t\tproperty = jQuery.prop( elem, name );\n\t\treturn property === true || typeof property !== \"boolean\" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tvar propName;\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\t// value is true since we know at this point it's type boolean and not false\n\t\t\t// Set boolean attributes to the same name and set the DOM property\n\t\t\tpropName = jQuery.propFix[ name ] || name;\n\t\t\tif ( propName in elem ) {\n\t\t\t\t// Only set the IDL specifically if it already exists on the element\n\t\t\t\telem[ propName ] = true;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, name.toLowerCase() );\n\t\t}\n\t\treturn name;\n\t}\n};\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\tfixSpecified = {\n\t\tname: true,\n\t\tid: true,\n\t\tcoords: true\n\t};\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret;\n\t\t\tret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( fixSpecified[ name ] ? ret.value !== \"\" : ret.specified ) ?\n\t\t\t\tret.value :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\tret = document.createAttribute( name );\n\t\t\t\telem.setAttributeNode( ret );\n\t\t\t}\n\t\t\treturn ( ret.value = value + \"\" );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === \"\" ) {\n\t\t\t\tvalue = \"false\";\n\t\t\t}\n\t\t\tnodeHook.set( elem, value, name );\n\t\t}\n\t};\n}\n\n\n// Some attributes require a special call on IE\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret === null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Normalize to lowercase since IE uppercases css property names\n\t\t\treturn elem.style.cssText.toLowerCase() || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\nvar rformElems = /^(?:textarea|input|select)$/i,\n\trtypenamespace = /^([^\\.]*|)(?:\\.(.+)|)$/,\n\trhoverHack = /(?:^|\\s)hover(\\.\\S+|)\\b/,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\thoverHack = function( events ) {\n\t\treturn jQuery.event.special.hover ? events : events.replace( rhoverHack, \"mouseenter$1 mouseleave$1\" );\n\t};\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar elemData, eventHandle, events,\n\t\t\tt, tns, type, namespaces, handleObj,\n\t\t\thandleObjIn, handlers, special;\n\n\t\t// Don't attach events to noData or text/comment nodes (allow plain objects tho)\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tevents = elemData.events;\n\t\tif ( !events ) {\n\t\t\telemData.events = events = {};\n\t\t}\n\t\teventHandle = elemData.handle;\n\t\tif ( !eventHandle ) {\n\t\t\telemData.handle = eventHandle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = jQuery.trim( hoverHack(types) ).split( \" \" );\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = tns[1];\n\t\t\tnamespaces = ( tns[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: tns[1],\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\thandlers = events[ type ];\n\t\t\tif ( !handlers ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\tglobal: {},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar t, tns, type, origType, namespaces, origCount,\n\t\t\tj, events, special, eventType, handleObj,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = jQuery.trim( hoverHack( types || \"\" ) ).split(\" \");\n\t\tfor ( t = 0; t < types.length; t++ ) {\n\t\t\ttns = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tns[1];\n\t\t\tnamespaces = tns[2];\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector? special.delegateType : special.bindType ) || type;\n\t\t\teventType = events[ type ] || [];\n\t\t\torigCount = eventType.length;\n\t\t\tnamespaces = namespaces ? new RegExp(\"(^|\\\\.)\" + namespaces.split(\".\").sort().join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null;\n\n\t\t\t// Remove matching events\n\t\t\tfor ( j = 0; j < eventType.length; j++ ) {\n\t\t\t\thandleObj = eventType[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t ( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t ( !namespaces || namespaces.test( handleObj.namespace ) ) &&\n\t\t\t\t\t ( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\teventType.splice( j--, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\teventType.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( eventType.length === 0 && origCount !== eventType.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery.removeData( elem, \"events\", true );\n\t\t}\n\t},\n\n\t// Events that are safe to short-circuit if no handlers are attached.\n\t// Native DOM events should not be added, they may have inline handlers.\n\tcustomEvent: {\n\t\t\"getData\": true,\n\t\t\"setData\": true,\n\t\t\"changeData\": true\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Event object or event type\n\t\tvar cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,\n\t\t\ttype = event.type || event,\n\t\t\tnamespaces = [];\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \"!\" ) >= 0 ) {\n\t\t\t// Exclusive events trigger only for the exact event (no namespaces)\n\t\t\ttype = type.slice(0, -1);\n\t\t\texclusive = true;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\n\t\tif ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {\n\t\t\t// No jQuery handlers for this event type, and it can't have inline handlers\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an Event, Object, or just an event type string\n\t\tevent = typeof event === \"object\" ?\n\t\t\t// jQuery.Event object\n\t\t\tevent[ jQuery.expando ] ? event :\n\t\t\t// Object literal\n\t\t\tnew jQuery.Event( type, event ) :\n\t\t\t// Just the event type (string)\n\t\t\tnew jQuery.Event( type );\n\n\t\tevent.type = type;\n\t\tevent.isTrigger = true;\n\t\tevent.exclusive = exclusive;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.namespace_re = event.namespace? new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\") : null;\n\t\tontype = type.indexOf( \":\" ) < 0 ? \"on\" + type : \"\";\n\n\t\t// Handle a global trigger\n\t\tif ( !elem ) {\n\n\t\t\t// TODO: Stop taunting the data cache; remove global events and always attach to document\n\t\t\tcache = jQuery.cache;\n\t\t\tfor ( i in cache ) {\n\t\t\t\tif ( cache[ i ].events && cache[ i ].events[ type ] ) {\n\t\t\t\t\tjQuery.event.trigger( event, data, cache[ i ].handle.elem, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data != null ? jQuery.makeArray( data ) : [];\n\t\tdata.unshift( event );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\teventPath = [[ elem, special.bindType || type ]];\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tcur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;\n\t\t\tfor ( old = elem; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push([ cur, bubbleType ]);\n\t\t\t\told = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( old === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\tfor ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {\n\n\t\t\tcur = eventPath[i][0];\n\t\t\tevent.type = eventPath[i][1];\n\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\t\t\t// Note that this is a bare JS function and not a jQuery handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486)\n\t\t\t\tif ( ontype && elem[ type ] && ((type !== \"focus\" && type !== \"blur\") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\told = elem[ ontype ];\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( old ) {\n\t\t\t\t\t\telem[ ontype ] = old;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event || window.event );\n\n\t\tvar i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,\n\t\t\thandlers = ( (jQuery._data( this, \"events\" ) || {} )[ event.type ] || []),\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\targs = core_slice.call( arguments ),\n\t\t\trun_all = !event.exclusive && !event.namespace,\n\t\t\tspecial = jQuery.event.special[ event.type ] || {},\n\t\t\thandlerQueue = [];\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers that should run if there are delegated events\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && !(event.button && event.type === \"click\") ) {\n\n\t\t\tfor ( cur = event.target; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tselMatch = {};\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\t\t\t\t\t\tsel = handleObj.selector;\n\n\t\t\t\t\t\tif ( selMatch[ sel ] === undefined ) {\n\t\t\t\t\t\t\tselMatch[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selMatch[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, matches: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( handlers.length > delegateCount ) {\n\t\t\thandlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\tfor ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {\n\t\t\tmatched = handlerQueue[ i ];\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tfor ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {\n\t\t\t\thandleObj = matched.matches[ j ];\n\n\t\t\t\t// Triggered event must either 1) be non-exclusive and have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.data = handleObj.data;\n\t\t\t\t\tevent.handleObj = handleObj;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tevent.result = ret;\n\t\t\t\t\t\tif ( ret === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\t// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***\n\tprops: \"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = jQuery.event.fixHooks[ event.type ] || {},\n\t\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = jQuery.Event( originalEvent );\n\n\t\tfor ( i = copy.length; i; ) {\n\t\t\tprop = copy[ --i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Target should not be a text node (#504, Safari)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\n\t\tfocus: {\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tsetup: function( data, namespaces, eventHandle ) {\n\t\t\t\t// We only want to do this special case on windows\n\t\t\t\tif ( jQuery.isWindow( this ) ) {\n\t\t\t\t\tthis.onbeforeunload = eventHandle;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tteardown: function( namespaces, eventHandle ) {\n\t\t\t\tif ( this.onbeforeunload === eventHandle ) {\n\t\t\t\t\tthis.onbeforeunload = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\n// Some plugins are using, but it's undocumented/deprecated and will be removed.\n// The 1.7 special event interface should provide all the hooks needed now.\njQuery.event.handle = jQuery.event.dispatch;\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8 –\n\t\t\t// detachEvent needed property on element, by name of that event, to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === \"undefined\" ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\nfunction returnFalse() {\n\treturn false;\n}\nfunction returnTrue() {\n\treturn true;\n}\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tpreventDefault: function() {\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// if preventDefault exists run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// otherwise set the returnValue property of the original event to false (IE)\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tvar e = this.originalEvent;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// if stopPropagation exists run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t\t// otherwise set the cancelBubble property of the original event to true (IE)\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t},\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj,\n\t\t\t\tselector = handleObj.selector;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !jQuery._data( form, \"_submit_attached\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( form, \"_submit_attached\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"_change_attached\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( elem, \"_change_attached\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) { // && selector != null\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tlive: function( types, data, fn ) {\n\t\tjQuery( this.context ).on( types, this.selector, data, fn );\n\t\treturn this;\n\t},\n\tdie: function( types, fn ) {\n\t\tjQuery( this.context ).off( types, this.selector || \"**\", fn );\n\t\treturn this;\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tif ( this[0] ) {\n\t\t\treturn jQuery.event.trigger( type, data, this[0], true );\n\t\t}\n\t},\n\n\ttoggle: function( fn ) {\n\t\t// Save reference to arguments for access in closure\n\t\tvar args = arguments,\n\t\t\tguid = fn.guid || jQuery.guid++,\n\t\t\ti = 0,\n\t\t\ttoggler = function( event ) {\n\t\t\t\t// Figure out which function to execute\n\t\t\t\tvar lastToggle = ( jQuery._data( this, \"lastToggle\" + fn.guid ) || 0 ) % i;\n\t\t\t\tjQuery._data( this, \"lastToggle\" + fn.guid, lastToggle + 1 );\n\n\t\t\t\t// Make sure that clicks stop\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// and execute the function\n\t\t\t\treturn args[ lastToggle ].apply( this, arguments ) || false;\n\t\t\t};\n\n\t\t// link all the functions, so any of them can unbind this click handler\n\t\ttoggler.guid = guid;\n\t\twhile ( i < args.length ) {\n\t\t\targs[ i++ ].guid = guid;\n\t\t}\n\n\t\treturn this.click( toggler );\n\t},\n\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n});\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tif ( fn == null ) {\n\t\t\tfn = data;\n\t\t\tdata = null;\n\t\t}\n\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n\n\tif ( rkeyEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;\n\t}\n\n\tif ( rmouseEvent.test( name ) ) {\n\t\tjQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;\n\t}\n});\n/*!\n * Sizzle CSS Selector Engine\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://sizzlejs.com/\n */\n(function( window, undefined ) {\n\nvar cachedruns,\n\tassertGetIdNotName,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcontains,\n\tcompile,\n\tsortOrder,\n\thasDuplicate,\n\toutermostContext,\n\n\tbaseHasDuplicate = true,\n\tstrundefined = \"undefined\",\n\n\texpando = ( \"sizcache\" + Math.random() ).replace( \".\", \"\" ),\n\n\tToken = String,\n\tdocument = window.document,\n\tdocElem = document.documentElement,\n\tdirruns = 0,\n\tdone = 0,\n\tpop = [].pop,\n\tpush = [].push,\n\tslice = [].slice,\n\t// Use a stripped-down indexOf if a native one is unavailable\n\tindexOf = [].indexOf || function( elem ) {\n\t\tvar i = 0,\n\t\t\tlen = this.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( this[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\t// Augment a function for special use by Sizzle\n\tmarkFunction = function( fn, value ) {\n\t\tfn[ expando ] = value == null || value;\n\t\treturn fn;\n\t},\n\n\tcreateCache = function() {\n\t\tvar cache = {},\n\t\t\tkeys = [];\n\n\t\treturn markFunction(function( key, value ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tif ( keys.push( key ) > Expr.cacheLength ) {\n\t\t\t\tdelete cache[ keys.shift() ];\n\t\t\t}\n\n\t\t\treturn (cache[ key ] = value);\n\t\t}, cache );\n\t},\n\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\n\t// Regex\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[-\\\\w]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\toperators = \"([*^$|!~]?=)\",\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:\" + operators + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n\t// Prefer arguments not in parens/brackets,\n\t//   then attribute selectors and non-pseudos (denoted by :),\n\t//   then anything else\n\t// These preferences are here to reduce the number of selectors\n\t//   needing tokenize in the PSEUDO preFilter\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\((?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\2|([^()[\\\\]]*|(?:(?:\" + attributes + \")|[^:]|\\\\\\\\.)*|.*))\\\\)|)\",\n\n\t// For matchExpr.POS and matchExpr.needsContext\n\tpos = \":(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + whitespace +\n\t\t\"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\" + whitespace + \"*\" ),\n\trpseudo = new RegExp( pseudos ),\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w\\-]+)|(\\w+)|\\.([\\w\\-]+))$/,\n\n\trnot = /^:not/,\n\trsibling = /[\\x20\\t\\r\\n\\f]*[+~]/,\n\trendsWithNot = /:not\\($/,\n\n\trheader = /h\\d/i,\n\trinputs = /input|select|textarea|button/i,\n\n\trbackslash = /\\\\(?!\\\\)/g,\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"NAME\": new RegExp( \"^\\\\[name=['\\\"]?(\" + characterEncoding + \")['\\\"]?\\\\]\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"POS\": new RegExp( pos, \"i\" ),\n\t\t\"CHILD\": new RegExp( \"^:(only|nth|first|last)-child(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|\" + pos, \"i\" )\n\t},\n\n\t// Support\n\n\t// Used for testing something on an element\n\tassert = function( fn ) {\n\t\tvar div = document.createElement(\"div\");\n\n\t\ttry {\n\t\t\treturn fn( div );\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t} finally {\n\t\t\t// release memory in IE\n\t\t\tdiv = null;\n\t\t}\n\t},\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tassertTagNameNoComments = assert(function( div ) {\n\t\tdiv.appendChild( document.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t}),\n\n\t// Check if getAttribute returns normalized href attributes\n\tassertHrefNotNormalized = assert(function( div ) {\n\t\tdiv.innerHTML = \"<a href='#'></a>\";\n\t\treturn div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") === \"#\";\n\t}),\n\n\t// Check if attributes should be retrieved by attribute nodes\n\tassertAttributes = assert(function( div ) {\n\t\tdiv.innerHTML = \"<select></select>\";\n\t\tvar type = typeof div.lastChild.getAttribute(\"multiple\");\n\t\t// IE8 returns a string for some attributes even when not present\n\t\treturn type !== \"boolean\" && type !== \"string\";\n\t}),\n\n\t// Check if getElementsByClassName can be trusted\n\tassertUsableClassName = assert(function( div ) {\n\t\t// Opera can't find a second classname (in 9.6)\n\t\tdiv.innerHTML = \"<div class='hidden e'></div><div class='hidden'></div>\";\n\t\tif ( !div.getElementsByClassName || !div.getElementsByClassName(\"e\").length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Safari 3.2 caches class attributes and doesn't catch changes\n\t\tdiv.lastChild.className = \"e\";\n\t\treturn div.getElementsByClassName(\"e\").length === 2;\n\t}),\n\n\t// Check if getElementById returns elements by name\n\t// Check if getElementsByName privileges form controls or returns elements by ID\n\tassertUsableName = assert(function( div ) {\n\t\t// Inject content\n\t\tdiv.id = expando + 0;\n\t\tdiv.innerHTML = \"<a name='\" + expando + \"'></a><div name='\" + expando + \"'></div>\";\n\t\tdocElem.insertBefore( div, docElem.firstChild );\n\n\t\t// Test\n\t\tvar pass = document.getElementsByName &&\n\t\t\t// buggy browsers will return fewer than the correct 2\n\t\t\tdocument.getElementsByName( expando ).length === 2 +\n\t\t\t// buggy browsers will return more than the correct 0\n\t\t\tdocument.getElementsByName( expando + 0 ).length;\n\t\tassertGetIdNotName = !document.getElementById( expando );\n\n\t\t// Cleanup\n\t\tdocElem.removeChild( div );\n\n\t\treturn pass;\n\t});\n\n// If slice is not available, provide a backup\ntry {\n\tslice.call( docElem.childNodes, 0 )[0].nodeType;\n} catch ( e ) {\n\tslice = function( i ) {\n\t\tvar elem,\n\t\t\tresults = [];\n\t\tfor ( ; (elem = this[i]); i++ ) {\n\t\t\tresults.push( elem );\n\t\t}\n\t\treturn results;\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\tvar match, elem, xml, m,\n\t\tnodeType = context.nodeType;\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tif ( nodeType !== 1 && nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\txml = isXML( context );\n\n\tif ( !xml && !seed ) {\n\t\tif ( (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed, xml );\n}\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\treturn Sizzle( expr, null, null, [ elem ] ).length > 0;\n};\n\n// Returns a function to use in pseudos for input types\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for buttons\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for positionals\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( nodeType ) {\n\t\tif ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent for elements\n\t\t\t// innerText usage removed for consistency of new lines (see #11153)\n\t\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else {\n\t\t\t\t// Traverse its children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t\t// Do not include comment or processing instruction nodes\n\t} else {\n\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( ; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t}\n\treturn ret;\n};\n\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n// Element contains another\ncontains = Sizzle.contains = docElem.contains ?\n\tfunction( a, b ) {\n\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\tbup = b && b.parentNode;\n\t\treturn a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );\n\t} :\n\tdocElem.compareDocumentPosition ?\n\tfunction( a, b ) {\n\t\treturn b && !!( a.compareDocumentPosition( b ) & 16 );\n\t} :\n\tfunction( a, b ) {\n\t\twhile ( (b = b.parentNode) ) {\n\t\t\tif ( b === a ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t};\n\nSizzle.attr = function( elem, name ) {\n\tvar val,\n\t\txml = isXML( elem );\n\n\tif ( !xml ) {\n\t\tname = name.toLowerCase();\n\t}\n\tif ( (val = Expr.attrHandle[ name ]) ) {\n\t\treturn val( elem );\n\t}\n\tif ( xml || assertAttributes ) {\n\t\treturn elem.getAttribute( name );\n\t}\n\tval = elem.getAttributeNode( name );\n\treturn val ?\n\t\ttypeof elem[ name ] === \"boolean\" ?\n\t\t\telem[ name ] ? name : null :\n\t\t\tval.specified ? val.value : null :\n\t\tnull;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\t// IE6/7 return a modified href\n\tattrHandle: assertHrefNotNormalized ?\n\t\t{} :\n\t\t{\n\t\t\t\"href\": function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t\t},\n\t\t\t\"type\": function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"type\");\n\t\t\t}\n\t\t},\n\n\tfind: {\n\t\t\"ID\": assertGetIdNotName ?\n\t\t\tfunction( id, context, xml ) {\n\t\t\t\tif ( typeof context.getElementById !== strundefined && !xml ) {\n\t\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t\t}\n\t\t\t} :\n\t\t\tfunction( id, context, xml ) {\n\t\t\t\tif ( typeof context.getElementById !== strundefined && !xml ) {\n\t\t\t\t\tvar m = context.getElementById( id );\n\n\t\t\t\t\treturn m ?\n\t\t\t\t\t\tm.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode(\"id\").value === id ?\n\t\t\t\t\t\t\t[m] :\n\t\t\t\t\t\t\tundefined :\n\t\t\t\t\t\t[];\n\t\t\t\t}\n\t\t\t},\n\n\t\t\"TAG\": assertTagNameNoComments ?\n\t\t\tfunction( tag, context ) {\n\t\t\t\tif ( typeof context.getElementsByTagName !== strundefined ) {\n\t\t\t\t\treturn context.getElementsByTagName( tag );\n\t\t\t\t}\n\t\t\t} :\n\t\t\tfunction( tag, context ) {\n\t\t\t\tvar results = context.getElementsByTagName( tag );\n\n\t\t\t\t// Filter out possible comments\n\t\t\t\tif ( tag === \"*\" ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\ttmp = [],\n\t\t\t\t\t\ti = 0;\n\n\t\t\t\t\tfor ( ; (elem = results[i]); i++ ) {\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn tmp;\n\t\t\t\t}\n\t\t\t\treturn results;\n\t\t\t},\n\n\t\t\"NAME\": assertUsableName && function( tag, context ) {\n\t\t\tif ( typeof context.getElementsByName !== strundefined ) {\n\t\t\t\treturn context.getElementsByName( name );\n\t\t\t}\n\t\t},\n\n\t\t\"CLASS\": assertUsableClassName && function( className, context, xml ) {\n\t\t\tif ( typeof context.getElementsByClassName !== strundefined && !xml ) {\n\t\t\t\treturn context.getElementsByClassName( className );\n\t\t\t}\n\t\t}\n\t},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( rbackslash, \"\" );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[4] || match[5] || \"\" ).replace( rbackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t3 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t4 sign of xn-component\n\t\t\t\t5 x of xn-component\n\t\t\t\t6 sign of y-component\n\t\t\t\t7 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\t// nth-child requires argument\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === \"even\" || match[2] === \"odd\" ) );\n\t\t\t\tmatch[4] = +( ( match[6] + match[7] ) || match[2] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar unquoted, excess;\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[3];\n\t\t\t} else if ( (unquoted = match[4]) ) {\n\t\t\t\t// Only check arguments that contain a pseudo\n\t\t\t\tif ( rpseudo.test(unquoted) &&\n\t\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t\t// excess is a negative index\n\t\t\t\t\tunquoted = unquoted.slice( 0, excess );\n\t\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\t}\n\t\t\t\tmatch[2] = unquoted;\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\t\t\"ID\": assertGetIdNotName ?\n\t\t\tfunction( id ) {\n\t\t\t\tid = id.replace( rbackslash, \"\" );\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\treturn elem.getAttribute(\"id\") === id;\n\t\t\t\t};\n\t\t\t} :\n\t\t\tfunction( id ) {\n\t\t\t\tid = id.replace( rbackslash, \"\" );\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\tvar node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n\t\t\t\t\treturn node && node.value === id;\n\t\t\t\t};\n\t\t\t},\n\n\t\t\"TAG\": function( nodeName ) {\n\t\t\tif ( nodeName === \"*\" ) {\n\t\t\t\treturn function() { return true; };\n\t\t\t}\n\t\t\tnodeName = nodeName.replace( rbackslash, \"\" ).toLowerCase();\n\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ expando ][ className ];\n\t\t\tif ( !pattern ) {\n\t\t\t\tpattern = classCache( className, new RegExp(\"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\") );\n\t\t\t}\n\t\t\treturn function( elem ) {\n\t\t\t\treturn pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\")) || \"\" );\n\t\t\t};\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem, context ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.substr( result.length - check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.substr( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, argument, first, last ) {\n\n\t\t\tif ( type === \"nth\" ) {\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\tvar node, diff,\n\t\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( parent ) {\n\t\t\t\t\t\tdiff = 0;\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tdiff++;\n\t\t\t\t\t\t\t\tif ( elem === node ) {\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Incorporate the offset (or cast to NaN), then check against cycle size\n\t\t\t\t\tdiff -= last;\n\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = elem;\n\n\t\t\t\tswitch ( type ) {\n\t\t\t\t\tcase \"only\":\n\t\t\t\t\tcase \"first\":\n\t\t\t\t\t\twhile ( (node = node.previousSibling) ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnode = elem;\n\n\t\t\t\t\t\t/* falls through */\n\t\t\t\t\tcase \"last\":\n\t\t\t\t\t\twhile ( (node = node.nextSibling) ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf.call( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n\t\t\t//   not comment, processing instructions, or others\n\t\t\t// Thanks to Diego Perini for the nodeName shortcut\n\t\t\t//   Greater than \"@\" means alpha characters (specifically not starting with \"#\" or \"?\")\n\t\t\tvar nodeType;\n\t\t\telem = elem.firstChild;\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.nodeName > \"@\" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\telem = elem.nextSibling;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar type, attr;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\t(type = elem.type) === \"text\" &&\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === type );\n\t\t},\n\n\t\t// Input types\n\t\t\"radio\": createInputPseudo(\"radio\"),\n\t\t\"checkbox\": createInputPseudo(\"checkbox\"),\n\t\t\"file\": createInputPseudo(\"file\"),\n\t\t\"password\": createInputPseudo(\"password\"),\n\t\t\"image\": createInputPseudo(\"image\"),\n\n\t\t\"submit\": createButtonPseudo(\"submit\"),\n\t\t\"reset\": createButtonPseudo(\"reset\"),\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\tvar doc = elem.ownerDocument;\n\t\t\treturn elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href);\n\t\t},\n\n\t\t\"active\": function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t},\n\n\t\t// Positional types\n\t\t\"first\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tfor ( var i = 0; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tfor ( var i = 1; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tfor ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tfor ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nfunction siblingCheck( a, b, ret ) {\n\tif ( a === b ) {\n\t\treturn ret;\n\t}\n\n\tvar cur = a.nextSibling;\n\n\twhile ( cur ) {\n\t\tif ( cur === b ) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tcur = cur.nextSibling;\n\t}\n\n\treturn 1;\n}\n\nsortOrder = docElem.compareDocumentPosition ?\n\tfunction( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn ( !a.compareDocumentPosition || !b.compareDocumentPosition ?\n\t\t\ta.compareDocumentPosition :\n\t\t\ta.compareDocumentPosition(b) & 4\n\t\t) ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// The nodes are identical, we can exit early\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Fallback to using sourceIndex (in IE) if it's available on both nodes\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\t// If the nodes are siblings (or identical) we can do a quick check\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t// If no parents were found then the nodes are disconnected\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Otherwise they're somewhere else in the tree so we need\n\t\t// to build up a full list of the parentNodes for comparison\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\t// Start walking down the tree looking for a discrepancy\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\t// We ended someplace up the tree so do a sibling check\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n// Always assume the presence of duplicates if sort doesn't\n// pass them to our comparison function (as in Google Chrome).\n[0, 0].sort( sortOrder );\nbaseHasDuplicate = !hasDuplicate;\n\n// Document sorting and removing duplicates\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\ti = 1;\n\n\thasDuplicate = baseHasDuplicate;\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\tfor ( ; (elem = results[i]); i++ ) {\n\t\t\tif ( elem === results[ i - 1 ] ) {\n\t\t\t\tresults.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\nfunction tokenize( selector, parseOnly ) {\n\tvar matched, match, tokens, type, soFar, groups, preFilters,\n\t\tcached = tokenCache[ expando ][ selector ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\tsoFar = soFar.slice( match[0].length );\n\t\t\t}\n\t\t\tgroups.push( tokens = [] );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\ttokens.push( matched = new Token( match.shift() ) );\n\t\t\tsoFar = soFar.slice( matched.length );\n\n\t\t\t// Cast descendant combinators to space\n\t\t\tmatched.type = match[0].replace( rtrim, \" \" );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t// The last two arguments here are (context, xml) for backCompat\n\t\t\t\t(match = preFilters[ type ]( match, document, true ))) ) {\n\n\t\t\t\ttokens.push( matched = new Token( match.shift() ) );\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t\tmatched.type = type;\n\t\t\t\tmatched.matches = match;\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && combinator.dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( checkNonElements || elem.nodeType === 1  ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( !xml ) {\n\t\t\t\tvar cache,\n\t\t\t\t\tdirkey = dirruns + \" \" + doneName + \" \",\n\t\t\t\t\tcachedkey = dirkey + cachedruns;\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( checkNonElements || elem.nodeType === 1 ) {\n\t\t\t\t\t\tif ( (cache = elem[ expando ]) === cachedkey ) {\n\t\t\t\t\t\t\treturn elem.sizset;\n\t\t\t\t\t\t} else if ( typeof cache === \"string\" && cache.indexOf(dirkey) === 0 ) {\n\t\t\t\t\t\t\tif ( elem.sizset ) {\n\t\t\t\t\t\t\t\treturn elem;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ expando ] = cachedkey;\n\t\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\t\telem.sizset = true;\n\t\t\t\t\t\t\t\treturn elem;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telem.sizset = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( checkNonElements || elem.nodeType === 1 ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn elem;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\t// Positional selectors apply to seed elements, so it is invalid to follow them with relative ones\n\t\tif ( seed && postFinder ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar i, elem, postFilterIn,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [], seed ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\tpostFilterIn = condense( matcherOut, postMap );\n\t\t\tpostFilter( postFilterIn, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = postFilterIn.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = postFilterIn[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Keep seed and results synchronized\n\t\tif ( seed ) {\n\t\t\t// Ignore postFinder because it can't coexist with seed\n\t\t\ti = preFilter && matcherOut.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\tseed[ preMap[i] ] = !(results[ preMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf.call( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\treturn ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];\n\t\t} else {\n\t\t\t// The concatenated values are (context, xml) for backCompat\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && tokens.slice( 0, i - 1 ).join(\"\").replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && tokens.join(\"\")\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, expandContext ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tsetMatched = [],\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\toutermost = expandContext != null,\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", expandContext && context.parentNode || context ),\n\t\t\t\t// Nested matchers should use non-integer dirruns\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t\tcachedruns = superMatcher.el;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tfor ( j = 0; (matcher = elementMatchers[j]); j++ ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t\tcachedruns = ++superMatcher.el;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tfor ( j = 0; (matcher = setMatchers[j]); j++ ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\tsuperMatcher.el = 0;\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ expando ][ selector ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !group ) {\n\t\t\tgroup = tokenize( selector );\n\t\t}\n\t\ti = group.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( group[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\t}\n\treturn cached;\n};\n\nfunction multipleContexts( selector, contexts, results, seed ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results, seed );\n\t}\n\treturn results;\n}\n\nfunction select( selector, context, results, seed, xml ) {\n\tvar i, tokens, token, type, find,\n\t\tmatch = tokenize( selector ),\n\t\tj = match.length;\n\n\tif ( !seed ) {\n\t\t// Try to minimize operations if there is only one group\n\t\tif ( match.length === 1 ) {\n\n\t\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\tcontext.nodeType === 9 && !xml &&\n\t\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\t\tcontext = Expr.find[\"ID\"]( token.matches[0].replace( rbackslash, \"\" ), context, xml )[0];\n\t\t\t\tif ( !context ) {\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\n\t\t\t\tselector = selector.slice( tokens.shift().length );\n\t\t\t}\n\n\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\tfor ( i = matchExpr[\"POS\"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {\n\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t// Abort if we hit a combinator\n\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\ttoken.matches[0].replace( rbackslash, \"\" ),\n\t\t\t\t\t\trsibling.test( tokens[0].type ) && context.parentNode || context,\n\t\t\t\t\t\txml\n\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\tselector = seed.length && tokens.join(\"\");\n\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\tpush.apply( results, slice.call( seed, 0 ) );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\tcompile( selector, match )(\n\t\tseed,\n\t\tcontext,\n\t\txml,\n\t\tresults,\n\t\trsibling.test( selector )\n\t);\n\treturn results;\n}\n\nif ( document.querySelectorAll ) {\n\t(function() {\n\t\tvar disconnectedMatch,\n\t\t\toldSelect = select,\n\t\t\trescape = /'|\\\\/g,\n\t\t\trattributeQuotes = /\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,\n\n\t\t\t// qSa(:focus) reports false when true (Chrome 21),\n\t\t\t// A support test would require too much code (would include document ready)\n\t\t\trbuggyQSA = [\":focus\"],\n\n\t\t\t// matchesSelector(:focus) reports false when true (Chrome 21),\n\t\t\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\t\t\t// A support test would require too much code (would include document ready)\n\t\t\t// just skip matchesSelector for :active\n\t\t\trbuggyMatches = [ \":active\", \":focus\" ],\n\t\t\tmatches = docElem.matchesSelector ||\n\t\t\t\tdocElem.mozMatchesSelector ||\n\t\t\t\tdocElem.webkitMatchesSelector ||\n\t\t\t\tdocElem.oMatchesSelector ||\n\t\t\t\tdocElem.msMatchesSelector;\n\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explictly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdiv.innerHTML = \"<select><option selected=''></option></select>\";\n\n\t\t\t// IE8 - Some boolean attributes are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here (do not put tests after this one)\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\n\t\t\t// Opera 10-12/IE9 - ^= $= *= and empty values\n\t\t\t// Should not select anything\n\t\t\tdiv.innerHTML = \"<p test=''></p>\";\n\t\t\tif ( div.querySelectorAll(\"[test^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\\\"\\\"|'')\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here (do not put tests after this one)\n\t\t\tdiv.innerHTML = \"<input type='hidden'/>\";\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push(\":enabled\", \":disabled\");\n\t\t\t}\n\t\t});\n\n\t\t// rbuggyQSA always contains :focus, so no need for a length check\n\t\trbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join(\"|\") );\n\n\t\tselect = function( selector, context, results, seed, xml ) {\n\t\t\t// Only use querySelectorAll when not filtering,\n\t\t\t// when this is not xml,\n\t\t\t// and when no QSA bugs apply\n\t\t\tif ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\t\tvar groups, i,\n\t\t\t\t\told = true,\n\t\t\t\t\tnid = expando,\n\t\t\t\t\tnewContext = context,\n\t\t\t\t\tnewSelector = context.nodeType === 9 && selector;\n\n\t\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t\t// IE 8 doesn't work on object elements\n\t\t\t\tif ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t}\n\t\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = nid + groups[i].join(\"\");\n\t\t\t\t\t}\n\t\t\t\t\tnewContext = rsibling.test( selector ) && context.parentNode || context;\n\t\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t\t}\n\n\t\t\t\tif ( newSelector ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpush.apply( results, slice.call( newContext.querySelectorAll(\n\t\t\t\t\t\t\tnewSelector\n\t\t\t\t\t\t), 0 ) );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t} catch(qsaError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSelect( selector, context, results, seed, xml );\n\t\t};\n\n\t\tif ( matches ) {\n\t\t\tassert(function( div ) {\n\t\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t\t// on a disconnected node (IE 9)\n\t\t\t\tdisconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t\t// This should fail with an exception\n\t\t\t\t// Gecko does not error, returns false instead\n\t\t\t\ttry {\n\t\t\t\t\tmatches.call( div, \"[test!='']:sizzle\" );\n\t\t\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t\t\t} catch ( e ) {}\n\t\t\t});\n\n\t\t\t// rbuggyMatches always contains :active and :focus, so no need for a length check\n\t\t\trbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join(\"|\") );\n\n\t\t\tSizzle.matchesSelector = function( elem, expr ) {\n\t\t\t\t// Make sure that attribute selectors are quoted\n\t\t\t\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\t\t\t\t// rbuggyMatches always contains :active, so no need for an existence check\n\t\t\t\tif ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\t\t\tif ( ret || disconnectedMatch ||\n\t\t\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch(e) {}\n\t\t\t\t}\n\n\t\t\t\treturn Sizzle( expr, null, null, [ elem ] ).length > 0;\n\t\t\t};\n\t\t}\n\t})();\n}\n\n// Deprecated\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Back-compat\nfunction setFilters() {}\nExpr.filters = setFilters.prototype = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})( window );\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prev(?:Until|All))/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\trneedsContext = jQuery.expr.match.needsContext,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i, l, length, n, r, ret,\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0, l = self.length; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tret = this.pushStack( \"\", \"find\", selector );\n\n\t\tfor ( i = 0, l = this.length; i < l; i++ ) {\n\t\t\tlength = ret.length;\n\t\t\tjQuery.find( selector, this[i], ret );\n\n\t\t\tif ( i > 0 ) {\n\t\t\t\t// Make sure that the results are unique\n\t\t\t\tfor ( n = length; n < ret.length; n++ ) {\n\t\t\t\t\tfor ( r = 0; r < length; r++ ) {\n\t\t\t\t\t\tif ( ret[r] === ret[n] ) {\n\t\t\t\t\t\t\tret.splice(n--, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false), \"not\", selector);\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true), \"filter\", selector );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\trneedsContext.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tret = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t}\n\n\t\tret = ret.length > 1 ? jQuery.unique( ret ) : ret;\n\n\t\treturn this.pushStack( ret, \"closest\", selectors );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?\n\t\t\tall :\n\t\t\tjQuery.unique( all ) );\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n// A painfully simple check to see if an element is disconnected\n// from a document (should be improved, where feasible).\nfunction isDisconnected( node ) {\n\treturn !node || !node.parentNode || node.parentNode.nodeType === 11;\n}\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( this.length > 1 && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret, name, core_slice.call( arguments ).join(\",\") );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem, i ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\trnocache = /<(?:script|object|embed|option|style)/i,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\trcheckableType = /^(?:checkbox|radio)$/,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /\\/(java|ecma)script/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|\\-\\-)|[\\]\\-]{2}>\\s*$/g,\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\t_default: [ 0, \"\", \"\" ]\n\t},\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n// unless wrapped in a div with non-breaking characters in front of it.\nif ( !jQuery.support.htmlSerialize ) {\n\twrapMap._default = [ 1, \"X<div>\", \"</div>\" ];\n}\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\tif ( !isDisconnected( this[0] ) ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t});\n\t\t}\n\n\t\tif ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\treturn this.pushStack( jQuery.merge( set, this ), \"before\", this.selector );\n\t\t}\n\t},\n\n\tafter: function() {\n\t\tif ( !isDisconnected( this[0] ) ) {\n\t\t\treturn this.domManip(arguments, false, function( elem ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t});\n\t\t}\n\n\t\tif ( arguments.length ) {\n\t\t\tvar set = jQuery.clean( arguments );\n\t\t\treturn this.pushStack( jQuery.merge( this, set ), \"after\", this.selector );\n\t\t}\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t\t\tjQuery.cleanData( [ elem ] );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( elem.getElementsByTagName(\"*\") );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( elem.getElementsByTagName( \"*\" ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tif ( !isDisconnected( this[0] ) ) {\n\t\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t\t// this can help fix replacing a parent with child elements\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each(function(i) {\n\t\t\t\t\tvar self = jQuery(this), old = self.html();\n\t\t\t\t\tself.replaceWith( value.call( this, i, old ) );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif ( typeof value !== \"string\" ) {\n\t\t\t\tvalue = jQuery( value ).detach();\n\t\t\t}\n\n\t\t\treturn this.each(function() {\n\t\t\t\tvar next = this.nextSibling,\n\t\t\t\t\tparent = this.parentNode;\n\n\t\t\t\tjQuery( this ).remove();\n\n\t\t\t\tif ( next ) {\n\t\t\t\t\tjQuery(next).before( value );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(parent).append( value );\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn this.length ?\n\t\t\tthis.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), \"replaceWith\", value ) :\n\t\t\tthis;\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = [].concat.apply( [], args );\n\n\t\tvar results, first, fragment, iNoClone,\n\t\t\ti = 0,\n\t\t\tvalue = args[0],\n\t\t\tscripts = [],\n\t\t\tl = this.length;\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( !jQuery.support.checkClone && l > 1 && typeof value === \"string\" && rchecked.test( value ) ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery(this).domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( jQuery.isFunction(value) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tvar self = jQuery(this);\n\t\t\t\targs[0] = value.call( this, i, table ? self.html() : undefined );\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\tresults = jQuery.buildFragment( args, this, scripts );\n\t\t\tfragment = results.fragment;\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\t// Fragments from the fragment cache must always be cloned and never used in place.\n\t\t\t\tfor ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable && jQuery.nodeName( this[i], \"table\" ) ?\n\t\t\t\t\t\t\tfindOrAppend( this[i], \"tbody\" ) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\ti === iNoClone ?\n\t\t\t\t\t\t\tfragment :\n\t\t\t\t\t\t\tjQuery.clone( fragment, true, true )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\tfragment = first = null;\n\n\t\t\tif ( scripts.length ) {\n\t\t\t\tjQuery.each( scripts, function( i, elem ) {\n\t\t\t\t\tif ( elem.src ) {\n\t\t\t\t\t\tif ( jQuery.ajax ) {\n\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\turl: elem.src,\n\t\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\t\tdataType: \"script\",\n\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\t\t\"throws\": true\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.error(\"no ajax\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction findOrAppend( elem, tag ) {\n\treturn elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction cloneFixAttributes( src, dest ) {\n\tvar nodeName;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// clearAttributes removes the attributes, which we don't want,\n\t// but also removes the attachEvent events, which we *do* want\n\tif ( dest.clearAttributes ) {\n\t\tdest.clearAttributes();\n\t}\n\n\t// mergeAttributes, in contrast, only merges back on the\n\t// original attributes, not the events\n\tif ( dest.mergeAttributes ) {\n\t\tdest.mergeAttributes( src );\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\tif ( nodeName === \"object\" ) {\n\t\t// IE6-10 improperly clones children of object elements using classid.\n\t\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\n\t// IE blanks contents when cloning scripts\n\t} else if ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdest.text = src.text;\n\t}\n\n\t// Event data gets referenced instead of copied if the expando\n\t// gets copied too\n\tdest.removeAttribute( jQuery.expando );\n}\n\njQuery.buildFragment = function( args, context, scripts ) {\n\tvar fragment, cacheable, cachehit,\n\t\tfirst = args[ 0 ];\n\n\t// Set context from what may come in as undefined or a jQuery collection or a node\n\t// Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &\n\t// also doubles as fix for #8950 where plain objects caused createDocumentFragment exception\n\tcontext = context || document;\n\tcontext = !context.nodeType && context[0] || context;\n\tcontext = context.ownerDocument || context;\n\n\t// Only cache \"small\" (1/2 KB) HTML strings that are associated with the main document\n\t// Cloning options loses the selected state, so don't cache them\n\t// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment\n\t// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache\n\t// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501\n\tif ( args.length === 1 && typeof first === \"string\" && first.length < 512 && context === document &&\n\t\tfirst.charAt(0) === \"<\" && !rnocache.test( first ) &&\n\t\t(jQuery.support.checkClone || !rchecked.test( first )) &&\n\t\t(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {\n\n\t\t// Mark cacheable and look for a hit\n\t\tcacheable = true;\n\t\tfragment = jQuery.fragments[ first ];\n\t\tcachehit = fragment !== undefined;\n\t}\n\n\tif ( !fragment ) {\n\t\tfragment = context.createDocumentFragment();\n\t\tjQuery.clean( args, context, fragment, scripts );\n\n\t\t// Update the cache, but only store false\n\t\t// unless this is a second parsing of the same content\n\t\tif ( cacheable ) {\n\t\t\tjQuery.fragments[ first ] = cachehit && fragment;\n\t\t}\n\t}\n\n\treturn { fragment: fragment, cacheable: cacheable };\n};\n\njQuery.fragments = {};\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tl = insert.length,\n\t\t\tparent = this.length === 1 && this[0].parentNode;\n\n\t\tif ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {\n\t\t\tinsert[ original ]( this[0] );\n\t\t\treturn this;\n\t\t} else {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\telems = ( i > 0 ? this.clone(true) : this ).get();\n\t\t\t\tjQuery( insert[i] )[ original ]( elems );\n\t\t\t\tret = ret.concat( elems );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret, name, insert.selector );\n\t\t}\n\t};\n});\n\nfunction getAll( elem ) {\n\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\treturn elem.getElementsByTagName( \"*\" );\n\n\t} else if ( typeof elem.querySelectorAll !== \"undefined\" ) {\n\t\treturn elem.querySelectorAll( \"*\" );\n\n\t} else {\n\t\treturn [];\n\t}\n}\n\n// Used in clean, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar srcElements,\n\t\t\tdestElements,\n\t\t\ti,\n\t\t\tclone;\n\n\t\tif ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\t\t\t// IE copies events bound via attachEvent when using cloneNode.\n\t\t\t// Calling detachEvent on the clone will also remove the events\n\t\t\t// from the original. In order to get around this, we use some\n\t\t\t// proprietary methods to clear the events. Thanks to MooTools\n\t\t\t// guys for this hotness.\n\n\t\t\tcloneFixAttributes( elem, clone );\n\n\t\t\t// Using Sizzle here is crazy slow, so we use getElementsByTagName instead\n\t\t\tsrcElements = getAll( elem );\n\t\t\tdestElements = getAll( clone );\n\n\t\t\t// Weird iteration because IE will replace the length property\n\t\t\t// with an element if you are cloning the body and one of the\n\t\t\t// elements on the page has a name or id of \"length\"\n\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tcloneFixAttributes( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tcloneCopyEvent( elem, clone );\n\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = getAll( elem );\n\t\t\t\tdestElements = getAll( clone );\n\n\t\t\t\tfor ( i = 0; srcElements[i]; ++i ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[i], destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tsrcElements = destElements = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tclean: function( elems, context, fragment, scripts ) {\n\t\tvar i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,\n\t\t\tsafe = context === document && safeFragment,\n\t\t\tret = [];\n\n\t\t// Ensure that context is a document\n\t\tif ( !context || typeof context.createDocumentFragment === \"undefined\" ) {\n\t\t\tcontext = document;\n\t\t}\n\n\t\t// Use the already-created safe fragment if context permits\n\t\tfor ( i = 0; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( typeof elem === \"number\" ) {\n\t\t\t\telem += \"\";\n\t\t\t}\n\n\t\t\tif ( !elem ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Convert html string into DOM nodes\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\tif ( !rhtml.test( elem ) ) {\n\t\t\t\t\telem = context.createTextNode( elem );\n\t\t\t\t} else {\n\t\t\t\t\t// Ensure a safe container in which to render the html\n\t\t\t\t\tsafe = safe || createSafeFragment( context );\n\t\t\t\t\tdiv = context.createElement(\"div\");\n\t\t\t\t\tsafe.appendChild( div );\n\n\t\t\t\t\t// Fix \"XHTML\"-style tags in all browsers\n\t\t\t\t\telem = elem.replace(rxhtmlTag, \"<$1></$2>\");\n\n\t\t\t\t\t// Go to html and back, then peel off extra wrappers\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\tdepth = wrap[0];\n\t\t\t\t\tdiv.innerHTML = wrap[1] + elem + wrap[2];\n\n\t\t\t\t\t// Move to the right depth\n\t\t\t\t\twhile ( depth-- ) {\n\t\t\t\t\t\tdiv = div.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\thasBody = rtbody.test(elem);\n\t\t\t\t\t\t\ttbody = tag === \"table\" && !hasBody ?\n\t\t\t\t\t\t\t\tdiv.firstChild && div.firstChild.childNodes :\n\n\t\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\t\twrap[1] === \"<table>\" && !hasBody ?\n\t\t\t\t\t\t\t\t\tdiv.childNodes :\n\t\t\t\t\t\t\t\t\t[];\n\n\t\t\t\t\t\tfor ( j = tbody.length - 1; j >= 0 ; --j ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( tbody[ j ], \"tbody\" ) && !tbody[ j ].childNodes.length ) {\n\t\t\t\t\t\t\t\ttbody[ j ].parentNode.removeChild( tbody[ j ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// IE completely kills leading whitespace when innerHTML is used\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tdiv.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\telem = div.childNodes;\n\n\t\t\t\t\t// Take out of fragment container (we need a fresh div each time)\n\t\t\t\t\tdiv.parentNode.removeChild( div );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( elem.nodeType ) {\n\t\t\t\tret.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( ret, elem );\n\t\t\t}\n\t\t}\n\n\t\t// Fix #11356: Clear elements from safeFragment\n\t\tif ( div ) {\n\t\t\telem = div = safe = null;\n\t\t}\n\n\t\t// Reset defaultChecked for any radios and checkboxes\n\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\tfor ( i = 0; (elem = ret[i]) != null; i++ ) {\n\t\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t\tfixDefaultChecked( elem );\n\t\t\t\t} else if ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\t\tjQuery.grep( elem.getElementsByTagName(\"input\"), fixDefaultChecked );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Append elements to a provided document fragment\n\t\tif ( fragment ) {\n\t\t\t// Special handling of each script element\n\t\t\thandleScript = function( elem ) {\n\t\t\t\t// Check if we consider it executable\n\t\t\t\tif ( !elem.type || rscriptType.test( elem.type ) ) {\n\t\t\t\t\t// Detach the script and store it in the scripts array (if provided) or the fragment\n\t\t\t\t\t// Return truthy to indicate that it has been handled\n\t\t\t\t\treturn scripts ?\n\t\t\t\t\t\tscripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :\n\t\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfor ( i = 0; (elem = ret[i]) != null; i++ ) {\n\t\t\t\t// Check if we're done after handling an executable script\n\t\t\t\tif ( !( jQuery.nodeName( elem, \"script\" ) && handleScript( elem ) ) ) {\n\t\t\t\t\t// Append to fragment and handle embedded scripts\n\t\t\t\t\tfragment.appendChild( elem );\n\t\t\t\t\tif ( typeof elem.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\t\t\t// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration\n\t\t\t\t\t\tjsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName(\"script\") ), handleScript );\n\n\t\t\t\t\t\t// Splice the scripts into ret after their former ancestor and advance our index beyond them\n\t\t\t\t\t\tret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );\n\t\t\t\t\t\ti += jsTags.length;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tcleanData: function( elems, /* internal */ acceptData ) {\n\t\tvar data, id, elem, type,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\n\t\t\tif ( acceptData || jQuery.acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t\t\t\t// we must handle all of these cases\n\t\t\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\t\t\tdelete elem[ internalKey ];\n\n\t\t\t\t\t\t} else if ( elem.removeAttribute ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tjQuery.deletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n// Limit scope pollution from any deprecated API\n(function() {\n\nvar matched, browser;\n\n// Use of jQuery.browser is frowned upon.\n// More details: http://api.jquery.com/jQuery.browser\n// jQuery.uaMatch maintained for back-compat\njQuery.uaMatch = function( ua ) {\n\tua = ua.toLowerCase();\n\n\tvar match = /(chrome)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(webkit)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(opera)(?:.*version|)[ \\/]([\\w.]+)/.exec( ua ) ||\n\t\t/(msie) ([\\w.]+)/.exec( ua ) ||\n\t\tua.indexOf(\"compatible\") < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec( ua ) ||\n\t\t[];\n\n\treturn {\n\t\tbrowser: match[ 1 ] || \"\",\n\t\tversion: match[ 2 ] || \"0\"\n\t};\n};\n\nmatched = jQuery.uaMatch( navigator.userAgent );\nbrowser = {};\n\nif ( matched.browser ) {\n\tbrowser[ matched.browser ] = true;\n\tbrowser.version = matched.version;\n}\n\n// Chrome is Webkit, but Webkit is also Safari.\nif ( browser.chrome ) {\n\tbrowser.webkit = true;\n} else if ( browser.webkit ) {\n\tbrowser.safari = true;\n}\n\njQuery.browser = browser;\n\njQuery.sub = function() {\n\tfunction jQuerySub( selector, context ) {\n\t\treturn new jQuerySub.fn.init( selector, context );\n\t}\n\tjQuery.extend( true, jQuerySub, this );\n\tjQuerySub.superclass = this;\n\tjQuerySub.fn = jQuerySub.prototype = this();\n\tjQuerySub.fn.constructor = jQuerySub;\n\tjQuerySub.sub = this.sub;\n\tjQuerySub.fn.init = function init( selector, context ) {\n\t\tif ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {\n\t\t\tcontext = jQuerySub( context );\n\t\t}\n\n\t\treturn jQuery.fn.init.call( this, selector, context, rootjQuerySub );\n\t};\n\tjQuerySub.fn.init.prototype = jQuerySub.fn;\n\tvar rootjQuerySub = jQuerySub(document);\n\treturn jQuerySub;\n};\n\n})();\nvar curCSS, iframe, iframeDoc,\n\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity=([^)]*)/,\n\trposition = /^(top|right|bottom|left)$/,\n\t// swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trmargin = /^margin/,\n\trnumsplit = new RegExp( \"^(\" + core_pnum + \")(.*)$\", \"i\" ),\n\trnumnonpx = new RegExp( \"^(\" + core_pnum + \")(?!px)[a-z%]+$\", \"i\" ),\n\trrelNum = new RegExp( \"^([-+])=(\" + core_pnum + \")\", \"i\" ),\n\telemdisplay = {},\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: 0,\n\t\tfontWeight: 400\n\t},\n\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ],\n\n\teventsToggle = jQuery.fn.toggle;\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction isHidden( elem, el ) {\n\telem = el || elem;\n\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n}\n\nfunction showHide( elements, show ) {\n\tvar elem, display,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && elem.style.display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\", css_defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\t\t\tdisplay = curCSS( elem, \"display\" );\n\n\t\t\tif ( !values[ index ] && display !== \"none\" ) {\n\t\t\t\tjQuery._data( elem, \"olddisplay\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn jQuery.access( this, function( elem, name, value ) {\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state, fn2 ) {\n\t\tvar bool = typeof state === \"boolean\";\n\n\t\tif ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {\n\t\t\treturn eventsToggle.apply( this, arguments );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( bool ? state : isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, numeric, extra ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( numeric || extra !== undefined ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn numeric || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback ) {\n\t\tvar ret, name,\n\t\t\told = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.call( elem );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// NOTE: To any future maintainer, we've window.getComputedStyle\n// because jsdom on node.js will break without it.\nif ( window.getComputedStyle ) {\n\tcurCSS = function( elem, name ) {\n\t\tvar ret, width, minWidth, maxWidth,\n\t\t\tcomputed = window.getComputedStyle( elem, null ),\n\t\t\tstyle = elem.style;\n\n\t\tif ( computed ) {\n\n\t\t\tret = computed[ name ];\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n} else if ( document.documentElement.currentStyle ) {\n\tcurCSS = function( elem, name ) {\n\t\tvar left, rsLeft,\n\t\t\tret = elem.currentStyle && elem.currentStyle[ name ],\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trsLeft = elem.runtimeStyle && elem.runtimeStyle.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\telem.runtimeStyle.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\t// we use jQuery.css instead of curCSS here\n\t\t\t// because of the reliableMarginRight CSS hook!\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true );\n\t\t}\n\n\t\t// From this point on we use curCSS for maximum performance (relevant in animations)\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= parseFloat( curCSS( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= parseFloat( curCSS( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t} else {\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += parseFloat( curCSS( elem, \"padding\" + cssExpand[ i ] ) ) || 0;\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += parseFloat( curCSS( elem, \"border\" + cssExpand[ i ] + \"Width\" ) ) || 0;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar val = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tvalueIsBorderBox = true,\n\t\tisBorderBox = jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\" ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox\n\t\t)\n\t) + \"px\";\n}\n\n\n// Try to determine the default display value of an element\nfunction css_defaultDisplay( nodeName ) {\n\tif ( elemdisplay[ nodeName ] ) {\n\t\treturn elemdisplay[ nodeName ];\n\t}\n\n\tvar elem = jQuery( \"<\" + nodeName + \">\" ).appendTo( document.body ),\n\t\tdisplay = elem.css(\"display\");\n\telem.remove();\n\n\t// If the simple way fails,\n\t// get element's real default display by attaching it to a temp iframe\n\tif ( display === \"none\" || display === \"\" ) {\n\t\t// Use the already-created iframe if possible\n\t\tiframe = document.body.appendChild(\n\t\t\tiframe || jQuery.extend( document.createElement(\"iframe\"), {\n\t\t\t\tframeBorder: 0,\n\t\t\t\twidth: 0,\n\t\t\t\theight: 0\n\t\t\t})\n\t\t);\n\n\t\t// Create a cacheable copy of the iframe document on first call.\n\t\t// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML\n\t\t// document to it; WebKit & Firefox won't allow reusing the iframe document.\n\t\tif ( !iframeDoc || !iframe.createElement ) {\n\t\t\tiframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;\n\t\t\tiframeDoc.write(\"<!doctype html><html><body>\");\n\t\t\tiframeDoc.close();\n\t\t}\n\n\t\telem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );\n\n\t\tdisplay = curCSS( elem, \"display\" );\n\t\tdocument.body.removeChild( iframe );\n\t}\n\n\t// Store the correct default display\n\telemdisplay[ nodeName ] = display;\n\n\treturn display;\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\tif ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, \"display\" ) ) ) {\n\t\t\t\t\treturn jQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\" ) === \"border-box\"\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\tif ( value >= 1 && jQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there there is no filter style applied in a css rule, we are done\n\t\t\t\tif ( currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\n// These hooks cannot be added until DOM ready because the support test\n// for it is not run until after DOM ready\njQuery(function() {\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" }, function() {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\treturn curCSS( elem, \"marginRight\" );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t}\n\n\t// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n\t// getComputedStyle returns percent when specified for top/left/bottom/right\n\t// rather than make the css module depend on the offset module, we just check for it here\n\tif ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n\t\tjQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\t\t\tjQuery.cssHooks[ prop ] = {\n\t\t\t\tget: function( elem, computed ) {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tvar ret = curCSS( elem, prop );\n\t\t\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\t\t\treturn rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + \"px\" : ret;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t}\n\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\treturn ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i,\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ],\n\t\t\t\texpanded = {};\n\n\t\t\tfor ( i = 0; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,\n\trselectTextarea = /^(?:select|textarea)/i;\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\treturn this.elements ? jQuery.makeArray( this.elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\treturn this.name && !this.disabled &&\n\t\t\t\t( this.checked || rselectTextarea.test( this.nodeName ) ||\n\t\t\t\t\trinput.test( this.type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val, i ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n//Serialize an array of form elements or a set of\n//key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// If array item is non-scalar (array or object), encode its\n\t\t\t\t// numeric index to resolve deserialization ambiguity issues.\n\t\t\t\t// Note that rack (as of 1.0.0) can't currently deserialize\n\t\t\t\t// nested arrays properly, and attempting to do so may cause\n\t\t\t\t// a server error. Possible fixes are to modify rack's\n\t\t\t\t// deserialization algorithm or to provide an option or flag\n\t\t\t\t// to force array serialization to be shallow.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\n\trhash = /#.*$/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trquery = /\\?/,\n\trscript = /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n\trts = /([?&])_=[^&]*/,\n\trurl = /^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = [\"*/\"] + [\"*\"];\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType, list, placeBefore,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),\n\t\t\ti = 0,\n\t\t\tlength = dataTypes.length;\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tdataType = dataTypes[ i ];\n\t\t\t\t// We control if we're asked to add before\n\t\t\t\t// any existing element\n\t\t\t\tplaceBefore = /^\\+/.test( dataType );\n\t\t\t\tif ( placeBefore ) {\n\t\t\t\t\tdataType = dataType.substr( 1 ) || \"*\";\n\t\t\t\t}\n\t\t\t\tlist = structure[ dataType ] = structure[ dataType ] || [];\n\t\t\t\t// then we add to the structure accordingly\n\t\t\t\tlist[ placeBefore ? \"unshift\" : \"push\" ]( func );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,\n\t\tdataType /* internal */, inspected /* internal */ ) {\n\n\tdataType = dataType || options.dataTypes[ 0 ];\n\tinspected = inspected || {};\n\n\tinspected[ dataType ] = true;\n\n\tvar selection,\n\t\tlist = structure[ dataType ],\n\t\ti = 0,\n\t\tlength = list ? list.length : 0,\n\t\texecuteOnly = ( structure === prefilters );\n\n\tfor ( ; i < length && ( executeOnly || !selection ); i++ ) {\n\t\tselection = list[ i ]( options, originalOptions, jqXHR );\n\t\t// If we got redirected to another dataType\n\t\t// we try there if executing only and not done already\n\t\tif ( typeof selection === \"string\" ) {\n\t\t\tif ( !executeOnly || inspected[ selection ] ) {\n\t\t\t\tselection = undefined;\n\t\t\t} else {\n\t\t\t\toptions.dataTypes.unshift( selection );\n\t\t\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\t\t\tstructure, options, originalOptions, jqXHR, selection, inspected );\n\t\t\t}\n\t\t}\n\t}\n\t// If we're only executing or nothing was selected\n\t// we try the catchall dataType if not done already\n\tif ( ( executeOnly || !selection ) && !inspected[ \"*\" ] ) {\n\t\tselection = inspectPrefiltersOrTransports(\n\t\t\t\tstructure, options, originalOptions, jqXHR, \"*\", inspected );\n\t}\n\t// unnecessary when only executing (prefilters)\n\t// but it'll be ignored by the caller in that case\n\treturn selection;\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n}\n\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\t// Don't do a request if no elements are being requested\n\tif ( !this.length ) {\n\t\treturn this;\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = url.slice( off, url.length );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// Request the remote document\n\tjQuery.ajax({\n\t\turl: url,\n\n\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\ttype: type,\n\t\tdataType: \"html\",\n\t\tdata: params,\n\t\tcomplete: function( jqXHR, status ) {\n\t\t\tif ( callback ) {\n\t\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t}\n\t\t}\n\t}).done(function( responseText ) {\n\n\t\t// Save response for use in complete callback\n\t\tresponse = arguments;\n\n\t\t// See if a selector was specified\n\t\tself.html( selector ?\n\n\t\t\t// Create a dummy div to hold the results\n\t\t\tjQuery(\"<div>\")\n\n\t\t\t\t// inject the contents of the document in, removing the scripts\n\t\t\t\t// to avoid any 'Permission Denied' errors in IE\n\t\t\t\t.append( responseText.replace( rscript, \"\" ) )\n\n\t\t\t\t// Locate the specified elements\n\t\t\t\t.find( selector ) :\n\n\t\t\t// If not, just inject the full result\n\t\t\tresponseText );\n\n\t});\n\n\treturn this;\n};\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( \"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split( \" \" ), function( i, o ){\n\tjQuery.fn[ o ] = function( f ){\n\t\treturn this.on( o, f );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\ttype: method,\n\t\t\turl: url,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\tdataType: type\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\tif ( settings ) {\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( target, jQuery.ajaxSettings );\n\t\t} else {\n\t\t\t// Extending ajaxSettings\n\t\t\tsettings = target;\n\t\t\ttarget = jQuery.ajaxSettings;\n\t\t}\n\t\tajaxExtend( target, settings );\n\t\treturn target;\n\t},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\ttype: \"GET\",\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\tprocessData: true,\n\t\tasync: true,\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\thtml: \"text/html\",\n\t\t\ttext: \"text/plain\",\n\t\t\tjson: \"application/json, text/javascript\",\n\t\t\t\"*\": allTypes\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// List of data converters\n\t\t// 1) key format is \"source_type destination_type\" (a single space in-between)\n\t\t// 2) the catchall symbol \"*\" can be used for source_type\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\tcontext: true,\n\t\t\turl: true\n\t\t}\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // ifModified key\n\t\t\tifModifiedKey,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// transport\n\t\t\ttransport,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events\n\t\t\t// It's the callbackContext if one was provided in the options\n\t\t\t// and if it's a DOM node or a jQuery collection\n\t\t\tglobalEventContext = callbackContext !== s &&\n\t\t\t\t( callbackContext.nodeType || callbackContext instanceof jQuery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) : jQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match === undefined ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tstatusText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( statusText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, statusText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Callback for when everything is done\n\t\t// It is defined here because jslint complains if it is declared\n\t\t// at the end of the function (which would be more logical and readable)\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ ifModifiedKey ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ ifModifiedKey ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If not modified\n\t\t\t\tif ( status === 304 ) {\n\n\t\t\t\t\tstatusText = \"notmodified\";\n\t\t\t\t\tisSuccess = true;\n\n\t\t\t\t// If we have data\n\t\t\t\t} else {\n\n\t\t\t\t\tisSuccess = ajaxConvert( s, response );\n\t\t\t\t\tstatusText = isSuccess.state;\n\t\t\t\t\tsuccess = isSuccess.data;\n\t\t\t\t\terror = isSuccess.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( !statusText || status ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajax\" + ( isSuccess ? \"Success\" : \"Error\" ),\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\t\tjqXHR.complete = completeDeferred.add;\n\n\t\t// Status-dependent callbacks\n\t\tjqXHR.statusCode = function( map ) {\n\t\t\tif ( map ) {\n\t\t\t\tvar tmp;\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tfor ( tmp in map ) {\n\t\t\t\t\t\tstatusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttmp = map[ jqXHR.status ];\n\t\t\t\t\tjqXHR.always( tmp );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this;\n\t\t};\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().split( core_rspace );\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() ) || false;\n\t\t\ts.crossDomain = parts && ( parts.join(\":\") + ( parts[ 3 ] ? \"\" : parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !==\n\t\t\t\t( ajaxLocParts.join(\":\") + ( ajaxLocParts[ 3 ] ? \"\" : ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) );\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.data;\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Get ifModifiedKey before adding the anti-cache parameter\n\t\t\tifModifiedKey = s.url;\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\n\t\t\t\tvar ts = jQuery.now(),\n\t\t\t\t\t// try replacing _= if it is there\n\t\t\t\t\tret = s.url.replace( rts, \"$1_=\" + ts );\n\n\t\t\t\t// if nothing was replaced, add timestamp to the end\n\t\t\t\ts.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? \"&\" : \"?\" ) + \"_=\" + ts : \"\" );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tifModifiedKey = ifModifiedKey || s.url;\n\t\t\tif ( jQuery.lastModified[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ ifModifiedKey ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ ifModifiedKey ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ ifModifiedKey ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t\t// Abort if not done already and return\n\t\t\t\treturn jqXHR.abort();\n\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout( function(){\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch (e) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {}\n\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"content-type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\n\tvar conv, conv2, current, tmp,\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice(),\n\t\tprev = dataTypes[ 0 ],\n\t\tconverters = {},\n\t\ti = 0;\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\t// Convert to each sequential dataType, tolerating list modification\n\tfor ( ; (current = dataTypes[++i]); ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\tif ( current !== \"*\" ) {\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\tif ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split(\" \");\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.splice( i--, 0, current );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[\"throws\"] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update prev for next iteration\n\t\t\tprev = current;\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\nvar oldCallbacks = [],\n\trquestion = /\\?/,\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/,\n\tnonce = jQuery.now();\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tdata = s.data,\n\t\turl = s.url,\n\t\thasCallback = s.jsonp !== false,\n\t\treplaceInUrl = hasCallback && rjsonp.test( url ),\n\t\treplaceInData = hasCallback && !replaceInUrl && typeof data === \"string\" &&\n\t\t\t!( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") &&\n\t\t\trjsonp.test( data );\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( s.dataTypes[ 0 ] === \"jsonp\" || replaceInUrl || replaceInData ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\t\toverwritten = window[ callbackName ];\n\n\t\t// Insert callback into url or form data\n\t\tif ( replaceInUrl ) {\n\t\t\ts.url = url.replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( replaceInData ) {\n\t\t\ts.data = data.replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( hasCallback ) {\n\t\t\ts.url += ( rquestion.test( url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /javascript|ecmascript/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || document.getElementsByTagName( \"head\" )[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = \"async\";\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( head && script.parentNode ) {\n\t\t\t\t\t\t\thead.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = undefined;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t// Use insertBefore instead of appendChild  to circumvent an IE6 bug.\n\t\t\t\t// This arises when a base node is used (#2709 and #4378).\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( 0, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\nvar xhrCallbacks,\n\t// #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject ? function() {\n\t\t// Abort all pending requests\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( 0, 1 );\n\t\t}\n\t} : false,\n\txhrId = 0;\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\n(function( xhr ) {\n\tjQuery.extend( jQuery.support, {\n\t\tajax: !!xhr,\n\t\tcors: !!xhr && ( \"withCredentials\" in xhr )\n\t});\n})( jQuery.ajaxSettings.xhr() );\n\n// Create transport if the browser can provide an xhr\nif ( jQuery.support.ajax ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar handle, i,\n\t\t\t\t\t\txhr = s.xhr();\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( _ ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\n\t\t\t\t\t\tvar status,\n\t\t\t\t\t\t\tstatusText,\n\t\t\t\t\t\t\tresponseHeaders,\n\t\t\t\t\t\t\tresponses,\n\t\t\t\t\t\t\txml;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occurred\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\txml = xhr.responseXML;\n\n\t\t\t\t\t\t\t\t\t// Construct response list\n\t\t\t\t\t\t\t\t\tif ( xml && xml.documentElement /* #4958 */ ) {\n\t\t\t\t\t\t\t\t\t\tresponses.xml = xml;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t} catch( _ ) {\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !s.async ) {\n\t\t\t\t\t\t// if we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\tsetTimeout( callback, 0 );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback(0,1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\nvar fxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([-+])=|)(\" + core_pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [function( prop, value ) {\n\t\t\tvar end, unit,\n\t\t\t\ttween = this.createTween( prop, value ),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tstart = +target || 0,\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( parts ) {\n\t\t\t\tend = +parts[2];\n\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\n\t\t\t\t// We need to compute starting value\n\t\t\t\tif ( unit !== \"px\" && start ) {\n\t\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\t\t// Prefer the current property, because this process will be trivial if it uses the same units\n\t\t\t\t\t// Fallback to end or a simple constant\n\t\t\t\t\tstart = jQuery.css( tween.elem, prop, true ) || end || 1;\n\n\t\t\t\t\tdo {\n\t\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n\t\t\t\t\t\t// Use a string for doubling factor so we don't accidentally see scale as unchanged below\n\t\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t\t// Adjust and apply\n\t\t\t\t\t\tstart = start / scale;\n\t\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t\t}\n\n\t\t\t\ttween.unit = unit;\n\t\t\t\ttween.start = start;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;\n\t\t\t}\n\t\t\treturn tween;\n\t\t}]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t}, 0 );\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction createTweens( animation, props ) {\n\tjQuery.each( props, function( prop, value ) {\n\t\tvar collection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\t\tindex = 0,\n\t\t\tlength = collection.length;\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tif ( collection[ index ].call( animation, prop, value ) ) {\n\n\t\t\t\t// we're done with this property\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tindex = 0,\n\t\ttweenerIndex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\tpercent = 1 - ( remaining / animation.duration || 0 ),\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end, easing ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tcreateTweens( animation, props );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue,\n\t\t\telem: elem\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\nfunction defaultPrefilter( elem, props, opts ) {\n\tvar index, prop, value, length, dataShow, tween, hooks, oldfire,\n\t\tanim = this,\n\t\tstyle = elem.style,\n\t\torig = {},\n\t\thandled = [],\n\t\thidden = elem.nodeType && isHidden( elem );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tif ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n\t\t\t\tjQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !jQuery.support.shrinkWrapBlocks ) {\n\t\t\tanim.done(function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t});\n\t\t}\n\t}\n\n\n\t// show/hide pass\n\tfor ( index in props ) {\n\t\tvalue = props[ index ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ index ];\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thandled.push( index );\n\t\t}\n\t}\n\n\tlength = handled.length;\n\tif ( length ) {\n\t\tdataShow = jQuery._data( elem, \"fxshow\" ) || jQuery._data( elem, \"fxshow\", {} );\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\t\t\tjQuery.removeData( elem, \"fxshow\", true );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( index = 0 ; index < length ; index++ ) {\n\t\t\tprop = handled[ index ];\n\t\t\ttween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );\n\t\t\torig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing any value as a 4th parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, false, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Remove in 2.0 - this supports IE8's panic based approach\n// to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ||\n\t\t\t// special check for .toggle( handler, handler, ... )\n\t\t\t( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations resolve immediately\n\t\t\t\tif ( empty ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t}\n});\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth? 1 : 0;\n\tfor( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p*Math.PI ) / 2;\n\t}\n};\n\njQuery.timers = [];\njQuery.fx = Tween.prototype.init;\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n};\n\njQuery.fx.timer = function( timer ) {\n\tif ( timer() && jQuery.timers.push( timer ) && !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\nvar rroot = /^(?:body|html)$/i;\n\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft,\n\t\tbox = { top: 0, left: 0 },\n\t\telem = this[ 0 ],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn;\n\t}\n\n\tif ( (body = doc.body) === elem ) {\n\t\treturn jQuery.offset.bodyOffset( elem );\n\t}\n\n\tdocElem = doc.documentElement;\n\n\t// Make sure it's not a disconnected DOM node\n\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\treturn box;\n\t}\n\n\t// If we don't have gBCR, just use 0,0 rather than error\n\t// BlackBerry 5, iOS 3 (original iPhone)\n\tif ( typeof elem.getBoundingClientRect !== \"undefined\" ) {\n\t\tbox = elem.getBoundingClientRect();\n\t}\n\twin = getWindow( doc );\n\tclientTop  = docElem.clientTop  || body.clientTop  || 0;\n\tclientLeft = docElem.clientLeft || body.clientLeft || 0;\n\tscrollTop  = win.pageYOffset || docElem.scrollTop;\n\tscrollLeft = win.pageXOffset || docElem.scrollLeft;\n\treturn {\n\t\ttop: box.top  + scrollTop  - clientTop,\n\t\tleft: box.left + scrollLeft - clientLeft\n\t};\n};\n\njQuery.offset = {\n\n\tbodyOffset: function( body ) {\n\t\tvar top = body.offsetTop,\n\t\t\tleft = body.offsetLeft;\n\n\t\tif ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {\n\t\t\ttop  += parseFloat( jQuery.css(body, \"marginTop\") ) || 0;\n\t\t\tleft += parseFloat( jQuery.css(body, \"marginLeft\") ) || 0;\n\t\t}\n\n\t\treturn { top: top, left: left };\n\t},\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[0] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar elem = this[0],\n\n\t\t// Get *real* offsetParent\n\t\toffsetParent = this.offsetParent(),\n\n\t\t// Get correct offsets\n\t\toffset       = this.offset(),\n\t\tparentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();\n\n\t\t// Subtract element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\toffset.top  -= parseFloat( jQuery.css(elem, \"marginTop\") ) || 0;\n\t\toffset.left -= parseFloat( jQuery.css(elem, \"marginLeft\") ) || 0;\n\n\t\t// Add offsetParent borders\n\t\tparentOffset.top  += parseFloat( jQuery.css(offsetParent[0], \"borderTopWidth\") ) || 0;\n\t\tparentOffset.left += parseFloat( jQuery.css(offsetParent[0], \"borderLeftWidth\") ) || 0;\n\n\t\t// Subtract the two offsets\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top,\n\t\t\tleft: offset.left - parentOffset.left\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.body;\n\t\t\twhile ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, \"position\") === \"static\") ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || document.body;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\t top ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, value, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n})( window );"
  },
  {
    "path": "30-jstraining/demos/backbone-demo/js/main.js",
    "content": "(function() {\n\nwindow.App = {\n\tModels: {},\n\tCollections: {},\n\tViews: {},\n\tRouter: {}\n};\n\nApp.Router = Backbone.Router.extend({\n\troutes: {\n\t\t'': 'index',\n\t\t'show/:id': 'show',\n\t\t'download/*random': 'download',\n\t\t'search/:query': 'search',\n\t\t'*other': 'default'\n\t},\n\n\tindex: function() {\n\t\t$(document.body).append(\"调用了 Index 路由<br>\");\n\t},\n\n\tshow: function(id) {\n\t\t$(document.body).append(\"调用了 Show 路由，id 等于 \" + id + \"<br>\");\n\t},\n\n\tdownload: function(random) {\n\t\t$(document.body).append(\"调用了 Download 路由，参数等于 \" + random + \"<br>\");\n\t},\n\n\tsearch: function(query) {\n\t\t$(document.body).append(\"调用了 Search 路由，参数等于 \" + query + \"<br>\");\n\t},\n\n\tdefault: function(other) {\n\t\t$(document.body).append(\"你访问的 \" + other + \" 路由未定义<br>\");\n\t\t\n\t}\n\n});\n\nnew App.Router();\nBackbone.history.start();\n\n})();\n"
  },
  {
    "path": "30-jstraining/demos/backbone-demo/js/underscore.js",
    "content": "//     Underscore.js 1.4.2\n//     http://underscorejs.org\n//     (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.\n//     Underscore may be freely distributed under the MIT license.\n\n(function() {\n\n  // Baseline setup\n  // --------------\n\n  // Establish the root object, `window` in the browser, or `global` on the server.\n  var root = this;\n\n  // Save the previous value of the `_` variable.\n  var previousUnderscore = root._;\n\n  // Establish the object that gets returned to break out of a loop iteration.\n  var breaker = {};\n\n  // Save bytes in the minified (but not gzipped) version:\n  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n  // Create quick reference variables for speed access to core prototypes.\n  var push             = ArrayProto.push,\n      slice            = ArrayProto.slice,\n      concat           = ArrayProto.concat,\n      unshift          = ArrayProto.unshift,\n      toString         = ObjProto.toString,\n      hasOwnProperty   = ObjProto.hasOwnProperty;\n\n  // All **ECMAScript 5** native function implementations that we hope to use\n  // are declared here.\n  var\n    nativeForEach      = ArrayProto.forEach,\n    nativeMap          = ArrayProto.map,\n    nativeReduce       = ArrayProto.reduce,\n    nativeReduceRight  = ArrayProto.reduceRight,\n    nativeFilter       = ArrayProto.filter,\n    nativeEvery        = ArrayProto.every,\n    nativeSome         = ArrayProto.some,\n    nativeIndexOf      = ArrayProto.indexOf,\n    nativeLastIndexOf  = ArrayProto.lastIndexOf,\n    nativeIsArray      = Array.isArray,\n    nativeKeys         = Object.keys,\n    nativeBind         = FuncProto.bind;\n\n  // Create a safe reference to the Underscore object for use below.\n  var _ = function(obj) {\n    if (obj instanceof _) return obj;\n    if (!(this instanceof _)) return new _(obj);\n    this._wrapped = obj;\n  };\n\n  // Export the Underscore object for **Node.js**, with\n  // backwards-compatibility for the old `require()` API. If we're in\n  // the browser, add `_` as a global object via a string identifier,\n  // for Closure Compiler \"advanced\" mode.\n  if (typeof exports !== 'undefined') {\n    if (typeof module !== 'undefined' && module.exports) {\n      exports = module.exports = _;\n    }\n    exports._ = _;\n  } else {\n    root['_'] = _;\n  }\n\n  // Current version.\n  _.VERSION = '1.4.2';\n\n  // Collection Functions\n  // --------------------\n\n  // The cornerstone, an `each` implementation, aka `forEach`.\n  // Handles objects with the built-in `forEach`, arrays, and raw objects.\n  // Delegates to **ECMAScript 5**'s native `forEach` if available.\n  var each = _.each = _.forEach = function(obj, iterator, context) {\n    if (obj == null) return;\n    if (nativeForEach && obj.forEach === nativeForEach) {\n      obj.forEach(iterator, context);\n    } else if (obj.length === +obj.length) {\n      for (var i = 0, l = obj.length; i < l; i++) {\n        if (iterator.call(context, obj[i], i, obj) === breaker) return;\n      }\n    } else {\n      for (var key in obj) {\n        if (_.has(obj, key)) {\n          if (iterator.call(context, obj[key], key, obj) === breaker) return;\n        }\n      }\n    }\n  };\n\n  // Return the results of applying the iterator to each element.\n  // Delegates to **ECMAScript 5**'s native `map` if available.\n  _.map = _.collect = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);\n    each(obj, function(value, index, list) {\n      results[results.length] = iterator.call(context, value, index, list);\n    });\n    return results;\n  };\n\n  // **Reduce** builds up a single result from a list of values, aka `inject`,\n  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.\n  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduce && obj.reduce === nativeReduce) {\n      if (context) iterator = _.bind(iterator, context);\n      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);\n    }\n    each(obj, function(value, index, list) {\n      if (!initial) {\n        memo = value;\n        initial = true;\n      } else {\n        memo = iterator.call(context, memo, value, index, list);\n      }\n    });\n    if (!initial) throw new TypeError('Reduce of empty array with no initial value');\n    return memo;\n  };\n\n  // The right-associative version of reduce, also known as `foldr`.\n  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.\n  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {\n    var initial = arguments.length > 2;\n    if (obj == null) obj = [];\n    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {\n      if (context) iterator = _.bind(iterator, context);\n      return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);\n    }\n    var length = obj.length;\n    if (length !== +length) {\n      var keys = _.keys(obj);\n      length = keys.length;\n    }\n    each(obj, function(value, index, list) {\n      index = keys ? keys[--length] : --length;\n      if (!initial) {\n        memo = obj[index];\n        initial = true;\n      } else {\n        memo = iterator.call(context, memo, obj[index], index, list);\n      }\n    });\n    if (!initial) throw new TypeError('Reduce of empty array with no initial value');\n    return memo;\n  };\n\n  // Return the first value which passes a truth test. Aliased as `detect`.\n  _.find = _.detect = function(obj, iterator, context) {\n    var result;\n    any(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) {\n        result = value;\n        return true;\n      }\n    });\n    return result;\n  };\n\n  // Return all the elements that pass a truth test.\n  // Delegates to **ECMAScript 5**'s native `filter` if available.\n  // Aliased as `select`.\n  _.filter = _.select = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);\n    each(obj, function(value, index, list) {\n      if (iterator.call(context, value, index, list)) results[results.length] = value;\n    });\n    return results;\n  };\n\n  // Return all the elements for which a truth test fails.\n  _.reject = function(obj, iterator, context) {\n    var results = [];\n    if (obj == null) return results;\n    each(obj, function(value, index, list) {\n      if (!iterator.call(context, value, index, list)) results[results.length] = value;\n    });\n    return results;\n  };\n\n  // Determine whether all of the elements match a truth test.\n  // Delegates to **ECMAScript 5**'s native `every` if available.\n  // Aliased as `all`.\n  _.every = _.all = function(obj, iterator, context) {\n    iterator || (iterator = _.identity);\n    var result = true;\n    if (obj == null) return result;\n    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);\n    each(obj, function(value, index, list) {\n      if (!(result = result && iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if at least one element in the object matches a truth test.\n  // Delegates to **ECMAScript 5**'s native `some` if available.\n  // Aliased as `any`.\n  var any = _.some = _.any = function(obj, iterator, context) {\n    iterator || (iterator = _.identity);\n    var result = false;\n    if (obj == null) return result;\n    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);\n    each(obj, function(value, index, list) {\n      if (result || (result = iterator.call(context, value, index, list))) return breaker;\n    });\n    return !!result;\n  };\n\n  // Determine if the array or object contains a given value (using `===`).\n  // Aliased as `include`.\n  _.contains = _.include = function(obj, target) {\n    var found = false;\n    if (obj == null) return found;\n    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;\n    found = any(obj, function(value) {\n      return value === target;\n    });\n    return found;\n  };\n\n  // Invoke a method (with arguments) on every item in a collection.\n  _.invoke = function(obj, method) {\n    var args = slice.call(arguments, 2);\n    return _.map(obj, function(value) {\n      return (_.isFunction(method) ? method : value[method]).apply(value, args);\n    });\n  };\n\n  // Convenience version of a common use case of `map`: fetching a property.\n  _.pluck = function(obj, key) {\n    return _.map(obj, function(value){ return value[key]; });\n  };\n\n  // Convenience version of a common use case of `filter`: selecting only objects\n  // with specific `key:value` pairs.\n  _.where = function(obj, attrs) {\n    if (_.isEmpty(attrs)) return [];\n    return _.filter(obj, function(value) {\n      for (var key in attrs) {\n        if (attrs[key] !== value[key]) return false;\n      }\n      return true;\n    });\n  };\n\n  // Return the maximum element or (element-based computation).\n  // Can't optimize arrays of integers longer than 65,535 elements.\n  // See: https://bugs.webkit.org/show_bug.cgi?id=80797\n  _.max = function(obj, iterator, context) {\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n      return Math.max.apply(Math, obj);\n    }\n    if (!iterator && _.isEmpty(obj)) return -Infinity;\n    var result = {computed : -Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed >= result.computed && (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Return the minimum element (or element-based computation).\n  _.min = function(obj, iterator, context) {\n    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n      return Math.min.apply(Math, obj);\n    }\n    if (!iterator && _.isEmpty(obj)) return Infinity;\n    var result = {computed : Infinity};\n    each(obj, function(value, index, list) {\n      var computed = iterator ? iterator.call(context, value, index, list) : value;\n      computed < result.computed && (result = {value : value, computed : computed});\n    });\n    return result.value;\n  };\n\n  // Shuffle an array.\n  _.shuffle = function(obj) {\n    var rand;\n    var index = 0;\n    var shuffled = [];\n    each(obj, function(value) {\n      rand = _.random(index++);\n      shuffled[index - 1] = shuffled[rand];\n      shuffled[rand] = value;\n    });\n    return shuffled;\n  };\n\n  // An internal function to generate lookup iterators.\n  var lookupIterator = function(value) {\n    return _.isFunction(value) ? value : function(obj){ return obj[value]; };\n  };\n\n  // Sort the object's values by a criterion produced by an iterator.\n  _.sortBy = function(obj, value, context) {\n    var iterator = lookupIterator(value);\n    return _.pluck(_.map(obj, function(value, index, list) {\n      return {\n        value : value,\n        index : index,\n        criteria : iterator.call(context, value, index, list)\n      };\n    }).sort(function(left, right) {\n      var a = left.criteria;\n      var b = right.criteria;\n      if (a !== b) {\n        if (a > b || a === void 0) return 1;\n        if (a < b || b === void 0) return -1;\n      }\n      return left.index < right.index ? -1 : 1;\n    }), 'value');\n  };\n\n  // An internal function used for aggregate \"group by\" operations.\n  var group = function(obj, value, context, behavior) {\n    var result = {};\n    var iterator = lookupIterator(value);\n    each(obj, function(value, index) {\n      var key = iterator.call(context, value, index, obj);\n      behavior(result, key, value);\n    });\n    return result;\n  };\n\n  // Groups the object's values by a criterion. Pass either a string attribute\n  // to group by, or a function that returns the criterion.\n  _.groupBy = function(obj, value, context) {\n    return group(obj, value, context, function(result, key, value) {\n      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);\n    });\n  };\n\n  // Counts instances of an object that group by a certain criterion. Pass\n  // either a string attribute to count by, or a function that returns the\n  // criterion.\n  _.countBy = function(obj, value, context) {\n    return group(obj, value, context, function(result, key, value) {\n      if (!_.has(result, key)) result[key] = 0;\n      result[key]++;\n    });\n  };\n\n  // Use a comparator function to figure out the smallest index at which\n  // an object should be inserted so as to maintain order. Uses binary search.\n  _.sortedIndex = function(array, obj, iterator, context) {\n    iterator = iterator == null ? _.identity : lookupIterator(iterator);\n    var value = iterator.call(context, obj);\n    var low = 0, high = array.length;\n    while (low < high) {\n      var mid = (low + high) >>> 1;\n      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;\n    }\n    return low;\n  };\n\n  // Safely convert anything iterable into a real, live array.\n  _.toArray = function(obj) {\n    if (!obj) return [];\n    if (obj.length === +obj.length) return slice.call(obj);\n    return _.values(obj);\n  };\n\n  // Return the number of elements in an object.\n  _.size = function(obj) {\n    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;\n  };\n\n  // Array Functions\n  // ---------------\n\n  // Get the first element of an array. Passing **n** will return the first N\n  // values in the array. Aliased as `head` and `take`. The **guard** check\n  // allows it to work with `_.map`.\n  _.first = _.head = _.take = function(array, n, guard) {\n    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];\n  };\n\n  // Returns everything but the last entry of the array. Especially useful on\n  // the arguments object. Passing **n** will return all the values in\n  // the array, excluding the last N. The **guard** check allows it to work with\n  // `_.map`.\n  _.initial = function(array, n, guard) {\n    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));\n  };\n\n  // Get the last element of an array. Passing **n** will return the last N\n  // values in the array. The **guard** check allows it to work with `_.map`.\n  _.last = function(array, n, guard) {\n    if ((n != null) && !guard) {\n      return slice.call(array, Math.max(array.length - n, 0));\n    } else {\n      return array[array.length - 1];\n    }\n  };\n\n  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\n  // Especially useful on the arguments object. Passing an **n** will return\n  // the rest N values in the array. The **guard**\n  // check allows it to work with `_.map`.\n  _.rest = _.tail = _.drop = function(array, n, guard) {\n    return slice.call(array, (n == null) || guard ? 1 : n);\n  };\n\n  // Trim out all falsy values from an array.\n  _.compact = function(array) {\n    return _.filter(array, function(value){ return !!value; });\n  };\n\n  // Internal implementation of a recursive `flatten` function.\n  var flatten = function(input, shallow, output) {\n    each(input, function(value) {\n      if (_.isArray(value)) {\n        shallow ? push.apply(output, value) : flatten(value, shallow, output);\n      } else {\n        output.push(value);\n      }\n    });\n    return output;\n  };\n\n  // Return a completely flattened version of an array.\n  _.flatten = function(array, shallow) {\n    return flatten(array, shallow, []);\n  };\n\n  // Return a version of the array that does not contain the specified value(s).\n  _.without = function(array) {\n    return _.difference(array, slice.call(arguments, 1));\n  };\n\n  // Produce a duplicate-free version of the array. If the array has already\n  // been sorted, you have the option of using a faster algorithm.\n  // Aliased as `unique`.\n  _.uniq = _.unique = function(array, isSorted, iterator, context) {\n    var initial = iterator ? _.map(array, iterator, context) : array;\n    var results = [];\n    var seen = [];\n    each(initial, function(value, index) {\n      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {\n        seen.push(value);\n        results.push(array[index]);\n      }\n    });\n    return results;\n  };\n\n  // Produce an array that contains the union: each distinct element from all of\n  // the passed-in arrays.\n  _.union = function() {\n    return _.uniq(concat.apply(ArrayProto, arguments));\n  };\n\n  // Produce an array that contains every item shared between all the\n  // passed-in arrays.\n  _.intersection = function(array) {\n    var rest = slice.call(arguments, 1);\n    return _.filter(_.uniq(array), function(item) {\n      return _.every(rest, function(other) {\n        return _.indexOf(other, item) >= 0;\n      });\n    });\n  };\n\n  // Take the difference between one array and a number of other arrays.\n  // Only the elements present in just the first array will remain.\n  _.difference = function(array) {\n    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));\n    return _.filter(array, function(value){ return !_.contains(rest, value); });\n  };\n\n  // Zip together multiple lists into a single array -- elements that share\n  // an index go together.\n  _.zip = function() {\n    var args = slice.call(arguments);\n    var length = _.max(_.pluck(args, 'length'));\n    var results = new Array(length);\n    for (var i = 0; i < length; i++) {\n      results[i] = _.pluck(args, \"\" + i);\n    }\n    return results;\n  };\n\n  // Converts lists into objects. Pass either a single array of `[key, value]`\n  // pairs, or two parallel arrays of the same length -- one of keys, and one of\n  // the corresponding values.\n  _.object = function(list, values) {\n    var result = {};\n    for (var i = 0, l = list.length; i < l; i++) {\n      if (values) {\n        result[list[i]] = values[i];\n      } else {\n        result[list[i][0]] = list[i][1];\n      }\n    }\n    return result;\n  };\n\n  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),\n  // we need this function. Return the position of the first occurrence of an\n  // item in an array, or -1 if the item is not included in the array.\n  // Delegates to **ECMAScript 5**'s native `indexOf` if available.\n  // If the array is large and already in sort order, pass `true`\n  // for **isSorted** to use binary search.\n  _.indexOf = function(array, item, isSorted) {\n    if (array == null) return -1;\n    var i = 0, l = array.length;\n    if (isSorted) {\n      if (typeof isSorted == 'number') {\n        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);\n      } else {\n        i = _.sortedIndex(array, item);\n        return array[i] === item ? i : -1;\n      }\n    }\n    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);\n    for (; i < l; i++) if (array[i] === item) return i;\n    return -1;\n  };\n\n  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.\n  _.lastIndexOf = function(array, item, from) {\n    if (array == null) return -1;\n    var hasIndex = from != null;\n    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {\n      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);\n    }\n    var i = (hasIndex ? from : array.length);\n    while (i--) if (array[i] === item) return i;\n    return -1;\n  };\n\n  // Generate an integer Array containing an arithmetic progression. A port of\n  // the native Python `range()` function. See\n  // [the Python documentation](http://docs.python.org/library/functions.html#range).\n  _.range = function(start, stop, step) {\n    if (arguments.length <= 1) {\n      stop = start || 0;\n      start = 0;\n    }\n    step = arguments[2] || 1;\n\n    var len = Math.max(Math.ceil((stop - start) / step), 0);\n    var idx = 0;\n    var range = new Array(len);\n\n    while(idx < len) {\n      range[idx++] = start;\n      start += step;\n    }\n\n    return range;\n  };\n\n  // Function (ahem) Functions\n  // ------------------\n\n  // Reusable constructor function for prototype setting.\n  var ctor = function(){};\n\n  // Create a function bound to a given object (assigning `this`, and arguments,\n  // optionally). Binding with arguments is also known as `curry`.\n  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.\n  // We check for `func.bind` first, to fail fast when `func` is undefined.\n  _.bind = function bind(func, context) {\n    var bound, args;\n    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n    if (!_.isFunction(func)) throw new TypeError;\n    args = slice.call(arguments, 2);\n    return bound = function() {\n      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));\n      ctor.prototype = func.prototype;\n      var self = new ctor;\n      var result = func.apply(self, args.concat(slice.call(arguments)));\n      if (Object(result) === result) return result;\n      return self;\n    };\n  };\n\n  // Bind all of an object's methods to that object. Useful for ensuring that\n  // all callbacks defined on an object belong to it.\n  _.bindAll = function(obj) {\n    var funcs = slice.call(arguments, 1);\n    if (funcs.length == 0) funcs = _.functions(obj);\n    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });\n    return obj;\n  };\n\n  // Memoize an expensive function by storing its results.\n  _.memoize = function(func, hasher) {\n    var memo = {};\n    hasher || (hasher = _.identity);\n    return function() {\n      var key = hasher.apply(this, arguments);\n      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));\n    };\n  };\n\n  // Delays a function for the given number of milliseconds, and then calls\n  // it with the arguments supplied.\n  _.delay = function(func, wait) {\n    var args = slice.call(arguments, 2);\n    return setTimeout(function(){ return func.apply(null, args); }, wait);\n  };\n\n  // Defers a function, scheduling it to run after the current call stack has\n  // cleared.\n  _.defer = function(func) {\n    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));\n  };\n\n  // Returns a function, that, when invoked, will only be triggered at most once\n  // during a given window of time.\n  _.throttle = function(func, wait) {\n    var context, args, timeout, throttling, more, result;\n    var whenDone = _.debounce(function(){ more = throttling = false; }, wait);\n    return function() {\n      context = this; args = arguments;\n      var later = function() {\n        timeout = null;\n        if (more) {\n          result = func.apply(context, args);\n        }\n        whenDone();\n      };\n      if (!timeout) timeout = setTimeout(later, wait);\n      if (throttling) {\n        more = true;\n      } else {\n        throttling = true;\n        result = func.apply(context, args);\n      }\n      whenDone();\n      return result;\n    };\n  };\n\n  // Returns a function, that, as long as it continues to be invoked, will not\n  // be triggered. The function will be called after it stops being called for\n  // N milliseconds. If `immediate` is passed, trigger the function on the\n  // leading edge, instead of the trailing.\n  _.debounce = function(func, wait, immediate) {\n    var timeout, result;\n    return function() {\n      var context = this, args = arguments;\n      var later = function() {\n        timeout = null;\n        if (!immediate) result = func.apply(context, args);\n      };\n      var callNow = immediate && !timeout;\n      clearTimeout(timeout);\n      timeout = setTimeout(later, wait);\n      if (callNow) result = func.apply(context, args);\n      return result;\n    };\n  };\n\n  // Returns a function that will be executed at most one time, no matter how\n  // often you call it. Useful for lazy initialization.\n  _.once = function(func) {\n    var ran = false, memo;\n    return function() {\n      if (ran) return memo;\n      ran = true;\n      memo = func.apply(this, arguments);\n      func = null;\n      return memo;\n    };\n  };\n\n  // Returns the first function passed as an argument to the second,\n  // allowing you to adjust arguments, run code before and after, and\n  // conditionally execute the original function.\n  _.wrap = function(func, wrapper) {\n    return function() {\n      var args = [func];\n      push.apply(args, arguments);\n      return wrapper.apply(this, args);\n    };\n  };\n\n  // Returns a function that is the composition of a list of functions, each\n  // consuming the return value of the function that follows.\n  _.compose = function() {\n    var funcs = arguments;\n    return function() {\n      var args = arguments;\n      for (var i = funcs.length - 1; i >= 0; i--) {\n        args = [funcs[i].apply(this, args)];\n      }\n      return args[0];\n    };\n  };\n\n  // Returns a function that will only be executed after being called N times.\n  _.after = function(times, func) {\n    if (times <= 0) return func();\n    return function() {\n      if (--times < 1) {\n        return func.apply(this, arguments);\n      }\n    };\n  };\n\n  // Object Functions\n  // ----------------\n\n  // Retrieve the names of an object's properties.\n  // Delegates to **ECMAScript 5**'s native `Object.keys`\n  _.keys = nativeKeys || function(obj) {\n    if (obj !== Object(obj)) throw new TypeError('Invalid object');\n    var keys = [];\n    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;\n    return keys;\n  };\n\n  // Retrieve the values of an object's properties.\n  _.values = function(obj) {\n    var values = [];\n    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);\n    return values;\n  };\n\n  // Convert an object into a list of `[key, value]` pairs.\n  _.pairs = function(obj) {\n    var pairs = [];\n    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);\n    return pairs;\n  };\n\n  // Invert the keys and values of an object. The values must be serializable.\n  _.invert = function(obj) {\n    var result = {};\n    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;\n    return result;\n  };\n\n  // Return a sorted list of the function names available on the object.\n  // Aliased as `methods`\n  _.functions = _.methods = function(obj) {\n    var names = [];\n    for (var key in obj) {\n      if (_.isFunction(obj[key])) names.push(key);\n    }\n    return names.sort();\n  };\n\n  // Extend a given object with all the properties in passed-in object(s).\n  _.extend = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      for (var prop in source) {\n        obj[prop] = source[prop];\n      }\n    });\n    return obj;\n  };\n\n  // Return a copy of the object only containing the whitelisted properties.\n  _.pick = function(obj) {\n    var copy = {};\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n    each(keys, function(key) {\n      if (key in obj) copy[key] = obj[key];\n    });\n    return copy;\n  };\n\n   // Return a copy of the object without the blacklisted properties.\n  _.omit = function(obj) {\n    var copy = {};\n    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n    for (var key in obj) {\n      if (!_.contains(keys, key)) copy[key] = obj[key];\n    }\n    return copy;\n  };\n\n  // Fill in a given object with default properties.\n  _.defaults = function(obj) {\n    each(slice.call(arguments, 1), function(source) {\n      for (var prop in source) {\n        if (obj[prop] == null) obj[prop] = source[prop];\n      }\n    });\n    return obj;\n  };\n\n  // Create a (shallow-cloned) duplicate of an object.\n  _.clone = function(obj) {\n    if (!_.isObject(obj)) return obj;\n    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n  };\n\n  // Invokes interceptor with the obj, and then returns obj.\n  // The primary purpose of this method is to \"tap into\" a method chain, in\n  // order to perform operations on intermediate results within the chain.\n  _.tap = function(obj, interceptor) {\n    interceptor(obj);\n    return obj;\n  };\n\n  // Internal recursive comparison function for `isEqual`.\n  var eq = function(a, b, aStack, bStack) {\n    // Identical objects are equal. `0 === -0`, but they aren't identical.\n    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.\n    if (a === b) return a !== 0 || 1 / a == 1 / b;\n    // A strict comparison is necessary because `null == undefined`.\n    if (a == null || b == null) return a === b;\n    // Unwrap any wrapped objects.\n    if (a instanceof _) a = a._wrapped;\n    if (b instanceof _) b = b._wrapped;\n    // Compare `[[Class]]` names.\n    var className = toString.call(a);\n    if (className != toString.call(b)) return false;\n    switch (className) {\n      // Strings, numbers, dates, and booleans are compared by value.\n      case '[object String]':\n        // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n        // equivalent to `new String(\"5\")`.\n        return a == String(b);\n      case '[object Number]':\n        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for\n        // other numeric values.\n        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);\n      case '[object Date]':\n      case '[object Boolean]':\n        // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n        // millisecond representations. Note that invalid dates with millisecond representations\n        // of `NaN` are not equivalent.\n        return +a == +b;\n      // RegExps are compared by their source patterns and flags.\n      case '[object RegExp]':\n        return a.source == b.source &&\n               a.global == b.global &&\n               a.multiline == b.multiline &&\n               a.ignoreCase == b.ignoreCase;\n    }\n    if (typeof a != 'object' || typeof b != 'object') return false;\n    // Assume equality for cyclic structures. The algorithm for detecting cyclic\n    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n    var length = aStack.length;\n    while (length--) {\n      // Linear search. Performance is inversely proportional to the number of\n      // unique nested structures.\n      if (aStack[length] == a) return bStack[length] == b;\n    }\n    // Add the first object to the stack of traversed objects.\n    aStack.push(a);\n    bStack.push(b);\n    var size = 0, result = true;\n    // Recursively compare objects and arrays.\n    if (className == '[object Array]') {\n      // Compare array lengths to determine if a deep comparison is necessary.\n      size = a.length;\n      result = size == b.length;\n      if (result) {\n        // Deep compare the contents, ignoring non-numeric properties.\n        while (size--) {\n          if (!(result = eq(a[size], b[size], aStack, bStack))) break;\n        }\n      }\n    } else {\n      // Objects with different constructors are not equivalent, but `Object`s\n      // from different frames are.\n      var aCtor = a.constructor, bCtor = b.constructor;\n      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&\n                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {\n        return false;\n      }\n      // Deep compare objects.\n      for (var key in a) {\n        if (_.has(a, key)) {\n          // Count the expected number of properties.\n          size++;\n          // Deep compare each member.\n          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;\n        }\n      }\n      // Ensure that both objects contain the same number of properties.\n      if (result) {\n        for (key in b) {\n          if (_.has(b, key) && !(size--)) break;\n        }\n        result = !size;\n      }\n    }\n    // Remove the first object from the stack of traversed objects.\n    aStack.pop();\n    bStack.pop();\n    return result;\n  };\n\n  // Perform a deep comparison to check if two objects are equal.\n  _.isEqual = function(a, b) {\n    return eq(a, b, [], []);\n  };\n\n  // Is a given array, string, or object empty?\n  // An \"empty\" object has no enumerable own-properties.\n  _.isEmpty = function(obj) {\n    if (obj == null) return true;\n    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;\n    for (var key in obj) if (_.has(obj, key)) return false;\n    return true;\n  };\n\n  // Is a given value a DOM element?\n  _.isElement = function(obj) {\n    return !!(obj && obj.nodeType === 1);\n  };\n\n  // Is a given value an array?\n  // Delegates to ECMA5's native Array.isArray\n  _.isArray = nativeIsArray || function(obj) {\n    return toString.call(obj) == '[object Array]';\n  };\n\n  // Is a given variable an object?\n  _.isObject = function(obj) {\n    return obj === Object(obj);\n  };\n\n  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.\n  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {\n    _['is' + name] = function(obj) {\n      return toString.call(obj) == '[object ' + name + ']';\n    };\n  });\n\n  // Define a fallback version of the method in browsers (ahem, IE), where\n  // there isn't any inspectable \"Arguments\" type.\n  if (!_.isArguments(arguments)) {\n    _.isArguments = function(obj) {\n      return !!(obj && _.has(obj, 'callee'));\n    };\n  }\n\n  // Optimize `isFunction` if appropriate.\n  if (typeof (/./) !== 'function') {\n    _.isFunction = function(obj) {\n      return typeof obj === 'function';\n    };\n  }\n\n  // Is a given object a finite number?\n  _.isFinite = function(obj) {\n    return _.isNumber(obj) && isFinite(obj);\n  };\n\n  // Is the given value `NaN`? (NaN is the only number which does not equal itself).\n  _.isNaN = function(obj) {\n    return _.isNumber(obj) && obj != +obj;\n  };\n\n  // Is a given value a boolean?\n  _.isBoolean = function(obj) {\n    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';\n  };\n\n  // Is a given value equal to null?\n  _.isNull = function(obj) {\n    return obj === null;\n  };\n\n  // Is a given variable undefined?\n  _.isUndefined = function(obj) {\n    return obj === void 0;\n  };\n\n  // Shortcut function for checking if an object has a given property directly\n  // on itself (in other words, not on a prototype).\n  _.has = function(obj, key) {\n    return hasOwnProperty.call(obj, key);\n  };\n\n  // Utility Functions\n  // -----------------\n\n  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n  // previous owner. Returns a reference to the Underscore object.\n  _.noConflict = function() {\n    root._ = previousUnderscore;\n    return this;\n  };\n\n  // Keep the identity function around for default iterators.\n  _.identity = function(value) {\n    return value;\n  };\n\n  // Run a function **n** times.\n  _.times = function(n, iterator, context) {\n    for (var i = 0; i < n; i++) iterator.call(context, i);\n  };\n\n  // Return a random integer between min and max (inclusive).\n  _.random = function(min, max) {\n    if (max == null) {\n      max = min;\n      min = 0;\n    }\n    return min + (0 | Math.random() * (max - min + 1));\n  };\n\n  // List of HTML entities for escaping.\n  var entityMap = {\n    escape: {\n      '&': '&amp;',\n      '<': '&lt;',\n      '>': '&gt;',\n      '\"': '&quot;',\n      \"'\": '&#x27;',\n      '/': '&#x2F;'\n    }\n  };\n  entityMap.unescape = _.invert(entityMap.escape);\n\n  // Regexes containing the keys and values listed immediately above.\n  var entityRegexes = {\n    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),\n    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')\n  };\n\n  // Functions for escaping and unescaping strings to/from HTML interpolation.\n  _.each(['escape', 'unescape'], function(method) {\n    _[method] = function(string) {\n      if (string == null) return '';\n      return ('' + string).replace(entityRegexes[method], function(match) {\n        return entityMap[method][match];\n      });\n    };\n  });\n\n  // If the value of the named property is a function then invoke it;\n  // otherwise, return it.\n  _.result = function(object, property) {\n    if (object == null) return null;\n    var value = object[property];\n    return _.isFunction(value) ? value.call(object) : value;\n  };\n\n  // Add your own custom functions to the Underscore object.\n  _.mixin = function(obj) {\n    each(_.functions(obj), function(name){\n      var func = _[name] = obj[name];\n      _.prototype[name] = function() {\n        var args = [this._wrapped];\n        push.apply(args, arguments);\n        return result.call(this, func.apply(_, args));\n      };\n    });\n  };\n\n  // Generate a unique integer id (unique within the entire client session).\n  // Useful for temporary DOM ids.\n  var idCounter = 0;\n  _.uniqueId = function(prefix) {\n    var id = idCounter++;\n    return prefix ? prefix + id : id;\n  };\n\n  // By default, Underscore uses ERB-style template delimiters, change the\n  // following template settings to use alternative delimiters.\n  _.templateSettings = {\n    evaluate    : /<%([\\s\\S]+?)%>/g,\n    interpolate : /<%=([\\s\\S]+?)%>/g,\n    escape      : /<%-([\\s\\S]+?)%>/g\n  };\n\n  // When customizing `templateSettings`, if you don't want to define an\n  // interpolation, evaluation or escaping regex, we need one that is\n  // guaranteed not to match.\n  var noMatch = /(.)^/;\n\n  // Certain characters need to be escaped so that they can be put into a\n  // string literal.\n  var escapes = {\n    \"'\":      \"'\",\n    '\\\\':     '\\\\',\n    '\\r':     'r',\n    '\\n':     'n',\n    '\\t':     't',\n    '\\u2028': 'u2028',\n    '\\u2029': 'u2029'\n  };\n\n  var escaper = /\\\\|'|\\r|\\n|\\t|\\u2028|\\u2029/g;\n\n  // JavaScript micro-templating, similar to John Resig's implementation.\n  // Underscore templating handles arbitrary delimiters, preserves whitespace,\n  // and correctly escapes quotes within interpolated code.\n  _.template = function(text, data, settings) {\n    settings = _.defaults({}, settings, _.templateSettings);\n\n    // Combine delimiters into one regular expression via alternation.\n    var matcher = new RegExp([\n      (settings.escape || noMatch).source,\n      (settings.interpolate || noMatch).source,\n      (settings.evaluate || noMatch).source\n    ].join('|') + '|$', 'g');\n\n    // Compile the template source, escaping string literals appropriately.\n    var index = 0;\n    var source = \"__p+='\";\n    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\n      source += text.slice(index, offset)\n        .replace(escaper, function(match) { return '\\\\' + escapes[match]; });\n      source +=\n        escape ? \"'+\\n((__t=(\" + escape + \"))==null?'':_.escape(__t))+\\n'\" :\n        interpolate ? \"'+\\n((__t=(\" + interpolate + \"))==null?'':__t)+\\n'\" :\n        evaluate ? \"';\\n\" + evaluate + \"\\n__p+='\" : '';\n      index = offset + match.length;\n    });\n    source += \"';\\n\";\n\n    // If a variable is not specified, place data values in local scope.\n    if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n    source = \"var __t,__p='',__j=Array.prototype.join,\" +\n      \"print=function(){__p+=__j.call(arguments,'');};\\n\" +\n      source + \"return __p;\\n\";\n\n    try {\n      var render = new Function(settings.variable || 'obj', '_', source);\n    } catch (e) {\n      e.source = source;\n      throw e;\n    }\n\n    if (data) return render(data, _);\n    var template = function(data) {\n      return render.call(this, data, _);\n    };\n\n    // Provide the compiled function source as a convenience for precompilation.\n    template.source = 'function(' + (settings.variable || 'obj') + '){\\n' + source + '}';\n\n    return template;\n  };\n\n  // Add a \"chain\" function, which will delegate to the wrapper.\n  _.chain = function(obj) {\n    return _(obj).chain();\n  };\n\n  // OOP\n  // ---------------\n  // If Underscore is called as a function, it returns a wrapped object that\n  // can be used OO-style. This wrapper holds altered versions of all the\n  // underscore functions. Wrapped objects may be chained.\n\n  // Helper function to continue chaining intermediate results.\n  var result = function(obj) {\n    return this._chain ? _(obj).chain() : obj;\n  };\n\n  // Add all of the Underscore functions to the wrapper object.\n  _.mixin(_);\n\n  // Add all mutator Array functions to the wrapper.\n  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      var obj = this._wrapped;\n      method.apply(obj, arguments);\n      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];\n      return result.call(this, obj);\n    };\n  });\n\n  // Add all accessor Array functions to the wrapper.\n  each(['concat', 'join', 'slice'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      return result.call(this, method.apply(this._wrapped, arguments));\n    };\n  });\n\n  _.extend(_.prototype, {\n\n    // Start chaining a wrapped Underscore object.\n    chain: function() {\n      this._chain = true;\n      return this;\n    },\n\n    // Extracts the result from a wrapped and chained object.\n    value: function() {\n      return this._wrapped;\n    }\n\n  });\n\n}).call(this);\n"
  },
  {
    "path": "30-jstraining/demos/eslint-demo/index.js",
    "content": "var x = 1;\nconsole.log('x is', x);\n"
  },
  {
    "path": "30-jstraining/demos/eslint-demo/package.json",
    "content": "{\n  \"name\": \"eslint-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "30-jstraining/demos/express-demo/app1.js",
    "content": "var express    = require('express');\nvar app        = express();\n\nvar port = process.env.PORT || 8080;\nvar router = express.Router();\n\nrouter.get('/', function(req, res) {\n  res.send('<h1>Hello World</h1>');\n});\n\napp.use('/home', router);\n\napp.listen(port);\nconsole.log('Magic happens on port ' + port);\n"
  },
  {
    "path": "30-jstraining/demos/express-demo/app2.js",
    "content": "var express    = require('express');\nvar app        = express();\n\nvar port = process.env.PORT || 8080;\nvar router = express.Router();\n\nrouter.get('/', function(req, res) {\n  res.send('<h1>Hello World</h1>');\n});\n\nrouter.get('/:name', function(req, res) {\n  res.send('<h1>Hello ' + req.params.name + '</h1>');\n});\n\napp.use('/home', router);\n\napp.listen(port);\nconsole.log('Magic happens on port ' + port);\n"
  },
  {
    "path": "30-jstraining/demos/express-demo/app3.js",
    "content": "var express    = require('express');\nvar app        = express();\nvar bodyParser = require('body-parser');\n\napp.use(bodyParser.urlencoded({ extended: true }));\n\nvar port = process.env.PORT || 8080;\nvar router = express.Router();\n\nrouter.get('/', function(req, res) {\n  res.send('<h1>Hello World</h1>');\n});\n\nrouter.get('/:name', function(req, res) {\n  res.send('<h1>Hello ' + req.params.name + '</h1>');\n});\n\nrouter.post('/', function (req, res) {\n  var name = req.body.name;\n  res.json({message: 'Hello ' + name});\n});\n\napp.use('/home', router);\n\napp.listen(port);\nconsole.log('Magic happens on port ' + port);\n"
  },
  {
    "path": "30-jstraining/demos/express-demo/app4.js",
    "content": "var express    = require('express');\nvar app        = express();\nvar bodyParser = require('body-parser');\n\napp.use(bodyParser.urlencoded({ extended: true }));\n\nvar port = process.env.PORT || 8080;\nvar router = express.Router();\n\nrouter.use(function(req, res, next) {\n  console.log('Thers is a requesting.');\n  next();\n});\n\nrouter.get('/', function(req, res) {\n  res.send('<h1>Hello World</h1>');\n});\n\nrouter.get('/:name', function(req, res) {\n  res.send('<h1>Hello ' + req.params.name + '</h1>');\n});\n\nrouter.post('/', function (req, res) {\n  var name = req.body.name;\n  res.json({message: 'Hello ' + name});\n});\n\napp.use('/home', router);\n\napp.listen(port);\nconsole.log('Magic happens on port ' + port);\n"
  },
  {
    "path": "30-jstraining/demos/express-demo/package.json",
    "content": "{\n    \"name\": \"node-api\",\n    \"main\": \"server.js\",\n    \"dependencies\": {\n        \"express\": \"~4.0.0\",\n        \"body-parser\": \"~1.0.1\"\n    }\n}\n"
  },
  {
    "path": "30-jstraining/demos/jsx-demo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\"></div>\n    <script type=\"text/babel\">\nReactDOM.render(\n  <span>Hello World!</span>,\n  document.getElementById('example')\n);\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/jsx-demo/react-dom.js",
    "content": "/**\n * ReactDOM v15.2.1\n *\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js\n;(function(f) {\n  // CommonJS\n  if (typeof exports === \"object\" && typeof module !== \"undefined\") {\n    module.exports = f(require('react'));\n\n  // RequireJS\n  } else if (typeof define === \"function\" && define.amd) {\n    define(['react'], f);\n\n  // <script>\n  } else {\n    var g;\n    if (typeof window !== \"undefined\") {\n      g = window;\n    } else if (typeof global !== \"undefined\") {\n      g = global;\n    } else if (typeof self !== \"undefined\") {\n      g = self;\n    } else {\n      // works providing we're not in \"use strict\";\n      // needed for Java 8 Nashorn\n      // see https://github.com/facebook/react/issues/3037\n      g = this;\n    }\n    g.ReactDOM = f(g.React);\n  }\n\n})(function(React) {\n  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n});\n"
  },
  {
    "path": "30-jstraining/demos/jsx-demo/react.js",
    "content": " /**\n  * React v15.2.1\n  */\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule AutoFocusUtils\n */\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar focusNode = _dereq_(155);\n\nvar AutoFocusUtils = {\n  focusDOMComponent: function () {\n    focusNode(ReactDOMComponentTree.getNodeFromInstance(this));\n  }\n};\n\nmodule.exports = AutoFocusUtils;\n},{\"155\":155,\"41\":41}],2:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule BeforeInputEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar FallbackCompositionState = _dereq_(21);\nvar SyntheticCompositionEvent = _dereq_(102);\nvar SyntheticInputEvent = _dereq_(106);\n\nvar keyOf = _dereq_(165);\n\nvar END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space\nvar START_KEYCODE = 229;\n\nvar canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;\n\nvar documentMode = null;\nif (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {\n  documentMode = document.documentMode;\n}\n\n// Webkit offers a very useful `textInput` event that can be used to\n// directly represent `beforeInput`. The IE `textinput` event is not as\n// useful, so we don't use it.\nvar canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();\n\n// In IE9+, we have access to composition events, but the data supplied\n// by the native compositionend event may be incorrect. Japanese ideographic\n// spaces, for instance (\\u3000) are not recorded correctly.\nvar useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);\n\n/**\n * Opera <= 12 includes TextEvent in window, but does not fire\n * text input events. Rely on keypress instead.\n */\nfunction isPresto() {\n  var opera = window.opera;\n  return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;\n}\n\nvar SPACEBAR_CODE = 32;\nvar SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\n// Events and their corresponding property names.\nvar eventTypes = {\n  beforeInput: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBeforeInput: null }),\n      captured: keyOf({ onBeforeInputCapture: null })\n    },\n    dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste]\n  },\n  compositionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionEnd: null }),\n      captured: keyOf({ onCompositionEndCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionStart: null }),\n      captured: keyOf({ onCompositionStartCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionUpdate: null }),\n      captured: keyOf({ onCompositionUpdateCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  }\n};\n\n// Track whether we've ever handled a keypress on the space key.\nvar hasSpaceKeypress = false;\n\n/**\n * Return whether a native keypress event is assumed to be a command.\n * This is required because Firefox fires `keypress` events for key commands\n * (cut, copy, select-all, etc.) even though no character is inserted.\n */\nfunction isKeypressCommand(nativeEvent) {\n  return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&\n  // ctrlKey && altKey is equivalent to AltGr, and is not a command.\n  !(nativeEvent.ctrlKey && nativeEvent.altKey);\n}\n\n/**\n * Translate native top level events into event types.\n *\n * @param {string} topLevelType\n * @return {object}\n */\nfunction getCompositionEventType(topLevelType) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionStart:\n      return eventTypes.compositionStart;\n    case topLevelTypes.topCompositionEnd:\n      return eventTypes.compositionEnd;\n    case topLevelTypes.topCompositionUpdate:\n      return eventTypes.compositionUpdate;\n  }\n}\n\n/**\n * Does our fallback best-guess model think this event signifies that\n * composition has begun?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionStart(topLevelType, nativeEvent) {\n  return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE;\n}\n\n/**\n * Does our fallback mode think that this event is the end of composition?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionEnd(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topKeyUp:\n      // Command keys insert or clear IME input.\n      return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;\n    case topLevelTypes.topKeyDown:\n      // Expect IME keyCode on each keydown. If we get any other\n      // code we must have exited earlier.\n      return nativeEvent.keyCode !== START_KEYCODE;\n    case topLevelTypes.topKeyPress:\n    case topLevelTypes.topMouseDown:\n    case topLevelTypes.topBlur:\n      // Events are not possible without cancelling IME.\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Google Input Tools provides composition data via a CustomEvent,\n * with the `data` property populated in the `detail` object. If this\n * is available on the event object, use it. If not, this is a plain\n * composition event and we have nothing special to extract.\n *\n * @param {object} nativeEvent\n * @return {?string}\n */\nfunction getDataFromCustomEvent(nativeEvent) {\n  var detail = nativeEvent.detail;\n  if (typeof detail === 'object' && 'data' in detail) {\n    return detail.data;\n  }\n  return null;\n}\n\n// Track the current IME composition fallback object, if any.\nvar currentComposition = null;\n\n/**\n * @return {?object} A SyntheticCompositionEvent.\n */\nfunction extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var eventType;\n  var fallbackData;\n\n  if (canUseCompositionEvent) {\n    eventType = getCompositionEventType(topLevelType);\n  } else if (!currentComposition) {\n    if (isFallbackCompositionStart(topLevelType, nativeEvent)) {\n      eventType = eventTypes.compositionStart;\n    }\n  } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n    eventType = eventTypes.compositionEnd;\n  }\n\n  if (!eventType) {\n    return null;\n  }\n\n  if (useFallbackCompositionData) {\n    // The current composition is stored statically and must not be\n    // overwritten while composition continues.\n    if (!currentComposition && eventType === eventTypes.compositionStart) {\n      currentComposition = FallbackCompositionState.getPooled(nativeEventTarget);\n    } else if (eventType === eventTypes.compositionEnd) {\n      if (currentComposition) {\n        fallbackData = currentComposition.getData();\n      }\n    }\n  }\n\n  var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);\n\n  if (fallbackData) {\n    // Inject data generated from fallback path into the synthetic event.\n    // This matches the property of native CompositionEventInterface.\n    event.data = fallbackData;\n  } else {\n    var customData = getDataFromCustomEvent(nativeEvent);\n    if (customData !== null) {\n      event.data = customData;\n    }\n  }\n\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The string corresponding to this `beforeInput` event.\n */\nfunction getNativeBeforeInputChars(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionEnd:\n      return getDataFromCustomEvent(nativeEvent);\n    case topLevelTypes.topKeyPress:\n      /**\n       * If native `textInput` events are available, our goal is to make\n       * use of them. However, there is a special case: the spacebar key.\n       * In Webkit, preventing default on a spacebar `textInput` event\n       * cancels character insertion, but it *also* causes the browser\n       * to fall back to its default spacebar behavior of scrolling the\n       * page.\n       *\n       * Tracking at:\n       * https://code.google.com/p/chromium/issues/detail?id=355103\n       *\n       * To avoid this issue, use the keypress event as if no `textInput`\n       * event is available.\n       */\n      var which = nativeEvent.which;\n      if (which !== SPACEBAR_CODE) {\n        return null;\n      }\n\n      hasSpaceKeypress = true;\n      return SPACEBAR_CHAR;\n\n    case topLevelTypes.topTextInput:\n      // Record the characters to be added to the DOM.\n      var chars = nativeEvent.data;\n\n      // If it's a spacebar character, assume that we have already handled\n      // it at the keypress level and bail immediately. Android Chrome\n      // doesn't give us keycodes, so we need to blacklist it.\n      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {\n        return null;\n      }\n\n      return chars;\n\n    default:\n      // For other native event types, do nothing.\n      return null;\n  }\n}\n\n/**\n * For browsers that do not provide the `textInput` event, extract the\n * appropriate string to use for SyntheticInputEvent.\n *\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The fallback string for this `beforeInput` event.\n */\nfunction getFallbackBeforeInputChars(topLevelType, nativeEvent) {\n  // If we are currently composing (IME) and using a fallback to do so,\n  // try to extract the composed characters from the fallback object.\n  if (currentComposition) {\n    if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n      var chars = currentComposition.getData();\n      FallbackCompositionState.release(currentComposition);\n      currentComposition = null;\n      return chars;\n    }\n    return null;\n  }\n\n  switch (topLevelType) {\n    case topLevelTypes.topPaste:\n      // If a paste event occurs after a keypress, throw out the input\n      // chars. Paste events should not lead to BeforeInput events.\n      return null;\n    case topLevelTypes.topKeyPress:\n      /**\n       * As of v27, Firefox may fire keypress events even when no character\n       * will be inserted. A few possibilities:\n       *\n       * - `which` is `0`. Arrow keys, Esc key, etc.\n       *\n       * - `which` is the pressed key code, but no char is available.\n       *   Ex: 'AltGr + d` in Polish. There is no modified character for\n       *   this key combination and no character is inserted into the\n       *   document, but FF fires the keypress for char code `100` anyway.\n       *   No `input` event will occur.\n       *\n       * - `which` is the pressed key code, but a command combination is\n       *   being used. Ex: `Cmd+C`. No character is inserted, and no\n       *   `input` event will occur.\n       */\n      if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {\n        return String.fromCharCode(nativeEvent.which);\n      }\n      return null;\n    case topLevelTypes.topCompositionEnd:\n      return useFallbackCompositionData ? null : nativeEvent.data;\n    default:\n      return null;\n  }\n}\n\n/**\n * Extract a SyntheticInputEvent for `beforeInput`, based on either native\n * `textInput` or fallback behavior.\n *\n * @return {?object} A SyntheticInputEvent.\n */\nfunction extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var chars;\n\n  if (canUseTextInputEvent) {\n    chars = getNativeBeforeInputChars(topLevelType, nativeEvent);\n  } else {\n    chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);\n  }\n\n  // If no characters are being inserted, no BeforeInput event should\n  // be fired.\n  if (!chars) {\n    return null;\n  }\n\n  var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);\n\n  event.data = chars;\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * Create an `onBeforeInput` event to match\n * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.\n *\n * This event plugin is based on the native `textInput` event\n * available in Chrome, Safari, Opera, and IE. This event fires after\n * `onKeyPress` and `onCompositionEnd`, but before `onInput`.\n *\n * `beforeInput` is spec'd but not implemented in any browsers, and\n * the `input` event does not provide any useful information about what has\n * actually been added, contrary to the spec. Thus, `textInput` is the best\n * available event to identify the characters that have actually been inserted\n * into the target node.\n *\n * This plugin is also responsible for emitting `composition` events, thus\n * allowing us to share composition fallback code for both `beforeInput` and\n * `composition` event types.\n */\nvar BeforeInputEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];\n  }\n};\n\nmodule.exports = BeforeInputEventPlugin;\n},{\"102\":102,\"106\":106,\"147\":147,\"16\":16,\"165\":165,\"20\":20,\"21\":21}],3:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSProperty\n */\n\n'use strict';\n\n/**\n * CSS properties which accept numbers but are not in units of \"px\".\n */\n\nvar isUnitlessNumber = {\n  animationIterationCount: true,\n  borderImageOutset: true,\n  borderImageSlice: true,\n  borderImageWidth: true,\n  boxFlex: true,\n  boxFlexGroup: true,\n  boxOrdinalGroup: true,\n  columnCount: true,\n  flex: true,\n  flexGrow: true,\n  flexPositive: true,\n  flexShrink: true,\n  flexNegative: true,\n  flexOrder: true,\n  gridRow: true,\n  gridColumn: true,\n  fontWeight: true,\n  lineClamp: true,\n  lineHeight: true,\n  opacity: true,\n  order: true,\n  orphans: true,\n  tabSize: true,\n  widows: true,\n  zIndex: true,\n  zoom: true,\n\n  // SVG-related properties\n  fillOpacity: true,\n  floodOpacity: true,\n  stopOpacity: true,\n  strokeDasharray: true,\n  strokeDashoffset: true,\n  strokeMiterlimit: true,\n  strokeOpacity: true,\n  strokeWidth: true\n};\n\n/**\n * @param {string} prefix vendor-specific prefix, eg: Webkit\n * @param {string} key style name, eg: transitionDuration\n * @return {string} style name prefixed with `prefix`, properly camelCased, eg:\n * WebkitTransitionDuration\n */\nfunction prefixKey(prefix, key) {\n  return prefix + key.charAt(0).toUpperCase() + key.substring(1);\n}\n\n/**\n * Support style names that may come passed in prefixed by adding permutations\n * of vendor prefixes.\n */\nvar prefixes = ['Webkit', 'ms', 'Moz', 'O'];\n\n// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an\n// infinite loop, because it iterates over the newly added props too.\nObject.keys(isUnitlessNumber).forEach(function (prop) {\n  prefixes.forEach(function (prefix) {\n    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];\n  });\n});\n\n/**\n * Most style properties can be unset by doing .style[prop] = '' but IE8\n * doesn't like doing that with shorthand properties so for the properties that\n * IE8 breaks on, which are listed here, we instead unset each of the\n * individual properties. See http://bugs.jquery.com/ticket/12385.\n * The 4-value 'clock' properties like margin, padding, border-width seem to\n * behave without any problems. Curiously, list-style works too without any\n * special prodding.\n */\nvar shorthandPropertyExpansions = {\n  background: {\n    backgroundAttachment: true,\n    backgroundColor: true,\n    backgroundImage: true,\n    backgroundPositionX: true,\n    backgroundPositionY: true,\n    backgroundRepeat: true\n  },\n  backgroundPosition: {\n    backgroundPositionX: true,\n    backgroundPositionY: true\n  },\n  border: {\n    borderWidth: true,\n    borderStyle: true,\n    borderColor: true\n  },\n  borderBottom: {\n    borderBottomWidth: true,\n    borderBottomStyle: true,\n    borderBottomColor: true\n  },\n  borderLeft: {\n    borderLeftWidth: true,\n    borderLeftStyle: true,\n    borderLeftColor: true\n  },\n  borderRight: {\n    borderRightWidth: true,\n    borderRightStyle: true,\n    borderRightColor: true\n  },\n  borderTop: {\n    borderTopWidth: true,\n    borderTopStyle: true,\n    borderTopColor: true\n  },\n  font: {\n    fontStyle: true,\n    fontVariant: true,\n    fontWeight: true,\n    fontSize: true,\n    lineHeight: true,\n    fontFamily: true\n  },\n  outline: {\n    outlineWidth: true,\n    outlineStyle: true,\n    outlineColor: true\n  }\n};\n\nvar CSSProperty = {\n  isUnitlessNumber: isUnitlessNumber,\n  shorthandPropertyExpansions: shorthandPropertyExpansions\n};\n\nmodule.exports = CSSProperty;\n},{}],4:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSPropertyOperations\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactInstrumentation = _dereq_(74);\n\nvar camelizeStyleName = _dereq_(149);\nvar dangerousStyleValue = _dereq_(120);\nvar hyphenateStyleName = _dereq_(160);\nvar memoizeStringOnly = _dereq_(167);\nvar warning = _dereq_(171);\n\nvar processStyleName = memoizeStringOnly(function (styleName) {\n  return hyphenateStyleName(styleName);\n});\n\nvar hasShorthandPropertyBug = false;\nvar styleFloatAccessor = 'cssFloat';\nif (ExecutionEnvironment.canUseDOM) {\n  var tempStyle = document.createElement('div').style;\n  try {\n    // IE8 throws \"Invalid argument.\" if resetting shorthand style properties.\n    tempStyle.font = '';\n  } catch (e) {\n    hasShorthandPropertyBug = true;\n  }\n  // IE8 only supports accessing cssFloat (standard) as styleFloat\n  if (document.documentElement.style.cssFloat === undefined) {\n    styleFloatAccessor = 'styleFloat';\n  }\n}\n\nif (\"development\" !== 'production') {\n  // 'msTransform' is correct, but the other prefixes should be capitalized\n  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;\n\n  // style values shouldn't contain a semicolon\n  var badStyleValueWithSemicolonPattern = /;\\s*$/;\n\n  var warnedStyleNames = {};\n  var warnedStyleValues = {};\n  var warnedForNaNValue = false;\n\n  var warnHyphenatedStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnBadVendoredStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnStyleValueWithSemicolon = function (name, value, owner) {\n    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {\n      return;\n    }\n\n    warnedStyleValues[value] = true;\n    \"development\" !== 'production' ? warning(false, 'Style property values shouldn\\'t contain a semicolon.%s ' + 'Try \"%s: %s\" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;\n  };\n\n  var warnStyleValueIsNaN = function (name, value, owner) {\n    if (warnedForNaNValue) {\n      return;\n    }\n\n    warnedForNaNValue = true;\n    \"development\" !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0;\n  };\n\n  var checkRenderMessage = function (owner) {\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' Check the render method of `' + name + '`.';\n      }\n    }\n    return '';\n  };\n\n  /**\n   * @param {string} name\n   * @param {*} value\n   * @param {ReactDOMComponent} component\n   */\n  var warnValidStyle = function (name, value, component) {\n    var owner;\n    if (component) {\n      owner = component._currentElement._owner;\n    }\n    if (name.indexOf('-') > -1) {\n      warnHyphenatedStyleName(name, owner);\n    } else if (badVendoredStyleNamePattern.test(name)) {\n      warnBadVendoredStyleName(name, owner);\n    } else if (badStyleValueWithSemicolonPattern.test(value)) {\n      warnStyleValueWithSemicolon(name, value, owner);\n    }\n\n    if (typeof value === 'number' && isNaN(value)) {\n      warnStyleValueIsNaN(name, value, owner);\n    }\n  };\n}\n\n/**\n * Operations for dealing with CSS properties.\n */\nvar CSSPropertyOperations = {\n\n  /**\n   * Serializes a mapping of style properties for use as inline styles:\n   *\n   *   > createMarkupForStyles({width: '200px', height: 0})\n   *   \"width:200px;height:0;\"\n   *\n   * Undefined values are ignored so that declarative programming is easier.\n   * The result should be HTML-escaped before insertion into the DOM.\n   *\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   * @return {?string}\n   */\n  createMarkupForStyles: function (styles, component) {\n    var serialized = '';\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      var styleValue = styles[styleName];\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styleValue, component);\n      }\n      if (styleValue != null) {\n        serialized += processStyleName(styleName) + ':';\n        serialized += dangerousStyleValue(styleName, styleValue, component) + ';';\n      }\n    }\n    return serialized || null;\n  },\n\n  /**\n   * Sets the value for multiple styles on a node.  If a value is specified as\n   * '' (empty string), the corresponding style property will be unset.\n   *\n   * @param {DOMElement} node\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   */\n  setValueForStyles: function (node, styles, component) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onHostOperation(component._debugID, 'update styles', styles);\n    }\n\n    var style = node.style;\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styles[styleName], component);\n      }\n      var styleValue = dangerousStyleValue(styleName, styles[styleName], component);\n      if (styleName === 'float' || styleName === 'cssFloat') {\n        styleName = styleFloatAccessor;\n      }\n      if (styleValue) {\n        style[styleName] = styleValue;\n      } else {\n        var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];\n        if (expansion) {\n          // Shorthand property that IE8 won't like unsetting, so unset each\n          // component to placate it\n          for (var individualStyleName in expansion) {\n            style[individualStyleName] = '';\n          }\n        } else {\n          style[styleName] = '';\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = CSSPropertyOperations;\n},{\"120\":120,\"147\":147,\"149\":149,\"160\":160,\"167\":167,\"171\":171,\"3\":3,\"74\":74}],5:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CallbackQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar invariant = _dereq_(161);\n\n/**\n * A specialized pseudo-event module to help keep track of components waiting to\n * be notified when their DOM representations are available for use.\n *\n * This implements `PooledClass`, so you should never need to instantiate this.\n * Instead, use `CallbackQueue.getPooled()`.\n *\n * @class ReactMountReady\n * @implements PooledClass\n * @internal\n */\nfunction CallbackQueue() {\n  this._callbacks = null;\n  this._contexts = null;\n}\n\n_assign(CallbackQueue.prototype, {\n\n  /**\n   * Enqueues a callback to be invoked when `notifyAll` is invoked.\n   *\n   * @param {function} callback Invoked when `notifyAll` is invoked.\n   * @param {?object} context Context to call `callback` with.\n   * @internal\n   */\n  enqueue: function (callback, context) {\n    this._callbacks = this._callbacks || [];\n    this._contexts = this._contexts || [];\n    this._callbacks.push(callback);\n    this._contexts.push(context);\n  },\n\n  /**\n   * Invokes all enqueued callbacks and clears the queue. This is invoked after\n   * the DOM representation of a component has been created or updated.\n   *\n   * @internal\n   */\n  notifyAll: function () {\n    var callbacks = this._callbacks;\n    var contexts = this._contexts;\n    if (callbacks) {\n      !(callbacks.length === contexts.length) ? \"development\" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : _prodInvariant('24') : void 0;\n      this._callbacks = null;\n      this._contexts = null;\n      for (var i = 0; i < callbacks.length; i++) {\n        callbacks[i].call(contexts[i]);\n      }\n      callbacks.length = 0;\n      contexts.length = 0;\n    }\n  },\n\n  checkpoint: function () {\n    return this._callbacks ? this._callbacks.length : 0;\n  },\n\n  rollback: function (len) {\n    if (this._callbacks) {\n      this._callbacks.length = len;\n      this._contexts.length = len;\n    }\n  },\n\n  /**\n   * Resets the internal queue.\n   *\n   * @internal\n   */\n  reset: function () {\n    this._callbacks = null;\n    this._contexts = null;\n  },\n\n  /**\n   * `PooledClass` looks for this.\n   */\n  destructor: function () {\n    this.reset();\n  }\n\n});\n\nPooledClass.addPoolingTo(CallbackQueue);\n\nmodule.exports = CallbackQueue;\n},{\"139\":139,\"161\":161,\"172\":172,\"25\":25}],6:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ChangeEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\nvar isEventSupported = _dereq_(135);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  change: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onChange: null }),\n      captured: keyOf({ onChangeCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topSelectionChange]\n  }\n};\n\n/**\n * For IE shims\n */\nvar activeElement = null;\nvar activeElementInst = null;\nvar activeElementValue = null;\nvar activeElementValueProp = null;\n\n/**\n * SECTION: handle `change` event\n */\nfunction shouldUseChangeEvent(elem) {\n  var nodeName = elem.nodeName && elem.nodeName.toLowerCase();\n  return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';\n}\n\nvar doesChangeEventBubble = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // See `handleChange` comment below\n  doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8);\n}\n\nfunction manualDispatchChangeEvent(nativeEvent) {\n  var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent));\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n\n  // If change and propertychange bubbled, we'd just bind to it like all the\n  // other events and have it go through ReactBrowserEventEmitter. Since it\n  // doesn't, we manually listen for the events and so we have to enqueue and\n  // process the abstract event manually.\n  //\n  // Batching is necessary here in order to ensure that all event handlers run\n  // before the next rerender (including event handlers attached to ancestor\n  // elements instead of directly on the input). Without this, controlled\n  // components don't work properly in conjunction with event bubbling because\n  // the component is rerendered and the value reverted before all the event\n  // handlers can run. See https://github.com/facebook/react/issues/708.\n  ReactUpdates.batchedUpdates(runEventInBatch, event);\n}\n\nfunction runEventInBatch(event) {\n  EventPluginHub.enqueueEvents(event);\n  EventPluginHub.processEventQueue(false);\n}\n\nfunction startWatchingForChangeEventIE8(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElement.attachEvent('onchange', manualDispatchChangeEvent);\n}\n\nfunction stopWatchingForChangeEventIE8() {\n  if (!activeElement) {\n    return;\n  }\n  activeElement.detachEvent('onchange', manualDispatchChangeEvent);\n  activeElement = null;\n  activeElementInst = null;\n}\n\nfunction getTargetInstForChangeEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topChange) {\n    return targetInst;\n  }\n}\nfunction handleEventsForChangeEventIE8(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForChangeEventIE8();\n    startWatchingForChangeEventIE8(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForChangeEventIE8();\n  }\n}\n\n/**\n * SECTION: handle `input` event\n */\nvar isInputEventSupported = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // IE9 claims to support the input event but fails to trigger it when\n  // deleting text, so we ignore its input events.\n  // IE10+ fire input events to often, such when a placeholder\n  // changes or when an input with a placeholder is focused.\n  isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11);\n}\n\n/**\n * (For IE <=11) Replacement getter/setter for the `value` property that gets\n * set on the active element.\n */\nvar newValueProp = {\n  get: function () {\n    return activeElementValueProp.get.call(this);\n  },\n  set: function (val) {\n    // Cast to a string so we can do equality checks.\n    activeElementValue = '' + val;\n    activeElementValueProp.set.call(this, val);\n  }\n};\n\n/**\n * (For IE <=11) Starts tracking propertychange events on the passed-in element\n * and override the value property so that we can distinguish user events from\n * value changes in JS.\n */\nfunction startWatchingForValueChange(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElementValue = target.value;\n  activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value');\n\n  // Not guarded in a canDefineProperty check: IE8 supports defineProperty only\n  // on DOM elements\n  Object.defineProperty(activeElement, 'value', newValueProp);\n  if (activeElement.attachEvent) {\n    activeElement.attachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.addEventListener('propertychange', handlePropertyChange, false);\n  }\n}\n\n/**\n * (For IE <=11) Removes the event listeners from the currently-tracked element,\n * if any exists.\n */\nfunction stopWatchingForValueChange() {\n  if (!activeElement) {\n    return;\n  }\n\n  // delete restores the original property definition\n  delete activeElement.value;\n\n  if (activeElement.detachEvent) {\n    activeElement.detachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.removeEventListener('propertychange', handlePropertyChange, false);\n  }\n\n  activeElement = null;\n  activeElementInst = null;\n  activeElementValue = null;\n  activeElementValueProp = null;\n}\n\n/**\n * (For IE <=11) Handles a propertychange event, sending a `change` event if\n * the value of the active element has changed.\n */\nfunction handlePropertyChange(nativeEvent) {\n  if (nativeEvent.propertyName !== 'value') {\n    return;\n  }\n  var value = nativeEvent.srcElement.value;\n  if (value === activeElementValue) {\n    return;\n  }\n  activeElementValue = value;\n\n  manualDispatchChangeEvent(nativeEvent);\n}\n\n/**\n * If a `change` event should be fired, returns the target's ID.\n */\nfunction getTargetInstForInputEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topInput) {\n    // In modern browsers (i.e., not IE8 or IE9), the input event is exactly\n    // what we want so fall through here and trigger an abstract event\n    return targetInst;\n  }\n}\n\nfunction handleEventsForInputEventIE(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // In IE8, we can capture almost all .value changes by adding a\n    // propertychange handler and looking for events with propertyName\n    // equal to 'value'\n    // In IE9-11, propertychange fires for most input events but is buggy and\n    // doesn't fire when text is deleted, but conveniently, selectionchange\n    // appears to fire in all of the remaining cases so we catch those and\n    // forward the event if the value has changed\n    // In either case, we don't want to call the event handler if the value\n    // is changed from JS so we redefine a setter for `.value` that updates\n    // our activeElementValue variable, allowing us to ignore those changes\n    //\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForValueChange();\n    startWatchingForValueChange(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForValueChange();\n  }\n}\n\n// For IE8 and IE9.\nfunction getTargetInstForInputEventIE(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) {\n    // On the selectionchange event, the target is just document which isn't\n    // helpful for us so just check activeElement instead.\n    //\n    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire\n    // propertychange on the first input event after setting `value` from a\n    // script and fires only keydown, keypress, keyup. Catching keyup usually\n    // gets it and catching keydown lets us fire an event for the first\n    // keystroke if user does a key repeat (it'll be a little delayed: right\n    // before the second keystroke). Other input methods (e.g., paste) seem to\n    // fire selectionchange normally.\n    if (activeElement && activeElement.value !== activeElementValue) {\n      activeElementValue = activeElement.value;\n      return activeElementInst;\n    }\n  }\n}\n\n/**\n * SECTION: handle `click` event\n */\nfunction shouldUseClickEvent(elem) {\n  // Use the `click` event to detect changes to checkbox and radio inputs.\n  // This approach works across all browsers, whereas `change` does not fire\n  // until `blur` in IE8.\n  return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');\n}\n\nfunction getTargetInstForClickEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topClick) {\n    return targetInst;\n  }\n}\n\n/**\n * This plugin creates an `onChange` event that normalizes change events\n * across form elements. This event fires at a time when it's possible to\n * change the element's value without seeing a flicker.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - select\n */\nvar ChangeEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    var getTargetInstFunc, handleEventFunc;\n    if (shouldUseChangeEvent(targetNode)) {\n      if (doesChangeEventBubble) {\n        getTargetInstFunc = getTargetInstForChangeEvent;\n      } else {\n        handleEventFunc = handleEventsForChangeEventIE8;\n      }\n    } else if (isTextInputElement(targetNode)) {\n      if (isInputEventSupported) {\n        getTargetInstFunc = getTargetInstForInputEvent;\n      } else {\n        getTargetInstFunc = getTargetInstForInputEventIE;\n        handleEventFunc = handleEventsForInputEventIE;\n      }\n    } else if (shouldUseClickEvent(targetNode)) {\n      getTargetInstFunc = getTargetInstForClickEvent;\n    }\n\n    if (getTargetInstFunc) {\n      var inst = getTargetInstFunc(topLevelType, targetInst);\n      if (inst) {\n        var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget);\n        event.type = 'change';\n        EventPropagators.accumulateTwoPhaseDispatches(event);\n        return event;\n      }\n    }\n\n    if (handleEventFunc) {\n      handleEventFunc(topLevelType, targetNode, targetInst);\n    }\n  }\n\n};\n\nmodule.exports = ChangeEventPlugin;\n},{\"104\":104,\"128\":128,\"135\":135,\"136\":136,\"147\":147,\"16\":16,\"165\":165,\"17\":17,\"20\":20,\"41\":41,\"95\":95}],7:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMChildrenOperations\n */\n\n'use strict';\n\nvar DOMLazyTree = _dereq_(8);\nvar Danger = _dereq_(12);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setInnerHTML = _dereq_(141);\nvar setTextContent = _dereq_(142);\n\nfunction getNodeAfter(parentNode, node) {\n  // Special case for text components, which return [open, close] comments\n  // from getHostNode.\n  if (Array.isArray(node)) {\n    node = node[1];\n  }\n  return node ? node.nextSibling : parentNode.firstChild;\n}\n\n/**\n * Inserts `childNode` as a child of `parentNode` at the `index`.\n *\n * @param {DOMElement} parentNode Parent node in which to insert.\n * @param {DOMElement} childNode Child node to insert.\n * @param {number} index Index at which to insert the child.\n * @internal\n */\nvar insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) {\n  // We rely exclusively on `insertBefore(node, null)` instead of also using\n  // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so\n  // we are careful to use `null`.)\n  parentNode.insertBefore(childNode, referenceNode);\n});\n\nfunction insertLazyTreeChildAt(parentNode, childTree, referenceNode) {\n  DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);\n}\n\nfunction moveChild(parentNode, childNode, referenceNode) {\n  if (Array.isArray(childNode)) {\n    moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);\n  } else {\n    insertChildAt(parentNode, childNode, referenceNode);\n  }\n}\n\nfunction removeChild(parentNode, childNode) {\n  if (Array.isArray(childNode)) {\n    var closingComment = childNode[1];\n    childNode = childNode[0];\n    removeDelimitedText(parentNode, childNode, closingComment);\n    parentNode.removeChild(closingComment);\n  }\n  parentNode.removeChild(childNode);\n}\n\nfunction moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) {\n  var node = openingComment;\n  while (true) {\n    var nextNode = node.nextSibling;\n    insertChildAt(parentNode, node, referenceNode);\n    if (node === closingComment) {\n      break;\n    }\n    node = nextNode;\n  }\n}\n\nfunction removeDelimitedText(parentNode, startNode, closingComment) {\n  while (true) {\n    var node = startNode.nextSibling;\n    if (node === closingComment) {\n      // The closing comment is removed by ReactMultiChild.\n      break;\n    } else {\n      parentNode.removeChild(node);\n    }\n  }\n}\n\nfunction replaceDelimitedText(openingComment, closingComment, stringText) {\n  var parentNode = openingComment.parentNode;\n  var nodeAfterComment = openingComment.nextSibling;\n  if (nodeAfterComment === closingComment) {\n    // There are no text nodes between the opening and closing comments; insert\n    // a new one if stringText isn't empty.\n    if (stringText) {\n      insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment);\n    }\n  } else {\n    if (stringText) {\n      // Set the text content of the first node after the opening comment, and\n      // remove all following nodes up until the closing comment.\n      setTextContent(nodeAfterComment, stringText);\n      removeDelimitedText(parentNode, nodeAfterComment, closingComment);\n    } else {\n      removeDelimitedText(parentNode, openingComment, closingComment);\n    }\n  }\n\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID, 'replace text', stringText);\n  }\n}\n\nvar dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup;\nif (\"development\" !== 'production') {\n  dangerouslyReplaceNodeWithMarkup = function (oldChild, markup, prevInstance) {\n    Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup);\n    if (prevInstance._debugID !== 0) {\n      ReactInstrumentation.debugTool.onHostOperation(prevInstance._debugID, 'replace with', markup.toString());\n    } else {\n      var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node);\n      if (nextInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(nextInstance._debugID, 'mount', markup.toString());\n      }\n    }\n  };\n}\n\n/**\n * Operations for updating with DOM children.\n */\nvar DOMChildrenOperations = {\n\n  dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,\n\n  replaceDelimitedText: replaceDelimitedText,\n\n  /**\n   * Updates a component's children by processing a series of updates. The\n   * update configurations are each expected to have a `parentNode` property.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  processUpdates: function (parentNode, updates) {\n    if (\"development\" !== 'production') {\n      var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID;\n    }\n\n    for (var k = 0; k < updates.length; k++) {\n      var update = updates[k];\n      switch (update.type) {\n        case ReactMultiChildUpdateTypes.INSERT_MARKUP:\n          insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'insert child', { toIndex: update.toIndex, content: update.content.toString() });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.MOVE_EXISTING:\n          moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'move child', { fromIndex: update.fromIndex, toIndex: update.toIndex });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.SET_MARKUP:\n          setInnerHTML(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace children', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.TEXT_CONTENT:\n          setTextContent(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace text', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.REMOVE_NODE:\n          removeChild(parentNode, update.fromNode);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'remove child', { fromIndex: update.fromIndex });\n          }\n          break;\n      }\n    }\n  }\n\n};\n\nmodule.exports = DOMChildrenOperations;\n},{\"119\":119,\"12\":12,\"141\":141,\"142\":142,\"41\":41,\"74\":74,\"79\":79,\"8\":8}],8:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMLazyTree\n */\n\n'use strict';\n\nvar DOMNamespaces = _dereq_(9);\nvar setInnerHTML = _dereq_(141);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setTextContent = _dereq_(142);\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\n/**\n * In IE (8-11) and Edge, appending nodes with no children is dramatically\n * faster than appending a full subtree, so we essentially queue up the\n * .appendChild calls here and apply them so each node is added to its parent\n * before any children are added.\n *\n * In other browsers, doing so is slower or neutral compared to the other order\n * (in Firefox, twice as slow) so we only do this inversion in IE.\n *\n * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.\n */\nvar enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\\bEdge\\/\\d/.test(navigator.userAgent);\n\nfunction insertTreeChildren(tree) {\n  if (!enableLazy) {\n    return;\n  }\n  var node = tree.node;\n  var children = tree.children;\n  if (children.length) {\n    for (var i = 0; i < children.length; i++) {\n      insertTreeBefore(node, children[i], null);\n    }\n  } else if (tree.html != null) {\n    setInnerHTML(node, tree.html);\n  } else if (tree.text != null) {\n    setTextContent(node, tree.text);\n  }\n}\n\nvar insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {\n  // DocumentFragments aren't actually part of the DOM after insertion so\n  // appending children won't update the DOM. We need to ensure the fragment\n  // is properly populated first, breaking out of our lazy approach for just\n  // this level. Also, some <object> plugins (like Flash Player) will read\n  // <param> nodes immediately upon insertion into the DOM, so <object>\n  // must also be populated prior to insertion into the DOM.\n  if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) {\n    insertTreeChildren(tree);\n    parentNode.insertBefore(tree.node, referenceNode);\n  } else {\n    parentNode.insertBefore(tree.node, referenceNode);\n    insertTreeChildren(tree);\n  }\n});\n\nfunction replaceChildWithTree(oldNode, newTree) {\n  oldNode.parentNode.replaceChild(newTree.node, oldNode);\n  insertTreeChildren(newTree);\n}\n\nfunction queueChild(parentTree, childTree) {\n  if (enableLazy) {\n    parentTree.children.push(childTree);\n  } else {\n    parentTree.node.appendChild(childTree.node);\n  }\n}\n\nfunction queueHTML(tree, html) {\n  if (enableLazy) {\n    tree.html = html;\n  } else {\n    setInnerHTML(tree.node, html);\n  }\n}\n\nfunction queueText(tree, text) {\n  if (enableLazy) {\n    tree.text = text;\n  } else {\n    setTextContent(tree.node, text);\n  }\n}\n\nfunction toString() {\n  return this.node.nodeName;\n}\n\nfunction DOMLazyTree(node) {\n  return {\n    node: node,\n    children: [],\n    html: null,\n    text: null,\n    toString: toString\n  };\n}\n\nDOMLazyTree.insertTreeBefore = insertTreeBefore;\nDOMLazyTree.replaceChildWithTree = replaceChildWithTree;\nDOMLazyTree.queueChild = queueChild;\nDOMLazyTree.queueHTML = queueHTML;\nDOMLazyTree.queueText = queueText;\n\nmodule.exports = DOMLazyTree;\n},{\"119\":119,\"141\":141,\"142\":142,\"9\":9}],9:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMNamespaces\n */\n\n'use strict';\n\nvar DOMNamespaces = {\n  html: 'http://www.w3.org/1999/xhtml',\n  mathml: 'http://www.w3.org/1998/Math/MathML',\n  svg: 'http://www.w3.org/2000/svg'\n};\n\nmodule.exports = DOMNamespaces;\n},{}],10:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMProperty\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nfunction checkMask(value, bitmask) {\n  return (value & bitmask) === bitmask;\n}\n\nvar DOMPropertyInjection = {\n  /**\n   * Mapping from normalized, camelcased property names to a configuration that\n   * specifies how the associated DOM property should be accessed or rendered.\n   */\n  MUST_USE_PROPERTY: 0x1,\n  HAS_BOOLEAN_VALUE: 0x4,\n  HAS_NUMERIC_VALUE: 0x8,\n  HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,\n  HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,\n\n  /**\n   * Inject some specialized knowledge about the DOM. This takes a config object\n   * with the following properties:\n   *\n   * isCustomAttribute: function that given an attribute name will return true\n   * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*\n   * attributes where it's impossible to enumerate all of the possible\n   * attribute names,\n   *\n   * Properties: object mapping DOM property name to one of the\n   * DOMPropertyInjection constants or null. If your attribute isn't in here,\n   * it won't get written to the DOM.\n   *\n   * DOMAttributeNames: object mapping React attribute name to the DOM\n   * attribute name. Attribute names not specified use the **lowercase**\n   * normalized name.\n   *\n   * DOMAttributeNamespaces: object mapping React attribute name to the DOM\n   * attribute namespace URL. (Attribute names not specified use no namespace.)\n   *\n   * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.\n   * Property names not specified use the normalized name.\n   *\n   * DOMMutationMethods: Properties that require special mutation methods. If\n   * `value` is undefined, the mutation method should unset the property.\n   *\n   * @param {object} domPropertyConfig the config as described above.\n   */\n  injectDOMPropertyConfig: function (domPropertyConfig) {\n    var Injection = DOMPropertyInjection;\n    var Properties = domPropertyConfig.Properties || {};\n    var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};\n    var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};\n    var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};\n    var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};\n\n    if (domPropertyConfig.isCustomAttribute) {\n      DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute);\n    }\n\n    for (var propName in Properties) {\n      !!DOMProperty.properties.hasOwnProperty(propName) ? \"development\" !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\\'re trying to inject DOM property \\'%s\\' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.', propName) : _prodInvariant('48', propName) : void 0;\n\n      var lowerCased = propName.toLowerCase();\n      var propConfig = Properties[propName];\n\n      var propertyInfo = {\n        attributeName: lowerCased,\n        attributeNamespace: null,\n        propertyName: propName,\n        mutationMethod: null,\n\n        mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),\n        hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),\n        hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),\n        hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),\n        hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE)\n      };\n      !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? \"development\" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : _prodInvariant('50', propName) : void 0;\n\n      if (\"development\" !== 'production') {\n        DOMProperty.getPossibleStandardName[lowerCased] = propName;\n      }\n\n      if (DOMAttributeNames.hasOwnProperty(propName)) {\n        var attributeName = DOMAttributeNames[propName];\n        propertyInfo.attributeName = attributeName;\n        if (\"development\" !== 'production') {\n          DOMProperty.getPossibleStandardName[attributeName] = propName;\n        }\n      }\n\n      if (DOMAttributeNamespaces.hasOwnProperty(propName)) {\n        propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];\n      }\n\n      if (DOMPropertyNames.hasOwnProperty(propName)) {\n        propertyInfo.propertyName = DOMPropertyNames[propName];\n      }\n\n      if (DOMMutationMethods.hasOwnProperty(propName)) {\n        propertyInfo.mutationMethod = DOMMutationMethods[propName];\n      }\n\n      DOMProperty.properties[propName] = propertyInfo;\n    }\n  }\n};\n\n/* eslint-disable max-len */\nvar ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\n/* eslint-enable max-len */\n\n/**\n * DOMProperty exports lookup objects that can be used like functions:\n *\n *   > DOMProperty.isValid['id']\n *   true\n *   > DOMProperty.isValid['foobar']\n *   undefined\n *\n * Although this may be confusing, it performs better in general.\n *\n * @see http://jsperf.com/key-exists\n * @see http://jsperf.com/key-missing\n */\nvar DOMProperty = {\n\n  ID_ATTRIBUTE_NAME: 'data-reactid',\n  ROOT_ATTRIBUTE_NAME: 'data-reactroot',\n\n  ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,\n  ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\\\-.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040',\n\n  /**\n   * Map from property \"standard name\" to an object with info about how to set\n   * the property in the DOM. Each object contains:\n   *\n   * attributeName:\n   *   Used when rendering markup or with `*Attribute()`.\n   * attributeNamespace\n   * propertyName:\n   *   Used on DOM node instances. (This includes properties that mutate due to\n   *   external factors.)\n   * mutationMethod:\n   *   If non-null, used instead of the property or `setAttribute()` after\n   *   initial render.\n   * mustUseProperty:\n   *   Whether the property must be accessed and mutated as an object property.\n   * hasBooleanValue:\n   *   Whether the property should be removed when set to a falsey value.\n   * hasNumericValue:\n   *   Whether the property must be numeric or parse as a numeric and should be\n   *   removed when set to a falsey value.\n   * hasPositiveNumericValue:\n   *   Whether the property must be positive numeric or parse as a positive\n   *   numeric and should be removed when set to a falsey value.\n   * hasOverloadedBooleanValue:\n   *   Whether the property can be used as a flag as well as with a value.\n   *   Removed when strictly equal to false; present without a value when\n   *   strictly equal to true; present with a value otherwise.\n   */\n  properties: {},\n\n  /**\n   * Mapping from lowercase property names to the properly cased version, used\n   * to warn in the case of missing properties. Available only in __DEV__.\n   * @type {Object}\n   */\n  getPossibleStandardName: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * All of the isCustomAttribute() functions that have been injected.\n   */\n  _isCustomAttributeFunctions: [],\n\n  /**\n   * Checks whether a property name is a custom attribute.\n   * @method\n   */\n  isCustomAttribute: function (attributeName) {\n    for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {\n      var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];\n      if (isCustomAttributeFn(attributeName)) {\n        return true;\n      }\n    }\n    return false;\n  },\n\n  injection: DOMPropertyInjection\n};\n\nmodule.exports = DOMProperty;\n},{\"139\":139,\"161\":161}],11:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMPropertyOperations\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInstrumentation = _dereq_(49);\nvar ReactInstrumentation = _dereq_(74);\n\nvar quoteAttributeValueForBrowser = _dereq_(138);\nvar warning = _dereq_(171);\n\nvar VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');\nvar illegalAttributeNameCache = {};\nvar validatedAttributeNameCache = {};\n\nfunction isAttributeNameSafe(attributeName) {\n  if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {\n    return true;\n  }\n  if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {\n    return false;\n  }\n  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {\n    validatedAttributeNameCache[attributeName] = true;\n    return true;\n  }\n  illegalAttributeNameCache[attributeName] = true;\n  \"development\" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;\n  return false;\n}\n\nfunction shouldIgnoreValue(propertyInfo, value) {\n  return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;\n}\n\n/**\n * Operations for dealing with DOM properties.\n */\nvar DOMPropertyOperations = {\n\n  /**\n   * Creates markup for the ID property.\n   *\n   * @param {string} id Unescaped ID.\n   * @return {string} Markup string.\n   */\n  createMarkupForID: function (id) {\n    return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);\n  },\n\n  setAttributeForID: function (node, id) {\n    node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);\n  },\n\n  createMarkupForRoot: function () {\n    return DOMProperty.ROOT_ATTRIBUTE_NAME + '=\"\"';\n  },\n\n  setAttributeForRoot: function (node) {\n    node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');\n  },\n\n  /**\n   * Creates markup for a property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {?string} Markup string, or null if the property was invalid.\n   */\n  createMarkupForProperty: function (name, value) {\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onCreateMarkupForProperty(name, value);\n    }\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      if (shouldIgnoreValue(propertyInfo, value)) {\n        return '';\n      }\n      var attributeName = propertyInfo.attributeName;\n      if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n        return attributeName + '=\"\"';\n      }\n      return attributeName + '=' + quoteAttributeValueForBrowser(value);\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      if (value == null) {\n        return '';\n      }\n      return name + '=' + quoteAttributeValueForBrowser(value);\n    }\n    return null;\n  },\n\n  /**\n   * Creates markup for a custom property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {string} Markup string, or empty string if the property was invalid.\n   */\n  createMarkupForCustomAttribute: function (name, value) {\n    if (!isAttributeNameSafe(name) || value == null) {\n      return '';\n    }\n    return name + '=' + quoteAttributeValueForBrowser(value);\n  },\n\n  /**\n   * Sets the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   * @param {*} value\n   */\n  setValueForProperty: function (node, name, value) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, value);\n      } else if (shouldIgnoreValue(propertyInfo, value)) {\n        this.deleteValueForProperty(node, name);\n        return;\n      } else if (propertyInfo.mustUseProperty) {\n        // Contrary to `setAttribute`, object properties are properly\n        // `toString`ed by IE8/9.\n        node[propertyInfo.propertyName] = value;\n      } else {\n        var attributeName = propertyInfo.attributeName;\n        var namespace = propertyInfo.attributeNamespace;\n        // `setAttribute` with objects becomes only `[object]` in IE8/9,\n        // ('' + value) makes it output the correct toString()-value.\n        if (namespace) {\n          node.setAttributeNS(namespace, attributeName, '' + value);\n        } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n          node.setAttribute(attributeName, '');\n        } else {\n          node.setAttribute(attributeName, '' + value);\n        }\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      DOMPropertyOperations.setValueForAttribute(node, name, value);\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onSetValueForProperty(node, name, value);\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  setValueForAttribute: function (node, name, value) {\n    if (!isAttributeNameSafe(name)) {\n      return;\n    }\n    if (value == null) {\n      node.removeAttribute(name);\n    } else {\n      node.setAttribute(name, '' + value);\n    }\n\n    if (\"development\" !== 'production') {\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  /**\n   * Deletes an attributes from a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForAttribute: function (node, name) {\n    node.removeAttribute(name);\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  },\n\n  /**\n   * Deletes the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForProperty: function (node, name) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, undefined);\n      } else if (propertyInfo.mustUseProperty) {\n        var propName = propertyInfo.propertyName;\n        if (propertyInfo.hasBooleanValue) {\n          node[propName] = false;\n        } else {\n          node[propName] = '';\n        }\n      } else {\n        node.removeAttribute(propertyInfo.attributeName);\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      node.removeAttribute(name);\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  }\n\n};\n\nmodule.exports = DOMPropertyOperations;\n},{\"10\":10,\"138\":138,\"171\":171,\"41\":41,\"49\":49,\"74\":74}],12:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Danger\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createNodesFromMarkup = _dereq_(152);\nvar emptyFunction = _dereq_(153);\nvar invariant = _dereq_(161);\n\nvar Danger = {\n\n  /**\n   * Replaces a node with a string of markup at its current position within its\n   * parent. The markup must render into a single root node.\n   *\n   * @param {DOMElement} oldChild Child node to replace.\n   * @param {string} markup Markup to render in place of the child node.\n   * @internal\n   */\n  dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) {\n    !ExecutionEnvironment.canUseDOM ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('56') : void 0;\n    !markup ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : _prodInvariant('57') : void 0;\n    !(oldChild.nodeName !== 'HTML') ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().') : _prodInvariant('58') : void 0;\n\n    if (typeof markup === 'string') {\n      var newChild = createNodesFromMarkup(markup, emptyFunction)[0];\n      oldChild.parentNode.replaceChild(newChild, oldChild);\n    } else {\n      DOMLazyTree.replaceChildWithTree(oldChild, markup);\n    }\n  }\n\n};\n\nmodule.exports = Danger;\n},{\"139\":139,\"147\":147,\"152\":152,\"153\":153,\"161\":161,\"8\":8}],13:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DefaultEventPluginOrder\n */\n\n'use strict';\n\nvar keyOf = _dereq_(165);\n\n/**\n * Module that is injectable into `EventPluginHub`, that specifies a\n * deterministic ordering of `EventPlugin`s. A convenient way to reason about\n * plugins, without having to package every one of them. This is better than\n * having plugins be ordered in the same order that they are injected because\n * that ordering would be influenced by the packaging order.\n * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that\n * preventing default on events is convenient in `SimpleEventPlugin` handlers.\n */\nvar DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })];\n\nmodule.exports = DefaultEventPluginOrder;\n},{\"165\":165}],14:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DisabledInputUtils\n */\n\n'use strict';\n\nvar disableableMouseListenerNames = {\n  onClick: true,\n  onDoubleClick: true,\n  onMouseDown: true,\n  onMouseMove: true,\n  onMouseUp: true,\n\n  onClickCapture: true,\n  onDoubleClickCapture: true,\n  onMouseDownCapture: true,\n  onMouseMoveCapture: true,\n  onMouseUpCapture: true\n};\n\n/**\n * Implements a host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar DisabledInputUtils = {\n  getHostProps: function (inst, props) {\n    if (!props.disabled) {\n      return props;\n    }\n\n    // Copy the props, except the mouse listeners\n    var hostProps = {};\n    for (var key in props) {\n      if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) {\n        hostProps[key] = props[key];\n      }\n    }\n\n    return hostProps;\n  }\n};\n\nmodule.exports = DisabledInputUtils;\n},{}],15:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EnterLeaveEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticMouseEvent = _dereq_(108);\n\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  mouseEnter: {\n    registrationName: keyOf({ onMouseEnter: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  },\n  mouseLeave: {\n    registrationName: keyOf({ onMouseLeave: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  }\n};\n\nvar EnterLeaveEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  /**\n   * For almost every interaction we care about, there will be both a top-level\n   * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that\n   * we do not extract duplicate events. However, moving the mouse into the\n   * browser from outside will not fire a `mouseout` event. In this case, we use\n   * the `mouseover` top-level event.\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {\n      return null;\n    }\n    if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) {\n      // Must not be a mouse in or mouse out - ignoring.\n      return null;\n    }\n\n    var win;\n    if (nativeEventTarget.window === nativeEventTarget) {\n      // `nativeEventTarget` is probably a window object.\n      win = nativeEventTarget;\n    } else {\n      // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n      var doc = nativeEventTarget.ownerDocument;\n      if (doc) {\n        win = doc.defaultView || doc.parentWindow;\n      } else {\n        win = window;\n      }\n    }\n\n    var from;\n    var to;\n    if (topLevelType === topLevelTypes.topMouseOut) {\n      from = targetInst;\n      var related = nativeEvent.relatedTarget || nativeEvent.toElement;\n      to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;\n    } else {\n      // Moving to a node from outside the window.\n      from = null;\n      to = targetInst;\n    }\n\n    if (from === to) {\n      // Nothing pertains to our managed components.\n      return null;\n    }\n\n    var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);\n    var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);\n\n    var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);\n    leave.type = 'mouseleave';\n    leave.target = fromNode;\n    leave.relatedTarget = toNode;\n\n    var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);\n    enter.type = 'mouseenter';\n    enter.target = toNode;\n    enter.relatedTarget = fromNode;\n\n    EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);\n\n    return [leave, enter];\n  }\n\n};\n\nmodule.exports = EnterLeaveEventPlugin;\n},{\"108\":108,\"16\":16,\"165\":165,\"20\":20,\"41\":41}],16:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventConstants\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar PropagationPhases = keyMirror({ bubbled: null, captured: null });\n\n/**\n * Types of raw signals from the browser caught at the top level.\n */\nvar topLevelTypes = keyMirror({\n  topAbort: null,\n  topAnimationEnd: null,\n  topAnimationIteration: null,\n  topAnimationStart: null,\n  topBlur: null,\n  topCanPlay: null,\n  topCanPlayThrough: null,\n  topChange: null,\n  topClick: null,\n  topCompositionEnd: null,\n  topCompositionStart: null,\n  topCompositionUpdate: null,\n  topContextMenu: null,\n  topCopy: null,\n  topCut: null,\n  topDoubleClick: null,\n  topDrag: null,\n  topDragEnd: null,\n  topDragEnter: null,\n  topDragExit: null,\n  topDragLeave: null,\n  topDragOver: null,\n  topDragStart: null,\n  topDrop: null,\n  topDurationChange: null,\n  topEmptied: null,\n  topEncrypted: null,\n  topEnded: null,\n  topError: null,\n  topFocus: null,\n  topInput: null,\n  topInvalid: null,\n  topKeyDown: null,\n  topKeyPress: null,\n  topKeyUp: null,\n  topLoad: null,\n  topLoadedData: null,\n  topLoadedMetadata: null,\n  topLoadStart: null,\n  topMouseDown: null,\n  topMouseMove: null,\n  topMouseOut: null,\n  topMouseOver: null,\n  topMouseUp: null,\n  topPaste: null,\n  topPause: null,\n  topPlay: null,\n  topPlaying: null,\n  topProgress: null,\n  topRateChange: null,\n  topReset: null,\n  topScroll: null,\n  topSeeked: null,\n  topSeeking: null,\n  topSelectionChange: null,\n  topStalled: null,\n  topSubmit: null,\n  topSuspend: null,\n  topTextInput: null,\n  topTimeUpdate: null,\n  topTouchCancel: null,\n  topTouchEnd: null,\n  topTouchMove: null,\n  topTouchStart: null,\n  topTransitionEnd: null,\n  topVolumeChange: null,\n  topWaiting: null,\n  topWheel: null\n});\n\nvar EventConstants = {\n  topLevelTypes: topLevelTypes,\n  PropagationPhases: PropagationPhases\n};\n\nmodule.exports = EventConstants;\n},{\"164\":164}],17:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginHub\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventPluginRegistry = _dereq_(18);\nvar EventPluginUtils = _dereq_(19);\nvar ReactErrorUtils = _dereq_(65);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar invariant = _dereq_(161);\n\n/**\n * Internal store for event listeners\n */\nvar listenerBank = {};\n\n/**\n * Internal queue of events that have accumulated their dispatches and are\n * waiting to have their dispatches executed.\n */\nvar eventQueue = null;\n\n/**\n * Dispatches an event and releases it back into the pool, unless persistent.\n *\n * @param {?object} event Synthetic event to be dispatched.\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @private\n */\nvar executeDispatchesAndRelease = function (event, simulated) {\n  if (event) {\n    EventPluginUtils.executeDispatchesInOrder(event, simulated);\n\n    if (!event.isPersistent()) {\n      event.constructor.release(event);\n    }\n  }\n};\nvar executeDispatchesAndReleaseSimulated = function (e) {\n  return executeDispatchesAndRelease(e, true);\n};\nvar executeDispatchesAndReleaseTopLevel = function (e) {\n  return executeDispatchesAndRelease(e, false);\n};\n\n/**\n * This is a unified interface for event plugins to be installed and configured.\n *\n * Event plugins can implement the following properties:\n *\n *   `extractEvents` {function(string, DOMEventTarget, string, object): *}\n *     Required. When a top-level event is fired, this method is expected to\n *     extract synthetic events that will in turn be queued and dispatched.\n *\n *   `eventTypes` {object}\n *     Optional, plugins that fire events must publish a mapping of registration\n *     names that are used to register listeners. Values of this mapping must\n *     be objects that contain `registrationName` or `phasedRegistrationNames`.\n *\n *   `executeDispatch` {function(object, function, string)}\n *     Optional, allows plugins to override how an event gets dispatched. By\n *     default, the listener is simply invoked.\n *\n * Each plugin that is injected into `EventsPluginHub` is immediately operable.\n *\n * @public\n */\nvar EventPluginHub = {\n\n  /**\n   * Methods for injecting dependencies.\n   */\n  injection: {\n\n    /**\n     * @param {array} InjectedEventPluginOrder\n     * @public\n     */\n    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,\n\n    /**\n     * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n     */\n    injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName\n\n  },\n\n  /**\n   * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {function} listener The callback to store.\n   */\n  putListener: function (inst, registrationName, listener) {\n    !(typeof listener === 'function') ? \"development\" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : _prodInvariant('94', registrationName, typeof listener) : void 0;\n\n    var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});\n    bankForRegistrationName[inst._rootNodeID] = listener;\n\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.didPutListener) {\n      PluginModule.didPutListener(inst, registrationName, listener);\n    }\n  },\n\n  /**\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @return {?function} The stored callback.\n   */\n  getListener: function (inst, registrationName) {\n    var bankForRegistrationName = listenerBank[registrationName];\n    return bankForRegistrationName && bankForRegistrationName[inst._rootNodeID];\n  },\n\n  /**\n   * Deletes a listener from the registration bank.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   */\n  deleteListener: function (inst, registrationName) {\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.willDeleteListener) {\n      PluginModule.willDeleteListener(inst, registrationName);\n    }\n\n    var bankForRegistrationName = listenerBank[registrationName];\n    // TODO: This should never be null -- when is it?\n    if (bankForRegistrationName) {\n      delete bankForRegistrationName[inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Deletes all listeners for the DOM element with the supplied ID.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   */\n  deleteAllListeners: function (inst) {\n    for (var registrationName in listenerBank) {\n      if (!listenerBank.hasOwnProperty(registrationName)) {\n        continue;\n      }\n\n      if (!listenerBank[registrationName][inst._rootNodeID]) {\n        continue;\n      }\n\n      var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n      if (PluginModule && PluginModule.willDeleteListener) {\n        PluginModule.willDeleteListener(inst, registrationName);\n      }\n\n      delete listenerBank[registrationName][inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Allows registered plugins an opportunity to extract events from top-level\n   * native browser events.\n   *\n   * @return {*} An accumulation of synthetic events.\n   * @internal\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events;\n    var plugins = EventPluginRegistry.plugins;\n    for (var i = 0; i < plugins.length; i++) {\n      // Not every plugin in the ordering may be loaded at runtime.\n      var possiblePlugin = plugins[i];\n      if (possiblePlugin) {\n        var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n        if (extractedEvents) {\n          events = accumulateInto(events, extractedEvents);\n        }\n      }\n    }\n    return events;\n  },\n\n  /**\n   * Enqueues a synthetic event that should be dispatched when\n   * `processEventQueue` is invoked.\n   *\n   * @param {*} events An accumulation of synthetic events.\n   * @internal\n   */\n  enqueueEvents: function (events) {\n    if (events) {\n      eventQueue = accumulateInto(eventQueue, events);\n    }\n  },\n\n  /**\n   * Dispatches all synthetic events on the event queue.\n   *\n   * @internal\n   */\n  processEventQueue: function (simulated) {\n    // Set `eventQueue` to null before processing it so that we can tell if more\n    // events get enqueued while processing.\n    var processingEventQueue = eventQueue;\n    eventQueue = null;\n    if (simulated) {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);\n    } else {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);\n    }\n    !!eventQueue ? \"development\" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : _prodInvariant('95') : void 0;\n    // This would be a good time to rethrow if any of the event handlers threw.\n    ReactErrorUtils.rethrowCaughtError();\n  },\n\n  /**\n   * These are needed for tests only. Do not use!\n   */\n  __purge: function () {\n    listenerBank = {};\n  },\n\n  __getListenerBank: function () {\n    return listenerBank;\n  }\n\n};\n\nmodule.exports = EventPluginHub;\n},{\"115\":115,\"124\":124,\"139\":139,\"161\":161,\"18\":18,\"19\":19,\"65\":65}],18:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginRegistry\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Injectable ordering of event plugins.\n */\nvar EventPluginOrder = null;\n\n/**\n * Injectable mapping from names to event plugin modules.\n */\nvar namesToPlugins = {};\n\n/**\n * Recomputes the plugin list using the injected plugins and plugin ordering.\n *\n * @private\n */\nfunction recomputePluginOrdering() {\n  if (!EventPluginOrder) {\n    // Wait until an `EventPluginOrder` is injected.\n    return;\n  }\n  for (var pluginName in namesToPlugins) {\n    var PluginModule = namesToPlugins[pluginName];\n    var pluginIndex = EventPluginOrder.indexOf(pluginName);\n    !(pluginIndex > -1) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0;\n    if (EventPluginRegistry.plugins[pluginIndex]) {\n      continue;\n    }\n    !PluginModule.extractEvents ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0;\n    EventPluginRegistry.plugins[pluginIndex] = PluginModule;\n    var publishedEvents = PluginModule.eventTypes;\n    for (var eventName in publishedEvents) {\n      !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('98', eventName, pluginName) : void 0;\n    }\n  }\n}\n\n/**\n * Publishes an event so that it can be dispatched by the supplied plugin.\n *\n * @param {object} dispatchConfig Dispatch configuration for the event.\n * @param {object} PluginModule Plugin publishing the event.\n * @return {boolean} True if the event was successfully published.\n * @private\n */\nfunction publishEventForPlugin(dispatchConfig, PluginModule, eventName) {\n  !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0;\n  EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;\n\n  var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;\n  if (phasedRegistrationNames) {\n    for (var phaseName in phasedRegistrationNames) {\n      if (phasedRegistrationNames.hasOwnProperty(phaseName)) {\n        var phasedRegistrationName = phasedRegistrationNames[phaseName];\n        publishRegistrationName(phasedRegistrationName, PluginModule, eventName);\n      }\n    }\n    return true;\n  } else if (dispatchConfig.registrationName) {\n    publishRegistrationName(dispatchConfig.registrationName, PluginModule, eventName);\n    return true;\n  }\n  return false;\n}\n\n/**\n * Publishes a registration name that is used to identify dispatched events and\n * can be used with `EventPluginHub.putListener` to register listeners.\n *\n * @param {string} registrationName Registration name to add.\n * @param {object} PluginModule Plugin publishing the event.\n * @private\n */\nfunction publishRegistrationName(registrationName, PluginModule, eventName) {\n  !!EventPluginRegistry.registrationNameModules[registrationName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0;\n  EventPluginRegistry.registrationNameModules[registrationName] = PluginModule;\n  EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies;\n\n  if (\"development\" !== 'production') {\n    var lowerCasedName = registrationName.toLowerCase();\n    EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;\n\n    if (registrationName === 'onDoubleClick') {\n      EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;\n    }\n  }\n}\n\n/**\n * Registers plugins so that they can extract and dispatch events.\n *\n * @see {EventPluginHub}\n */\nvar EventPluginRegistry = {\n\n  /**\n   * Ordered list of injected plugins.\n   */\n  plugins: [],\n\n  /**\n   * Mapping from event name to dispatch config\n   */\n  eventNameDispatchConfigs: {},\n\n  /**\n   * Mapping from registration name to plugin module\n   */\n  registrationNameModules: {},\n\n  /**\n   * Mapping from registration name to event name\n   */\n  registrationNameDependencies: {},\n\n  /**\n   * Mapping from lowercase registration names to the properly cased version,\n   * used to warn in the case of missing event handlers. Available\n   * only in __DEV__.\n   * @type {Object}\n   */\n  possibleRegistrationNames: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * Injects an ordering of plugins (by plugin name). This allows the ordering\n   * to be decoupled from injection of the actual plugins so that ordering is\n   * always deterministic regardless of packaging, on-the-fly injection, etc.\n   *\n   * @param {array} InjectedEventPluginOrder\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginOrder}\n   */\n  injectEventPluginOrder: function (InjectedEventPluginOrder) {\n    !!EventPluginOrder ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : _prodInvariant('101') : void 0;\n    // Clone the ordering so it cannot be dynamically mutated.\n    EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);\n    recomputePluginOrdering();\n  },\n\n  /**\n   * Injects plugins to be used by `EventPluginHub`. The plugin names must be\n   * in the ordering injected by `injectEventPluginOrder`.\n   *\n   * Plugins can be injected as part of page initialization or on-the-fly.\n   *\n   * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginsByName}\n   */\n  injectEventPluginsByName: function (injectedNamesToPlugins) {\n    var isOrderingDirty = false;\n    for (var pluginName in injectedNamesToPlugins) {\n      if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {\n        continue;\n      }\n      var PluginModule = injectedNamesToPlugins[pluginName];\n      if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== PluginModule) {\n        !!namesToPlugins[pluginName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0;\n        namesToPlugins[pluginName] = PluginModule;\n        isOrderingDirty = true;\n      }\n    }\n    if (isOrderingDirty) {\n      recomputePluginOrdering();\n    }\n  },\n\n  /**\n   * Looks up the plugin for the supplied event.\n   *\n   * @param {object} event A synthetic event.\n   * @return {?object} The plugin that created the supplied event.\n   * @internal\n   */\n  getPluginModuleForEvent: function (event) {\n    var dispatchConfig = event.dispatchConfig;\n    if (dispatchConfig.registrationName) {\n      return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null;\n    }\n    for (var phase in dispatchConfig.phasedRegistrationNames) {\n      if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) {\n        continue;\n      }\n      var PluginModule = EventPluginRegistry.registrationNameModules[dispatchConfig.phasedRegistrationNames[phase]];\n      if (PluginModule) {\n        return PluginModule;\n      }\n    }\n    return null;\n  },\n\n  /**\n   * Exposed for unit testing.\n   * @private\n   */\n  _resetEventPlugins: function () {\n    EventPluginOrder = null;\n    for (var pluginName in namesToPlugins) {\n      if (namesToPlugins.hasOwnProperty(pluginName)) {\n        delete namesToPlugins[pluginName];\n      }\n    }\n    EventPluginRegistry.plugins.length = 0;\n\n    var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs;\n    for (var eventName in eventNameDispatchConfigs) {\n      if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {\n        delete eventNameDispatchConfigs[eventName];\n      }\n    }\n\n    var registrationNameModules = EventPluginRegistry.registrationNameModules;\n    for (var registrationName in registrationNameModules) {\n      if (registrationNameModules.hasOwnProperty(registrationName)) {\n        delete registrationNameModules[registrationName];\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames;\n      for (var lowerCasedName in possibleRegistrationNames) {\n        if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) {\n          delete possibleRegistrationNames[lowerCasedName];\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = EventPluginRegistry;\n},{\"139\":139,\"161\":161}],19:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar ReactErrorUtils = _dereq_(65);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Injected dependencies:\n */\n\n/**\n * - `ComponentTree`: [required] Module that can convert between React instances\n *   and actual node references.\n */\nvar ComponentTree;\nvar TreeTraversal;\nvar injection = {\n  injectComponentTree: function (Injected) {\n    ComponentTree = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;\n    }\n  },\n  injectTreeTraversal: function (Injected) {\n    TreeTraversal = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;\n    }\n  }\n};\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nfunction isEndish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel;\n}\n\nfunction isMoveish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove;\n}\nfunction isStartish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart;\n}\n\nvar validateEventDispatches;\nif (\"development\" !== 'production') {\n  validateEventDispatches = function (event) {\n    var dispatchListeners = event._dispatchListeners;\n    var dispatchInstances = event._dispatchInstances;\n\n    var listenersIsArr = Array.isArray(dispatchListeners);\n    var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;\n\n    var instancesIsArr = Array.isArray(dispatchInstances);\n    var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;\n\n    \"development\" !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;\n  };\n}\n\n/**\n * Dispatch the event to the listener.\n * @param {SyntheticEvent} event SyntheticEvent to handle\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @param {function} listener Application-level callback\n * @param {*} inst Internal component instance\n */\nfunction executeDispatch(event, simulated, listener, inst) {\n  var type = event.type || 'unknown-event';\n  event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);\n  if (simulated) {\n    ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);\n  } else {\n    ReactErrorUtils.invokeGuardedCallback(type, listener, event);\n  }\n  event.currentTarget = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches.\n */\nfunction executeDispatchesInOrder(event, simulated) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);\n    }\n  } else if (dispatchListeners) {\n    executeDispatch(event, simulated, dispatchListeners, dispatchInstances);\n  }\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches, but stops\n * at the first dispatch execution returning true, and returns that id.\n *\n * @return {?string} id of the first dispatch execution who's listener returns\n * true, or null if no listener returned true.\n */\nfunction executeDispatchesInOrderStopAtTrueImpl(event) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      if (dispatchListeners[i](event, dispatchInstances[i])) {\n        return dispatchInstances[i];\n      }\n    }\n  } else if (dispatchListeners) {\n    if (dispatchListeners(event, dispatchInstances)) {\n      return dispatchInstances;\n    }\n  }\n  return null;\n}\n\n/**\n * @see executeDispatchesInOrderStopAtTrueImpl\n */\nfunction executeDispatchesInOrderStopAtTrue(event) {\n  var ret = executeDispatchesInOrderStopAtTrueImpl(event);\n  event._dispatchInstances = null;\n  event._dispatchListeners = null;\n  return ret;\n}\n\n/**\n * Execution of a \"direct\" dispatch - there must be at most one dispatch\n * accumulated on the event or it is considered an error. It doesn't really make\n * sense for an event with multiple dispatches (bubbled) to keep track of the\n * return values at each dispatch execution, but it does tend to make sense when\n * dealing with \"direct\" dispatches.\n *\n * @return {*} The return value of executing the single dispatch.\n */\nfunction executeDirectDispatch(event) {\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  var dispatchListener = event._dispatchListeners;\n  var dispatchInstance = event._dispatchInstances;\n  !!Array.isArray(dispatchListener) ? \"development\" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0;\n  event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;\n  var res = dispatchListener ? dispatchListener(event) : null;\n  event.currentTarget = null;\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n  return res;\n}\n\n/**\n * @param {SyntheticEvent} event\n * @return {boolean} True iff number of dispatches accumulated is greater than 0.\n */\nfunction hasDispatches(event) {\n  return !!event._dispatchListeners;\n}\n\n/**\n * General utilities that are useful in creating custom Event Plugins.\n */\nvar EventPluginUtils = {\n  isEndish: isEndish,\n  isMoveish: isMoveish,\n  isStartish: isStartish,\n\n  executeDirectDispatch: executeDirectDispatch,\n  executeDispatchesInOrder: executeDispatchesInOrder,\n  executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,\n  hasDispatches: hasDispatches,\n\n  getInstanceFromNode: function (node) {\n    return ComponentTree.getInstanceFromNode(node);\n  },\n  getNodeFromInstance: function (node) {\n    return ComponentTree.getNodeFromInstance(node);\n  },\n  isAncestor: function (a, b) {\n    return TreeTraversal.isAncestor(a, b);\n  },\n  getLowestCommonAncestor: function (a, b) {\n    return TreeTraversal.getLowestCommonAncestor(a, b);\n  },\n  getParentInstance: function (inst) {\n    return TreeTraversal.getParentInstance(inst);\n  },\n  traverseTwoPhase: function (target, fn, arg) {\n    return TreeTraversal.traverseTwoPhase(target, fn, arg);\n  },\n  traverseEnterLeave: function (from, to, fn, argFrom, argTo) {\n    return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);\n  },\n\n  injection: injection\n};\n\nmodule.exports = EventPluginUtils;\n},{\"139\":139,\"16\":16,\"161\":161,\"171\":171,\"65\":65}],20:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPropagators\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar warning = _dereq_(171);\n\nvar PropagationPhases = EventConstants.PropagationPhases;\nvar getListener = EventPluginHub.getListener;\n\n/**\n * Some event types have a notion of different registration names for different\n * \"phases\" of propagation. This finds listeners by a given phase.\n */\nfunction listenerAtPhase(inst, event, propagationPhase) {\n  var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];\n  return getListener(inst, registrationName);\n}\n\n/**\n * Tags a `SyntheticEvent` with dispatched listeners. Creating this function\n * here, allows us to not have to bind or create functions for each event.\n * Mutating the event's members allows us to not have to create a wrapping\n * \"dispatch\" object that pairs the event with the listener.\n */\nfunction accumulateDirectionalDispatches(inst, upwards, event) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;\n  }\n  var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured;\n  var listener = listenerAtPhase(inst, event, phase);\n  if (listener) {\n    event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n  }\n}\n\n/**\n * Collect dispatches (must be entirely collected before dispatching - see unit\n * tests). Lazily allocate the array to conserve memory.  We must loop through\n * each event and perform the traversal for each one. We cannot perform a\n * single traversal for the entire collection of events because each event may\n * have a different target.\n */\nfunction accumulateTwoPhaseDispatchesSingle(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.\n */\nfunction accumulateTwoPhaseDispatchesSingleSkipTarget(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    var targetInst = event._targetInst;\n    var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;\n    EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Accumulates without regard to direction, does not look for phased\n * registration names. Same as `accumulateDirectDispatchesSingle` but without\n * requiring that the `dispatchMarker` be the same as the dispatched ID.\n */\nfunction accumulateDispatches(inst, ignoredDirection, event) {\n  if (event && event.dispatchConfig.registrationName) {\n    var registrationName = event.dispatchConfig.registrationName;\n    var listener = getListener(inst, registrationName);\n    if (listener) {\n      event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n    }\n  }\n}\n\n/**\n * Accumulates dispatches on an `SyntheticEvent`, but only for the\n * `dispatchMarker`.\n * @param {SyntheticEvent} event\n */\nfunction accumulateDirectDispatchesSingle(event) {\n  if (event && event.dispatchConfig.registrationName) {\n    accumulateDispatches(event._targetInst, null, event);\n  }\n}\n\nfunction accumulateTwoPhaseDispatches(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);\n}\n\nfunction accumulateTwoPhaseDispatchesSkipTarget(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);\n}\n\nfunction accumulateEnterLeaveDispatches(leave, enter, from, to) {\n  EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);\n}\n\nfunction accumulateDirectDispatches(events) {\n  forEachAccumulated(events, accumulateDirectDispatchesSingle);\n}\n\n/**\n * A small set of propagation patterns, each of which will accept a small amount\n * of information, and generate a set of \"dispatch ready event objects\" - which\n * are sets of events that have already been annotated with a set of dispatched\n * listener functions/ids. The API is designed this way to discourage these\n * propagation strategies from actually executing the dispatches, since we\n * always want to collect the entire set of dispatches before executing event a\n * single one.\n *\n * @constructor EventPropagators\n */\nvar EventPropagators = {\n  accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,\n  accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,\n  accumulateDirectDispatches: accumulateDirectDispatches,\n  accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches\n};\n\nmodule.exports = EventPropagators;\n},{\"115\":115,\"124\":124,\"16\":16,\"17\":17,\"171\":171,\"19\":19}],21:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule FallbackCompositionState\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * This helper class stores information about text content of a target node,\n * allowing comparison of content before and after a given event.\n *\n * Identify the node where selection currently begins, then observe\n * both its text content and its current position in the DOM. Since the\n * browser may natively replace the target node during composition, we can\n * use its position to find its replacement.\n *\n * @param {DOMEventTarget} root\n */\nfunction FallbackCompositionState(root) {\n  this._root = root;\n  this._startText = this.getText();\n  this._fallbackText = null;\n}\n\n_assign(FallbackCompositionState.prototype, {\n  destructor: function () {\n    this._root = null;\n    this._startText = null;\n    this._fallbackText = null;\n  },\n\n  /**\n   * Get current text of input.\n   *\n   * @return {string}\n   */\n  getText: function () {\n    if ('value' in this._root) {\n      return this._root.value;\n    }\n    return this._root[getTextContentAccessor()];\n  },\n\n  /**\n   * Determine the differing substring between the initially stored\n   * text content and the current content.\n   *\n   * @return {string}\n   */\n  getData: function () {\n    if (this._fallbackText) {\n      return this._fallbackText;\n    }\n\n    var start;\n    var startValue = this._startText;\n    var startLength = startValue.length;\n    var end;\n    var endValue = this.getText();\n    var endLength = endValue.length;\n\n    for (start = 0; start < startLength; start++) {\n      if (startValue[start] !== endValue[start]) {\n        break;\n      }\n    }\n\n    var minEnd = startLength - start;\n    for (end = 1; end <= minEnd; end++) {\n      if (startValue[startLength - end] !== endValue[endLength - end]) {\n        break;\n      }\n    }\n\n    var sliceTail = end > 1 ? 1 - end : undefined;\n    this._fallbackText = endValue.slice(start, sliceTail);\n    return this._fallbackText;\n  }\n});\n\nPooledClass.addPoolingTo(FallbackCompositionState);\n\nmodule.exports = FallbackCompositionState;\n},{\"132\":132,\"172\":172,\"25\":25}],22:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule HTMLDOMPropertyConfig\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\n\nvar MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;\nvar HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;\nvar HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;\nvar HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;\nvar HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;\n\nvar HTMLDOMPropertyConfig = {\n  isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')),\n  Properties: {\n    /**\n     * Standard Properties\n     */\n    accept: 0,\n    acceptCharset: 0,\n    accessKey: 0,\n    action: 0,\n    allowFullScreen: HAS_BOOLEAN_VALUE,\n    allowTransparency: 0,\n    alt: 0,\n    async: HAS_BOOLEAN_VALUE,\n    autoComplete: 0,\n    // autoFocus is polyfilled/normalized by AutoFocusUtils\n    // autoFocus: HAS_BOOLEAN_VALUE,\n    autoPlay: HAS_BOOLEAN_VALUE,\n    capture: HAS_BOOLEAN_VALUE,\n    cellPadding: 0,\n    cellSpacing: 0,\n    charSet: 0,\n    challenge: 0,\n    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    cite: 0,\n    classID: 0,\n    className: 0,\n    cols: HAS_POSITIVE_NUMERIC_VALUE,\n    colSpan: 0,\n    content: 0,\n    contentEditable: 0,\n    contextMenu: 0,\n    controls: HAS_BOOLEAN_VALUE,\n    coords: 0,\n    crossOrigin: 0,\n    data: 0, // For `<object />` acts as `src`.\n    dateTime: 0,\n    'default': HAS_BOOLEAN_VALUE,\n    defer: HAS_BOOLEAN_VALUE,\n    dir: 0,\n    disabled: HAS_BOOLEAN_VALUE,\n    download: HAS_OVERLOADED_BOOLEAN_VALUE,\n    draggable: 0,\n    encType: 0,\n    form: 0,\n    formAction: 0,\n    formEncType: 0,\n    formMethod: 0,\n    formNoValidate: HAS_BOOLEAN_VALUE,\n    formTarget: 0,\n    frameBorder: 0,\n    headers: 0,\n    height: 0,\n    hidden: HAS_BOOLEAN_VALUE,\n    high: 0,\n    href: 0,\n    hrefLang: 0,\n    htmlFor: 0,\n    httpEquiv: 0,\n    icon: 0,\n    id: 0,\n    inputMode: 0,\n    integrity: 0,\n    is: 0,\n    keyParams: 0,\n    keyType: 0,\n    kind: 0,\n    label: 0,\n    lang: 0,\n    list: 0,\n    loop: HAS_BOOLEAN_VALUE,\n    low: 0,\n    manifest: 0,\n    marginHeight: 0,\n    marginWidth: 0,\n    max: 0,\n    maxLength: 0,\n    media: 0,\n    mediaGroup: 0,\n    method: 0,\n    min: 0,\n    minLength: 0,\n    // Caution; `option.selected` is not updated if `select.multiple` is\n    // disabled with `removeAttribute`.\n    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    name: 0,\n    nonce: 0,\n    noValidate: HAS_BOOLEAN_VALUE,\n    open: HAS_BOOLEAN_VALUE,\n    optimum: 0,\n    pattern: 0,\n    placeholder: 0,\n    poster: 0,\n    preload: 0,\n    profile: 0,\n    radioGroup: 0,\n    readOnly: HAS_BOOLEAN_VALUE,\n    rel: 0,\n    required: HAS_BOOLEAN_VALUE,\n    reversed: HAS_BOOLEAN_VALUE,\n    role: 0,\n    rows: HAS_POSITIVE_NUMERIC_VALUE,\n    rowSpan: HAS_NUMERIC_VALUE,\n    sandbox: 0,\n    scope: 0,\n    scoped: HAS_BOOLEAN_VALUE,\n    scrolling: 0,\n    seamless: HAS_BOOLEAN_VALUE,\n    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    shape: 0,\n    size: HAS_POSITIVE_NUMERIC_VALUE,\n    sizes: 0,\n    span: HAS_POSITIVE_NUMERIC_VALUE,\n    spellCheck: 0,\n    src: 0,\n    srcDoc: 0,\n    srcLang: 0,\n    srcSet: 0,\n    start: HAS_NUMERIC_VALUE,\n    step: 0,\n    style: 0,\n    summary: 0,\n    tabIndex: 0,\n    target: 0,\n    title: 0,\n    // Setting .type throws on non-<input> tags\n    type: 0,\n    useMap: 0,\n    value: 0,\n    width: 0,\n    wmode: 0,\n    wrap: 0,\n\n    /**\n     * RDFa Properties\n     */\n    about: 0,\n    datatype: 0,\n    inlist: 0,\n    prefix: 0,\n    // property is also supported for OpenGraph in meta tags.\n    property: 0,\n    resource: 0,\n    'typeof': 0,\n    vocab: 0,\n\n    /**\n     * Non-standard Properties\n     */\n    // autoCapitalize and autoCorrect are supported in Mobile Safari for\n    // keyboard hints.\n    autoCapitalize: 0,\n    autoCorrect: 0,\n    // autoSave allows WebKit/Blink to persist values of input fields on page reloads\n    autoSave: 0,\n    // color is for Safari mask-icon link\n    color: 0,\n    // itemProp, itemScope, itemType are for\n    // Microdata support. See http://schema.org/docs/gs.html\n    itemProp: 0,\n    itemScope: HAS_BOOLEAN_VALUE,\n    itemType: 0,\n    // itemID and itemRef are for Microdata support as well but\n    // only specified in the WHATWG spec document. See\n    // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api\n    itemID: 0,\n    itemRef: 0,\n    // results show looking glass icon and recent searches on input\n    // search fields in WebKit/Blink\n    results: 0,\n    // IE-only attribute that specifies security restrictions on an iframe\n    // as an alternative to the sandbox attribute on IE<10\n    security: 0,\n    // IE-only attribute that controls focus behavior\n    unselectable: 0\n  },\n  DOMAttributeNames: {\n    acceptCharset: 'accept-charset',\n    className: 'class',\n    htmlFor: 'for',\n    httpEquiv: 'http-equiv'\n  },\n  DOMPropertyNames: {}\n};\n\nmodule.exports = HTMLDOMPropertyConfig;\n},{\"10\":10}],23:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule KeyEscapeUtils\n * \n */\n\n'use strict';\n\n/**\n * Escape and wrap key so it is safe to use as a reactid\n *\n * @param {string} key to be escaped.\n * @return {string} the escaped key.\n */\n\nfunction escape(key) {\n  var escapeRegex = /[=:]/g;\n  var escaperLookup = {\n    '=': '=0',\n    ':': '=2'\n  };\n  var escapedString = ('' + key).replace(escapeRegex, function (match) {\n    return escaperLookup[match];\n  });\n\n  return '$' + escapedString;\n}\n\n/**\n * Unescape and unwrap key for human-readable display\n *\n * @param {string} key to unescape.\n * @return {string} the unescaped key.\n */\nfunction unescape(key) {\n  var unescapeRegex = /(=0|=2)/g;\n  var unescaperLookup = {\n    '=0': '=',\n    '=2': ':'\n  };\n  var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);\n\n  return ('' + keySubstring).replace(unescapeRegex, function (match) {\n    return unescaperLookup[match];\n  });\n}\n\nvar KeyEscapeUtils = {\n  escape: escape,\n  unescape: unescape\n};\n\nmodule.exports = KeyEscapeUtils;\n},{}],24:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule LinkedValueUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypes = _dereq_(85);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar hasReadOnlyValue = {\n  'button': true,\n  'checkbox': true,\n  'image': true,\n  'hidden': true,\n  'radio': true,\n  'reset': true,\n  'submit': true\n};\n\nfunction _assertSingleLink(inputProps) {\n  !(inputProps.checkedLink == null || inputProps.valueLink == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don\\'t want to use valueLink and vice versa.') : _prodInvariant('87') : void 0;\n}\nfunction _assertValueLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.value == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don\\'t want to use valueLink.') : _prodInvariant('88') : void 0;\n}\n\nfunction _assertCheckedLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.checked == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don\\'t want to use checkedLink') : _prodInvariant('89') : void 0;\n}\n\nvar propTypes = {\n  value: function (props, propName, componentName) {\n    if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  checked: function (props, propName, componentName) {\n    if (!props[propName] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  onChange: ReactPropTypes.func\n};\n\nvar loggedTypeFailures = {};\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Provide a linked `value` attribute for controlled forms. You should not use\n * this outside of the ReactDOM controlled form components.\n */\nvar LinkedValueUtils = {\n  checkPropTypes: function (tagName, props, owner) {\n    for (var propName in propTypes) {\n      if (propTypes.hasOwnProperty(propName)) {\n        var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop);\n      }\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var addendum = getDeclarationErrorAddendum(owner);\n        \"development\" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0;\n      }\n    }\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current value of the input either from value prop or link.\n   */\n  getValue: function (inputProps) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.value;\n    }\n    return inputProps.value;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current checked status of the input either from checked prop\n   *             or link.\n   */\n  getChecked: function (inputProps) {\n    if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.value;\n    }\n    return inputProps.checked;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @param {SyntheticEvent} event change event to handle\n   */\n  executeOnChange: function (inputProps, event) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.requestChange(event.target.value);\n    } else if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.requestChange(event.target.checked);\n    } else if (inputProps.onChange) {\n      return inputProps.onChange.call(undefined, event);\n    }\n  }\n};\n\nmodule.exports = LinkedValueUtils;\n},{\"139\":139,\"161\":161,\"171\":171,\"84\":84,\"85\":85}],25:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule PooledClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Static poolers. Several custom versions for each potential number of\n * arguments. A completely generic pooler is easy to implement, but would\n * require accessing the `arguments` object. In each of these, `this` refers to\n * the Class itself, not an instance. If any others are needed, simply add them\n * here, or in their own files.\n */\nvar oneArgumentPooler = function (copyFieldsFrom) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, copyFieldsFrom);\n    return instance;\n  } else {\n    return new Klass(copyFieldsFrom);\n  }\n};\n\nvar twoArgumentPooler = function (a1, a2) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2);\n    return instance;\n  } else {\n    return new Klass(a1, a2);\n  }\n};\n\nvar threeArgumentPooler = function (a1, a2, a3) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3);\n  }\n};\n\nvar fourArgumentPooler = function (a1, a2, a3, a4) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4);\n  }\n};\n\nvar fiveArgumentPooler = function (a1, a2, a3, a4, a5) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4, a5);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4, a5);\n  }\n};\n\nvar standardReleaser = function (instance) {\n  var Klass = this;\n  !(instance instanceof Klass) ? \"development\" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0;\n  instance.destructor();\n  if (Klass.instancePool.length < Klass.poolSize) {\n    Klass.instancePool.push(instance);\n  }\n};\n\nvar DEFAULT_POOL_SIZE = 10;\nvar DEFAULT_POOLER = oneArgumentPooler;\n\n/**\n * Augments `CopyConstructor` to be a poolable class, augmenting only the class\n * itself (statically) not adding any prototypical fields. Any CopyConstructor\n * you give this may have a `poolSize` property, and will look for a\n * prototypical `destructor` on instances.\n *\n * @param {Function} CopyConstructor Constructor that can be used to reset.\n * @param {Function} pooler Customizable pooler.\n */\nvar addPoolingTo = function (CopyConstructor, pooler) {\n  var NewKlass = CopyConstructor;\n  NewKlass.instancePool = [];\n  NewKlass.getPooled = pooler || DEFAULT_POOLER;\n  if (!NewKlass.poolSize) {\n    NewKlass.poolSize = DEFAULT_POOL_SIZE;\n  }\n  NewKlass.release = standardReleaser;\n  return NewKlass;\n};\n\nvar PooledClass = {\n  addPoolingTo: addPoolingTo,\n  oneArgumentPooler: oneArgumentPooler,\n  twoArgumentPooler: twoArgumentPooler,\n  threeArgumentPooler: threeArgumentPooler,\n  fourArgumentPooler: fourArgumentPooler,\n  fiveArgumentPooler: fiveArgumentPooler\n};\n\nmodule.exports = PooledClass;\n},{\"139\":139,\"161\":161}],26:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule React\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactComponent = _dereq_(31);\nvar ReactClass = _dereq_(30);\nvar ReactDOMFactories = _dereq_(45);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypes = _dereq_(85);\nvar ReactVersion = _dereq_(96);\n\nvar onlyChild = _dereq_(137);\nvar warning = _dereq_(171);\n\nvar createElement = ReactElement.createElement;\nvar createFactory = ReactElement.createFactory;\nvar cloneElement = ReactElement.cloneElement;\n\nif (\"development\" !== 'production') {\n  var ReactElementValidator = _dereq_(63);\n  createElement = ReactElementValidator.createElement;\n  createFactory = ReactElementValidator.createFactory;\n  cloneElement = ReactElementValidator.cloneElement;\n}\n\nvar __spread = _assign;\n\nif (\"development\" !== 'production') {\n  var warned = false;\n  __spread = function () {\n    \"development\" !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;\n    warned = true;\n    return _assign.apply(null, arguments);\n  };\n}\n\nvar React = {\n\n  // Modern\n\n  Children: {\n    map: ReactChildren.map,\n    forEach: ReactChildren.forEach,\n    count: ReactChildren.count,\n    toArray: ReactChildren.toArray,\n    only: onlyChild\n  },\n\n  Component: ReactComponent,\n\n  createElement: createElement,\n  cloneElement: cloneElement,\n  isValidElement: ReactElement.isValidElement,\n\n  // Classic\n\n  PropTypes: ReactPropTypes,\n  createClass: ReactClass.createClass,\n  createFactory: createFactory,\n  createMixin: function (mixin) {\n    // Currently a noop. Will be used to validate and trace mixins.\n    return mixin;\n  },\n\n  // This looks DOM specific but these are actually isomorphic helpers\n  // since they are just generating DOM strings.\n  DOM: ReactDOMFactories,\n\n  version: ReactVersion,\n\n  // Deprecated hook for JSX spread, don't use this for anything.\n  __spread: __spread\n};\n\nmodule.exports = React;\n},{\"137\":137,\"171\":171,\"172\":172,\"29\":29,\"30\":30,\"31\":31,\"45\":45,\"62\":62,\"63\":63,\"85\":85,\"96\":96}],27:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactBrowserEventEmitter\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventConstants = _dereq_(16);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactEventEmitterMixin = _dereq_(66);\nvar ViewportMetrics = _dereq_(114);\n\nvar getVendorPrefixedEventName = _dereq_(133);\nvar isEventSupported = _dereq_(135);\n\n/**\n * Summary of `ReactBrowserEventEmitter` event handling:\n *\n *  - Top-level delegation is used to trap most native browser events. This\n *    may only occur in the main thread and is the responsibility of\n *    ReactEventListener, which is injected and can therefore support pluggable\n *    event sources. This is the only work that occurs in the main thread.\n *\n *  - We normalize and de-duplicate events to account for browser quirks. This\n *    may be done in the worker thread.\n *\n *  - Forward these native events (with the associated top-level type used to\n *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want\n *    to extract any synthetic events.\n *\n *  - The `EventPluginHub` will then process each event by annotating them with\n *    \"dispatches\", a sequence of listeners and IDs that care about that event.\n *\n *  - The `EventPluginHub` then dispatches the events.\n *\n * Overview of React and the event system:\n *\n * +------------+    .\n * |    DOM     |    .\n * +------------+    .\n *       |           .\n *       v           .\n * +------------+    .\n * | ReactEvent |    .\n * |  Listener  |    .\n * +------------+    .                         +-----------+\n *       |           .               +--------+|SimpleEvent|\n *       |           .               |         |Plugin     |\n * +-----|------+    .               v         +-----------+\n * |     |      |    .    +--------------+                    +------------+\n * |     +-----------.--->|EventPluginHub|                    |    Event   |\n * |            |    .    |              |     +-----------+  | Propagators|\n * | ReactEvent |    .    |              |     |TapEvent   |  |------------|\n * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|\n * |            |    .    |              |     +-----------+  |  utilities |\n * |     +-----------.--->|              |                    +------------+\n * |     |      |    .    +--------------+\n * +-----|------+    .                ^        +-----------+\n *       |           .                |        |Enter/Leave|\n *       +           .                +-------+|Plugin     |\n * +-------------+   .                         +-----------+\n * | application |   .\n * |-------------|   .\n * |             |   .\n * |             |   .\n * +-------------+   .\n *                   .\n *    React Core     .  General Purpose Event Plugin System\n */\n\nvar hasEventPageXY;\nvar alreadyListeningTo = {};\nvar isMonitoringScrollValue = false;\nvar reactTopListenersCounter = 0;\n\n// For events like 'submit' which don't consistently bubble (which we trap at a\n// lower node than `document`), binding at `document` would cause duplicate\n// events so we don't include them here\nvar topEventMapping = {\n  topAbort: 'abort',\n  topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',\n  topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',\n  topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',\n  topBlur: 'blur',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topChange: 'change',\n  topClick: 'click',\n  topCompositionEnd: 'compositionend',\n  topCompositionStart: 'compositionstart',\n  topCompositionUpdate: 'compositionupdate',\n  topContextMenu: 'contextmenu',\n  topCopy: 'copy',\n  topCut: 'cut',\n  topDoubleClick: 'dblclick',\n  topDrag: 'drag',\n  topDragEnd: 'dragend',\n  topDragEnter: 'dragenter',\n  topDragExit: 'dragexit',\n  topDragLeave: 'dragleave',\n  topDragOver: 'dragover',\n  topDragStart: 'dragstart',\n  topDrop: 'drop',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topFocus: 'focus',\n  topInput: 'input',\n  topKeyDown: 'keydown',\n  topKeyPress: 'keypress',\n  topKeyUp: 'keyup',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topMouseDown: 'mousedown',\n  topMouseMove: 'mousemove',\n  topMouseOut: 'mouseout',\n  topMouseOver: 'mouseover',\n  topMouseUp: 'mouseup',\n  topPaste: 'paste',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topScroll: 'scroll',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topSelectionChange: 'selectionchange',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTextInput: 'textInput',\n  topTimeUpdate: 'timeupdate',\n  topTouchCancel: 'touchcancel',\n  topTouchEnd: 'touchend',\n  topTouchMove: 'touchmove',\n  topTouchStart: 'touchstart',\n  topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting',\n  topWheel: 'wheel'\n};\n\n/**\n * To ensure no conflicts with other potential React instances on the page\n */\nvar topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2);\n\nfunction getListeningForDocument(mountAt) {\n  // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`\n  // directly.\n  if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {\n    mountAt[topListenersIDKey] = reactTopListenersCounter++;\n    alreadyListeningTo[mountAt[topListenersIDKey]] = {};\n  }\n  return alreadyListeningTo[mountAt[topListenersIDKey]];\n}\n\n/**\n * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For\n * example:\n *\n *   EventPluginHub.putListener('myID', 'onClick', myFunction);\n *\n * This would allocate a \"registration\" of `('onClick', myFunction)` on 'myID'.\n *\n * @internal\n */\nvar ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {\n\n  /**\n   * Injectable event backend\n   */\n  ReactEventListener: null,\n\n  injection: {\n    /**\n     * @param {object} ReactEventListener\n     */\n    injectReactEventListener: function (ReactEventListener) {\n      ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel);\n      ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;\n    }\n  },\n\n  /**\n   * Sets whether or not any created callbacks should be enabled.\n   *\n   * @param {boolean} enabled True if callbacks should be enabled.\n   */\n  setEnabled: function (enabled) {\n    if (ReactBrowserEventEmitter.ReactEventListener) {\n      ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled);\n    }\n  },\n\n  /**\n   * @return {boolean} True if callbacks are enabled.\n   */\n  isEnabled: function () {\n    return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled());\n  },\n\n  /**\n   * We listen for bubbled touch events on the document object.\n   *\n   * Firefox v8.01 (and possibly others) exhibited strange behavior when\n   * mounting `onmousemove` events at some node that was not the document\n   * element. The symptoms were that if your mouse is not moving over something\n   * contained within that mount point (for example on the background) the\n   * top-level listeners for `onmousemove` won't be called. However, if you\n   * register the `mousemove` on the document object, then it will of course\n   * catch all `mousemove`s. This along with iOS quirks, justifies restricting\n   * top-level listeners to the document object only, at least for these\n   * movement types of events and possibly all events.\n   *\n   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html\n   *\n   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but\n   * they bubble to document.\n   *\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {object} contentDocumentHandle Document which owns the container\n   */\n  listenTo: function (registrationName, contentDocumentHandle) {\n    var mountAt = contentDocumentHandle;\n    var isListening = getListeningForDocument(mountAt);\n    var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName];\n\n    var topLevelTypes = EventConstants.topLevelTypes;\n    for (var i = 0; i < dependencies.length; i++) {\n      var dependency = dependencies[i];\n      if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {\n        if (dependency === topLevelTypes.topWheel) {\n          if (isEventSupported('wheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);\n          } else if (isEventSupported('mousewheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);\n          } else {\n            // Firefox needs to capture a different mouse scroll event.\n            // @see http://www.quirksmode.org/dom/events/tests/scroll.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt);\n          }\n        } else if (dependency === topLevelTypes.topScroll) {\n\n          if (isEventSupported('scroll', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);\n          } else {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE);\n          }\n        } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) {\n\n          if (isEventSupported('focus', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);\n          } else if (isEventSupported('focusin')) {\n            // IE has `focusin` and `focusout` events which bubble.\n            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);\n          }\n\n          // to make sure blur and focus event listeners are only attached once\n          isListening[topLevelTypes.topBlur] = true;\n          isListening[topLevelTypes.topFocus] = true;\n        } else if (topEventMapping.hasOwnProperty(dependency)) {\n          ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt);\n        }\n\n        isListening[dependency] = true;\n      }\n    }\n  },\n\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  /**\n   * Listens to window scroll and resize events. We cache scroll values so that\n   * application code can access them without triggering reflows.\n   *\n   * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when\n   * pageX/pageY isn't supported (legacy browsers).\n   *\n   * NOTE: Scroll events do not bubble.\n   *\n   * @see http://www.quirksmode.org/dom/events/scroll.html\n   */\n  ensureScrollValueMonitoring: function () {\n    if (hasEventPageXY === undefined) {\n      hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent');\n    }\n    if (!hasEventPageXY && !isMonitoringScrollValue) {\n      var refresh = ViewportMetrics.refreshScrollValues;\n      ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);\n      isMonitoringScrollValue = true;\n    }\n  }\n\n});\n\nmodule.exports = ReactBrowserEventEmitter;\n},{\"114\":114,\"133\":133,\"135\":135,\"16\":16,\"172\":172,\"18\":18,\"66\":66}],28:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildReconciler\n */\n\n'use strict';\n\nvar ReactReconciler = _dereq_(87);\n\nvar instantiateReactComponent = _dereq_(134);\nvar KeyEscapeUtils = _dereq_(23);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\nfunction instantiateChild(childInstances, child, name, selfDebugID) {\n  // We found a component instance.\n  var keyUnique = childInstances[name] === undefined;\n  if (\"development\" !== 'production') {\n    var ReactComponentTreeDevtool = _dereq_(34);\n    \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n  }\n  if (child != null && keyUnique) {\n    childInstances[name] = instantiateReactComponent(child, true);\n  }\n}\n\n/**\n * ReactChildReconciler provides helpers for initializing or updating a set of\n * children. Its output is suitable for passing it onto ReactMultiChild which\n * does diffed reordering and insertion.\n */\nvar ReactChildReconciler = {\n  /**\n   * Generates a \"mount image\" for each of the supplied children. In the case\n   * of `ReactDOMComponent`, a mount image is a string of markup.\n   *\n   * @param {?object} nestedChildNodes Nested child maps.\n   * @return {?object} A set of child instances.\n   * @internal\n   */\n  instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID // __DEV__ only\n  ) {\n    if (nestedChildNodes == null) {\n      return null;\n    }\n    var childInstances = {};\n\n    if (\"development\" !== 'production') {\n      traverseAllChildren(nestedChildNodes, function (childInsts, child, name) {\n        return instantiateChild(childInsts, child, name, selfDebugID);\n      }, childInstances);\n    } else {\n      traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);\n    }\n    return childInstances;\n  },\n\n  /**\n   * Updates the rendered children and returns a new set of children.\n   *\n   * @param {?object} prevChildren Previously initialized set of children.\n   * @param {?object} nextChildren Flat child element maps.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @return {?object} A new set of child instances.\n   * @internal\n   */\n  updateChildren: function (prevChildren, nextChildren, removedNodes, transaction, context) {\n    // We currently don't have a way to track moves here but if we use iterators\n    // instead of for..in we can zip the iterators and check if an item has\n    // moved.\n    // TODO: If nothing has changed, return the prevChildren object so that we\n    // can quickly bailout if nothing has changed.\n    if (!nextChildren && !prevChildren) {\n      return;\n    }\n    var name;\n    var prevChild;\n    for (name in nextChildren) {\n      if (!nextChildren.hasOwnProperty(name)) {\n        continue;\n      }\n      prevChild = prevChildren && prevChildren[name];\n      var prevElement = prevChild && prevChild._currentElement;\n      var nextElement = nextChildren[name];\n      if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {\n        ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);\n        nextChildren[name] = prevChild;\n      } else {\n        if (prevChild) {\n          removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n          ReactReconciler.unmountComponent(prevChild, false);\n        }\n        // The child must be instantiated before it's mounted.\n        var nextChildInstance = instantiateReactComponent(nextElement, true);\n        nextChildren[name] = nextChildInstance;\n      }\n    }\n    // Unmount children that are no longer present.\n    for (name in prevChildren) {\n      if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {\n        prevChild = prevChildren[name];\n        removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n        ReactReconciler.unmountComponent(prevChild, false);\n      }\n    }\n  },\n\n  /**\n   * Unmounts all rendered children. This should be used to clean up children\n   * when this component is unmounted.\n   *\n   * @param {?object} renderedChildren Previously initialized set of children.\n   * @internal\n   */\n  unmountChildren: function (renderedChildren, safely) {\n    for (var name in renderedChildren) {\n      if (renderedChildren.hasOwnProperty(name)) {\n        var renderedChild = renderedChildren[name];\n        ReactReconciler.unmountComponent(renderedChild, safely);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactChildReconciler;\n},{\"134\":134,\"143\":143,\"144\":144,\"171\":171,\"23\":23,\"34\":34,\"87\":87}],29:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildren\n */\n\n'use strict';\n\nvar PooledClass = _dereq_(25);\nvar ReactElement = _dereq_(62);\n\nvar emptyFunction = _dereq_(153);\nvar traverseAllChildren = _dereq_(144);\n\nvar twoArgumentPooler = PooledClass.twoArgumentPooler;\nvar fourArgumentPooler = PooledClass.fourArgumentPooler;\n\nvar userProvidedKeyEscapeRegex = /\\/+/g;\nfunction escapeUserProvidedKey(text) {\n  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * traversal. Allows avoiding binding callbacks.\n *\n * @constructor ForEachBookKeeping\n * @param {!function} forEachFunction Function to perform traversal with.\n * @param {?*} forEachContext Context to perform context with.\n */\nfunction ForEachBookKeeping(forEachFunction, forEachContext) {\n  this.func = forEachFunction;\n  this.context = forEachContext;\n  this.count = 0;\n}\nForEachBookKeeping.prototype.destructor = function () {\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);\n\nfunction forEachSingleChild(bookKeeping, child, name) {\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n  func.call(context, child, bookKeeping.count++);\n}\n\n/**\n * Iterates through children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach\n *\n * The provided forEachFunc(child, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} forEachFunc\n * @param {*} forEachContext Context for forEachContext.\n */\nfunction forEachChildren(children, forEachFunc, forEachContext) {\n  if (children == null) {\n    return children;\n  }\n  var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);\n  traverseAllChildren(children, forEachSingleChild, traverseContext);\n  ForEachBookKeeping.release(traverseContext);\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * mapping. Allows avoiding binding callbacks.\n *\n * @constructor MapBookKeeping\n * @param {!*} mapResult Object containing the ordered map of results.\n * @param {!function} mapFunction Function to perform mapping with.\n * @param {?*} mapContext Context to perform mapping with.\n */\nfunction MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {\n  this.result = mapResult;\n  this.keyPrefix = keyPrefix;\n  this.func = mapFunction;\n  this.context = mapContext;\n  this.count = 0;\n}\nMapBookKeeping.prototype.destructor = function () {\n  this.result = null;\n  this.keyPrefix = null;\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);\n\nfunction mapSingleChildIntoContext(bookKeeping, child, childKey) {\n  var result = bookKeeping.result;\n  var keyPrefix = bookKeeping.keyPrefix;\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n\n  var mappedChild = func.call(context, child, bookKeeping.count++);\n  if (Array.isArray(mappedChild)) {\n    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);\n  } else if (mappedChild != null) {\n    if (ReactElement.isValidElement(mappedChild)) {\n      mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,\n      // Keep both the (mapped) and old keys if they differ, just as\n      // traverseAllChildren used to do for objects as children\n      keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);\n    }\n    result.push(mappedChild);\n  }\n}\n\nfunction mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {\n  var escapedPrefix = '';\n  if (prefix != null) {\n    escapedPrefix = escapeUserProvidedKey(prefix) + '/';\n  }\n  var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);\n  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);\n  MapBookKeeping.release(traverseContext);\n}\n\n/**\n * Maps children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.map\n *\n * The provided mapFunction(child, key, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} func The map function.\n * @param {*} context Context for mapFunction.\n * @return {object} Object containing the ordered map of results.\n */\nfunction mapChildren(children, func, context) {\n  if (children == null) {\n    return children;\n  }\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, func, context);\n  return result;\n}\n\nfunction forEachSingleChildDummy(traverseContext, child, name) {\n  return null;\n}\n\n/**\n * Count the number of children that are typically specified as\n * `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.count\n *\n * @param {?*} children Children tree container.\n * @return {number} The number of children.\n */\nfunction countChildren(children, context) {\n  return traverseAllChildren(children, forEachSingleChildDummy, null);\n}\n\n/**\n * Flatten a children object (typically specified as `props.children`) and\n * return an array with appropriately re-keyed children.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray\n */\nfunction toArray(children) {\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);\n  return result;\n}\n\nvar ReactChildren = {\n  forEach: forEachChildren,\n  map: mapChildren,\n  mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,\n  count: countChildren,\n  toArray: toArray\n};\n\nmodule.exports = ReactChildren;\n},{\"144\":144,\"153\":153,\"25\":25,\"62\":62}],30:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponent = _dereq_(31);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactPropTypeLocationNames = _dereq_(83);\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar keyMirror = _dereq_(164);\nvar keyOf = _dereq_(165);\nvar warning = _dereq_(171);\n\nvar MIXINS_KEY = keyOf({ mixins: null });\n\n/**\n * Policies that describe methods in `ReactClassInterface`.\n */\nvar SpecPolicy = keyMirror({\n  /**\n   * These methods may be defined only once by the class specification or mixin.\n   */\n  DEFINE_ONCE: null,\n  /**\n   * These methods may be defined by both the class specification and mixins.\n   * Subsequent definitions will be chained. These methods must return void.\n   */\n  DEFINE_MANY: null,\n  /**\n   * These methods are overriding the base class.\n   */\n  OVERRIDE_BASE: null,\n  /**\n   * These methods are similar to DEFINE_MANY, except we assume they return\n   * objects. We try to merge the keys of the return values of all the mixed in\n   * functions. If there is a key conflict we throw.\n   */\n  DEFINE_MANY_MERGED: null\n});\n\nvar injectedMixins = [];\n\n/**\n * Composite components are higher-level components that compose other composite\n * or host components.\n *\n * To create a new type of `ReactClass`, pass a specification of\n * your new class to `React.createClass`. The only requirement of your class\n * specification is that you implement a `render` method.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return <div>Hello World</div>;\n *     }\n *   });\n *\n * The class specification supports a specific protocol of methods that have\n * special meaning (e.g. `render`). See `ReactClassInterface` for\n * more the comprehensive protocol. Any other properties and methods in the\n * class specification will be available on the prototype.\n *\n * @interface ReactClassInterface\n * @internal\n */\nvar ReactClassInterface = {\n\n  /**\n   * An array of Mixin objects to include when defining your component.\n   *\n   * @type {array}\n   * @optional\n   */\n  mixins: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * An object containing properties and methods that should be defined on\n   * the component's constructor instead of its prototype (static methods).\n   *\n   * @type {object}\n   * @optional\n   */\n  statics: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of prop types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  propTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  contextTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types this component sets for its children.\n   *\n   * @type {object}\n   * @optional\n   */\n  childContextTypes: SpecPolicy.DEFINE_MANY,\n\n  // ==== Definition methods ====\n\n  /**\n   * Invoked when the component is mounted. Values in the mapping will be set on\n   * `this.props` if that prop is not specified (i.e. using an `in` check).\n   *\n   * This method is invoked before `getInitialState` and therefore cannot rely\n   * on `this.state` or use `this.setState`.\n   *\n   * @return {object}\n   * @optional\n   */\n  getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Invoked once before the component is mounted. The return value will be used\n   * as the initial value of `this.state`.\n   *\n   *   getInitialState: function() {\n   *     return {\n   *       isOn: false,\n   *       fooBaz: new BazFoo()\n   *     }\n   *   }\n   *\n   * @return {object}\n   * @optional\n   */\n  getInitialState: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * @return {object}\n   * @optional\n   */\n  getChildContext: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Uses props from `this.props` and state from `this.state` to render the\n   * structure of the component.\n   *\n   * No guarantees are made about when or how often this method is invoked, so\n   * it must not have side effects.\n   *\n   *   render: function() {\n   *     var name = this.props.name;\n   *     return <div>Hello, {name}!</div>;\n   *   }\n   *\n   * @return {ReactComponent}\n   * @nosideeffects\n   * @required\n   */\n  render: SpecPolicy.DEFINE_ONCE,\n\n  // ==== Delegate methods ====\n\n  /**\n   * Invoked when the component is initially created and about to be mounted.\n   * This may have side effects, but any external subscriptions or data created\n   * by this method must be cleaned up in `componentWillUnmount`.\n   *\n   * @optional\n   */\n  componentWillMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component has been mounted and has a DOM representation.\n   * However, there is no guarantee that the DOM node is in the document.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been mounted (initialized and rendered) for the first time.\n   *\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked before the component receives new props.\n   *\n   * Use this as an opportunity to react to a prop transition by updating the\n   * state using `this.setState`. Current props are accessed via `this.props`.\n   *\n   *   componentWillReceiveProps: function(nextProps, nextContext) {\n   *     this.setState({\n   *       likesIncreasing: nextProps.likeCount > this.props.likeCount\n   *     });\n   *   }\n   *\n   * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop\n   * transition may cause a state change, but the opposite is not true. If you\n   * need it, you are probably looking for `componentWillUpdate`.\n   *\n   * @param {object} nextProps\n   * @optional\n   */\n  componentWillReceiveProps: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked while deciding if the component should be updated as a result of\n   * receiving new props, state and/or context.\n   *\n   * Use this as an opportunity to `return false` when you're certain that the\n   * transition to the new props/state/context will not require a component\n   * update.\n   *\n   *   shouldComponentUpdate: function(nextProps, nextState, nextContext) {\n   *     return !equal(nextProps, this.props) ||\n   *       !equal(nextState, this.state) ||\n   *       !equal(nextContext, this.context);\n   *   }\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @return {boolean} True if the component should update.\n   * @optional\n   */\n  shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,\n\n  /**\n   * Invoked when the component is about to update due to a transition from\n   * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`\n   * and `nextContext`.\n   *\n   * Use this as an opportunity to perform preparation before an update occurs.\n   *\n   * NOTE: You **cannot** use `this.setState()` in this method.\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @param {ReactReconcileTransaction} transaction\n   * @optional\n   */\n  componentWillUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component's DOM representation has been updated.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been updated.\n   *\n   * @param {object} prevProps\n   * @param {?object} prevState\n   * @param {?object} prevContext\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component is about to be removed from its parent and have\n   * its DOM representation destroyed.\n   *\n   * Use this as an opportunity to deallocate any external resources.\n   *\n   * NOTE: There is no `componentDidUnmount` since your component will have been\n   * destroyed by that point.\n   *\n   * @optional\n   */\n  componentWillUnmount: SpecPolicy.DEFINE_MANY,\n\n  // ==== Advanced methods ====\n\n  /**\n   * Updates the component's currently mounted DOM representation.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   * @overridable\n   */\n  updateComponent: SpecPolicy.OVERRIDE_BASE\n\n};\n\n/**\n * Mapping from class specification keys to special processing functions.\n *\n * Although these are declared like instance properties in the specification\n * when defining classes using `React.createClass`, they are actually static\n * and are accessible on the constructor instead of the prototype. Despite\n * being static, they must be defined outside of the \"statics\" key under\n * which all other static methods are defined.\n */\nvar RESERVED_SPEC_KEYS = {\n  displayName: function (Constructor, displayName) {\n    Constructor.displayName = displayName;\n  },\n  mixins: function (Constructor, mixins) {\n    if (mixins) {\n      for (var i = 0; i < mixins.length; i++) {\n        mixSpecIntoComponent(Constructor, mixins[i]);\n      }\n    }\n  },\n  childContextTypes: function (Constructor, childContextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext);\n    }\n    Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes);\n  },\n  contextTypes: function (Constructor, contextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context);\n    }\n    Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes);\n  },\n  /**\n   * Special case getDefaultProps which should move into statics but requires\n   * automatic merging.\n   */\n  getDefaultProps: function (Constructor, getDefaultProps) {\n    if (Constructor.getDefaultProps) {\n      Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps);\n    } else {\n      Constructor.getDefaultProps = getDefaultProps;\n    }\n  },\n  propTypes: function (Constructor, propTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop);\n    }\n    Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes);\n  },\n  statics: function (Constructor, statics) {\n    mixStaticSpecIntoComponent(Constructor, statics);\n  },\n  autobind: function () {} };\n\n// noop\nfunction validateTypeDef(Constructor, typeDef, location) {\n  for (var propName in typeDef) {\n    if (typeDef.hasOwnProperty(propName)) {\n      // use a warning instead of an invariant so components\n      // don't show up in prod but only in __DEV__\n      \"development\" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0;\n    }\n  }\n}\n\nfunction validateMethodOverride(isAlreadyDefined, name) {\n  var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null;\n\n  // Disallow overriding of base class methods unless explicitly allowed.\n  if (ReactClassMixin.hasOwnProperty(name)) {\n    !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.', name) : _prodInvariant('73', name) : void 0;\n  }\n\n  // Disallow defining methods more than once unless explicitly allowed.\n  if (isAlreadyDefined) {\n    !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('74', name) : void 0;\n  }\n}\n\n/**\n * Mixin helper which handles policy validation and reserved\n * specification keys when building React classes.\n */\nfunction mixSpecIntoComponent(Constructor, spec) {\n  if (!spec) {\n    return;\n  }\n\n  !(typeof spec !== 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component class or function as a mixin. Instead, just use a regular object.') : _prodInvariant('75') : void 0;\n  !!ReactElement.isValidElement(spec) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component as a mixin. Instead, just use a regular object.') : _prodInvariant('76') : void 0;\n\n  var proto = Constructor.prototype;\n  var autoBindPairs = proto.__reactAutoBindPairs;\n\n  // By handling mixins before any other properties, we ensure the same\n  // chaining order is applied to methods with DEFINE_MANY policy, whether\n  // mixins are listed before or after these methods in the spec.\n  if (spec.hasOwnProperty(MIXINS_KEY)) {\n    RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);\n  }\n\n  for (var name in spec) {\n    if (!spec.hasOwnProperty(name)) {\n      continue;\n    }\n\n    if (name === MIXINS_KEY) {\n      // We have already handled mixins in a special case above.\n      continue;\n    }\n\n    var property = spec[name];\n    var isAlreadyDefined = proto.hasOwnProperty(name);\n    validateMethodOverride(isAlreadyDefined, name);\n\n    if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {\n      RESERVED_SPEC_KEYS[name](Constructor, property);\n    } else {\n      // Setup methods on prototype:\n      // The following member methods should not be automatically bound:\n      // 1. Expected ReactClass methods (in the \"interface\").\n      // 2. Overridden methods (that were mixed in).\n      var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);\n      var isFunction = typeof property === 'function';\n      var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;\n\n      if (shouldAutoBind) {\n        autoBindPairs.push(name, property);\n        proto[name] = property;\n      } else {\n        if (isAlreadyDefined) {\n          var specPolicy = ReactClassInterface[name];\n\n          // These cases should already be caught by validateMethodOverride.\n          !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.', specPolicy, name) : _prodInvariant('77', specPolicy, name) : void 0;\n\n          // For methods which are defined more than once, call the existing\n          // methods before calling the new property, merging if appropriate.\n          if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {\n            proto[name] = createMergedResultFunction(proto[name], property);\n          } else if (specPolicy === SpecPolicy.DEFINE_MANY) {\n            proto[name] = createChainedFunction(proto[name], property);\n          }\n        } else {\n          proto[name] = property;\n          if (\"development\" !== 'production') {\n            // Add verbose displayName to the function, which helps when looking\n            // at profiling tools.\n            if (typeof property === 'function' && spec.displayName) {\n              proto[name].displayName = spec.displayName + '_' + name;\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction mixStaticSpecIntoComponent(Constructor, statics) {\n  if (!statics) {\n    return;\n  }\n  for (var name in statics) {\n    var property = statics[name];\n    if (!statics.hasOwnProperty(name)) {\n      continue;\n    }\n\n    var isReserved = name in RESERVED_SPEC_KEYS;\n    !!isReserved ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved property, `%s`, that shouldn\\'t be on the \"statics\" key. Define it as an instance property instead; it will still be accessible on the constructor.', name) : _prodInvariant('78', name) : void 0;\n\n    var isInherited = name in Constructor;\n    !!isInherited ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('79', name) : void 0;\n    Constructor[name] = property;\n  }\n}\n\n/**\n * Merge two objects, but throw if both contain the same key.\n *\n * @param {object} one The first object, which is mutated.\n * @param {object} two The second object\n * @return {object} one after it has been mutated to contain everything in two.\n */\nfunction mergeIntoWithNoDuplicateKeys(one, two) {\n  !(one && two && typeof one === 'object' && typeof two === 'object') ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : _prodInvariant('80') : void 0;\n\n  for (var key in two) {\n    if (two.hasOwnProperty(key)) {\n      !(one[key] === undefined) ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.', key) : _prodInvariant('81', key) : void 0;\n      one[key] = two[key];\n    }\n  }\n  return one;\n}\n\n/**\n * Creates a function that invokes two functions and merges their return values.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createMergedResultFunction(one, two) {\n  return function mergedResult() {\n    var a = one.apply(this, arguments);\n    var b = two.apply(this, arguments);\n    if (a == null) {\n      return b;\n    } else if (b == null) {\n      return a;\n    }\n    var c = {};\n    mergeIntoWithNoDuplicateKeys(c, a);\n    mergeIntoWithNoDuplicateKeys(c, b);\n    return c;\n  };\n}\n\n/**\n * Creates a function that invokes two functions and ignores their return vales.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createChainedFunction(one, two) {\n  return function chainedFunction() {\n    one.apply(this, arguments);\n    two.apply(this, arguments);\n  };\n}\n\n/**\n * Binds a method to the component.\n *\n * @param {object} component Component whose method is going to be bound.\n * @param {function} method Method to be bound.\n * @return {function} The bound method.\n */\nfunction bindAutoBindMethod(component, method) {\n  var boundMethod = method.bind(component);\n  if (\"development\" !== 'production') {\n    boundMethod.__reactBoundContext = component;\n    boundMethod.__reactBoundMethod = method;\n    boundMethod.__reactBoundArguments = null;\n    var componentName = component.constructor.displayName;\n    var _bind = boundMethod.bind;\n    boundMethod.bind = function (newThis) {\n      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n        args[_key - 1] = arguments[_key];\n      }\n\n      // User is trying to bind() an autobound method; we effectively will\n      // ignore the value of \"this\" that the user is trying to use, so\n      // let's warn.\n      if (newThis !== component && newThis !== null) {\n        \"development\" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0;\n      } else if (!args.length) {\n        \"development\" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0;\n        return boundMethod;\n      }\n      var reboundMethod = _bind.apply(boundMethod, arguments);\n      reboundMethod.__reactBoundContext = component;\n      reboundMethod.__reactBoundMethod = method;\n      reboundMethod.__reactBoundArguments = args;\n      return reboundMethod;\n    };\n  }\n  return boundMethod;\n}\n\n/**\n * Binds all auto-bound methods in a component.\n *\n * @param {object} component Component whose method is going to be bound.\n */\nfunction bindAutoBindMethods(component) {\n  var pairs = component.__reactAutoBindPairs;\n  for (var i = 0; i < pairs.length; i += 2) {\n    var autoBindKey = pairs[i];\n    var method = pairs[i + 1];\n    component[autoBindKey] = bindAutoBindMethod(component, method);\n  }\n}\n\n/**\n * Add more to the ReactClass base class. These are all legacy features and\n * therefore not already part of the modern ReactComponent.\n */\nvar ReactClassMixin = {\n\n  /**\n   * TODO: This will be deprecated because state should always keep a consistent\n   * type signature and the only use case for this, is to avoid that.\n   */\n  replaceState: function (newState, callback) {\n    this.updater.enqueueReplaceState(this, newState);\n    if (callback) {\n      this.updater.enqueueCallback(this, callback, 'replaceState');\n    }\n  },\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function () {\n    return this.updater.isMounted(this);\n  }\n};\n\nvar ReactClassComponent = function () {};\n_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);\n\n/**\n * Module for creating composite components.\n *\n * @class ReactClass\n */\nvar ReactClass = {\n\n  /**\n   * Creates a composite component class given a class specification.\n   * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass\n   *\n   * @param {object} spec Class specification (which must define `render`).\n   * @return {function} Component constructor function.\n   * @public\n   */\n  createClass: function (spec) {\n    var Constructor = function (props, context, updater) {\n      // This constructor gets overridden by mocks. The argument is used\n      // by mocks to assert on what gets mounted.\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0;\n      }\n\n      // Wire up auto-binding\n      if (this.__reactAutoBindPairs.length) {\n        bindAutoBindMethods(this);\n      }\n\n      this.props = props;\n      this.context = context;\n      this.refs = emptyObject;\n      this.updater = updater || ReactNoopUpdateQueue;\n\n      this.state = null;\n\n      // ReactClasses doesn't have constructors. Instead, they use the\n      // getInitialState and componentWillMount methods for initialization.\n\n      var initialState = this.getInitialState ? this.getInitialState() : null;\n      if (\"development\" !== 'production') {\n        // We allow auto-mocks to proceed as if they're returning null.\n        if (initialState === undefined && this.getInitialState._isMockFunction) {\n          // This is probably bad practice. Consider warning here and\n          // deprecating this convenience.\n          initialState = null;\n        }\n      }\n      !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : _prodInvariant('82', Constructor.displayName || 'ReactCompositeComponent') : void 0;\n\n      this.state = initialState;\n    };\n    Constructor.prototype = new ReactClassComponent();\n    Constructor.prototype.constructor = Constructor;\n    Constructor.prototype.__reactAutoBindPairs = [];\n\n    injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));\n\n    mixSpecIntoComponent(Constructor, spec);\n\n    // Initialize the defaultProps property after all mixins have been merged.\n    if (Constructor.getDefaultProps) {\n      Constructor.defaultProps = Constructor.getDefaultProps();\n    }\n\n    if (\"development\" !== 'production') {\n      // This is a tag to indicate that the use of these method names is ok,\n      // since it's used with createClass. If it's not, then it's likely a\n      // mistake so we'll warn you to use the static property, property\n      // initializer or constructor respectively.\n      if (Constructor.getDefaultProps) {\n        Constructor.getDefaultProps.isReactClassApproved = {};\n      }\n      if (Constructor.prototype.getInitialState) {\n        Constructor.prototype.getInitialState.isReactClassApproved = {};\n      }\n    }\n\n    !Constructor.prototype.render ? \"development\" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : _prodInvariant('83') : void 0;\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0;\n    }\n\n    // Reduce time spent doing lookups by setting these on the prototype.\n    for (var methodName in ReactClassInterface) {\n      if (!Constructor.prototype[methodName]) {\n        Constructor.prototype[methodName] = null;\n      }\n    }\n\n    return Constructor;\n  },\n\n  injection: {\n    injectMixin: function (mixin) {\n      injectedMixins.push(mixin);\n    }\n  }\n\n};\n\nmodule.exports = ReactClass;\n},{\"139\":139,\"154\":154,\"161\":161,\"164\":164,\"165\":165,\"171\":171,\"172\":172,\"31\":31,\"62\":62,\"81\":81,\"83\":83,\"84\":84}],31:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar canDefineProperty = _dereq_(117);\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Base class helpers for the updating state of a component.\n */\nfunction ReactComponent(props, context, updater) {\n  this.props = props;\n  this.context = context;\n  this.refs = emptyObject;\n  // We initialize the default updater but the real one gets injected by the\n  // renderer.\n  this.updater = updater || ReactNoopUpdateQueue;\n}\n\nReactComponent.prototype.isReactComponent = {};\n\n/**\n * Sets a subset of the state. Always use this to mutate\n * state. You should treat `this.state` as immutable.\n *\n * There is no guarantee that `this.state` will be immediately updated, so\n * accessing `this.state` after calling this method may return the old value.\n *\n * There is no guarantee that calls to `setState` will run synchronously,\n * as they may eventually be batched together.  You can provide an optional\n * callback that will be executed when the call to setState is actually\n * completed.\n *\n * When a function is provided to setState, it will be called at some point in\n * the future (not synchronously). It will be called with the up to date\n * component arguments (state, props, context). These values can be different\n * from this.* because your function may be called after receiveProps but before\n * shouldComponentUpdate, and this new state, props, and context will not yet be\n * assigned to this.\n *\n * @param {object|function} partialState Next partial state or function to\n *        produce next partial state to be merged with current state.\n * @param {?function} callback Called after state is updated.\n * @final\n * @protected\n */\nReactComponent.prototype.setState = function (partialState, callback) {\n  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? \"development\" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;\n  this.updater.enqueueSetState(this, partialState);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'setState');\n  }\n};\n\n/**\n * Forces an update. This should only be invoked when it is known with\n * certainty that we are **not** in a DOM transaction.\n *\n * You may want to call this when you know that some deeper aspect of the\n * component's state has changed but `setState` was not called.\n *\n * This will not invoke `shouldComponentUpdate`, but it will invoke\n * `componentWillUpdate` and `componentDidUpdate`.\n *\n * @param {?function} callback Called after update is complete.\n * @final\n * @protected\n */\nReactComponent.prototype.forceUpdate = function (callback) {\n  this.updater.enqueueForceUpdate(this);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'forceUpdate');\n  }\n};\n\n/**\n * Deprecated APIs. These APIs used to exist on classic React classes but since\n * we would like to deprecate them, we're not going to move them over to this\n * modern base class. Instead, we define a getter that warns if it's accessed.\n */\nif (\"development\" !== 'production') {\n  var deprecatedAPIs = {\n    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],\n    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']\n  };\n  var defineDeprecationWarning = function (methodName, info) {\n    if (canDefineProperty) {\n      Object.defineProperty(ReactComponent.prototype, methodName, {\n        get: function () {\n          \"development\" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0;\n          return undefined;\n        }\n      });\n    }\n  };\n  for (var fnName in deprecatedAPIs) {\n    if (deprecatedAPIs.hasOwnProperty(fnName)) {\n      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);\n    }\n  }\n}\n\nmodule.exports = ReactComponent;\n},{\"117\":117,\"139\":139,\"154\":154,\"161\":161,\"171\":171,\"81\":81}],32:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentBrowserEnvironment\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMIDOperations = _dereq_(47);\n\n/**\n * Abstracts away all functionality of the reconciler that requires knowledge of\n * the browser context. TODO: These callers should be refactored to avoid the\n * need for this injection.\n */\nvar ReactComponentBrowserEnvironment = {\n\n  processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,\n\n  replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup,\n\n  /**\n   * If a particular environment requires that some resources be cleaned up,\n   * specify this in the injected Mixin. In the DOM, we would likely want to\n   * purge any cached node ID lookups.\n   *\n   * @private\n   */\n  unmountIDFromEnvironment: function (rootNodeID) {}\n\n};\n\nmodule.exports = ReactComponentBrowserEnvironment;\n},{\"47\":47,\"7\":7}],33:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentEnvironment\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nvar injected = false;\n\nvar ReactComponentEnvironment = {\n\n  /**\n   * Optionally injectable environment dependent cleanup hook. (server vs.\n   * browser etc). Example: A browser system caches DOM nodes based on component\n   * ID and must remove that cache entry when this instance is unmounted.\n   */\n  unmountIDFromEnvironment: null,\n\n  /**\n   * Optionally injectable hook for swapping out mount images in the middle of\n   * the tree.\n   */\n  replaceNodeWithMarkup: null,\n\n  /**\n   * Optionally injectable hook for processing a queue of child updates. Will\n   * later move into MultiChildComponents.\n   */\n  processChildrenUpdates: null,\n\n  injection: {\n    injectEnvironment: function (environment) {\n      !!injected ? \"development\" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0;\n      ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment;\n      ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;\n      ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;\n      injected = true;\n    }\n  }\n\n};\n\nmodule.exports = ReactComponentEnvironment;\n},{\"139\":139,\"161\":161}],34:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentTreeDevtool\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar tree = {};\nvar unmountedIDs = {};\nvar rootIDs = {};\n\nfunction updateTree(id, update) {\n  if (!tree[id]) {\n    tree[id] = {\n      element: null,\n      parentID: null,\n      ownerID: null,\n      text: null,\n      childIDs: [],\n      displayName: 'Unknown',\n      isMounted: false,\n      updateCount: 0\n    };\n  }\n  update(tree[id]);\n}\n\nfunction purgeDeep(id) {\n  var item = tree[id];\n  if (item) {\n    var childIDs = item.childIDs;\n\n    delete tree[id];\n    childIDs.forEach(purgeDeep);\n  }\n}\n\nfunction describeComponentFrame(name, source, ownerName) {\n  return '\\n    in ' + name + (source ? ' (at ' + source.fileName.replace(/^.*[\\\\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');\n}\n\nfunction describeID(id) {\n  var name = ReactComponentTreeDevtool.getDisplayName(id);\n  var element = ReactComponentTreeDevtool.getElement(id);\n  var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n  var ownerName;\n  if (ownerID) {\n    ownerName = ReactComponentTreeDevtool.getDisplayName(ownerID);\n  }\n  \"development\" !== 'production' ? warning(element, 'ReactComponentTreeDevtool: Missing React element for debugID %s when ' + 'building stack', id) : void 0;\n  return describeComponentFrame(name, element && element._source, ownerName);\n}\n\nvar ReactComponentTreeDevtool = {\n  onSetDisplayName: function (id, displayName) {\n    updateTree(id, function (item) {\n      return item.displayName = displayName;\n    });\n  },\n  onSetChildren: function (id, nextChildIDs) {\n    updateTree(id, function (item) {\n      item.childIDs = nextChildIDs;\n\n      nextChildIDs.forEach(function (nextChildID) {\n        var nextChild = tree[nextChildID];\n        !nextChild ? \"development\" !== 'production' ? invariant(false, 'Expected devtool events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('68') : void 0;\n        !(nextChild.displayName != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('69') : void 0;\n        !(nextChild.childIDs != null || nextChild.text != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('70') : void 0;\n        !nextChild.isMounted ? \"development\" !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;\n        if (nextChild.parentID == null) {\n          nextChild.parentID = id;\n          // TODO: This shouldn't be necessary but mounting a new root during in\n          // componentWillMount currently causes not-yet-mounted components to\n          // be purged from our tree data so their parent ID is missing.\n        }\n        !(nextChild.parentID === id) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('72', nextChildID, nextChild.parentID, id) : void 0;\n      });\n    });\n  },\n  onSetOwner: function (id, ownerID) {\n    updateTree(id, function (item) {\n      return item.ownerID = ownerID;\n    });\n  },\n  onSetParent: function (id, parentID) {\n    updateTree(id, function (item) {\n      return item.parentID = parentID;\n    });\n  },\n  onSetText: function (id, text) {\n    updateTree(id, function (item) {\n      return item.text = text;\n    });\n  },\n  onBeforeMountComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onBeforeUpdateComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onMountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = true;\n    });\n  },\n  onMountRootComponent: function (id) {\n    rootIDs[id] = true;\n  },\n  onUpdateComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.updateCount++;\n    });\n  },\n  onUnmountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = false;\n    });\n    unmountedIDs[id] = true;\n    delete rootIDs[id];\n  },\n  purgeUnmountedComponents: function () {\n    if (ReactComponentTreeDevtool._preventPurging) {\n      // Should only be used for testing.\n      return;\n    }\n\n    for (var id in unmountedIDs) {\n      purgeDeep(id);\n    }\n    unmountedIDs = {};\n  },\n  isMounted: function (id) {\n    var item = tree[id];\n    return item ? item.isMounted : false;\n  },\n  getCurrentStackAddendum: function (topElement) {\n    var info = '';\n    if (topElement) {\n      var type = topElement.type;\n      var name = typeof type === 'function' ? type.displayName || type.name : type;\n      var owner = topElement._owner;\n      info += describeComponentFrame(name || 'Unknown', topElement._source, owner && owner.getName());\n    }\n\n    var currentOwner = ReactCurrentOwner.current;\n    var id = currentOwner && currentOwner._debugID;\n\n    info += ReactComponentTreeDevtool.getStackAddendumByID(id);\n    return info;\n  },\n  getStackAddendumByID: function (id) {\n    var info = '';\n    while (id) {\n      info += describeID(id);\n      id = ReactComponentTreeDevtool.getParentID(id);\n    }\n    return info;\n  },\n  getChildIDs: function (id) {\n    var item = tree[id];\n    return item ? item.childIDs : [];\n  },\n  getDisplayName: function (id) {\n    var item = tree[id];\n    return item ? item.displayName : 'Unknown';\n  },\n  getElement: function (id) {\n    var item = tree[id];\n    return item ? item.element : null;\n  },\n  getOwnerID: function (id) {\n    var item = tree[id];\n    return item ? item.ownerID : null;\n  },\n  getParentID: function (id) {\n    var item = tree[id];\n    return item ? item.parentID : null;\n  },\n  getSource: function (id) {\n    var item = tree[id];\n    var element = item ? item.element : null;\n    var source = element != null ? element._source : null;\n    return source;\n  },\n  getText: function (id) {\n    var item = tree[id];\n    return item ? item.text : null;\n  },\n  getUpdateCount: function (id) {\n    var item = tree[id];\n    return item ? item.updateCount : 0;\n  },\n  getRootIDs: function () {\n    return Object.keys(rootIDs);\n  },\n  getRegisteredIDs: function () {\n    return Object.keys(tree);\n  }\n};\n\nmodule.exports = ReactComponentTreeDevtool;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36}],35:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCompositeComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\nvar ReactErrorUtils = _dereq_(65);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactNodeTypes = _dereq_(80);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactReconciler = _dereq_(87);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nfunction StatelessComponent(Component) {}\nStatelessComponent.prototype.render = function () {\n  var Component = ReactInstanceMap.get(this)._currentElement.type;\n  var element = Component(this.props, this.context, this.updater);\n  warnIfInvalidElement(Component, element);\n  return element;\n};\n\nfunction warnIfInvalidElement(Component, element) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;\n    \"development\" !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0;\n  }\n}\n\nfunction invokeComponentDidMountWithTimer() {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n  publicInstance.componentDidMount();\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n}\n\nfunction invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n  publicInstance.componentDidUpdate(prevProps, prevState, prevContext);\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n}\n\nfunction shouldConstruct(Component) {\n  return Component.prototype && Component.prototype.isReactComponent;\n}\n\n/**\n * ------------------ The Life-Cycle of a Composite Component ------------------\n *\n * - constructor: Initialization of state. The instance is now retained.\n *   - componentWillMount\n *   - render\n *   - [children's constructors]\n *     - [children's componentWillMount and render]\n *     - [children's componentDidMount]\n *     - componentDidMount\n *\n *       Update Phases:\n *       - componentWillReceiveProps (only called if parent updated)\n *       - shouldComponentUpdate\n *         - componentWillUpdate\n *           - render\n *           - [children's constructors or receive props phases]\n *         - componentDidUpdate\n *\n *     - componentWillUnmount\n *     - [children's componentWillUnmount]\n *   - [children destroyed]\n * - (destroyed): The instance is now blank, released by React and ready for GC.\n *\n * -----------------------------------------------------------------------------\n */\n\n/**\n * An incrementing ID assigned to each component when it is mounted. This is\n * used to enforce the order in which `ReactUpdates` updates dirty components.\n *\n * @private\n */\nvar nextMountID = 1;\n\n/**\n * @lends {ReactCompositeComponent.prototype}\n */\nvar ReactCompositeComponentMixin = {\n\n  /**\n   * Base constructor for all composite component.\n   *\n   * @param {ReactElement} element\n   * @final\n   * @internal\n   */\n  construct: function (element) {\n    this._currentElement = element;\n    this._rootNodeID = null;\n    this._instance = null;\n    this._hostParent = null;\n    this._hostContainerInfo = null;\n\n    // See ReactUpdateQueue\n    this._updateBatchNumber = null;\n    this._pendingElement = null;\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    this._renderedNodeType = null;\n    this._renderedComponent = null;\n    this._context = null;\n    this._mountOrder = 0;\n    this._topLevelWrapper = null;\n\n    // See ReactUpdates and ReactUpdateQueue.\n    this._pendingCallbacks = null;\n\n    // ComponentWillUnmount shall only be called once\n    this._calledComponentWillUnmount = false;\n\n    if (\"development\" !== 'production') {\n      this._warnedAboutRefsInRender = false;\n    }\n  },\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} hostParent\n   * @param {?object} hostContainerInfo\n   * @param {?object} context\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._context = context;\n    this._mountOrder = nextMountID++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var publicProps = this._currentElement.props;\n    var publicContext = this._processContext(context);\n\n    var Component = this._currentElement.type;\n\n    var updateQueue = transaction.getUpdateQueue();\n\n    // Initialize the public class\n    var inst = this._constructComponent(publicProps, publicContext, updateQueue);\n    var renderedElement;\n\n    // Support functional components\n    if (!shouldConstruct(Component) && (inst == null || inst.render == null)) {\n      renderedElement = inst;\n      warnIfInvalidElement(Component, renderedElement);\n      !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? \"development\" !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0;\n      inst = new StatelessComponent(Component);\n    }\n\n    if (\"development\" !== 'production') {\n      // This will throw later in _renderValidatedComponent, but add an early\n      // warning now to help debugging\n      if (inst.render == null) {\n        \"development\" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0;\n      }\n\n      var propsMutated = inst.props !== publicProps;\n      var componentName = Component.displayName || Component.name || 'Component';\n\n      \"development\" !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\\'s constructor was passed.', componentName, componentName) : void 0;\n    }\n\n    // These should be set up in the constructor, but as a convenience for\n    // simpler class abstractions, we set them up after the fact.\n    inst.props = publicProps;\n    inst.context = publicContext;\n    inst.refs = emptyObject;\n    inst.updater = updateQueue;\n\n    this._instance = inst;\n\n    // Store a reference from the instance back to the internal representation\n    ReactInstanceMap.set(inst, this);\n\n    if (\"development\" !== 'production') {\n      // Since plain JS classes are defined without any special initialization\n      // logic, we can not catch common errors early. Therefore, we have to\n      // catch them here, at initialization time, instead.\n      \"development\" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0;\n    }\n\n    var initialState = inst.state;\n    if (initialState === undefined) {\n      inst.state = initialState = null;\n    }\n    !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    var markup;\n    if (inst.unstable_handleError) {\n      markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } else {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n\n    if (inst.componentDidMount) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);\n      }\n    }\n\n    return markup;\n  },\n\n  _constructComponent: function (publicProps, publicContext, updateQueue) {\n    if (\"development\" !== 'production') {\n      ReactCurrentOwner.current = this;\n      try {\n        return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n      } finally {\n        ReactCurrentOwner.current = null;\n      }\n    } else {\n      return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n    }\n  },\n\n  _constructComponentWithoutOwner: function (publicProps, publicContext, updateQueue) {\n    var Component = this._currentElement.type;\n    var instanceOrElement;\n    if (shouldConstruct(Component)) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n      instanceOrElement = new Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n    } else {\n      // This can still be an instance in case of factory components\n      // but we'll count this as time spent rendering as the more common case.\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n      instanceOrElement = Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n    }\n    return instanceOrElement;\n  },\n\n  performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var markup;\n    var checkpoint = transaction.checkpoint();\n    try {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } catch (e) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onError();\n        }\n      }\n      // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint\n      transaction.rollback(checkpoint);\n      this._instance.unstable_handleError(e);\n      if (this._pendingStateQueue) {\n        this._instance.state = this._processPendingState(this._instance.props, this._instance.context);\n      }\n      checkpoint = transaction.checkpoint();\n\n      this._renderedComponent.unmountComponent(true);\n      transaction.rollback(checkpoint);\n\n      // Try again - we've informed the component about the error, so they can render an error message this time.\n      // If this throws again, the error will bubble up (and can be caught by a higher error boundary).\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n    return markup;\n  },\n\n  performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var inst = this._instance;\n    if (inst.componentWillMount) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      inst.componentWillMount();\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      // When mounting, calls to `setState` by `componentWillMount` will set\n      // `this._pendingStateQueue` without triggering a re-render.\n      if (this._pendingStateQueue) {\n        inst.state = this._processPendingState(inst.props, inst.context);\n      }\n    }\n\n    // If not a stateless component, we now render\n    if (renderedElement === undefined) {\n      renderedElement = this._renderValidatedComponent();\n    }\n\n    var nodeType = ReactNodeTypes.getType(renderedElement);\n    this._renderedNodeType = nodeType;\n    var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n    );\n    this._renderedComponent = child;\n    if (\"development\" !== 'production') {\n      if (child._debugID !== 0 && this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n      }\n    }\n\n    var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context));\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n      }\n    }\n\n    return markup;\n  },\n\n  getHostNode: function () {\n    return ReactReconciler.getHostNode(this._renderedComponent);\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    if (!this._renderedComponent) {\n      return;\n    }\n    var inst = this._instance;\n\n    if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {\n      inst._calledComponentWillUnmount = true;\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n      if (safely) {\n        var name = this.getName() + '.componentWillUnmount()';\n        ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));\n      } else {\n        inst.componentWillUnmount();\n      }\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n    }\n\n    if (this._renderedComponent) {\n      ReactReconciler.unmountComponent(this._renderedComponent, safely);\n      this._renderedNodeType = null;\n      this._renderedComponent = null;\n      this._instance = null;\n    }\n\n    // Reset pending fields\n    // Even if this component is scheduled for another update in ReactUpdates,\n    // it would still be ignored because these fields are reset.\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n    this._pendingCallbacks = null;\n    this._pendingElement = null;\n\n    // These fields do not really need to be reset since this object is no\n    // longer accessible.\n    this._context = null;\n    this._rootNodeID = null;\n    this._topLevelWrapper = null;\n\n    // Delete the reference from the instance to this internal representation\n    // which allow the internals to be properly cleaned up even if the user\n    // leaks a reference to the public instance.\n    ReactInstanceMap.remove(inst);\n\n    // Some existing components rely on inst.props even after they've been\n    // destroyed (in event handlers).\n    // TODO: inst.props = null;\n    // TODO: inst.state = null;\n    // TODO: inst.context = null;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _maskContext: function (context) {\n    var Component = this._currentElement.type;\n    var contextTypes = Component.contextTypes;\n    if (!contextTypes) {\n      return emptyObject;\n    }\n    var maskedContext = {};\n    for (var contextName in contextTypes) {\n      maskedContext[contextName] = context[contextName];\n    }\n    return maskedContext;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`, and asserts that they are valid.\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _processContext: function (context) {\n    var maskedContext = this._maskContext(context);\n    if (\"development\" !== 'production') {\n      var Component = this._currentElement.type;\n      if (Component.contextTypes) {\n        this._checkContextTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);\n      }\n    }\n    return maskedContext;\n  },\n\n  /**\n   * @param {object} currentContext\n   * @return {object}\n   * @private\n   */\n  _processChildContext: function (currentContext) {\n    var Component = this._currentElement.type;\n    var inst = this._instance;\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onBeginProcessingChildContext();\n    }\n    var childContext = inst.getChildContext && inst.getChildContext();\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onEndProcessingChildContext();\n    }\n    if (childContext) {\n      !(typeof Component.childContextTypes === 'object') ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;\n      if (\"development\" !== 'production') {\n        this._checkContextTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);\n      }\n      for (var name in childContext) {\n        !(name in Component.childContextTypes) ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): key \"%s\" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0;\n      }\n      return _assign({}, currentContext, childContext);\n    }\n    return currentContext;\n  },\n\n  /**\n   * Assert that the context types are valid\n   *\n   * @param {object} typeSpecs Map of context field to a ReactPropType\n   * @param {object} values Runtime values that need to be type-checked\n   * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n   * @private\n   */\n  _checkContextTypes: function (typeSpecs, values, location) {\n    checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);\n  },\n\n  receiveComponent: function (nextElement, transaction, nextContext) {\n    var prevElement = this._currentElement;\n    var prevContext = this._context;\n\n    this._pendingElement = null;\n\n    this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);\n  },\n\n  /**\n   * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`\n   * is set, update the component.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (transaction) {\n    if (this._pendingElement != null) {\n      ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);\n    } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {\n      this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);\n    } else {\n      this._updateBatchNumber = null;\n    }\n  },\n\n  /**\n   * Perform an update to a mounted component. The componentWillReceiveProps and\n   * shouldComponentUpdate methods are called, then (assuming the update isn't\n   * skipped) the remaining update lifecycle methods are called and the DOM\n   * representation is updated.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevParentElement\n   * @param {ReactElement} nextParentElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {\n    var inst = this._instance;\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    var willReceive = false;\n    var nextContext;\n    var nextProps;\n\n    // Determine if the context has changed or not\n    if (this._context === nextUnmaskedContext) {\n      nextContext = inst.context;\n    } else {\n      nextContext = this._processContext(nextUnmaskedContext);\n      willReceive = true;\n    }\n\n    nextProps = nextParentElement.props;\n\n    // Not a simple state update but a props update\n    if (prevParentElement !== nextParentElement) {\n      willReceive = true;\n    }\n\n    // An update here will schedule an update but immediately set\n    // _pendingStateQueue which will ensure that any state updates gets\n    // immediately reconciled instead of waiting for the next batch.\n    if (willReceive && inst.componentWillReceiveProps) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n      inst.componentWillReceiveProps(nextProps, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n    }\n\n    var nextState = this._processPendingState(nextProps, nextContext);\n    var shouldUpdate = true;\n\n    if (!this._pendingForceUpdate && inst.shouldComponentUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n      shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;\n    }\n\n    this._updateBatchNumber = null;\n    if (shouldUpdate) {\n      this._pendingForceUpdate = false;\n      // Will set `this.props`, `this.state` and `this.context`.\n      this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);\n    } else {\n      // If it's determined that a component should not update, we still want\n      // to set props and state but we shortcut the rest of the update.\n      this._currentElement = nextParentElement;\n      this._context = nextUnmaskedContext;\n      inst.props = nextProps;\n      inst.state = nextState;\n      inst.context = nextContext;\n    }\n  },\n\n  _processPendingState: function (props, context) {\n    var inst = this._instance;\n    var queue = this._pendingStateQueue;\n    var replace = this._pendingReplaceState;\n    this._pendingReplaceState = false;\n    this._pendingStateQueue = null;\n\n    if (!queue) {\n      return inst.state;\n    }\n\n    if (replace && queue.length === 1) {\n      return queue[0];\n    }\n\n    var nextState = _assign({}, replace ? queue[0] : inst.state);\n    for (var i = replace ? 1 : 0; i < queue.length; i++) {\n      var partial = queue[i];\n      _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);\n    }\n\n    return nextState;\n  },\n\n  /**\n   * Merges new props and state, notifies delegate methods of update and\n   * performs update.\n   *\n   * @param {ReactElement} nextElement Next element\n   * @param {object} nextProps Next public object to set as properties.\n   * @param {?object} nextState Next object to set as state.\n   * @param {?object} nextContext Next public object to set as context.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {?object} unmaskedContext\n   * @private\n   */\n  _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {\n    var inst = this._instance;\n\n    var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);\n    var prevProps;\n    var prevState;\n    var prevContext;\n    if (hasComponentDidUpdate) {\n      prevProps = inst.props;\n      prevState = inst.state;\n      prevContext = inst.context;\n    }\n\n    if (inst.componentWillUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n      inst.componentWillUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n    }\n\n    this._currentElement = nextElement;\n    this._context = unmaskedContext;\n    inst.props = nextProps;\n    inst.state = nextState;\n    inst.context = nextContext;\n\n    this._updateRenderedComponent(transaction, unmaskedContext);\n\n    if (hasComponentDidUpdate) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);\n      }\n    }\n  },\n\n  /**\n   * Call the component's `render` method and update the DOM accordingly.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  _updateRenderedComponent: function (transaction, context) {\n    var prevComponentInstance = this._renderedComponent;\n    var prevRenderedElement = prevComponentInstance._currentElement;\n    var nextRenderedElement = this._renderValidatedComponent();\n    if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {\n      ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));\n    } else {\n      var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);\n      ReactReconciler.unmountComponent(prevComponentInstance, false);\n\n      var nodeType = ReactNodeTypes.getType(nextRenderedElement);\n      this._renderedNodeType = nodeType;\n      var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n      );\n      this._renderedComponent = child;\n      if (\"development\" !== 'production') {\n        if (child._debugID !== 0 && this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n        }\n      }\n\n      var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context));\n\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n        }\n      }\n\n      this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);\n    }\n  },\n\n  /**\n   * Overridden in shallow rendering.\n   *\n   * @protected\n   */\n  _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {\n    ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);\n  },\n\n  /**\n   * @protected\n   */\n  _renderValidatedComponentWithoutOwnerOrContext: function () {\n    var inst = this._instance;\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n    var renderedComponent = inst.render();\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      // We allow auto-mocks to proceed as if they're returning null.\n      if (renderedComponent === undefined && inst.render._isMockFunction) {\n        // This is probably bad practice. Consider warning here and\n        // deprecating this convenience.\n        renderedComponent = null;\n      }\n    }\n\n    return renderedComponent;\n  },\n\n  /**\n   * @private\n   */\n  _renderValidatedComponent: function () {\n    var renderedComponent;\n    ReactCurrentOwner.current = this;\n    try {\n      renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();\n    } finally {\n      ReactCurrentOwner.current = null;\n    }\n    !(\n    // TODO: An `isValidNode` function would probably be more appropriate\n    renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? \"development\" !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    return renderedComponent;\n  },\n\n  /**\n   * Lazily allocates the refs object and stores `component` as `ref`.\n   *\n   * @param {string} ref Reference name.\n   * @param {component} component Component to store as `ref`.\n   * @final\n   * @private\n   */\n  attachRef: function (ref, component) {\n    var inst = this.getPublicInstance();\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0;\n    var publicComponentInstance = component.getPublicInstance();\n    if (\"development\" !== 'production') {\n      var componentName = component && component.getName ? component.getName() : 'a component';\n      \"development\" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref \"%s\" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;\n    }\n    var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;\n    refs[ref] = publicComponentInstance;\n  },\n\n  /**\n   * Detaches a reference name.\n   *\n   * @param {string} ref Name to dereference.\n   * @final\n   * @private\n   */\n  detachRef: function (ref) {\n    var refs = this.getPublicInstance().refs;\n    delete refs[ref];\n  },\n\n  /**\n   * Get a text description of the component that can be used to identify it\n   * in error messages.\n   * @return {string} The name or null.\n   * @internal\n   */\n  getName: function () {\n    var type = this._currentElement.type;\n    var constructor = this._instance && this._instance.constructor;\n    return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;\n  },\n\n  /**\n   * Get the publicly accessible representation of this component - i.e. what\n   * is exposed by refs and returned by render. Can be null for stateless\n   * components.\n   *\n   * @return {ReactComponent} the public component instance.\n   * @internal\n   */\n  getPublicInstance: function () {\n    var inst = this._instance;\n    if (inst instanceof StatelessComponent) {\n      return null;\n    }\n    return inst;\n  },\n\n  // Stub\n  _instantiateReactComponent: null\n\n};\n\nvar ReactCompositeComponent = {\n\n  Mixin: ReactCompositeComponentMixin\n\n};\n\nmodule.exports = ReactCompositeComponent;\n},{\"118\":118,\"139\":139,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"172\":172,\"33\":33,\"36\":36,\"62\":62,\"65\":65,\"73\":73,\"74\":74,\"80\":80,\"84\":84,\"87\":87}],36:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCurrentOwner\n */\n\n'use strict';\n\n/**\n * Keeps track of the current owner.\n *\n * The current owner is the component who should own any components that are\n * currently being constructed.\n */\n\nvar ReactCurrentOwner = {\n\n  /**\n   * @internal\n   * @type {ReactComponent}\n   */\n  current: null\n\n};\n\nmodule.exports = ReactCurrentOwner;\n},{}],37:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOM\n */\n\n/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactMount = _dereq_(77);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdates = _dereq_(95);\nvar ReactVersion = _dereq_(96);\n\nvar findDOMNode = _dereq_(122);\nvar getHostComponentFromComposite = _dereq_(129);\nvar renderSubtreeIntoContainer = _dereq_(140);\nvar warning = _dereq_(171);\n\nReactDefaultInjection.inject();\n\nvar React = {\n  findDOMNode: findDOMNode,\n  render: ReactMount.render,\n  unmountComponentAtNode: ReactMount.unmountComponentAtNode,\n  version: ReactVersion,\n\n  /* eslint-disable camelcase */\n  unstable_batchedUpdates: ReactUpdates.batchedUpdates,\n  unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer\n};\n\n// Inject the runtime into a devtools global hook regardless of browser.\n// Allows for debugging when the hook is injected on the page.\n/* eslint-enable camelcase */\nif (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {\n  __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({\n    ComponentTree: {\n      getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,\n      getNodeFromInstance: function (inst) {\n        // inst is an internal instance (but could be a composite)\n        if (inst._renderedComponent) {\n          inst = getHostComponentFromComposite(inst);\n        }\n        if (inst) {\n          return ReactDOMComponentTree.getNodeFromInstance(inst);\n        } else {\n          return null;\n        }\n      }\n    },\n    Mount: ReactMount,\n    Reconciler: ReactReconciler\n  });\n}\n\nif (\"development\" !== 'production') {\n  var ExecutionEnvironment = _dereq_(147);\n  if (ExecutionEnvironment.canUseDOM && window.top === window.self) {\n\n    // First check if devtools is not installed\n    if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {\n      // If we're in Chrome or Firefox, provide a download link if not installed.\n      if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {\n        // Firefox does not have the issue with devtools loaded over file://\n        var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;\n        console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');\n      }\n    }\n\n    var testFunc = function testFn() {};\n    \"development\" !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;\n\n    // If we're in IE8, check to see if we are in compatibility mode and provide\n    // information on preventing compatibility mode\n    var ieCompatibilityMode = document.documentMode && document.documentMode < 8;\n\n    \"development\" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />') : void 0;\n\n    var expectedFeatures = [\n    // shims\n    Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim];\n\n    for (var i = 0; i < expectedFeatures.length; i++) {\n      if (!expectedFeatures[i]) {\n        \"development\" !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;\n        break;\n      }\n    }\n  }\n}\n\nmodule.exports = React;\n},{\"122\":122,\"129\":129,\"140\":140,\"147\":147,\"171\":171,\"41\":41,\"61\":61,\"77\":77,\"87\":87,\"95\":95,\"96\":96}],38:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMButton\n */\n\n'use strict';\n\nvar DisabledInputUtils = _dereq_(14);\n\n/**\n * Implements a <button> host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar ReactDOMButton = {\n  getHostProps: DisabledInputUtils.getHostProps\n};\n\nmodule.exports = ReactDOMButton;\n},{\"14\":14}],39:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponent\n */\n\n/* global hasOwnProperty:true */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar AutoFocusUtils = _dereq_(1);\nvar CSSPropertyOperations = _dereq_(4);\nvar DOMLazyTree = _dereq_(8);\nvar DOMNamespaces = _dereq_(9);\nvar DOMProperty = _dereq_(10);\nvar DOMPropertyOperations = _dereq_(11);\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMButton = _dereq_(38);\nvar ReactDOMComponentFlags = _dereq_(40);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInput = _dereq_(48);\nvar ReactDOMOption = _dereq_(51);\nvar ReactDOMSelect = _dereq_(52);\nvar ReactDOMTextarea = _dereq_(56);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChild = _dereq_(78);\nvar ReactServerRenderingTransaction = _dereq_(91);\n\nvar emptyFunction = _dereq_(153);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar isEventSupported = _dereq_(135);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\nvar validateDOMNesting = _dereq_(145);\nvar warning = _dereq_(171);\n\nvar Flags = ReactDOMComponentFlags;\nvar deleteListener = EventPluginHub.deleteListener;\nvar getNode = ReactDOMComponentTree.getNodeFromInstance;\nvar listenTo = ReactBrowserEventEmitter.listenTo;\nvar registrationNameModules = EventPluginRegistry.registrationNameModules;\n\n// For quickly matching children type, to test if can be treated as content.\nvar CONTENT_TYPES = { 'string': true, 'number': true };\n\nvar STYLE = keyOf({ style: null });\nvar HTML = keyOf({ __html: null });\nvar RESERVED_PROPS = {\n  children: null,\n  dangerouslySetInnerHTML: null,\n  suppressContentEditableWarning: null\n};\n\n// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).\nvar DOC_FRAGMENT_TYPE = 11;\n\nfunction getDeclarationErrorAddendum(internalInstance) {\n  if (internalInstance) {\n    var owner = internalInstance._currentElement._owner || null;\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' This DOM node was rendered by `' + name + '`.';\n      }\n    }\n  }\n  return '';\n}\n\nfunction friendlyStringify(obj) {\n  if (typeof obj === 'object') {\n    if (Array.isArray(obj)) {\n      return '[' + obj.map(friendlyStringify).join(', ') + ']';\n    } else {\n      var pairs = [];\n      for (var key in obj) {\n        if (Object.prototype.hasOwnProperty.call(obj, key)) {\n          var keyEscaped = /^[a-z$_][\\w$_]*$/i.test(key) ? key : JSON.stringify(key);\n          pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));\n        }\n      }\n      return '{' + pairs.join(', ') + '}';\n    }\n  } else if (typeof obj === 'string') {\n    return JSON.stringify(obj);\n  } else if (typeof obj === 'function') {\n    return '[function object]';\n  }\n  // Differs from JSON.stringify in that undefined because undefined and that\n  // inf and nan don't become null\n  return String(obj);\n}\n\nvar styleMutationWarning = {};\n\nfunction checkAndWarnForMutatedStyle(style1, style2, component) {\n  if (style1 == null || style2 == null) {\n    return;\n  }\n  if (shallowEqual(style1, style2)) {\n    return;\n  }\n\n  var componentName = component._tag;\n  var owner = component._currentElement._owner;\n  var ownerName;\n  if (owner) {\n    ownerName = owner.getName();\n  }\n\n  var hash = ownerName + '|' + componentName;\n\n  if (styleMutationWarning.hasOwnProperty(hash)) {\n    return;\n  }\n\n  styleMutationWarning[hash] = true;\n\n  \"development\" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;\n}\n\n/**\n * @param {object} component\n * @param {?object} props\n */\nfunction assertValidProps(component, props) {\n  if (!props) {\n    return;\n  }\n  // Note the use of `==` which checks for null or undefined.\n  if (voidElementTags[component._tag]) {\n    !(props.children == null && props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : _prodInvariant('137', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : void 0;\n  }\n  if (props.dangerouslySetInnerHTML != null) {\n    !(props.children == null) ? \"development\" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : _prodInvariant('60') : void 0;\n    !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? \"development\" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : _prodInvariant('61') : void 0;\n  }\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;\n    \"development\" !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0;\n    \"development\" !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;\n  }\n  !(props.style == null || typeof props.style === 'object') ? \"development\" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \\'em\\'}} when using JSX.%s', getDeclarationErrorAddendum(component)) : _prodInvariant('62', getDeclarationErrorAddendum(component)) : void 0;\n}\n\nfunction enqueuePutListener(inst, registrationName, listener, transaction) {\n  if (transaction instanceof ReactServerRenderingTransaction) {\n    return;\n  }\n  if (\"development\" !== 'production') {\n    // IE8 has no API for event capturing and the `onScroll` event doesn't\n    // bubble.\n    \"development\" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\\'t support the `onScroll` event') : void 0;\n  }\n  var containerInfo = inst._hostContainerInfo;\n  var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;\n  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;\n  listenTo(registrationName, doc);\n  transaction.getReactMountReady().enqueue(putListener, {\n    inst: inst,\n    registrationName: registrationName,\n    listener: listener\n  });\n}\n\nfunction putListener() {\n  var listenerToPut = this;\n  EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);\n}\n\nfunction inputPostMount() {\n  var inst = this;\n  ReactDOMInput.postMountWrapper(inst);\n}\n\nfunction textareaPostMount() {\n  var inst = this;\n  ReactDOMTextarea.postMountWrapper(inst);\n}\n\nfunction optionPostMount() {\n  var inst = this;\n  ReactDOMOption.postMountWrapper(inst);\n}\n\nvar setContentChildForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  setContentChildForInstrumentation = function (content) {\n    var hasExistingContent = this._contentDebugID != null;\n    var debugID = this._debugID;\n    var contentDebugID = debugID + '#text';\n\n    if (content == null) {\n      if (hasExistingContent) {\n        ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);\n      }\n      this._contentDebugID = null;\n      return;\n    }\n\n    this._contentDebugID = contentDebugID;\n    var text = '' + content;\n\n    ReactInstrumentation.debugTool.onSetDisplayName(contentDebugID, '#text');\n    ReactInstrumentation.debugTool.onSetParent(contentDebugID, debugID);\n    ReactInstrumentation.debugTool.onSetText(contentDebugID, text);\n\n    if (hasExistingContent) {\n      ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);\n    } else {\n      ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onMountComponent(contentDebugID);\n      ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);\n    }\n  };\n}\n\n// There are so many media events, it makes sense to just\n// maintain a list rather than create a `trapBubbledEvent` for each\nvar mediaEvents = {\n  topAbort: 'abort',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTimeUpdate: 'timeupdate',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting'\n};\n\nfunction trapBubbledEventsLocal() {\n  var inst = this;\n  // If a component renders to null or if another component fatals and causes\n  // the state of the tree to be corrupted, `node` here can be null.\n  !inst._rootNodeID ? \"development\" !== 'production' ? invariant(false, 'Must be mounted to trap events') : _prodInvariant('63') : void 0;\n  var node = getNode(inst);\n  !node ? \"development\" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : _prodInvariant('64') : void 0;\n\n  switch (inst._tag) {\n    case 'iframe':\n    case 'object':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'video':\n    case 'audio':\n\n      inst._wrapperState.listeners = [];\n      // Create listener for each media event\n      for (var event in mediaEvents) {\n        if (mediaEvents.hasOwnProperty(event)) {\n          inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));\n        }\n      }\n      break;\n    case 'source':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node)];\n      break;\n    case 'img':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'form':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];\n      break;\n    case 'input':\n    case 'select':\n    case 'textarea':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topInvalid, 'invalid', node)];\n      break;\n  }\n}\n\nfunction postUpdateSelectWrapper() {\n  ReactDOMSelect.postUpdateWrapper(this);\n}\n\n// For HTML, certain tags should omit their close tag. We keep a whitelist for\n// those special-case tags.\n\nvar omittedCloseTags = {\n  'area': true,\n  'base': true,\n  'br': true,\n  'col': true,\n  'embed': true,\n  'hr': true,\n  'img': true,\n  'input': true,\n  'keygen': true,\n  'link': true,\n  'meta': true,\n  'param': true,\n  'source': true,\n  'track': true,\n  'wbr': true\n};\n\n// NOTE: menuitem's close tag should be omitted, but that causes problems.\nvar newlineEatingTags = {\n  'listing': true,\n  'pre': true,\n  'textarea': true\n};\n\n// For HTML, certain tags cannot have children. This has the same purpose as\n// `omittedCloseTags` except that `menuitem` should still have its closing tag.\n\nvar voidElementTags = _assign({\n  'menuitem': true\n}, omittedCloseTags);\n\n// We accept any tag to be rendered but since this gets injected into arbitrary\n// HTML, we want to make sure that it's a safe tag.\n// http://www.w3.org/TR/REC-xml/#NT-Name\n\nvar VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\\.\\-\\d]*$/; // Simplified subset\nvar validatedTagCache = {};\nvar hasOwnProperty = {}.hasOwnProperty;\n\nfunction validateDangerousTag(tag) {\n  if (!hasOwnProperty.call(validatedTagCache, tag)) {\n    !VALID_TAG_REGEX.test(tag) ? \"development\" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : _prodInvariant('65', tag) : void 0;\n    validatedTagCache[tag] = true;\n  }\n}\n\nfunction isCustomComponent(tagName, props) {\n  return tagName.indexOf('-') >= 0 || props.is != null;\n}\n\nvar globalIdCounter = 1;\n\n/**\n * Creates a new React class that is idempotent and capable of containing other\n * React components. It accepts event listeners and DOM properties that are\n * valid according to `DOMProperty`.\n *\n *  - Event listeners: `onClick`, `onMouseDown`, etc.\n *  - DOM properties: `className`, `name`, `title`, etc.\n *\n * The `style` property functions differently from the DOM API. It accepts an\n * object mapping of style properties to values.\n *\n * @constructor ReactDOMComponent\n * @extends ReactMultiChild\n */\nfunction ReactDOMComponent(element) {\n  var tag = element.type;\n  validateDangerousTag(tag);\n  this._currentElement = element;\n  this._tag = tag.toLowerCase();\n  this._namespaceURI = null;\n  this._renderedChildren = null;\n  this._previousStyle = null;\n  this._previousStyleCopy = null;\n  this._hostNode = null;\n  this._hostParent = null;\n  this._rootNodeID = null;\n  this._domID = null;\n  this._hostContainerInfo = null;\n  this._wrapperState = null;\n  this._topLevelWrapper = null;\n  this._flags = 0;\n  if (\"development\" !== 'production') {\n    this._ancestorInfo = null;\n    setContentChildForInstrumentation.call(this, null);\n  }\n}\n\nReactDOMComponent.displayName = 'ReactDOMComponent';\n\nReactDOMComponent.Mixin = {\n\n  /**\n   * Generates root tag markup then recurses. This method has side effects and\n   * is not idempotent.\n   *\n   * @internal\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?ReactDOMComponent} the containing DOM component instance\n   * @param {?object} info about the host container\n   * @param {object} context\n   * @return {string} The computed markup.\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._rootNodeID = globalIdCounter++;\n    this._domID = hostContainerInfo._idCounter++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var props = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        this._wrapperState = {\n          listeners: null\n        };\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'button':\n        props = ReactDOMButton.getHostProps(this, props, hostParent);\n        break;\n      case 'input':\n        ReactDOMInput.mountWrapper(this, props, hostParent);\n        props = ReactDOMInput.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'option':\n        ReactDOMOption.mountWrapper(this, props, hostParent);\n        props = ReactDOMOption.getHostProps(this, props);\n        break;\n      case 'select':\n        ReactDOMSelect.mountWrapper(this, props, hostParent);\n        props = ReactDOMSelect.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.mountWrapper(this, props, hostParent);\n        props = ReactDOMTextarea.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n    }\n\n    assertValidProps(this, props);\n\n    // We create tags in the namespace of their parent container, except HTML\n    // tags get no namespace.\n    var namespaceURI;\n    var parentTag;\n    if (hostParent != null) {\n      namespaceURI = hostParent._namespaceURI;\n      parentTag = hostParent._tag;\n    } else if (hostContainerInfo._tag) {\n      namespaceURI = hostContainerInfo._namespaceURI;\n      parentTag = hostContainerInfo._tag;\n    }\n    if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {\n      namespaceURI = DOMNamespaces.html;\n    }\n    if (namespaceURI === DOMNamespaces.html) {\n      if (this._tag === 'svg') {\n        namespaceURI = DOMNamespaces.svg;\n      } else if (this._tag === 'math') {\n        namespaceURI = DOMNamespaces.mathml;\n      }\n    }\n    this._namespaceURI = namespaceURI;\n\n    if (\"development\" !== 'production') {\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo._tag) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting(this._tag, this, parentInfo);\n      }\n      this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);\n    }\n\n    var mountImage;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var el;\n      if (namespaceURI === DOMNamespaces.html) {\n        if (this._tag === 'script') {\n          // Create the script via .innerHTML so its \"parser-inserted\" flag is\n          // set to true and it does not execute\n          var div = ownerDocument.createElement('div');\n          var type = this._currentElement.type;\n          div.innerHTML = '<' + type + '></' + type + '>';\n          el = div.removeChild(div.firstChild);\n        } else if (props.is) {\n          el = ownerDocument.createElement(this._currentElement.type, props.is);\n        } else {\n          // Separate else branch instead of using `props.is || undefined` above becuase of a Firefox bug.\n          // See discussion in https://github.com/facebook/react/pull/6896\n          // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240\n          el = ownerDocument.createElement(this._currentElement.type);\n        }\n      } else {\n        el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);\n      }\n      ReactDOMComponentTree.precacheNode(this, el);\n      this._flags |= Flags.hasCachedChildNodes;\n      if (!this._hostParent) {\n        DOMPropertyOperations.setAttributeForRoot(el);\n      }\n      this._updateDOMProperties(null, props, transaction);\n      var lazyTree = DOMLazyTree(el);\n      this._createInitialChildren(transaction, props, context, lazyTree);\n      mountImage = lazyTree;\n    } else {\n      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);\n      var tagContent = this._createContentMarkup(transaction, props, context);\n      if (!tagContent && omittedCloseTags[this._tag]) {\n        mountImage = tagOpen + '/>';\n      } else {\n        mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';\n      }\n    }\n\n    switch (this._tag) {\n      case 'input':\n        transaction.getReactMountReady().enqueue(inputPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'textarea':\n        transaction.getReactMountReady().enqueue(textareaPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'select':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'button':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'option':\n        transaction.getReactMountReady().enqueue(optionPostMount, this);\n        break;\n    }\n\n    return mountImage;\n  },\n\n  /**\n   * Creates markup for the open tag and all attributes.\n   *\n   * This method has side effects because events get registered.\n   *\n   * Iterating over object properties is faster than iterating over arrays.\n   * @see http://jsperf.com/obj-vs-arr-iteration\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @return {string} Markup of opening tag.\n   */\n  _createOpenTagMarkupAndPutListeners: function (transaction, props) {\n    var ret = '<' + this._currentElement.type;\n\n    for (var propKey in props) {\n      if (!props.hasOwnProperty(propKey)) {\n        continue;\n      }\n      var propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (propValue) {\n          enqueuePutListener(this, propKey, propValue, transaction);\n        }\n      } else {\n        if (propKey === STYLE) {\n          if (propValue) {\n            if (\"development\" !== 'production') {\n              // See `_updateDOMProperties`. style block\n              this._previousStyle = propValue;\n            }\n            propValue = this._previousStyleCopy = _assign({}, props.style);\n          }\n          propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);\n        }\n        var markup = null;\n        if (this._tag != null && isCustomComponent(this._tag, props)) {\n          if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n            markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);\n          }\n        } else {\n          markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);\n        }\n        if (markup) {\n          ret += ' ' + markup;\n        }\n      }\n    }\n\n    // For static pages, no need to put React ID and checksum. Saves lots of\n    // bytes.\n    if (transaction.renderToStaticMarkup) {\n      return ret;\n    }\n\n    if (!this._hostParent) {\n      ret += ' ' + DOMPropertyOperations.createMarkupForRoot();\n    }\n    ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);\n    return ret;\n  },\n\n  /**\n   * Creates markup for the content between the tags.\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @param {object} context\n   * @return {string} Content markup.\n   */\n  _createContentMarkup: function (transaction, props, context) {\n    var ret = '';\n\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        ret = innerHTML.__html;\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        ret = escapeTextContentForBrowser(contentToUse);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        ret = mountImages.join('');\n      }\n    }\n    if (newlineEatingTags[this._tag] && ret.charAt(0) === '\\n') {\n      // text/html ignores the first character in these tags if it's a newline\n      // Prefer to break application/xml over text/html (for now) by adding\n      // a newline specifically to get eaten by the parser. (Alternately for\n      // textareas, replacing \"^\\n\" with \"\\r\\n\" doesn't get eaten, and the first\n      // \\r is normalized out by HTMLTextAreaElement#value.)\n      // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>\n      // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>\n      // See: <http://www.w3.org/TR/html5/syntax.html#newlines>\n      // See: Parsing of \"textarea\" \"listing\" and \"pre\" elements\n      //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>\n      return '\\n' + ret;\n    } else {\n      return ret;\n    }\n  },\n\n  _createInitialChildren: function (transaction, props, context, lazyTree) {\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n        DOMLazyTree.queueText(lazyTree, contentToUse);\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        for (var i = 0; i < mountImages.length; i++) {\n          DOMLazyTree.queueChild(lazyTree, mountImages[i]);\n        }\n      }\n    }\n  },\n\n  /**\n   * Receives a next element and updates the component.\n   *\n   * @internal\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} context\n   */\n  receiveComponent: function (nextElement, transaction, context) {\n    var prevElement = this._currentElement;\n    this._currentElement = nextElement;\n    this.updateComponent(transaction, prevElement, nextElement, context);\n  },\n\n  /**\n   * Updates a DOM component after it has already been allocated and\n   * attached to the DOM. Reconciles the root DOM node, then recurses.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevElement\n   * @param {ReactElement} nextElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevElement, nextElement, context) {\n    var lastProps = prevElement.props;\n    var nextProps = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'button':\n        lastProps = ReactDOMButton.getHostProps(this, lastProps);\n        nextProps = ReactDOMButton.getHostProps(this, nextProps);\n        break;\n      case 'input':\n        ReactDOMInput.updateWrapper(this);\n        lastProps = ReactDOMInput.getHostProps(this, lastProps);\n        nextProps = ReactDOMInput.getHostProps(this, nextProps);\n        break;\n      case 'option':\n        lastProps = ReactDOMOption.getHostProps(this, lastProps);\n        nextProps = ReactDOMOption.getHostProps(this, nextProps);\n        break;\n      case 'select':\n        lastProps = ReactDOMSelect.getHostProps(this, lastProps);\n        nextProps = ReactDOMSelect.getHostProps(this, nextProps);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.updateWrapper(this);\n        lastProps = ReactDOMTextarea.getHostProps(this, lastProps);\n        nextProps = ReactDOMTextarea.getHostProps(this, nextProps);\n        break;\n    }\n\n    assertValidProps(this, nextProps);\n    this._updateDOMProperties(lastProps, nextProps, transaction);\n    this._updateDOMChildren(lastProps, nextProps, transaction, context);\n\n    if (this._tag === 'select') {\n      // <select> value update needs to occur after <option> children\n      // reconciliation\n      transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);\n    }\n  },\n\n  /**\n   * Reconciles the properties by detecting differences in property values and\n   * updating the DOM as necessary. This function is probably the single most\n   * critical path for performance optimization.\n   *\n   * TODO: Benchmark whether checking for changed values in memory actually\n   *       improves performance (especially statically positioned elements).\n   * TODO: Benchmark the effects of putting this at the top since 99% of props\n   *       do not change for a given reconciliation.\n   * TODO: Benchmark areas that can be improved with caching.\n   *\n   * @private\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {?DOMElement} node\n   */\n  _updateDOMProperties: function (lastProps, nextProps, transaction) {\n    var propKey;\n    var styleName;\n    var styleUpdates;\n    for (propKey in lastProps) {\n      if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        var lastStyle = this._previousStyleCopy;\n        for (styleName in lastStyle) {\n          if (lastStyle.hasOwnProperty(styleName)) {\n            styleUpdates = styleUpdates || {};\n            styleUpdates[styleName] = '';\n          }\n        }\n        this._previousStyleCopy = null;\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (lastProps[propKey]) {\n          // Only call deleteListener if there was a listener previously or\n          // else willDeleteListener gets called when there wasn't actually a\n          // listener (e.g., onClick={null})\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, lastProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);\n      }\n    }\n    for (propKey in nextProps) {\n      var nextProp = nextProps[propKey];\n      var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;\n      if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        if (nextProp) {\n          if (\"development\" !== 'production') {\n            checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);\n            this._previousStyle = nextProp;\n          }\n          nextProp = this._previousStyleCopy = _assign({}, nextProp);\n        } else {\n          this._previousStyleCopy = null;\n        }\n        if (lastProp) {\n          // Unset styles on `lastProp` but not on `nextProp`.\n          for (styleName in lastProp) {\n            if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = '';\n            }\n          }\n          // Update styles that changed since `lastProp`.\n          for (styleName in nextProp) {\n            if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = nextProp[styleName];\n            }\n          }\n        } else {\n          // Relies on `updateStylesByID` not mutating `styleUpdates`.\n          styleUpdates = nextProp;\n        }\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (nextProp) {\n          enqueuePutListener(this, propKey, nextProp, transaction);\n        } else if (lastProp) {\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, nextProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        var node = getNode(this);\n        // If we're updating to null or undefined, we should remove the property\n        // from the DOM node instead of inadvertently setting to a string. This\n        // brings us in line with the same behavior we have on initial render.\n        if (nextProp != null) {\n          DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);\n        } else {\n          DOMPropertyOperations.deleteValueForProperty(node, propKey);\n        }\n      }\n    }\n    if (styleUpdates) {\n      CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);\n    }\n  },\n\n  /**\n   * Reconciles the children with the various properties that affect the\n   * children content.\n   *\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   */\n  _updateDOMChildren: function (lastProps, nextProps, transaction, context) {\n    var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;\n    var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;\n\n    var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;\n    var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;\n\n    // Note the use of `!=` which checks for null or undefined.\n    var lastChildren = lastContent != null ? null : lastProps.children;\n    var nextChildren = nextContent != null ? null : nextProps.children;\n\n    // If we're switching from children to content/html or vice versa, remove\n    // the old content\n    var lastHasContentOrHtml = lastContent != null || lastHtml != null;\n    var nextHasContentOrHtml = nextContent != null || nextHtml != null;\n    if (lastChildren != null && nextChildren == null) {\n      this.updateChildren(null, transaction, context);\n    } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {\n      this.updateTextContent('');\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    }\n\n    if (nextContent != null) {\n      if (lastContent !== nextContent) {\n        this.updateTextContent('' + nextContent);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, nextContent);\n        }\n      }\n    } else if (nextHtml != null) {\n      if (lastHtml !== nextHtml) {\n        this.updateMarkup('' + nextHtml);\n      }\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    } else if (nextChildren != null) {\n      if (\"development\" !== 'production') {\n        setContentChildForInstrumentation.call(this, null);\n      }\n\n      this.updateChildren(nextChildren, transaction, context);\n    }\n  },\n\n  getHostNode: function () {\n    return getNode(this);\n  },\n\n  /**\n   * Destroys all event registrations for this instance. Does not remove from\n   * the DOM. That must be done by the parent.\n   *\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        var listeners = this._wrapperState.listeners;\n        if (listeners) {\n          for (var i = 0; i < listeners.length; i++) {\n            listeners[i].remove();\n          }\n        }\n        break;\n      case 'html':\n      case 'head':\n      case 'body':\n        /**\n         * Components like <html> <head> and <body> can't be removed or added\n         * easily in a cross-browser way, however it's valuable to be able to\n         * take advantage of React's reconciliation for styling and <title>\n         * management. So we just document it and throw in dangerous cases.\n         */\n        !false ? \"development\" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.', this._tag) : _prodInvariant('66', this._tag) : void 0;\n        break;\n    }\n\n    this.unmountChildren(safely);\n    ReactDOMComponentTree.uncacheNode(this);\n    EventPluginHub.deleteAllListeners(this);\n    ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);\n    this._rootNodeID = null;\n    this._domID = null;\n    this._wrapperState = null;\n\n    if (\"development\" !== 'production') {\n      setContentChildForInstrumentation.call(this, null);\n    }\n  },\n\n  getPublicInstance: function () {\n    return getNode(this);\n  }\n\n};\n\n_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);\n\nmodule.exports = ReactDOMComponent;\n},{\"1\":1,\"10\":10,\"11\":11,\"121\":121,\"135\":135,\"139\":139,\"145\":145,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"17\":17,\"170\":170,\"171\":171,\"172\":172,\"18\":18,\"27\":27,\"32\":32,\"38\":38,\"4\":4,\"40\":40,\"41\":41,\"48\":48,\"51\":51,\"52\":52,\"56\":56,\"74\":74,\"78\":78,\"8\":8,\"9\":9,\"91\":91}],40:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentFlags\n */\n\n'use strict';\n\nvar ReactDOMComponentFlags = {\n  hasCachedChildNodes: 1 << 0\n};\n\nmodule.exports = ReactDOMComponentFlags;\n},{}],41:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentTree\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentFlags = _dereq_(40);\n\nvar invariant = _dereq_(161);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar Flags = ReactDOMComponentFlags;\n\nvar internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);\n\n/**\n * Drill down (through composites and empty components) until we get a host or\n * host text component.\n *\n * This is pretty polymorphic but unavoidable with the current structure we have\n * for `_renderedChildren`.\n */\nfunction getRenderedHostOrTextFromComponent(component) {\n  var rendered;\n  while (rendered = component._renderedComponent) {\n    component = rendered;\n  }\n  return component;\n}\n\n/**\n * Populate `_hostNode` on the rendered host/text component with the given\n * DOM node. The passed `inst` can be a composite.\n */\nfunction precacheNode(inst, node) {\n  var hostInst = getRenderedHostOrTextFromComponent(inst);\n  hostInst._hostNode = node;\n  node[internalInstanceKey] = hostInst;\n}\n\nfunction uncacheNode(inst) {\n  var node = inst._hostNode;\n  if (node) {\n    delete node[internalInstanceKey];\n    inst._hostNode = null;\n  }\n}\n\n/**\n * Populate `_hostNode` on each child of `inst`, assuming that the children\n * match up with the DOM (element) children of `node`.\n *\n * We cache entire levels at once to avoid an n^2 problem where we access the\n * children of a node sequentially and have to walk from the start to our target\n * node every time.\n *\n * Since we update `_renderedChildren` and the actual DOM at (slightly)\n * different times, we could race here and see a newer `_renderedChildren` than\n * the DOM nodes we see. To avoid this, ReactMultiChild calls\n * `prepareToManageChildren` before we change `_renderedChildren`, at which\n * time the container's child nodes are always cached (until it unmounts).\n */\nfunction precacheChildNodes(inst, node) {\n  if (inst._flags & Flags.hasCachedChildNodes) {\n    return;\n  }\n  var children = inst._renderedChildren;\n  var childNode = node.firstChild;\n  outer: for (var name in children) {\n    if (!children.hasOwnProperty(name)) {\n      continue;\n    }\n    var childInst = children[name];\n    var childID = getRenderedHostOrTextFromComponent(childInst)._domID;\n    if (childID == null) {\n      // We're currently unmounting this child in ReactMultiChild; skip it.\n      continue;\n    }\n    // We assume the child nodes are in the same order as the child instances.\n    for (; childNode !== null; childNode = childNode.nextSibling) {\n      if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') {\n        precacheNode(childInst, childNode);\n        continue outer;\n      }\n    }\n    // We reached the end of the DOM children without finding an ID match.\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : _prodInvariant('32', childID) : void 0;\n  }\n  inst._flags |= Flags.hasCachedChildNodes;\n}\n\n/**\n * Given a DOM node, return the closest ReactDOMComponent or\n * ReactDOMTextComponent instance ancestor.\n */\nfunction getClosestInstanceFromNode(node) {\n  if (node[internalInstanceKey]) {\n    return node[internalInstanceKey];\n  }\n\n  // Walk up the tree until we find an ancestor whose instance we have cached.\n  var parents = [];\n  while (!node[internalInstanceKey]) {\n    parents.push(node);\n    if (node.parentNode) {\n      node = node.parentNode;\n    } else {\n      // Top of the tree. This node must not be part of a React tree (or is\n      // unmounted, potentially).\n      return null;\n    }\n  }\n\n  var closest;\n  var inst;\n  for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {\n    closest = inst;\n    if (parents.length) {\n      precacheChildNodes(inst, node);\n    }\n  }\n\n  return closest;\n}\n\n/**\n * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent\n * instance, or null if the node was not rendered by this React.\n */\nfunction getInstanceFromNode(node) {\n  var inst = getClosestInstanceFromNode(node);\n  if (inst != null && inst._hostNode === node) {\n    return inst;\n  } else {\n    return null;\n  }\n}\n\n/**\n * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding\n * DOM node.\n */\nfunction getNodeFromInstance(inst) {\n  // Without this first invariant, passing a non-DOM-component triggers the next\n  // invariant for a missing parent, which is super confusing.\n  !(inst._hostNode !== undefined) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  if (inst._hostNode) {\n    return inst._hostNode;\n  }\n\n  // Walk up the tree until we find an ancestor whose DOM node we have cached.\n  var parents = [];\n  while (!inst._hostNode) {\n    parents.push(inst);\n    !inst._hostParent ? \"development\" !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') : _prodInvariant('34') : void 0;\n    inst = inst._hostParent;\n  }\n\n  // Now parents contains each ancestor that does *not* have a cached native\n  // node, and `inst` is the deepest ancestor that does.\n  for (; parents.length; inst = parents.pop()) {\n    precacheChildNodes(inst, inst._hostNode);\n  }\n\n  return inst._hostNode;\n}\n\nvar ReactDOMComponentTree = {\n  getClosestInstanceFromNode: getClosestInstanceFromNode,\n  getInstanceFromNode: getInstanceFromNode,\n  getNodeFromInstance: getNodeFromInstance,\n  precacheChildNodes: precacheChildNodes,\n  precacheNode: precacheNode,\n  uncacheNode: uncacheNode\n};\n\nmodule.exports = ReactDOMComponentTree;\n},{\"10\":10,\"139\":139,\"161\":161,\"40\":40}],42:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMContainerInfo\n */\n\n'use strict';\n\nvar validateDOMNesting = _dereq_(145);\n\nvar DOC_NODE_TYPE = 9;\n\nfunction ReactDOMContainerInfo(topLevelWrapper, node) {\n  var info = {\n    _topLevelWrapper: topLevelWrapper,\n    _idCounter: 1,\n    _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null,\n    _node: node,\n    _tag: node ? node.nodeName.toLowerCase() : null,\n    _namespaceURI: node ? node.namespaceURI : null\n  };\n  if (\"development\" !== 'production') {\n    info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null;\n  }\n  return info;\n}\n\nmodule.exports = ReactDOMContainerInfo;\n},{\"145\":145}],43:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMDebugTool\n */\n\n'use strict';\n\nvar ReactDOMNullInputValuePropDevtool = _dereq_(50);\nvar ReactDOMUnknownPropertyDevtool = _dereq_(58);\nvar ReactDebugTool = _dereq_(59);\n\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar ReactDOMDebugTool = {\n  addDevtool: function (devtool) {\n    ReactDebugTool.addDevtool(devtool);\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    ReactDebugTool.removeDevtool(devtool);\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  onCreateMarkupForProperty: function (name, value) {\n    emitEvent('onCreateMarkupForProperty', name, value);\n  },\n  onSetValueForProperty: function (node, name, value) {\n    emitEvent('onSetValueForProperty', node, name, value);\n  },\n  onDeleteValueForProperty: function (node, name) {\n    emitEvent('onDeleteValueForProperty', node, name);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool);\nReactDOMDebugTool.addDevtool(ReactDOMNullInputValuePropDevtool);\n\nmodule.exports = ReactDOMDebugTool;\n},{\"171\":171,\"50\":50,\"58\":58,\"59\":59}],44:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMEmptyComponent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar ReactDOMEmptyComponent = function (instantiate) {\n  // ReactCompositeComponent uses this:\n  this._currentElement = null;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n  this._hostContainerInfo = null;\n  this._domID = null;\n};\n_assign(ReactDOMEmptyComponent.prototype, {\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    var domID = hostContainerInfo._idCounter++;\n    this._domID = domID;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var nodeValue = ' react-empty: ' + this._domID + ' ';\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var node = ownerDocument.createComment(nodeValue);\n      ReactDOMComponentTree.precacheNode(this, node);\n      return DOMLazyTree(node);\n    } else {\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd insert a comment node, but since this is a situation\n        // where React won't take over (static pages), we can simply return\n        // nothing.\n        return '';\n      }\n      return '<!--' + nodeValue + '-->';\n    }\n  },\n  receiveComponent: function () {},\n  getHostNode: function () {\n    return ReactDOMComponentTree.getNodeFromInstance(this);\n  },\n  unmountComponent: function () {\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n});\n\nmodule.exports = ReactDOMEmptyComponent;\n},{\"172\":172,\"41\":41,\"8\":8}],45:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFactories\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\n\nvar mapObject = _dereq_(166);\n\n/**\n * Create a factory that creates HTML tag elements.\n *\n * @param {string} tag Tag name (e.g. `div`).\n * @private\n */\nfunction createDOMFactory(tag) {\n  if (\"development\" !== 'production') {\n    var ReactElementValidator = _dereq_(63);\n    return ReactElementValidator.createFactory(tag);\n  }\n  return ReactElement.createFactory(tag);\n}\n\n/**\n * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.\n * This is also accessible via `React.DOM`.\n *\n * @public\n */\nvar ReactDOMFactories = mapObject({\n  a: 'a',\n  abbr: 'abbr',\n  address: 'address',\n  area: 'area',\n  article: 'article',\n  aside: 'aside',\n  audio: 'audio',\n  b: 'b',\n  base: 'base',\n  bdi: 'bdi',\n  bdo: 'bdo',\n  big: 'big',\n  blockquote: 'blockquote',\n  body: 'body',\n  br: 'br',\n  button: 'button',\n  canvas: 'canvas',\n  caption: 'caption',\n  cite: 'cite',\n  code: 'code',\n  col: 'col',\n  colgroup: 'colgroup',\n  data: 'data',\n  datalist: 'datalist',\n  dd: 'dd',\n  del: 'del',\n  details: 'details',\n  dfn: 'dfn',\n  dialog: 'dialog',\n  div: 'div',\n  dl: 'dl',\n  dt: 'dt',\n  em: 'em',\n  embed: 'embed',\n  fieldset: 'fieldset',\n  figcaption: 'figcaption',\n  figure: 'figure',\n  footer: 'footer',\n  form: 'form',\n  h1: 'h1',\n  h2: 'h2',\n  h3: 'h3',\n  h4: 'h4',\n  h5: 'h5',\n  h6: 'h6',\n  head: 'head',\n  header: 'header',\n  hgroup: 'hgroup',\n  hr: 'hr',\n  html: 'html',\n  i: 'i',\n  iframe: 'iframe',\n  img: 'img',\n  input: 'input',\n  ins: 'ins',\n  kbd: 'kbd',\n  keygen: 'keygen',\n  label: 'label',\n  legend: 'legend',\n  li: 'li',\n  link: 'link',\n  main: 'main',\n  map: 'map',\n  mark: 'mark',\n  menu: 'menu',\n  menuitem: 'menuitem',\n  meta: 'meta',\n  meter: 'meter',\n  nav: 'nav',\n  noscript: 'noscript',\n  object: 'object',\n  ol: 'ol',\n  optgroup: 'optgroup',\n  option: 'option',\n  output: 'output',\n  p: 'p',\n  param: 'param',\n  picture: 'picture',\n  pre: 'pre',\n  progress: 'progress',\n  q: 'q',\n  rp: 'rp',\n  rt: 'rt',\n  ruby: 'ruby',\n  s: 's',\n  samp: 'samp',\n  script: 'script',\n  section: 'section',\n  select: 'select',\n  small: 'small',\n  source: 'source',\n  span: 'span',\n  strong: 'strong',\n  style: 'style',\n  sub: 'sub',\n  summary: 'summary',\n  sup: 'sup',\n  table: 'table',\n  tbody: 'tbody',\n  td: 'td',\n  textarea: 'textarea',\n  tfoot: 'tfoot',\n  th: 'th',\n  thead: 'thead',\n  time: 'time',\n  title: 'title',\n  tr: 'tr',\n  track: 'track',\n  u: 'u',\n  ul: 'ul',\n  'var': 'var',\n  video: 'video',\n  wbr: 'wbr',\n\n  // SVG\n  circle: 'circle',\n  clipPath: 'clipPath',\n  defs: 'defs',\n  ellipse: 'ellipse',\n  g: 'g',\n  image: 'image',\n  line: 'line',\n  linearGradient: 'linearGradient',\n  mask: 'mask',\n  path: 'path',\n  pattern: 'pattern',\n  polygon: 'polygon',\n  polyline: 'polyline',\n  radialGradient: 'radialGradient',\n  rect: 'rect',\n  stop: 'stop',\n  svg: 'svg',\n  text: 'text',\n  tspan: 'tspan'\n\n}, createDOMFactory);\n\nmodule.exports = ReactDOMFactories;\n},{\"166\":166,\"62\":62,\"63\":63}],46:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFeatureFlags\n */\n\n'use strict';\n\nvar ReactDOMFeatureFlags = {\n  useCreateElement: true\n};\n\nmodule.exports = ReactDOMFeatureFlags;\n},{}],47:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMIDOperations\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMComponentTree = _dereq_(41);\n\n/**\n * Operations used to process updates to DOM nodes.\n */\nvar ReactDOMIDOperations = {\n\n  /**\n   * Updates a component's children by processing a series of updates.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  dangerouslyProcessChildrenUpdates: function (parentInst, updates) {\n    var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);\n    DOMChildrenOperations.processUpdates(node, updates);\n  }\n};\n\nmodule.exports = ReactDOMIDOperations;\n},{\"41\":41,\"7\":7}],48:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInput\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar DOMPropertyOperations = _dereq_(11);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnCheckedLink = false;\nvar didWarnValueDefaultValue = false;\nvar didWarnCheckedDefaultChecked = false;\nvar didWarnControlledToUncontrolled = false;\nvar didWarnUncontrolledToControlled = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMInput.updateWrapper(this);\n  }\n}\n\nfunction isControlled(props) {\n  var usesChecked = props.type === 'checkbox' || props.type === 'radio';\n  return usesChecked ? props.checked !== undefined : props.value !== undefined;\n}\n\n/**\n * Implements an <input> host component that allows setting these optional\n * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.\n *\n * If `checked` or `value` are not supplied (or null/undefined), user actions\n * that affect the checked state or value will trigger updates to the element.\n *\n * If they are supplied (and not null/undefined), the rendered element will not\n * trigger updates to the element. Instead, the props must change in order for\n * the rendered element to be updated.\n *\n * The rendered element will be initialized as unchecked (or `defaultChecked`)\n * with an empty value (or `defaultValue`).\n *\n * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html\n */\nvar ReactDOMInput = {\n  getHostProps: function (inst, props) {\n    var value = LinkedValueUtils.getValue(props);\n    var checked = LinkedValueUtils.getChecked(props);\n\n    var hostProps = _assign({\n      // Make sure we set .type before any other properties (setting .value\n      // before .type means .value is lost in IE11 and below)\n      type: undefined\n    }, DisabledInputUtils.getHostProps(inst, props), {\n      defaultChecked: undefined,\n      defaultValue: undefined,\n      value: value != null ? value : inst._wrapperState.initialValue,\n      checked: checked != null ? checked : inst._wrapperState.initialChecked,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);\n\n      var owner = inst._currentElement._owner;\n\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.checkedLink !== undefined && !didWarnCheckedLink) {\n        \"development\" !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnCheckedLink = true;\n      }\n      if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnCheckedDefaultChecked = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnValueDefaultValue = true;\n      }\n    }\n\n    var defaultValue = props.defaultValue;\n    inst._wrapperState = {\n      initialChecked: props.checked != null ? props.checked : props.defaultChecked,\n      initialValue: props.value != null ? props.value : defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n\n    if (\"development\" !== 'production') {\n      inst._wrapperState.controlled = isControlled(props);\n    }\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    if (\"development\" !== 'production') {\n      var controlled = isControlled(props);\n      var owner = inst._currentElement._owner;\n\n      if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnUncontrolledToControlled = true;\n      }\n      if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnControlledToUncontrolled = true;\n      }\n    }\n\n    // TODO: Shouldn't this be getChecked(props)?\n    var checked = props.checked;\n    if (checked != null) {\n      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);\n    }\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n    } else {\n      if (props.value == null && props.defaultValue != null) {\n        node.defaultValue = '' + props.defaultValue;\n      }\n      if (props.checked == null && props.defaultChecked != null) {\n        node.defaultChecked = !!props.defaultChecked;\n      }\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Detach value from defaultValue. We won't do anything if we're working on\n    // submit or reset inputs as those values & defaultValues are linked. They\n    // are not resetable nodes so this operation doesn't matter and actually\n    // removes browser-default values (eg \"Submit Query\") when no value is\n    // provided.\n    if (props.type !== 'submit' && props.type !== 'reset') {\n      node.value = node.value;\n    }\n\n    // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug\n    // this is needed to work around a chrome bug where setting defaultChecked\n    // will sometimes influence the value of checked (even after detachment).\n    // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416\n    // We need to temporarily unset name to avoid disrupting radio button groups.\n    var name = node.name;\n    if (name !== '') {\n      node.name = '';\n    }\n    node.defaultChecked = !node.defaultChecked;\n    node.defaultChecked = !node.defaultChecked;\n    if (name !== '') {\n      node.name = name;\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  // Here we use asap to wait until all updates have propagated, which\n  // is important when using controlled components within layers:\n  // https://github.com/facebook/react/issues/1698\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n\n  var name = props.name;\n  if (props.type === 'radio' && name != null) {\n    var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);\n    var queryRoot = rootNode;\n\n    while (queryRoot.parentNode) {\n      queryRoot = queryRoot.parentNode;\n    }\n\n    // If `rootNode.form` was non-null, then we could try `form.elements`,\n    // but that sometimes behaves strangely in IE8. We could also try using\n    // `form.getElementsByName`, but that will only return direct children\n    // and won't include inputs that use the HTML5 `form=` attribute. Since\n    // the input might not even be in a form, let's just use the global\n    // `querySelectorAll` to ensure we don't miss anything.\n    var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type=\"radio\"]');\n\n    for (var i = 0; i < group.length; i++) {\n      var otherNode = group[i];\n      if (otherNode === rootNode || otherNode.form !== rootNode.form) {\n        continue;\n      }\n      // This will throw if radio buttons rendered by different copies of React\n      // and the same name are rendered into the same form (same as #1939).\n      // That's probably okay; we don't support it just as we don't support\n      // mixing React radio buttons with non-React ones.\n      var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);\n      !otherInstance ? \"development\" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;\n      // If this is a controlled radio button group, forcing the input that\n      // was previously checked to update will cause it to be come re-checked\n      // as appropriate.\n      ReactUpdates.asap(forceUpdateIfMounted, otherInstance);\n    }\n  }\n\n  return returnValue;\n}\n\nmodule.exports = ReactDOMInput;\n},{\"11\":11,\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],49:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDOMDebugTool = _dereq_(43);\n  debugTool = ReactDOMDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"43\":43}],50:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMNullInputValuePropDevtool\n */\n\n'use strict';\n\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueNull = false;\n\nfunction handleElement(debugID, element) {\n  if (element == null) {\n    return;\n  }\n  if (element.type !== 'input' && element.type !== 'textarea' && element.type !== 'select') {\n    return;\n  }\n  if (element.props != null && element.props.value === null && !didWarnValueNull) {\n    \"development\" !== 'production' ? warning(false, '`value` prop on `%s` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n\n    didWarnValueNull = true;\n  }\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"171\":171,\"34\":34}],51:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMOption\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMSelect = _dereq_(52);\n\nvar warning = _dereq_(171);\nvar didWarnInvalidOptionChildren = false;\n\nfunction flattenChildren(children) {\n  var content = '';\n\n  // Flatten children and warn if they aren't strings or numbers;\n  // invalid types are ignored.\n  ReactChildren.forEach(children, function (child) {\n    if (child == null) {\n      return;\n    }\n    if (typeof child === 'string' || typeof child === 'number') {\n      content += child;\n    } else if (!didWarnInvalidOptionChildren) {\n      didWarnInvalidOptionChildren = true;\n      \"development\" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;\n    }\n  });\n\n  return content;\n}\n\n/**\n * Implements an <option> host component that warns when `selected` is set.\n */\nvar ReactDOMOption = {\n  mountWrapper: function (inst, props, hostParent) {\n    // TODO (yungsters): Remove support for `selected` in <option>.\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;\n    }\n\n    // Look up whether this option is 'selected'\n    var selectValue = null;\n    if (hostParent != null) {\n      var selectParent = hostParent;\n\n      if (selectParent._tag === 'optgroup') {\n        selectParent = selectParent._hostParent;\n      }\n\n      if (selectParent != null && selectParent._tag === 'select') {\n        selectValue = ReactDOMSelect.getSelectValueContext(selectParent);\n      }\n    }\n\n    // If the value is null (e.g., no specified value or after initial mount)\n    // or missing (e.g., for <datalist>), we don't change props.selected\n    var selected = null;\n    if (selectValue != null) {\n      var value;\n      if (props.value != null) {\n        value = props.value + '';\n      } else {\n        value = flattenChildren(props.children);\n      }\n      selected = false;\n      if (Array.isArray(selectValue)) {\n        // multiple\n        for (var i = 0; i < selectValue.length; i++) {\n          if ('' + selectValue[i] === value) {\n            selected = true;\n            break;\n          }\n        }\n      } else {\n        selected = '' + selectValue === value;\n      }\n    }\n\n    inst._wrapperState = { selected: selected };\n  },\n\n  postMountWrapper: function (inst) {\n    // value=\"\" should make a value attribute (#6219)\n    var props = inst._currentElement.props;\n    if (props.value != null) {\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      node.setAttribute('value', props.value);\n    }\n  },\n\n  getHostProps: function (inst, props) {\n    var hostProps = _assign({ selected: undefined, children: undefined }, props);\n\n    // Read state only from initial mount because <select> updates value\n    // manually; we need the initial state only for server rendering\n    if (inst._wrapperState.selected != null) {\n      hostProps.selected = inst._wrapperState.selected;\n    }\n\n    var content = flattenChildren(props.children);\n\n    if (content) {\n      hostProps.children = content;\n    }\n\n    return hostProps;\n  }\n\n};\n\nmodule.exports = ReactDOMOption;\n},{\"171\":171,\"172\":172,\"29\":29,\"41\":41,\"52\":52}],52:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelect\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValueDefaultValue = false;\n\nfunction updateOptionsIfPendingUpdateAndMounted() {\n  if (this._rootNodeID && this._wrapperState.pendingUpdate) {\n    this._wrapperState.pendingUpdate = false;\n\n    var props = this._currentElement.props;\n    var value = LinkedValueUtils.getValue(props);\n\n    if (value != null) {\n      updateOptions(this, Boolean(props.multiple), value);\n    }\n  }\n}\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nvar valuePropNames = ['value', 'defaultValue'];\n\n/**\n * Validation function for `value` and `defaultValue`.\n * @private\n */\nfunction checkSelectPropTypes(inst, props) {\n  var owner = inst._currentElement._owner;\n  LinkedValueUtils.checkPropTypes('select', props, owner);\n\n  if (props.valueLink !== undefined && !didWarnValueLink) {\n    \"development\" !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;\n    didWarnValueLink = true;\n  }\n\n  for (var i = 0; i < valuePropNames.length; i++) {\n    var propName = valuePropNames[i];\n    if (props[propName] == null) {\n      continue;\n    }\n    if (props.multiple) {\n      \"development\" !== 'production' ? warning(Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    } else {\n      \"development\" !== 'production' ? warning(!Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    }\n  }\n}\n\n/**\n * @param {ReactDOMComponent} inst\n * @param {boolean} multiple\n * @param {*} propValue A stringable (with `multiple`, a list of stringables).\n * @private\n */\nfunction updateOptions(inst, multiple, propValue) {\n  var selectedValue, i;\n  var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;\n\n  if (multiple) {\n    selectedValue = {};\n    for (i = 0; i < propValue.length; i++) {\n      selectedValue['' + propValue[i]] = true;\n    }\n    for (i = 0; i < options.length; i++) {\n      var selected = selectedValue.hasOwnProperty(options[i].value);\n      if (options[i].selected !== selected) {\n        options[i].selected = selected;\n      }\n    }\n  } else {\n    // Do not set `select.value` as exact behavior isn't consistent across all\n    // browsers for all cases.\n    selectedValue = '' + propValue;\n    for (i = 0; i < options.length; i++) {\n      if (options[i].value === selectedValue) {\n        options[i].selected = true;\n        return;\n      }\n    }\n    if (options.length) {\n      options[0].selected = true;\n    }\n  }\n}\n\n/**\n * Implements a <select> host component that allows optionally setting the\n * props `value` and `defaultValue`. If `multiple` is false, the prop must be a\n * stringable. If `multiple` is true, the prop must be an array of stringables.\n *\n * If `value` is not supplied (or null/undefined), user actions that change the\n * selected option will trigger updates to the rendered options.\n *\n * If it is supplied (and not null/undefined), the rendered options will not\n * update in response to user actions. Instead, the `value` prop must change in\n * order for the rendered options to update.\n *\n * If `defaultValue` is provided, any options with the supplied values will be\n * selected.\n */\nvar ReactDOMSelect = {\n  getHostProps: function (inst, props) {\n    return _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      onChange: inst._wrapperState.onChange,\n      value: undefined\n    });\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      checkSelectPropTypes(inst, props);\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    inst._wrapperState = {\n      pendingUpdate: false,\n      initialValue: value != null ? value : props.defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst),\n      wasMultiple: Boolean(props.multiple)\n    };\n\n    if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n      \"development\" !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n      didWarnValueDefaultValue = true;\n    }\n  },\n\n  getSelectValueContext: function (inst) {\n    // ReactDOMOption looks at this initial value so the initial generated\n    // markup has correct `selected` attributes\n    return inst._wrapperState.initialValue;\n  },\n\n  postUpdateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // After the initial mount, we control selected-ness manually so don't pass\n    // this value down\n    inst._wrapperState.initialValue = undefined;\n\n    var wasMultiple = inst._wrapperState.wasMultiple;\n    inst._wrapperState.wasMultiple = Boolean(props.multiple);\n\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      inst._wrapperState.pendingUpdate = false;\n      updateOptions(inst, Boolean(props.multiple), value);\n    } else if (wasMultiple !== Boolean(props.multiple)) {\n      // For simplicity, reapply `defaultValue` if `multiple` is toggled.\n      if (props.defaultValue != null) {\n        updateOptions(inst, Boolean(props.multiple), props.defaultValue);\n      } else {\n        // Revert the select back to its default unselected state.\n        updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : '');\n      }\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  if (this._rootNodeID) {\n    this._wrapperState.pendingUpdate = true;\n  }\n  ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMSelect;\n},{\"14\":14,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],53:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelection\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar getNodeForCharacterOffset = _dereq_(131);\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * While `isCollapsed` is available on the Selection object and `collapsed`\n * is available on the Range object, IE11 sometimes gets them wrong.\n * If the anchor/focus nodes and offsets are the same, the range is collapsed.\n */\nfunction isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {\n  return anchorNode === focusNode && anchorOffset === focusOffset;\n}\n\n/**\n * Get the appropriate anchor and focus node/offset pairs for IE.\n *\n * The catch here is that IE's selection API doesn't provide information\n * about whether the selection is forward or backward, so we have to\n * behave as though it's always forward.\n *\n * IE text differs from modern selection in that it behaves as though\n * block elements end with a new line. This means character offsets will\n * differ between the two APIs.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getIEOffsets(node) {\n  var selection = document.selection;\n  var selectedRange = selection.createRange();\n  var selectedLength = selectedRange.text.length;\n\n  // Duplicate selection so we can move range without breaking user selection.\n  var fromStart = selectedRange.duplicate();\n  fromStart.moveToElementText(node);\n  fromStart.setEndPoint('EndToStart', selectedRange);\n\n  var startOffset = fromStart.text.length;\n  var endOffset = startOffset + selectedLength;\n\n  return {\n    start: startOffset,\n    end: endOffset\n  };\n}\n\n/**\n * @param {DOMElement} node\n * @return {?object}\n */\nfunction getModernOffsets(node) {\n  var selection = window.getSelection && window.getSelection();\n\n  if (!selection || selection.rangeCount === 0) {\n    return null;\n  }\n\n  var anchorNode = selection.anchorNode;\n  var anchorOffset = selection.anchorOffset;\n  var focusNode = selection.focusNode;\n  var focusOffset = selection.focusOffset;\n\n  var currentRange = selection.getRangeAt(0);\n\n  // In Firefox, range.startContainer and range.endContainer can be \"anonymous\n  // divs\", e.g. the up/down buttons on an <input type=\"number\">. Anonymous\n  // divs do not seem to expose properties, triggering a \"Permission denied\n  // error\" if any of its properties are accessed. The only seemingly possible\n  // way to avoid erroring is to access a property that typically works for\n  // non-anonymous divs and catch any error that may otherwise arise. See\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=208427\n  try {\n    /* eslint-disable no-unused-expressions */\n    currentRange.startContainer.nodeType;\n    currentRange.endContainer.nodeType;\n    /* eslint-enable no-unused-expressions */\n  } catch (e) {\n    return null;\n  }\n\n  // If the node and offset values are the same, the selection is collapsed.\n  // `Selection.isCollapsed` is available natively, but IE sometimes gets\n  // this value wrong.\n  var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);\n\n  var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;\n\n  var tempRange = currentRange.cloneRange();\n  tempRange.selectNodeContents(node);\n  tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);\n\n  var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset);\n\n  var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;\n  var end = start + rangeLength;\n\n  // Detect whether the selection is backward.\n  var detectionRange = document.createRange();\n  detectionRange.setStart(anchorNode, anchorOffset);\n  detectionRange.setEnd(focusNode, focusOffset);\n  var isBackward = detectionRange.collapsed;\n\n  return {\n    start: isBackward ? end : start,\n    end: isBackward ? start : end\n  };\n}\n\n/**\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setIEOffsets(node, offsets) {\n  var range = document.selection.createRange().duplicate();\n  var start, end;\n\n  if (offsets.end === undefined) {\n    start = offsets.start;\n    end = start;\n  } else if (offsets.start > offsets.end) {\n    start = offsets.end;\n    end = offsets.start;\n  } else {\n    start = offsets.start;\n    end = offsets.end;\n  }\n\n  range.moveToElementText(node);\n  range.moveStart('character', start);\n  range.setEndPoint('EndToStart', range);\n  range.moveEnd('character', end - start);\n  range.select();\n}\n\n/**\n * In modern non-IE browsers, we can support both forward and backward\n * selections.\n *\n * Note: IE10+ supports the Selection object, but it does not support\n * the `extend` method, which means that even in modern IE, it's not possible\n * to programmatically create a backward selection. Thus, for all IE\n * versions, we use the old IE API to create our selections.\n *\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setModernOffsets(node, offsets) {\n  if (!window.getSelection) {\n    return;\n  }\n\n  var selection = window.getSelection();\n  var length = node[getTextContentAccessor()].length;\n  var start = Math.min(offsets.start, length);\n  var end = offsets.end === undefined ? start : Math.min(offsets.end, length);\n\n  // IE 11 uses modern selection, but doesn't support the extend method.\n  // Flip backward selections, so we can set with a single range.\n  if (!selection.extend && start > end) {\n    var temp = end;\n    end = start;\n    start = temp;\n  }\n\n  var startMarker = getNodeForCharacterOffset(node, start);\n  var endMarker = getNodeForCharacterOffset(node, end);\n\n  if (startMarker && endMarker) {\n    var range = document.createRange();\n    range.setStart(startMarker.node, startMarker.offset);\n    selection.removeAllRanges();\n\n    if (start > end) {\n      selection.addRange(range);\n      selection.extend(endMarker.node, endMarker.offset);\n    } else {\n      range.setEnd(endMarker.node, endMarker.offset);\n      selection.addRange(range);\n    }\n  }\n}\n\nvar useIEOffsets = ExecutionEnvironment.canUseDOM && 'selection' in document && !('getSelection' in window);\n\nvar ReactDOMSelection = {\n  /**\n   * @param {DOMElement} node\n   */\n  getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,\n\n  /**\n   * @param {DOMElement|DOMTextNode} node\n   * @param {object} offsets\n   */\n  setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets\n};\n\nmodule.exports = ReactDOMSelection;\n},{\"131\":131,\"132\":132,\"147\":147}],54:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMServer\n */\n\n'use strict';\n\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactServerRendering = _dereq_(90);\nvar ReactVersion = _dereq_(96);\n\nReactDefaultInjection.inject();\n\nvar ReactDOMServer = {\n  renderToString: ReactServerRendering.renderToString,\n  renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup,\n  version: ReactVersion\n};\n\nmodule.exports = ReactDOMServer;\n},{\"61\":61,\"90\":90,\"96\":96}],55:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DOMChildrenOperations = _dereq_(7);\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar validateDOMNesting = _dereq_(145);\n\n/**\n * Text nodes violate a couple assumptions that React makes about components:\n *\n *  - When mounting text into the DOM, adjacent text nodes are merged.\n *  - Text nodes cannot be assigned a React root ID.\n *\n * This component is used to wrap strings between comment nodes so that they\n * can undergo the same reconciliation that is applied to elements.\n *\n * TODO: Investigate representing React components in the DOM with text nodes.\n *\n * @class ReactDOMTextComponent\n * @extends ReactComponent\n * @internal\n */\nvar ReactDOMTextComponent = function (text) {\n  // TODO: This is really a ReactText (ReactNode), not a ReactElement\n  this._currentElement = text;\n  this._stringText = '' + text;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n\n  // Properties\n  this._domID = null;\n  this._mountIndex = 0;\n  this._closingComment = null;\n  this._commentNodes = null;\n};\n\n_assign(ReactDOMTextComponent.prototype, {\n\n  /**\n   * Creates the markup for this text node. This node is not intended to have\n   * any features besides containing text content.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @return {string} Markup for this text node.\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetText(this._debugID, this._stringText);\n\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo != null) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting('#text', this, parentInfo);\n      }\n    }\n\n    var domID = hostContainerInfo._idCounter++;\n    var openingValue = ' react-text: ' + domID + ' ';\n    var closingValue = ' /react-text ';\n    this._domID = domID;\n    this._hostParent = hostParent;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var openingComment = ownerDocument.createComment(openingValue);\n      var closingComment = ownerDocument.createComment(closingValue);\n      var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment());\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment));\n      if (this._stringText) {\n        DOMLazyTree.queueChild(lazyTree, DOMLazyTree(ownerDocument.createTextNode(this._stringText)));\n      }\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment));\n      ReactDOMComponentTree.precacheNode(this, openingComment);\n      this._closingComment = closingComment;\n      return lazyTree;\n    } else {\n      var escapedText = escapeTextContentForBrowser(this._stringText);\n\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd wrap this between comment nodes for the reasons stated\n        // above, but since this is a situation where React won't take over\n        // (static pages), we can simply return the text as it is.\n        return escapedText;\n      }\n\n      return '<!--' + openingValue + '-->' + escapedText + '<!--' + closingValue + '-->';\n    }\n  },\n\n  /**\n   * Updates this component by updating the text content.\n   *\n   * @param {ReactText} nextText The next text content\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  receiveComponent: function (nextText, transaction) {\n    if (nextText !== this._currentElement) {\n      this._currentElement = nextText;\n      var nextStringText = '' + nextText;\n      if (nextStringText !== this._stringText) {\n        // TODO: Save this as pending props and use performUpdateIfNecessary\n        // and/or updateComponent to do the actual update for consistency with\n        // other component types?\n        this._stringText = nextStringText;\n        var commentNodes = this.getHostNode();\n        DOMChildrenOperations.replaceDelimitedText(commentNodes[0], commentNodes[1], nextStringText);\n\n        if (\"development\" !== 'production') {\n          ReactInstrumentation.debugTool.onSetText(this._debugID, nextStringText);\n        }\n      }\n    }\n  },\n\n  getHostNode: function () {\n    var hostNode = this._commentNodes;\n    if (hostNode) {\n      return hostNode;\n    }\n    if (!this._closingComment) {\n      var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);\n      var node = openingComment.nextSibling;\n      while (true) {\n        !(node != null) ? \"development\" !== 'production' ? invariant(false, 'Missing closing comment for text component %s', this._domID) : _prodInvariant('67', this._domID) : void 0;\n        if (node.nodeType === 8 && node.nodeValue === ' /react-text ') {\n          this._closingComment = node;\n          break;\n        }\n        node = node.nextSibling;\n      }\n    }\n    hostNode = [this._hostNode, this._closingComment];\n    this._commentNodes = hostNode;\n    return hostNode;\n  },\n\n  unmountComponent: function () {\n    this._closingComment = null;\n    this._commentNodes = null;\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n\n});\n\nmodule.exports = ReactDOMTextComponent;\n},{\"121\":121,\"139\":139,\"145\":145,\"161\":161,\"172\":172,\"41\":41,\"7\":7,\"74\":74,\"8\":8}],56:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextarea\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValDefaultVal = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMTextarea.updateWrapper(this);\n  }\n}\n\n/**\n * Implements a <textarea> host component that allows setting `value`, and\n * `defaultValue`. This differs from the traditional DOM API because value is\n * usually set as PCDATA children.\n *\n * If `value` is not supplied (or null/undefined), user actions that affect the\n * value will trigger updates to the element.\n *\n * If `value` is supplied (and not null/undefined), the rendered element will\n * not trigger updates to the element. Instead, the `value` prop must change in\n * order for the rendered element to be updated.\n *\n * The rendered element will be initialized with an empty value, the prop\n * `defaultValue` if specified, or the children content (deprecated).\n */\nvar ReactDOMTextarea = {\n  getHostProps: function (inst, props) {\n    !(props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : _prodInvariant('91') : void 0;\n\n    // Always set children to the same thing. In IE9, the selection range will\n    // get reset if `textContent` is mutated.  We could add a check in setTextContent\n    // to only set the value if/when the value differs from the node value (which would\n    // completely solve this IE9 bug), but Sebastian+Ben seemed to like this solution.\n    // The value can be a boolean or object so that's why it's forced to be a string.\n    var hostProps = _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      value: undefined,\n      defaultValue: undefined,\n      children: '' + inst._wrapperState.initialValue,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `textarea` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {\n        \"development\" !== 'production' ? warning(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n        didWarnValDefaultVal = true;\n      }\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    var initialValue = value;\n\n    // Only bother fetching default value if we're going to use it\n    if (value == null) {\n      var defaultValue = props.defaultValue;\n      // TODO (yungsters): Remove support for children content in <textarea>.\n      var children = props.children;\n      if (children != null) {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.') : void 0;\n        }\n        !(defaultValue == null) ? \"development\" !== 'production' ? invariant(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : _prodInvariant('92') : void 0;\n        if (Array.isArray(children)) {\n          !(children.length <= 1) ? \"development\" !== 'production' ? invariant(false, '<textarea> can only have at most one child.') : _prodInvariant('93') : void 0;\n          children = children[0];\n        }\n\n        defaultValue = '' + children;\n      }\n      if (defaultValue == null) {\n        defaultValue = '';\n      }\n      initialValue = defaultValue;\n    }\n\n    inst._wrapperState = {\n      initialValue: '' + initialValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n      if (props.defaultValue == null) {\n        node.defaultValue = newValue;\n      }\n    }\n    if (props.defaultValue != null) {\n      node.defaultValue = props.defaultValue;\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Warning: node.value may be the empty string at this point (IE11) if placeholder is set.\n    node.value = node.textContent; // Detach value from defaultValue\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMTextarea;\n},{\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],57:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTreeTraversal\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Return the lowest common ancestor of A and B, or null if they are in\n * different trees.\n */\nfunction getLowestCommonAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  var depthA = 0;\n  for (var tempA = instA; tempA; tempA = tempA._hostParent) {\n    depthA++;\n  }\n  var depthB = 0;\n  for (var tempB = instB; tempB; tempB = tempB._hostParent) {\n    depthB++;\n  }\n\n  // If A is deeper, crawl up.\n  while (depthA - depthB > 0) {\n    instA = instA._hostParent;\n    depthA--;\n  }\n\n  // If B is deeper, crawl up.\n  while (depthB - depthA > 0) {\n    instB = instB._hostParent;\n    depthB--;\n  }\n\n  // Walk in lockstep until we find a match.\n  var depth = depthA;\n  while (depth--) {\n    if (instA === instB) {\n      return instA;\n    }\n    instA = instA._hostParent;\n    instB = instB._hostParent;\n  }\n  return null;\n}\n\n/**\n * Return if A is an ancestor of B.\n */\nfunction isAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n\n  while (instB) {\n    if (instB === instA) {\n      return true;\n    }\n    instB = instB._hostParent;\n  }\n  return false;\n}\n\n/**\n * Return the parent instance of the passed-in instance.\n */\nfunction getParentInstance(inst) {\n  !('_hostNode' in inst) ? \"development\" !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : _prodInvariant('36') : void 0;\n\n  return inst._hostParent;\n}\n\n/**\n * Simulates the traversal of a two-phase, capture/bubble event dispatch.\n */\nfunction traverseTwoPhase(inst, fn, arg) {\n  var path = [];\n  while (inst) {\n    path.push(inst);\n    inst = inst._hostParent;\n  }\n  var i;\n  for (i = path.length; i-- > 0;) {\n    fn(path[i], false, arg);\n  }\n  for (i = 0; i < path.length; i++) {\n    fn(path[i], true, arg);\n  }\n}\n\n/**\n * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that\n * should would receive a `mouseEnter` or `mouseLeave` event.\n *\n * Does not invoke the callback on the nearest common ancestor because nothing\n * \"entered\" or \"left\" that element.\n */\nfunction traverseEnterLeave(from, to, fn, argFrom, argTo) {\n  var common = from && to ? getLowestCommonAncestor(from, to) : null;\n  var pathFrom = [];\n  while (from && from !== common) {\n    pathFrom.push(from);\n    from = from._hostParent;\n  }\n  var pathTo = [];\n  while (to && to !== common) {\n    pathTo.push(to);\n    to = to._hostParent;\n  }\n  var i;\n  for (i = 0; i < pathFrom.length; i++) {\n    fn(pathFrom[i], true, argFrom);\n  }\n  for (i = pathTo.length; i-- > 0;) {\n    fn(pathTo[i], false, argTo);\n  }\n}\n\nmodule.exports = {\n  isAncestor: isAncestor,\n  getLowestCommonAncestor: getLowestCommonAncestor,\n  getParentInstance: getParentInstance,\n  traverseTwoPhase: traverseTwoPhase,\n  traverseEnterLeave: traverseEnterLeave\n};\n},{\"139\":139,\"161\":161}],58:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMUnknownPropertyDevtool\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var reactProps = {\n    children: true,\n    dangerouslySetInnerHTML: true,\n    key: true,\n    ref: true,\n\n    autoFocus: true,\n    defaultValue: true,\n    valueLink: true,\n    defaultChecked: true,\n    checkedLink: true,\n    innerHTML: true,\n    suppressContentEditableWarning: true,\n    onFocusIn: true,\n    onFocusOut: true\n  };\n  var warnedProperties = {};\n\n  var validateProperty = function (tagName, name, debugID) {\n    if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) {\n      return true;\n    }\n    if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {\n      return true;\n    }\n    if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) {\n      return true;\n    }\n    warnedProperties[name] = true;\n    var lowerCasedName = name.toLowerCase();\n\n    // data-* attributes should be lowercase; suggest the lowercase version\n    var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;\n\n    var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : null;\n\n    if (standardName != null) {\n      \"development\" !== 'production' ? warning(standardName == null, 'Unknown DOM property %s. Did you mean %s?%s', name, standardName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else if (registrationName != null) {\n      \"development\" !== 'production' ? warning(registrationName == null, 'Unknown event handler property %s. Did you mean `%s`?%s', name, registrationName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else {\n      // We were unable to guess which prop the user intended.\n      // It is likely that the user was just blindly spreading/forwarding props\n      // Components should be careful to only render valid props/attributes.\n      // Warning will be invoked in warnUnknownProperties to allow grouping.\n      return false;\n    }\n  };\n}\n\nvar warnUnknownProperties = function (debugID, element) {\n  var unknownProps = [];\n  for (var key in element.props) {\n    var isValid = validateProperty(element.type, key, debugID);\n    if (!isValid) {\n      unknownProps.push(key);\n    }\n  }\n\n  var unknownPropString = unknownProps.map(function (prop) {\n    return '`' + prop + '`';\n  }).join(', ');\n\n  if (unknownProps.length === 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown prop %s on <%s> tag. Remove this prop from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  } else if (unknownProps.length > 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown props %s on <%s> tag. Remove these props from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  }\n};\n\nfunction handleElement(debugID, element) {\n  if (element == null || typeof element.type !== 'string') {\n    return;\n  }\n  if (element.type.indexOf('-') >= 0 || element.props.is) {\n    return;\n  }\n  warnUnknownProperties(debugID, element);\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"10\":10,\"171\":171,\"18\":18,\"34\":34}],59:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDebugTool\n */\n\n'use strict';\n\nvar ReactInvalidSetStateWarningDevTool = _dereq_(75);\nvar ReactHostOperationHistoryDevtool = _dereq_(70);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performanceNow = _dereq_(169);\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar isProfiling = false;\nvar flushHistory = [];\nvar lifeCycleTimerStack = [];\nvar currentFlushNesting = 0;\nvar currentFlushMeasurements = null;\nvar currentFlushStartTime = null;\nvar currentTimerDebugID = null;\nvar currentTimerStartTime = null;\nvar currentTimerNestedFlushDuration = null;\nvar currentTimerType = null;\n\nfunction clearHistory() {\n  ReactComponentTreeDevtool.purgeUnmountedComponents();\n  ReactHostOperationHistoryDevtool.clearHistory();\n}\n\nfunction getTreeSnapshot(registeredIDs) {\n  return registeredIDs.reduce(function (tree, id) {\n    var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n    var parentID = ReactComponentTreeDevtool.getParentID(id);\n    tree[id] = {\n      displayName: ReactComponentTreeDevtool.getDisplayName(id),\n      text: ReactComponentTreeDevtool.getText(id),\n      updateCount: ReactComponentTreeDevtool.getUpdateCount(id),\n      childIDs: ReactComponentTreeDevtool.getChildIDs(id),\n      // Text nodes don't have owners but this is close enough.\n      ownerID: ownerID || ReactComponentTreeDevtool.getOwnerID(parentID),\n      parentID: parentID\n    };\n    return tree;\n  }, {});\n}\n\nfunction resetMeasurements() {\n  var previousStartTime = currentFlushStartTime;\n  var previousMeasurements = currentFlushMeasurements || [];\n  var previousOperations = ReactHostOperationHistoryDevtool.getHistory();\n\n  if (currentFlushNesting === 0) {\n    currentFlushStartTime = null;\n    currentFlushMeasurements = null;\n    clearHistory();\n    return;\n  }\n\n  if (previousMeasurements.length || previousOperations.length) {\n    var registeredIDs = ReactComponentTreeDevtool.getRegisteredIDs();\n    flushHistory.push({\n      duration: performanceNow() - previousStartTime,\n      measurements: previousMeasurements || [],\n      operations: previousOperations || [],\n      treeSnapshot: getTreeSnapshot(registeredIDs)\n    });\n  }\n\n  clearHistory();\n  currentFlushStartTime = performanceNow();\n  currentFlushMeasurements = [];\n}\n\nfunction checkDebugID(debugID) {\n  \"development\" !== 'production' ? warning(debugID, 'ReactDebugTool: debugID may not be empty.') : void 0;\n}\n\nfunction beginLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(!currentTimerType, 'There is an internal error in the React performance measurement code. ' + 'Did not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  currentTimerStartTime = performanceNow();\n  currentTimerNestedFlushDuration = 0;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nfunction endLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(currentTimerType === timerType, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  if (isProfiling) {\n    currentFlushMeasurements.push({\n      timerType: timerType,\n      instanceID: debugID,\n      duration: performanceNow() - currentTimerStartTime - currentTimerNestedFlushDuration\n    });\n  }\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction pauseCurrentLifeCycleTimer() {\n  var currentTimer = {\n    startTime: currentTimerStartTime,\n    nestedFlushStartTime: performanceNow(),\n    debugID: currentTimerDebugID,\n    timerType: currentTimerType\n  };\n  lifeCycleTimerStack.push(currentTimer);\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction resumeCurrentLifeCycleTimer() {\n  var _lifeCycleTimerStack$ = lifeCycleTimerStack.pop();\n\n  var startTime = _lifeCycleTimerStack$.startTime;\n  var nestedFlushStartTime = _lifeCycleTimerStack$.nestedFlushStartTime;\n  var debugID = _lifeCycleTimerStack$.debugID;\n  var timerType = _lifeCycleTimerStack$.timerType;\n\n  var nestedFlushDuration = performanceNow() - nestedFlushStartTime;\n  currentTimerStartTime = startTime;\n  currentTimerNestedFlushDuration += nestedFlushDuration;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nvar ReactDebugTool = {\n  addDevtool: function (devtool) {\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  isProfiling: function () {\n    return isProfiling;\n  },\n  beginProfiling: function () {\n    if (isProfiling) {\n      return;\n    }\n\n    isProfiling = true;\n    flushHistory.length = 0;\n    resetMeasurements();\n    ReactDebugTool.addDevtool(ReactHostOperationHistoryDevtool);\n  },\n  endProfiling: function () {\n    if (!isProfiling) {\n      return;\n    }\n\n    isProfiling = false;\n    resetMeasurements();\n    ReactDebugTool.removeDevtool(ReactHostOperationHistoryDevtool);\n  },\n  getFlushHistory: function () {\n    return flushHistory;\n  },\n  onBeginFlush: function () {\n    currentFlushNesting++;\n    resetMeasurements();\n    pauseCurrentLifeCycleTimer();\n    emitEvent('onBeginFlush');\n  },\n  onEndFlush: function () {\n    resetMeasurements();\n    currentFlushNesting--;\n    resumeCurrentLifeCycleTimer();\n    emitEvent('onEndFlush');\n  },\n  onBeginLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginLifeCycleTimer', debugID, timerType);\n    beginLifeCycleTimer(debugID, timerType);\n  },\n  onEndLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    endLifeCycleTimer(debugID, timerType);\n    emitEvent('onEndLifeCycleTimer', debugID, timerType);\n  },\n  onBeginReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginReconcilerTimer', debugID, timerType);\n  },\n  onEndReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onEndReconcilerTimer', debugID, timerType);\n  },\n  onError: function (debugID) {\n    if (currentTimerDebugID != null) {\n      endLifeCycleTimer(currentTimerDebugID, currentTimerType);\n    }\n    emitEvent('onError', debugID);\n  },\n  onBeginProcessingChildContext: function () {\n    emitEvent('onBeginProcessingChildContext');\n  },\n  onEndProcessingChildContext: function () {\n    emitEvent('onEndProcessingChildContext');\n  },\n  onHostOperation: function (debugID, type, payload) {\n    checkDebugID(debugID);\n    emitEvent('onHostOperation', debugID, type, payload);\n  },\n  onSetState: function () {\n    emitEvent('onSetState');\n  },\n  onSetDisplayName: function (debugID, displayName) {\n    checkDebugID(debugID);\n    emitEvent('onSetDisplayName', debugID, displayName);\n  },\n  onSetChildren: function (debugID, childDebugIDs) {\n    checkDebugID(debugID);\n    childDebugIDs.forEach(checkDebugID);\n    emitEvent('onSetChildren', debugID, childDebugIDs);\n  },\n  onSetOwner: function (debugID, ownerDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetOwner', debugID, ownerDebugID);\n  },\n  onSetParent: function (debugID, parentDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetParent', debugID, parentDebugID);\n  },\n  onSetText: function (debugID, text) {\n    checkDebugID(debugID);\n    emitEvent('onSetText', debugID, text);\n  },\n  onMountRootComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountRootComponent', debugID);\n  },\n  onBeforeMountComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeMountComponent', debugID, element);\n  },\n  onMountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountComponent', debugID);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeUpdateComponent', debugID, element);\n  },\n  onUpdateComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUpdateComponent', debugID);\n  },\n  onUnmountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUnmountComponent', debugID);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool);\nReactDebugTool.addDevtool(ReactComponentTreeDevtool);\nvar url = ExecutionEnvironment.canUseDOM && window.location.href || '';\nif (/[?&]react_perf\\b/.test(url)) {\n  ReactDebugTool.beginProfiling();\n}\n\nmodule.exports = ReactDebugTool;\n},{\"147\":147,\"169\":169,\"171\":171,\"34\":34,\"70\":70,\"75\":75}],60:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultBatchingStrategy\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactUpdates = _dereq_(95);\nvar Transaction = _dereq_(113);\n\nvar emptyFunction = _dereq_(153);\n\nvar RESET_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: function () {\n    ReactDefaultBatchingStrategy.isBatchingUpdates = false;\n  }\n};\n\nvar FLUSH_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)\n};\n\nvar TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];\n\nfunction ReactDefaultBatchingStrategyTransaction() {\n  this.reinitializeTransaction();\n}\n\n_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  }\n});\n\nvar transaction = new ReactDefaultBatchingStrategyTransaction();\n\nvar ReactDefaultBatchingStrategy = {\n  isBatchingUpdates: false,\n\n  /**\n   * Call the provided function in a context within which calls to `setState`\n   * and friends are batched such that components aren't updated unnecessarily.\n   */\n  batchedUpdates: function (callback, a, b, c, d, e) {\n    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;\n\n    ReactDefaultBatchingStrategy.isBatchingUpdates = true;\n\n    // The code is written this way to avoid extra allocations\n    if (alreadyBatchingUpdates) {\n      callback(a, b, c, d, e);\n    } else {\n      transaction.perform(callback, null, a, b, c, d, e);\n    }\n  }\n};\n\nmodule.exports = ReactDefaultBatchingStrategy;\n},{\"113\":113,\"153\":153,\"172\":172,\"95\":95}],61:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultInjection\n */\n\n'use strict';\n\nvar BeforeInputEventPlugin = _dereq_(2);\nvar ChangeEventPlugin = _dereq_(6);\nvar DefaultEventPluginOrder = _dereq_(13);\nvar EnterLeaveEventPlugin = _dereq_(15);\nvar HTMLDOMPropertyConfig = _dereq_(22);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMComponent = _dereq_(39);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMEmptyComponent = _dereq_(44);\nvar ReactDOMTreeTraversal = _dereq_(57);\nvar ReactDOMTextComponent = _dereq_(55);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactEventListener = _dereq_(67);\nvar ReactInjection = _dereq_(71);\nvar ReactReconcileTransaction = _dereq_(86);\nvar SVGDOMPropertyConfig = _dereq_(97);\nvar SelectEventPlugin = _dereq_(98);\nvar SimpleEventPlugin = _dereq_(99);\n\nvar alreadyInjected = false;\n\nfunction inject() {\n  if (alreadyInjected) {\n    // TODO: This is currently true because these injections are shared between\n    // the client and the server package. They should be built independently\n    // and not share any injection state. Then this problem will be solved.\n    return;\n  }\n  alreadyInjected = true;\n\n  ReactInjection.EventEmitter.injectReactEventListener(ReactEventListener);\n\n  /**\n   * Inject modules for resolving DOM hierarchy and plugin ordering.\n   */\n  ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);\n  ReactInjection.EventPluginUtils.injectComponentTree(ReactDOMComponentTree);\n  ReactInjection.EventPluginUtils.injectTreeTraversal(ReactDOMTreeTraversal);\n\n  /**\n   * Some important event plugins included by default (without having to require\n   * them).\n   */\n  ReactInjection.EventPluginHub.injectEventPluginsByName({\n    SimpleEventPlugin: SimpleEventPlugin,\n    EnterLeaveEventPlugin: EnterLeaveEventPlugin,\n    ChangeEventPlugin: ChangeEventPlugin,\n    SelectEventPlugin: SelectEventPlugin,\n    BeforeInputEventPlugin: BeforeInputEventPlugin\n  });\n\n  ReactInjection.HostComponent.injectGenericComponentClass(ReactDOMComponent);\n\n  ReactInjection.HostComponent.injectTextComponentClass(ReactDOMTextComponent);\n\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);\n\n  ReactInjection.EmptyComponent.injectEmptyComponentFactory(function (instantiate) {\n    return new ReactDOMEmptyComponent(instantiate);\n  });\n\n  ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction);\n  ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n\n  ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);\n}\n\nmodule.exports = {\n  inject: inject\n};\n},{\"13\":13,\"15\":15,\"2\":2,\"22\":22,\"32\":32,\"39\":39,\"41\":41,\"44\":44,\"55\":55,\"57\":57,\"6\":6,\"60\":60,\"67\":67,\"71\":71,\"86\":86,\"97\":97,\"98\":98,\"99\":99}],62:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElement\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar warning = _dereq_(171);\nvar canDefineProperty = _dereq_(117);\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// The Symbol used to tag the ReactElement type. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;\n\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\n\nvar specialPropKeyWarningShown, specialPropRefWarningShown;\n\nfunction hasValidRef(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.key !== undefined;\n}\n\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, no instanceof check\n * will work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} key\n * @param {string|object} ref\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @param {*} owner\n * @param {*} props\n * @internal\n */\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allow us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  if (\"development\" !== 'production') {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {};\n\n    // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n    if (canDefineProperty) {\n      Object.defineProperty(element._store, 'validated', {\n        configurable: false,\n        enumerable: false,\n        writable: true,\n        value: false\n      });\n      // self and source are DEV only properties.\n      Object.defineProperty(element, '_self', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: self\n      });\n      // Two elements created in two different places should be considered\n      // equal for testing purposes and therefore we hide it from enumeration.\n      Object.defineProperty(element, '_source', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: source\n      });\n    } else {\n      element._store.validated = false;\n      element._self = self;\n      element._source = source;\n    }\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n\n/**\n * Create and return a new ReactElement of the given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createelement\n */\nReactElement.createElement = function (type, config, children) {\n  var propName;\n\n  // Reserved names are extracted\n  var props = {};\n\n  var key = null;\n  var ref = null;\n  var self = null;\n  var source = null;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.createElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    self = config.__self === undefined ? null : config.__self;\n    source = config.__source === undefined ? null : config.__source;\n    // Remaining properties are added to a new props object\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  // Resolve default props\n  if (type && type.defaultProps) {\n    var defaultProps = type.defaultProps;\n    for (propName in defaultProps) {\n      if (props[propName] === undefined) {\n        props[propName] = defaultProps[propName];\n      }\n    }\n  }\n  if (\"development\" !== 'production') {\n    var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n    // Create dummy `key` and `ref` property to `props` to warn users against its use\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingKey.isReactWarning = true;\n\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingRef.isReactWarning = true;\n\n    if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) {\n      if (!props.hasOwnProperty('key')) {\n        Object.defineProperty(props, 'key', {\n          get: warnAboutAccessingKey,\n          configurable: true\n        });\n      }\n      if (!props.hasOwnProperty('ref')) {\n        Object.defineProperty(props, 'ref', {\n          get: warnAboutAccessingRef,\n          configurable: true\n        });\n      }\n    }\n  }\n  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n};\n\n/**\n * Return a function that produces ReactElements of a given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createfactory\n */\nReactElement.createFactory = function (type) {\n  var factory = ReactElement.createElement.bind(null, type);\n  // Expose the type on the factory and the prototype so that it can be\n  // easily accessed on elements. E.g. `<Foo />.type === Foo`.\n  // This should not be named `constructor` since this may not be the function\n  // that created the element, and it may not even be a constructor.\n  // Legacy hook TODO: Warn if this is accessed\n  factory.type = type;\n  return factory;\n};\n\nReactElement.cloneAndReplaceKey = function (oldElement, newKey) {\n  var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);\n\n  return newElement;\n};\n\n/**\n * Clone and return a new ReactElement using element as the starting point.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement\n */\nReactElement.cloneElement = function (element, config, children) {\n  var propName;\n\n  // Original props are copied\n  var props = _assign({}, element.props);\n\n  // Reserved names are extracted\n  var key = element.key;\n  var ref = element.ref;\n  // Self is preserved since the owner is preserved.\n  var self = element._self;\n  // Source is preserved since cloneElement is unlikely to be targeted by a\n  // transpiler, and the original source is probably a better indicator of the\n  // true owner.\n  var source = element._source;\n\n  // Owner will be preserved, unless ref is overridden\n  var owner = element._owner;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.cloneElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      // Silently steal the ref from the parent.\n      ref = config.ref;\n      owner = ReactCurrentOwner.current;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    // Remaining properties override existing props\n    var defaultProps;\n    if (element.type && element.type.defaultProps) {\n      defaultProps = element.type.defaultProps;\n    }\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        if (config[propName] === undefined && defaultProps !== undefined) {\n          // Resolve default props\n          props[propName] = defaultProps[propName];\n        } else {\n          props[propName] = config[propName];\n        }\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  return ReactElement(element.type, key, ref, self, source, owner, props);\n};\n\n/**\n * Verifies the object is a ReactElement.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a valid component.\n * @final\n */\nReactElement.isValidElement = function (object) {\n  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n};\n\nReactElement.REACT_ELEMENT_TYPE = REACT_ELEMENT_TYPE;\n\nmodule.exports = ReactElement;\n},{\"117\":117,\"171\":171,\"172\":172,\"36\":36}],63:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElementValidator\n */\n\n/**\n * ReactElementValidator provides a wrapper around a element factory\n * which validates the props passed to the element. This is intended to be\n * used only in DEV and could be replaced by a static type checker for languages\n * that support it.\n */\n\n'use strict';\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar canDefineProperty = _dereq_(117);\nvar getIteratorFn = _dereq_(130);\nvar warning = _dereq_(171);\n\nfunction getDeclarationErrorAddendum() {\n  if (ReactCurrentOwner.current) {\n    var name = ReactCurrentOwner.current.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  var info = getDeclarationErrorAddendum();\n\n  if (!info) {\n    var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n    if (parentName) {\n      info = ' Check the top-level render call using <' + parentName + '>.';\n    }\n  }\n  return info;\n}\n\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\nfunction validateExplicitKey(element, parentType) {\n  if (!element._store || element._store.validated || element.key != null) {\n    return;\n  }\n  element._store.validated = true;\n\n  var memoizer = ownerHasKeyUseWarning.uniqueKey || (ownerHasKeyUseWarning.uniqueKey = {});\n\n  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n  if (memoizer[currentComponentErrorInfo]) {\n    return;\n  }\n  memoizer[currentComponentErrorInfo] = true;\n\n  // Usually the current owner is the offender, but if it accepts children as a\n  // property, it may be the creator of the child that's responsible for\n  // assigning it a key.\n  var childOwner = '';\n  if (element && element._owner && element._owner !== ReactCurrentOwner.current) {\n    // Give the component that originally created this child.\n    childOwner = ' It was passed a child from ' + element._owner.getName() + '.';\n  }\n\n  \"development\" !== 'production' ? warning(false, 'Each child in an array or iterator should have a unique \"key\" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.%s', currentComponentErrorInfo, childOwner, ReactComponentTreeDevtool.getCurrentStackAddendum(element)) : void 0;\n}\n\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\nfunction validateChildKeys(node, parentType) {\n  if (typeof node !== 'object') {\n    return;\n  }\n  if (Array.isArray(node)) {\n    for (var i = 0; i < node.length; i++) {\n      var child = node[i];\n      if (ReactElement.isValidElement(child)) {\n        validateExplicitKey(child, parentType);\n      }\n    }\n  } else if (ReactElement.isValidElement(node)) {\n    // This element was passed in a valid location.\n    if (node._store) {\n      node._store.validated = true;\n    }\n  } else if (node) {\n    var iteratorFn = getIteratorFn(node);\n    // Entry iterators provide implicit keys.\n    if (iteratorFn) {\n      if (iteratorFn !== node.entries) {\n        var iterator = iteratorFn.call(node);\n        var step;\n        while (!(step = iterator.next()).done) {\n          if (ReactElement.isValidElement(step.value)) {\n            validateExplicitKey(step.value, parentType);\n          }\n        }\n      }\n    }\n  }\n}\n\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\nfunction validatePropTypes(element) {\n  var componentClass = element.type;\n  if (typeof componentClass !== 'function') {\n    return;\n  }\n  var name = componentClass.displayName || componentClass.name;\n  if (componentClass.propTypes) {\n    checkReactTypeSpec(componentClass.propTypes, element.props, ReactPropTypeLocations.prop, name, element, null);\n  }\n  if (typeof componentClass.getDefaultProps === 'function') {\n    \"development\" !== 'production' ? warning(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0;\n  }\n}\n\nvar ReactElementValidator = {\n\n  createElement: function (type, props, children) {\n    var validType = typeof type === 'string' || typeof type === 'function';\n    // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n    \"development\" !== 'production' ? warning(validType, 'React.createElement: type should not be null, undefined, boolean, or ' + 'number. It should be a string (for DOM elements) or a ReactClass ' + '(for composite components).%s', getDeclarationErrorAddendum()) : void 0;\n\n    var element = ReactElement.createElement.apply(this, arguments);\n\n    // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n    if (element == null) {\n      return element;\n    }\n\n    // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n    if (validType) {\n      for (var i = 2; i < arguments.length; i++) {\n        validateChildKeys(arguments[i], type);\n      }\n    }\n\n    validatePropTypes(element);\n\n    return element;\n  },\n\n  createFactory: function (type) {\n    var validatedFactory = ReactElementValidator.createElement.bind(null, type);\n    // Legacy hook TODO: Warn if this is accessed\n    validatedFactory.type = type;\n\n    if (\"development\" !== 'production') {\n      if (canDefineProperty) {\n        Object.defineProperty(validatedFactory, 'type', {\n          enumerable: false,\n          get: function () {\n            \"development\" !== 'production' ? warning(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.') : void 0;\n            Object.defineProperty(this, 'type', {\n              value: type\n            });\n            return type;\n          }\n        });\n      }\n    }\n\n    return validatedFactory;\n  },\n\n  cloneElement: function (element, props, children) {\n    var newElement = ReactElement.cloneElement.apply(this, arguments);\n    for (var i = 2; i < arguments.length; i++) {\n      validateChildKeys(arguments[i], newElement.type);\n    }\n    validatePropTypes(newElement);\n    return newElement;\n  }\n\n};\n\nmodule.exports = ReactElementValidator;\n},{\"117\":117,\"118\":118,\"130\":130,\"171\":171,\"34\":34,\"36\":36,\"62\":62,\"84\":84}],64:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEmptyComponent\n */\n\n'use strict';\n\nvar emptyComponentFactory;\n\nvar ReactEmptyComponentInjection = {\n  injectEmptyComponentFactory: function (factory) {\n    emptyComponentFactory = factory;\n  }\n};\n\nvar ReactEmptyComponent = {\n  create: function (instantiate) {\n    return emptyComponentFactory(instantiate);\n  }\n};\n\nReactEmptyComponent.injection = ReactEmptyComponentInjection;\n\nmodule.exports = ReactEmptyComponent;\n},{}],65:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactErrorUtils\n */\n\n'use strict';\n\nvar caughtError = null;\n\n/**\n * Call a function while guarding against errors that happens within it.\n *\n * @param {?String} name of the guard to use for logging or debugging\n * @param {Function} func The function to invoke\n * @param {*} a First argument\n * @param {*} b Second argument\n */\nfunction invokeGuardedCallback(name, func, a, b) {\n  try {\n    return func(a, b);\n  } catch (x) {\n    if (caughtError === null) {\n      caughtError = x;\n    }\n    return undefined;\n  }\n}\n\nvar ReactErrorUtils = {\n  invokeGuardedCallback: invokeGuardedCallback,\n\n  /**\n   * Invoked by ReactTestUtils.Simulate so that any errors thrown by the event\n   * handler are sure to be rethrown by rethrowCaughtError.\n   */\n  invokeGuardedCallbackWithCatch: invokeGuardedCallback,\n\n  /**\n   * During execution of guarded functions we will capture the first error which\n   * we will rethrow to be handled by the top level error handler.\n   */\n  rethrowCaughtError: function () {\n    if (caughtError) {\n      var error = caughtError;\n      caughtError = null;\n      throw error;\n    }\n  }\n};\n\nif (\"development\" !== 'production') {\n  /**\n   * To help development we can get better devtools integration by simulating a\n   * real browser event.\n   */\n  if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {\n    var fakeNode = document.createElement('react');\n    ReactErrorUtils.invokeGuardedCallback = function (name, func, a, b) {\n      var boundFunc = func.bind(null, a, b);\n      var evtType = 'react-' + name;\n      fakeNode.addEventListener(evtType, boundFunc, false);\n      var evt = document.createEvent('Event');\n      evt.initEvent(evtType, false, false);\n      fakeNode.dispatchEvent(evt);\n      fakeNode.removeEventListener(evtType, boundFunc, false);\n    };\n  }\n}\n\nmodule.exports = ReactErrorUtils;\n},{}],66:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventEmitterMixin\n */\n\n'use strict';\n\nvar EventPluginHub = _dereq_(17);\n\nfunction runEventQueueInBatch(events) {\n  EventPluginHub.enqueueEvents(events);\n  EventPluginHub.processEventQueue(false);\n}\n\nvar ReactEventEmitterMixin = {\n\n  /**\n   * Streams a fired top-level event to `EventPluginHub` where plugins have the\n   * opportunity to create `ReactEvent`s to be dispatched.\n   */\n  handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events = EventPluginHub.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n    runEventQueueInBatch(events);\n  }\n};\n\nmodule.exports = ReactEventEmitterMixin;\n},{\"17\":17}],67:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventListener\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventListener = _dereq_(146);\nvar ExecutionEnvironment = _dereq_(147);\nvar PooledClass = _dereq_(25);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar getEventTarget = _dereq_(128);\nvar getUnboundedScrollPosition = _dereq_(158);\n\n/**\n * Find the deepest React component completely containing the root of the\n * passed-in instance (for use when entire React trees are nested within each\n * other). If React trees are not nested, returns null.\n */\nfunction findParent(inst) {\n  // TODO: It may be a good idea to cache this to prevent unnecessary DOM\n  // traversal, but caching is difficult to do correctly without using a\n  // mutation observer to listen for all DOM changes.\n  while (inst._hostParent) {\n    inst = inst._hostParent;\n  }\n  var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);\n  var container = rootNode.parentNode;\n  return ReactDOMComponentTree.getClosestInstanceFromNode(container);\n}\n\n// Used to store ancestor hierarchy in top level callback\nfunction TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {\n  this.topLevelType = topLevelType;\n  this.nativeEvent = nativeEvent;\n  this.ancestors = [];\n}\n_assign(TopLevelCallbackBookKeeping.prototype, {\n  destructor: function () {\n    this.topLevelType = null;\n    this.nativeEvent = null;\n    this.ancestors.length = 0;\n  }\n});\nPooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler);\n\nfunction handleTopLevelImpl(bookKeeping) {\n  var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);\n  var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);\n\n  // Loop through the hierarchy, in case there's any nested components.\n  // It's important that we build the array of ancestors before calling any\n  // event handlers, because event handlers can modify the DOM, leading to\n  // inconsistencies with ReactMount's node cache. See #1105.\n  var ancestor = targetInst;\n  do {\n    bookKeeping.ancestors.push(ancestor);\n    ancestor = ancestor && findParent(ancestor);\n  } while (ancestor);\n\n  for (var i = 0; i < bookKeeping.ancestors.length; i++) {\n    targetInst = bookKeeping.ancestors[i];\n    ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));\n  }\n}\n\nfunction scrollValueMonitor(cb) {\n  var scrollPosition = getUnboundedScrollPosition(window);\n  cb(scrollPosition);\n}\n\nvar ReactEventListener = {\n  _enabled: true,\n  _handleTopLevel: null,\n\n  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,\n\n  setHandleTopLevel: function (handleTopLevel) {\n    ReactEventListener._handleTopLevel = handleTopLevel;\n  },\n\n  setEnabled: function (enabled) {\n    ReactEventListener._enabled = !!enabled;\n  },\n\n  isEnabled: function () {\n    return ReactEventListener._enabled;\n  },\n\n  /**\n   * Traps top-level events by using event bubbling.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  /**\n   * Traps a top-level event by using event capturing.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  monitorScrollValue: function (refresh) {\n    var callback = scrollValueMonitor.bind(null, refresh);\n    EventListener.listen(window, 'scroll', callback);\n  },\n\n  dispatchEvent: function (topLevelType, nativeEvent) {\n    if (!ReactEventListener._enabled) {\n      return;\n    }\n\n    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);\n    try {\n      // Event queue being processed in the same cycle allows\n      // `preventDefault`.\n      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);\n    } finally {\n      TopLevelCallbackBookKeeping.release(bookKeeping);\n    }\n  }\n};\n\nmodule.exports = ReactEventListener;\n},{\"128\":128,\"146\":146,\"147\":147,\"158\":158,\"172\":172,\"25\":25,\"41\":41,\"95\":95}],68:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactFeatureFlags\n * \n */\n\n'use strict';\n\nvar ReactFeatureFlags = {\n  // When true, call console.time() before and .timeEnd() after each top-level\n  // render (both initial renders and updates). Useful when looking at prod-mode\n  // timeline profiles in Chrome, for example.\n  logTopLevelRenders: false\n};\n\nmodule.exports = ReactFeatureFlags;\n},{}],69:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar invariant = _dereq_(161);\n\nvar genericComponentClass = null;\n// This registry keeps track of wrapper classes around host tags.\nvar tagToComponentClass = {};\nvar textComponentClass = null;\n\nvar ReactHostComponentInjection = {\n  // This accepts a class that receives the tag string. This is a catch all\n  // that can render any kind of tag.\n  injectGenericComponentClass: function (componentClass) {\n    genericComponentClass = componentClass;\n  },\n  // This accepts a text component class that takes the text string to be\n  // rendered as props.\n  injectTextComponentClass: function (componentClass) {\n    textComponentClass = componentClass;\n  },\n  // This accepts a keyed object with classes as values. Each key represents a\n  // tag. That particular tag will use this class instead of the generic one.\n  injectComponentClasses: function (componentClasses) {\n    _assign(tagToComponentClass, componentClasses);\n  }\n};\n\n/**\n * Get a host internal component class for a specific tag.\n *\n * @param {ReactElement} element The element to create.\n * @return {function} The internal class constructor function.\n */\nfunction createInternalComponent(element) {\n  !genericComponentClass ? \"development\" !== 'production' ? invariant(false, 'There is no registered component for the tag %s', element.type) : _prodInvariant('111', element.type) : void 0;\n  return new genericComponentClass(element);\n}\n\n/**\n * @param {ReactText} text\n * @return {ReactComponent}\n */\nfunction createInstanceForText(text) {\n  return new textComponentClass(text);\n}\n\n/**\n * @param {ReactComponent} component\n * @return {boolean}\n */\nfunction isTextComponent(component) {\n  return component instanceof textComponentClass;\n}\n\nvar ReactHostComponent = {\n  createInternalComponent: createInternalComponent,\n  createInstanceForText: createInstanceForText,\n  isTextComponent: isTextComponent,\n  injection: ReactHostComponentInjection\n};\n\nmodule.exports = ReactHostComponent;\n},{\"139\":139,\"161\":161,\"172\":172}],70:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostOperationHistoryDevtool\n */\n\n'use strict';\n\nvar history = [];\n\nvar ReactHostOperationHistoryDevtool = {\n  onHostOperation: function (debugID, type, payload) {\n    history.push({\n      instanceID: debugID,\n      type: type,\n      payload: payload\n    });\n  },\n  clearHistory: function () {\n    if (ReactHostOperationHistoryDevtool._preventClearing) {\n      // Should only be used for tests.\n      return;\n    }\n\n    history = [];\n  },\n  getHistory: function () {\n    return history;\n  }\n};\n\nmodule.exports = ReactHostOperationHistoryDevtool;\n},{}],71:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInjection\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactClass = _dereq_(30);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactHostComponent = _dereq_(69);\nvar ReactUpdates = _dereq_(95);\n\nvar ReactInjection = {\n  Component: ReactComponentEnvironment.injection,\n  Class: ReactClass.injection,\n  DOMProperty: DOMProperty.injection,\n  EmptyComponent: ReactEmptyComponent.injection,\n  EventPluginHub: EventPluginHub.injection,\n  EventPluginUtils: EventPluginUtils.injection,\n  EventEmitter: ReactBrowserEventEmitter.injection,\n  HostComponent: ReactHostComponent.injection,\n  Updates: ReactUpdates.injection\n};\n\nmodule.exports = ReactInjection;\n},{\"10\":10,\"17\":17,\"19\":19,\"27\":27,\"30\":30,\"33\":33,\"64\":64,\"69\":69,\"95\":95}],72:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInputSelection\n */\n\n'use strict';\n\nvar ReactDOMSelection = _dereq_(53);\n\nvar containsNode = _dereq_(150);\nvar focusNode = _dereq_(155);\nvar getActiveElement = _dereq_(156);\n\nfunction isInDocument(node) {\n  return containsNode(document.documentElement, node);\n}\n\n/**\n * @ReactInputSelection: React input selection module. Based on Selection.js,\n * but modified to be suitable for react and has a couple of bug fixes (doesn't\n * assume buttons have range selections allowed).\n * Input selection module for React.\n */\nvar ReactInputSelection = {\n\n  hasSelectionCapabilities: function (elem) {\n    var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n    return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');\n  },\n\n  getSelectionInformation: function () {\n    var focusedElem = getActiveElement();\n    return {\n      focusedElem: focusedElem,\n      selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null\n    };\n  },\n\n  /**\n   * @restoreSelection: If any selection information was potentially lost,\n   * restore it. This is useful when performing operations that could remove dom\n   * nodes and place them back in, resulting in focus being lost.\n   */\n  restoreSelection: function (priorSelectionInformation) {\n    var curFocusedElem = getActiveElement();\n    var priorFocusedElem = priorSelectionInformation.focusedElem;\n    var priorSelectionRange = priorSelectionInformation.selectionRange;\n    if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {\n      if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {\n        ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);\n      }\n      focusNode(priorFocusedElem);\n    }\n  },\n\n  /**\n   * @getSelection: Gets the selection bounds of a focused textarea, input or\n   * contentEditable node.\n   * -@input: Look up selection bounds of this input\n   * -@return {start: selectionStart, end: selectionEnd}\n   */\n  getSelection: function (input) {\n    var selection;\n\n    if ('selectionStart' in input) {\n      // Modern browser with input or textarea.\n      selection = {\n        start: input.selectionStart,\n        end: input.selectionEnd\n      };\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      // IE8 input.\n      var range = document.selection.createRange();\n      // There can only be one selection per document in IE, so it must\n      // be in our element.\n      if (range.parentElement() === input) {\n        selection = {\n          start: -range.moveStart('character', -input.value.length),\n          end: -range.moveEnd('character', -input.value.length)\n        };\n      }\n    } else {\n      // Content editable or old IE textarea.\n      selection = ReactDOMSelection.getOffsets(input);\n    }\n\n    return selection || { start: 0, end: 0 };\n  },\n\n  /**\n   * @setSelection: Sets the selection bounds of a textarea or input and focuses\n   * the input.\n   * -@input     Set selection bounds of this input or textarea\n   * -@offsets   Object of same form that is returned from get*\n   */\n  setSelection: function (input, offsets) {\n    var start = offsets.start;\n    var end = offsets.end;\n    if (end === undefined) {\n      end = start;\n    }\n\n    if ('selectionStart' in input) {\n      input.selectionStart = start;\n      input.selectionEnd = Math.min(end, input.value.length);\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      var range = input.createTextRange();\n      range.collapse(true);\n      range.moveStart('character', start);\n      range.moveEnd('character', end - start);\n      range.select();\n    } else {\n      ReactDOMSelection.setOffsets(input, offsets);\n    }\n  }\n};\n\nmodule.exports = ReactInputSelection;\n},{\"150\":150,\"155\":155,\"156\":156,\"53\":53}],73:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstanceMap\n */\n\n'use strict';\n\n/**\n * `ReactInstanceMap` maintains a mapping from a public facing stateful\n * instance (key) and the internal representation (value). This allows public\n * methods to accept the user facing instance as an argument and map them back\n * to internal methods.\n */\n\n// TODO: Replace this with ES6: var ReactInstanceMap = new Map();\n\nvar ReactInstanceMap = {\n\n  /**\n   * This API should be called `delete` but we'd have to make sure to always\n   * transform these to strings for IE support. When this transform is fully\n   * supported we can rename it.\n   */\n  remove: function (key) {\n    key._reactInternalInstance = undefined;\n  },\n\n  get: function (key) {\n    return key._reactInternalInstance;\n  },\n\n  has: function (key) {\n    return key._reactInternalInstance !== undefined;\n  },\n\n  set: function (key, value) {\n    key._reactInternalInstance = value;\n  }\n\n};\n\nmodule.exports = ReactInstanceMap;\n},{}],74:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDebugTool = _dereq_(59);\n  debugTool = ReactDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"59\":59}],75:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInvalidSetStateWarningDevTool\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var processingChildContext = false;\n\n  var warnInvalidSetState = function () {\n    \"development\" !== 'production' ? warning(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()') : void 0;\n  };\n}\n\nvar ReactInvalidSetStateWarningDevTool = {\n  onBeginProcessingChildContext: function () {\n    processingChildContext = true;\n  },\n  onEndProcessingChildContext: function () {\n    processingChildContext = false;\n  },\n  onSetState: function () {\n    warnInvalidSetState();\n  }\n};\n\nmodule.exports = ReactInvalidSetStateWarningDevTool;\n},{\"171\":171}],76:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMarkupChecksum\n */\n\n'use strict';\n\nvar adler32 = _dereq_(116);\n\nvar TAG_END = /\\/?>/;\nvar COMMENT_START = /^<\\!\\-\\-/;\n\nvar ReactMarkupChecksum = {\n  CHECKSUM_ATTR_NAME: 'data-react-checksum',\n\n  /**\n   * @param {string} markup Markup string\n   * @return {string} Markup string with checksum attribute attached\n   */\n  addChecksumToMarkup: function (markup) {\n    var checksum = adler32(markup);\n\n    // Add checksum (handle both parent tags, comments and self-closing tags)\n    if (COMMENT_START.test(markup)) {\n      return markup;\n    } else {\n      return markup.replace(TAG_END, ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '=\"' + checksum + '\"$&');\n    }\n  },\n\n  /**\n   * @param {string} markup to use\n   * @param {DOMElement} element root React element\n   * @returns {boolean} whether or not the markup is the same\n   */\n  canReuseMarkup: function (markup, element) {\n    var existingChecksum = element.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n    existingChecksum = existingChecksum && parseInt(existingChecksum, 10);\n    var markupChecksum = adler32(markup);\n    return markupChecksum === existingChecksum;\n  }\n};\n\nmodule.exports = ReactMarkupChecksum;\n},{\"116\":116}],77:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMount\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar DOMProperty = _dereq_(10);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDOMFeatureFlags = _dereq_(46);\nvar ReactElement = _dereq_(62);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdateQueue = _dereq_(94);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\nvar setInnerHTML = _dereq_(141);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOC_NODE_TYPE = 9;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\nvar instancesByReactRootID = {};\n\n/**\n * Finds the index of the first character\n * that's not common between the two given strings.\n *\n * @return {number} the index of the character where the strings diverge\n */\nfunction firstDifferenceIndex(string1, string2) {\n  var minLen = Math.min(string1.length, string2.length);\n  for (var i = 0; i < minLen; i++) {\n    if (string1.charAt(i) !== string2.charAt(i)) {\n      return i;\n    }\n  }\n  return string1.length === string2.length ? -1 : minLen;\n}\n\n/**\n * @param {DOMElement|DOMDocument} container DOM element that may contain\n * a React component\n * @return {?*} DOM element that may have the reactRoot ID, or null.\n */\nfunction getReactRootElementInContainer(container) {\n  if (!container) {\n    return null;\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    return container.documentElement;\n  } else {\n    return container.firstChild;\n  }\n}\n\nfunction internalGetID(node) {\n  // If node is something like a window, document, or text node, none of\n  // which support attributes or a .getAttribute method, gracefully return\n  // the empty string, as if the attribute were missing.\n  return node.getAttribute && node.getAttribute(ATTR_NAME) || '';\n}\n\n/**\n * Mounts this component and inserts it into the DOM.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {ReactReconcileTransaction} transaction\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) {\n  var markerName;\n  if (ReactFeatureFlags.logTopLevelRenders) {\n    var wrappedElement = wrapperInstance._currentElement.props;\n    var type = wrappedElement.type;\n    markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name);\n    console.time(markerName);\n  }\n\n  var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context);\n\n  if (markerName) {\n    console.timeEnd(markerName);\n  }\n\n  wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;\n  ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction);\n}\n\n/**\n * Batched mount.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) {\n  var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */\n  !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement);\n  transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context);\n  ReactUpdates.ReactReconcileTransaction.release(transaction);\n}\n\n/**\n * Unmounts a component and removes it from the DOM.\n *\n * @param {ReactComponent} instance React component instance.\n * @param {DOMElement} container DOM element to unmount from.\n * @final\n * @internal\n * @see {ReactMount.unmountComponentAtNode}\n */\nfunction unmountComponentFromNode(instance, container, safely) {\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onBeginFlush();\n  }\n  ReactReconciler.unmountComponent(instance, safely);\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onEndFlush();\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    container = container.documentElement;\n  }\n\n  // http://jsperf.com/emptying-a-node\n  while (container.lastChild) {\n    container.removeChild(container.lastChild);\n  }\n}\n\n/**\n * True if the supplied DOM node has a direct React-rendered child that is\n * not a React root element. Useful for warning in `render`,\n * `unmountComponentAtNode`, etc.\n *\n * @param {?DOMElement} node The candidate DOM node.\n * @return {boolean} True if the DOM element contains a direct child that was\n * rendered by React but is not a root element.\n * @internal\n */\nfunction hasNonRootReactChild(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  if (rootEl) {\n    var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);\n    return !!(inst && inst._hostParent);\n  }\n}\n\nfunction getHostRootInstanceInContainer(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  var prevHostInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);\n  return prevHostInstance && !prevHostInstance._hostParent ? prevHostInstance : null;\n}\n\nfunction getTopLevelWrapperInContainer(container) {\n  var root = getHostRootInstanceInContainer(container);\n  return root ? root._hostContainerInfo._topLevelWrapper : null;\n}\n\n/**\n * Temporary (?) hack so that we can store all top-level pending updates on\n * composites instead of having to worry about different types of components\n * here.\n */\nvar topLevelRootCounter = 1;\nvar TopLevelWrapper = function () {\n  this.rootID = topLevelRootCounter++;\n};\nTopLevelWrapper.prototype.isReactComponent = {};\nif (\"development\" !== 'production') {\n  TopLevelWrapper.displayName = 'TopLevelWrapper';\n}\nTopLevelWrapper.prototype.render = function () {\n  // this.props is actually a ReactElement\n  return this.props;\n};\n\n/**\n * Mounting is the process of initializing a React component by creating its\n * representative DOM elements and inserting them into a supplied `container`.\n * Any prior content inside `container` is destroyed in the process.\n *\n *   ReactMount.render(\n *     component,\n *     document.getElementById('container')\n *   );\n *\n *   <div id=\"container\">                   <-- Supplied `container`.\n *     <div data-reactid=\".3\">              <-- Rendered reactRoot of React\n *       // ...                                 component.\n *     </div>\n *   </div>\n *\n * Inside of `container`, the first element rendered is the \"reactRoot\".\n */\nvar ReactMount = {\n\n  TopLevelWrapper: TopLevelWrapper,\n\n  /**\n   * Used by devtools. The keys are not important.\n   */\n  _instancesByReactRootID: instancesByReactRootID,\n\n  /**\n   * This is a hook provided to support rendering React components while\n   * ensuring that the apparent scroll position of its `container` does not\n   * change.\n   *\n   * @param {DOMElement} container The `container` being rendered into.\n   * @param {function} renderCallback This must be called once to do the render.\n   */\n  scrollMonitor: function (container, renderCallback) {\n    renderCallback();\n  },\n\n  /**\n   * Take a component that's already mounted into the DOM and replace its props\n   * @param {ReactComponent} prevComponent component instance already in the DOM\n   * @param {ReactElement} nextElement component instance to render\n   * @param {DOMElement} container container to render into\n   * @param {?function} callback function triggered on completion\n   */\n  _updateRootComponent: function (prevComponent, nextElement, nextContext, container, callback) {\n    ReactMount.scrollMonitor(container, function () {\n      ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement, nextContext);\n      if (callback) {\n        ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);\n      }\n    });\n\n    return prevComponent;\n  },\n\n  /**\n   * Render a new component into the DOM. Hooked by devtools!\n   *\n   * @param {ReactElement} nextElement element to render\n   * @param {DOMElement} container container to render into\n   * @param {boolean} shouldReuseMarkup if we should skip the markup insertion\n   * @return {ReactComponent} nextComponent\n   */\n  _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case.\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '_renderNewRootComponent(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from ' + 'render is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : _prodInvariant('37') : void 0;\n\n    ReactBrowserEventEmitter.ensureScrollValueMonitoring();\n    var componentInstance = instantiateReactComponent(nextElement, false);\n\n    // The initial render is synchronous but any updates that happen during\n    // rendering, in componentWillMount or componentDidMount, will be batched\n    // according to the current batching strategy.\n\n    ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);\n\n    var wrapperID = componentInstance._instance.rootID;\n    instancesByReactRootID[wrapperID] = componentInstance;\n\n    if (\"development\" !== 'production') {\n      // The instance here is TopLevelWrapper so we report mount for its child.\n      ReactInstrumentation.debugTool.onMountRootComponent(componentInstance._renderedComponent._debugID);\n    }\n\n    return componentInstance;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactComponent} parentComponent The conceptual parent of this render tree.\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    !(parentComponent != null && ReactInstanceMap.has(parentComponent)) ? \"development\" !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : _prodInvariant('38') : void 0;\n    return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback);\n  },\n\n  _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');\n    !ReactElement.isValidElement(nextElement) ? \"development\" !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' :\n    // Check if it quacks like an element\n    nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : _prodInvariant('39', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : void 0;\n\n    \"development\" !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0;\n\n    var nextWrappedElement = ReactElement(TopLevelWrapper, null, null, null, null, null, nextElement);\n\n    var nextContext;\n    if (parentComponent) {\n      var parentInst = ReactInstanceMap.get(parentComponent);\n      nextContext = parentInst._processChildContext(parentInst._context);\n    } else {\n      nextContext = emptyObject;\n    }\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n\n    if (prevComponent) {\n      var prevWrappedElement = prevComponent._currentElement;\n      var prevElement = prevWrappedElement.props;\n      if (shouldUpdateReactComponent(prevElement, nextElement)) {\n        var publicInst = prevComponent._renderedComponent.getPublicInstance();\n        var updatedCallback = callback && function () {\n          callback.call(publicInst);\n        };\n        ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);\n        return publicInst;\n      } else {\n        ReactMount.unmountComponentAtNode(container);\n      }\n    }\n\n    var reactRootElement = getReactRootElementInContainer(container);\n    var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);\n    var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0;\n\n      if (!containerHasReactMarkup || reactRootElement.nextSibling) {\n        var rootElementSibling = reactRootElement;\n        while (rootElementSibling) {\n          if (internalGetID(rootElementSibling)) {\n            \"development\" !== 'production' ? warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.') : void 0;\n            break;\n          }\n          rootElementSibling = rootElementSibling.nextSibling;\n        }\n      }\n    }\n\n    var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;\n    var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();\n    if (callback) {\n      callback.call(component);\n    }\n    return component;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  render: function (nextElement, container, callback) {\n    return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);\n  },\n\n  /**\n   * Unmounts and destroys the React component rendered in the `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode\n   *\n   * @param {DOMElement} container DOM element containing a React component.\n   * @return {boolean} True if a component was found in and unmounted from\n   *                   `container`\n   */\n  unmountComponentAtNode: function (container) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case. (Strictly speaking, unmounting won't cause a\n    // render but we still don't expect to be in a render call here.)\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : _prodInvariant('40') : void 0;\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n    if (!prevComponent) {\n      // Check if the node being unmounted was rendered by React, but isn't a\n      // root node.\n      var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n      // Check if the container itself is a React root node.\n      var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME);\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'unmountComponentAtNode(): The node you\\'re attempting to unmount ' + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0;\n      }\n\n      return false;\n    }\n    delete instancesByReactRootID[prevComponent._instance.rootID];\n    ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false);\n    return true;\n  },\n\n  _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) {\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : _prodInvariant('41') : void 0;\n\n    if (shouldReuseMarkup) {\n      var rootElement = getReactRootElementInContainer(container);\n      if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {\n        ReactDOMComponentTree.precacheNode(instance, rootElement);\n        return;\n      } else {\n        var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n        rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n\n        var rootMarkup = rootElement.outerHTML;\n        rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum);\n\n        var normalizedMarkup = markup;\n        if (\"development\" !== 'production') {\n          // because rootMarkup is retrieved from the DOM, various normalizations\n          // will have occurred which will not be present in `markup`. Here,\n          // insert markup into a <div> or <iframe> depending on the container\n          // type to perform the same normalizations before comparing.\n          var normalizer;\n          if (container.nodeType === ELEMENT_NODE_TYPE) {\n            normalizer = document.createElement('div');\n            normalizer.innerHTML = markup;\n            normalizedMarkup = normalizer.innerHTML;\n          } else {\n            normalizer = document.createElement('iframe');\n            document.body.appendChild(normalizer);\n            normalizer.contentDocument.write(markup);\n            normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;\n            document.body.removeChild(normalizer);\n          }\n        }\n\n        var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);\n        var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);\n\n        !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure. React cannot handle this case due to cross-browser quirks by rendering at the document root. You should look for environment dependent code in your components and ensure the props are the same client and server side:\\n%s', difference) : _prodInvariant('42', difference) : void 0;\n\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'React attempted to reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are ' + 'using server rendering and the markup generated on the ' + 'server was not what the client was expecting. React injected ' + 'new markup to compensate which works but you have lost many ' + 'of the benefits of server rendering. Instead, figure out ' + 'why the markup being generated is different on the client ' + 'or server:\\n%s', difference) : void 0;\n        }\n      }\n    }\n\n    !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document but you didn\\'t use server rendering. We can\\'t do this without using server rendering due to cross-browser quirks. See ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('43') : void 0;\n\n    if (transaction.useCreateElement) {\n      while (container.lastChild) {\n        container.removeChild(container.lastChild);\n      }\n      DOMLazyTree.insertTreeBefore(container, markup, null);\n    } else {\n      setInnerHTML(container, markup);\n      ReactDOMComponentTree.precacheNode(instance, container.firstChild);\n    }\n\n    if (\"development\" !== 'production') {\n      var hostNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);\n      if (hostNode._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(hostNode._debugID, 'mount', markup.toString());\n      }\n    }\n  }\n};\n\nmodule.exports = ReactMount;\n},{\"10\":10,\"134\":134,\"139\":139,\"141\":141,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"27\":27,\"36\":36,\"41\":41,\"42\":42,\"46\":46,\"62\":62,\"68\":68,\"73\":73,\"74\":74,\"76\":76,\"8\":8,\"87\":87,\"94\":94,\"95\":95}],78:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChild\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactReconciler = _dereq_(87);\nvar ReactChildReconciler = _dereq_(28);\n\nvar emptyFunction = _dereq_(153);\nvar flattenChildren = _dereq_(123);\nvar invariant = _dereq_(161);\n\n/**\n * Make an update for markup to be rendered and inserted at a supplied index.\n *\n * @param {string} markup Markup that renders into an element.\n * @param {number} toIndex Destination index.\n * @private\n */\nfunction makeInsertMarkup(markup, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.INSERT_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for moving an existing element to another index.\n *\n * @param {number} fromIndex Source index of the existing element.\n * @param {number} toIndex Destination index of the element.\n * @private\n */\nfunction makeMove(child, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.MOVE_EXISTING,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: ReactReconciler.getHostNode(child),\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for removing an element at an index.\n *\n * @param {number} fromIndex Index of the element to remove.\n * @private\n */\nfunction makeRemove(child, node) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.REMOVE_NODE,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: node,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the markup of a node.\n *\n * @param {string} markup Markup that renders into an element.\n * @private\n */\nfunction makeSetMarkup(markup) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.SET_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the text content.\n *\n * @param {string} textContent Text content to set.\n * @private\n */\nfunction makeTextContent(textContent) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.TEXT_CONTENT,\n    content: textContent,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Push an update, if any, onto the queue. Creates a new queue if none is\n * passed and always returns the queue. Mutative.\n */\nfunction enqueue(queue, update) {\n  if (update) {\n    queue = queue || [];\n    queue.push(update);\n  }\n  return queue;\n}\n\n/**\n * Processes any enqueued updates.\n *\n * @private\n */\nfunction processQueue(inst, updateQueue) {\n  ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue);\n}\n\nvar setParentForInstrumentation = emptyFunction;\nvar setChildrenForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  var getDebugID = function (inst) {\n    if (!inst._debugID) {\n      // Check for ART-like instances. TODO: This is silly/gross.\n      var internal;\n      if (internal = ReactInstanceMap.get(inst)) {\n        inst = internal;\n      }\n    }\n    return inst._debugID;\n  };\n  setParentForInstrumentation = function (child) {\n    if (child._debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetParent(child._debugID, getDebugID(this));\n    }\n  };\n  setChildrenForInstrumentation = function (children) {\n    var debugID = getDebugID(this);\n    // TODO: React Native empty components are also multichild.\n    // This means they still get into this method but don't have _debugID.\n    if (debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetChildren(debugID, children ? Object.keys(children).map(function (key) {\n        return children[key]._debugID;\n      }) : []);\n    }\n  };\n}\n\n/**\n * ReactMultiChild are capable of reconciling multiple children.\n *\n * @class ReactMultiChild\n * @internal\n */\nvar ReactMultiChild = {\n\n  /**\n   * Provides common functionality for components that must reconcile multiple\n   * children. This is used by `ReactDOMComponent` to mount, update, and\n   * unmount child components.\n   *\n   * @lends {ReactMultiChild.prototype}\n   */\n  Mixin: {\n\n    _reconcilerInstantiateChildren: function (nestedChildren, transaction, context) {\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n        }\n      }\n      return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context);\n    },\n\n    _reconcilerUpdateChildren: function (prevChildren, nextNestedChildrenElements, removedNodes, transaction, context) {\n      var nextChildren;\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            nextChildren = flattenChildren(nextNestedChildrenElements, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n          ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n          return nextChildren;\n        }\n      }\n      nextChildren = flattenChildren(nextNestedChildrenElements);\n      ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n      return nextChildren;\n    },\n\n    /**\n     * Generates a \"mount image\" for each of the supplied children. In the case\n     * of `ReactDOMComponent`, a mount image is a string of markup.\n     *\n     * @param {?object} nestedChildren Nested child maps.\n     * @return {array} An array of mounted representations.\n     * @internal\n     */\n    mountChildren: function (nestedChildren, transaction, context) {\n      var children = this._reconcilerInstantiateChildren(nestedChildren, transaction, context);\n      this._renderedChildren = children;\n\n      var mountImages = [];\n      var index = 0;\n      for (var name in children) {\n        if (children.hasOwnProperty(name)) {\n          var child = children[name];\n          if (\"development\" !== 'production') {\n            setParentForInstrumentation.call(this, child);\n          }\n          var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n          child._mountIndex = index++;\n          mountImages.push(mountImage);\n        }\n      }\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, children);\n      }\n\n      return mountImages;\n    },\n\n    /**\n     * Replaces any rendered children with a text content string.\n     *\n     * @param {string} nextContent String of content.\n     * @internal\n     */\n    updateTextContent: function (nextContent) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      // Set new text content.\n      var updates = [makeTextContent(nextContent)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Replaces any rendered children with a markup string.\n     *\n     * @param {string} nextMarkup String of markup.\n     * @internal\n     */\n    updateMarkup: function (nextMarkup) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      var updates = [makeSetMarkup(nextMarkup)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Updates the rendered children with new children.\n     *\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @internal\n     */\n    updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      // Hook used by React ART\n      this._updateChildren(nextNestedChildrenElements, transaction, context);\n    },\n\n    /**\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @final\n     * @protected\n     */\n    _updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      var prevChildren = this._renderedChildren;\n      var removedNodes = {};\n      var nextChildren = this._reconcilerUpdateChildren(prevChildren, nextNestedChildrenElements, removedNodes, transaction, context);\n      if (!nextChildren && !prevChildren) {\n        return;\n      }\n      var updates = null;\n      var name;\n      // `nextIndex` will increment for each child in `nextChildren`, but\n      // `lastIndex` will be the last index visited in `prevChildren`.\n      var lastIndex = 0;\n      var nextIndex = 0;\n      var lastPlacedNode = null;\n      for (name in nextChildren) {\n        if (!nextChildren.hasOwnProperty(name)) {\n          continue;\n        }\n        var prevChild = prevChildren && prevChildren[name];\n        var nextChild = nextChildren[name];\n        if (prevChild === nextChild) {\n          updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));\n          lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n          prevChild._mountIndex = nextIndex;\n        } else {\n          if (prevChild) {\n            // Update `lastIndex` before `_mountIndex` gets unset by unmounting.\n            lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n            // The `removedNodes` loop below will actually remove the child.\n          }\n          // The child must be instantiated before it's mounted.\n          updates = enqueue(updates, this._mountChildAtIndex(nextChild, lastPlacedNode, nextIndex, transaction, context));\n        }\n        nextIndex++;\n        lastPlacedNode = ReactReconciler.getHostNode(nextChild);\n      }\n      // Remove children that are no longer present.\n      for (name in removedNodes) {\n        if (removedNodes.hasOwnProperty(name)) {\n          updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name]));\n        }\n      }\n      if (updates) {\n        processQueue(this, updates);\n      }\n      this._renderedChildren = nextChildren;\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, nextChildren);\n      }\n    },\n\n    /**\n     * Unmounts all rendered children. This should be used to clean up children\n     * when this component is unmounted. It does not actually perform any\n     * backend operations.\n     *\n     * @internal\n     */\n    unmountChildren: function (safely) {\n      var renderedChildren = this._renderedChildren;\n      ReactChildReconciler.unmountChildren(renderedChildren, safely);\n      this._renderedChildren = null;\n    },\n\n    /**\n     * Moves a child component to the supplied index.\n     *\n     * @param {ReactComponent} child Component to move.\n     * @param {number} toIndex Destination index of the element.\n     * @param {number} lastIndex Last index visited of the siblings of `child`.\n     * @protected\n     */\n    moveChild: function (child, afterNode, toIndex, lastIndex) {\n      // If the index of `child` is less than `lastIndex`, then it needs to\n      // be moved. Otherwise, we do not need to move it because a child will be\n      // inserted or moved before `child`.\n      if (child._mountIndex < lastIndex) {\n        return makeMove(child, afterNode, toIndex);\n      }\n    },\n\n    /**\n     * Creates a child component.\n     *\n     * @param {ReactComponent} child Component to create.\n     * @param {string} mountImage Markup to insert.\n     * @protected\n     */\n    createChild: function (child, afterNode, mountImage) {\n      return makeInsertMarkup(mountImage, afterNode, child._mountIndex);\n    },\n\n    /**\n     * Removes a child component.\n     *\n     * @param {ReactComponent} child Child to remove.\n     * @protected\n     */\n    removeChild: function (child, node) {\n      return makeRemove(child, node);\n    },\n\n    /**\n     * Mounts a child with the supplied name.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to mount.\n     * @param {string} name Name of the child.\n     * @param {number} index Index at which to insert the child.\n     * @param {ReactReconcileTransaction} transaction\n     * @private\n     */\n    _mountChildAtIndex: function (child, afterNode, index, transaction, context) {\n      var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n      child._mountIndex = index;\n      return this.createChild(child, afterNode, mountImage);\n    },\n\n    /**\n     * Unmounts a rendered child.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to unmount.\n     * @private\n     */\n    _unmountChild: function (child, node) {\n      var update = this.removeChild(child, node);\n      child._mountIndex = null;\n      return update;\n    }\n\n  }\n\n};\n\nmodule.exports = ReactMultiChild;\n},{\"123\":123,\"139\":139,\"153\":153,\"161\":161,\"28\":28,\"33\":33,\"36\":36,\"73\":73,\"74\":74,\"79\":79,\"87\":87}],79:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChildUpdateTypes\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\n/**\n * When a component's children are updated, a series of update configuration\n * objects are created in order to batch and serialize the required changes.\n *\n * Enumerates all the possible types of update configurations.\n *\n * @internal\n */\nvar ReactMultiChildUpdateTypes = keyMirror({\n  INSERT_MARKUP: null,\n  MOVE_EXISTING: null,\n  REMOVE_NODE: null,\n  SET_MARKUP: null,\n  TEXT_CONTENT: null\n});\n\nmodule.exports = ReactMultiChildUpdateTypes;\n},{\"164\":164}],80:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNodeTypes\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\nvar ReactNodeTypes = {\n  HOST: 0,\n  COMPOSITE: 1,\n  EMPTY: 2,\n\n  getType: function (node) {\n    if (node === null || node === false) {\n      return ReactNodeTypes.EMPTY;\n    } else if (ReactElement.isValidElement(node)) {\n      if (typeof node.type === 'function') {\n        return ReactNodeTypes.COMPOSITE;\n      } else {\n        return ReactNodeTypes.HOST;\n      }\n    }\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unexpected node: %s', node) : _prodInvariant('26', node) : void 0;\n  }\n};\n\nmodule.exports = ReactNodeTypes;\n},{\"139\":139,\"161\":161,\"62\":62}],81:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNoopUpdateQueue\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the abstract API for an update queue.\n */\nvar ReactNoopUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    return false;\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback) {},\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    warnNoop(publicInstance, 'forceUpdate');\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    warnNoop(publicInstance, 'replaceState');\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    warnNoop(publicInstance, 'setState');\n  }\n};\n\nmodule.exports = ReactNoopUpdateQueue;\n},{\"171\":171}],82:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactOwner\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * ReactOwners are capable of storing references to owned components.\n *\n * All components are capable of //being// referenced by owner components, but\n * only ReactOwner components are capable of //referencing// owned components.\n * The named reference is known as a \"ref\".\n *\n * Refs are available when mounted and updated during reconciliation.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return (\n *         <div onClick={this.handleClick}>\n *           <CustomComponent ref=\"custom\" />\n *         </div>\n *       );\n *     },\n *     handleClick: function() {\n *       this.refs.custom.handleClick();\n *     },\n *     componentDidMount: function() {\n *       this.refs.custom.initialize();\n *     }\n *   });\n *\n * Refs should rarely be used. When refs are used, they should only be done to\n * control data that is not handled by React's data flow.\n *\n * @class ReactOwner\n */\nvar ReactOwner = {\n\n  /**\n   * @param {?object} object\n   * @return {boolean} True if `object` is a valid owner.\n   * @final\n   */\n  isValidOwner: function (object) {\n    return !!(object && typeof object.attachRef === 'function' && typeof object.detachRef === 'function');\n  },\n\n  /**\n   * Adds a component by ref to an owner component.\n   *\n   * @param {ReactComponent} component Component to reference.\n   * @param {string} ref Name by which to refer to the component.\n   * @param {ReactOwner} owner Component on which to record the ref.\n   * @final\n   * @internal\n   */\n  addComponentAsRefTo: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('119') : void 0;\n    owner.attachRef(ref, component);\n  },\n\n  /**\n   * Removes a component by ref from an owner component.\n   *\n   * @param {ReactComponent} component Component to dereference.\n   * @param {string} ref Name of the ref to remove.\n   * @param {ReactOwner} owner Component on which the ref is recorded.\n   * @final\n   * @internal\n   */\n  removeComponentAsRefFrom: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('120') : void 0;\n    var ownerPublicInstance = owner.getPublicInstance();\n    // Check that `component`'s owner is still alive and that `component` is still the current ref\n    // because we do not want to detach the ref if another component stole it.\n    if (ownerPublicInstance && ownerPublicInstance.refs[ref] === component.getPublicInstance()) {\n      owner.detachRef(ref);\n    }\n  }\n\n};\n\nmodule.exports = ReactOwner;\n},{\"139\":139,\"161\":161}],83:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocationNames\n */\n\n'use strict';\n\nvar ReactPropTypeLocationNames = {};\n\nif (\"development\" !== 'production') {\n  ReactPropTypeLocationNames = {\n    prop: 'prop',\n    context: 'context',\n    childContext: 'child context'\n  };\n}\n\nmodule.exports = ReactPropTypeLocationNames;\n},{}],84:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocations\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar ReactPropTypeLocations = keyMirror({\n  prop: null,\n  context: null,\n  childContext: null\n});\n\nmodule.exports = ReactPropTypeLocations;\n},{\"164\":164}],85:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypes\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar emptyFunction = _dereq_(153);\nvar getIteratorFn = _dereq_(130);\n\n/**\n * Collection of methods that allow declaration and validation of props that are\n * supplied to React components. Example usage:\n *\n *   var Props = require('ReactPropTypes');\n *   var MyArticle = React.createClass({\n *     propTypes: {\n *       // An optional string prop named \"description\".\n *       description: Props.string,\n *\n *       // A required enum prop named \"category\".\n *       category: Props.oneOf(['News','Photos']).isRequired,\n *\n *       // A prop named \"dialog\" that requires an instance of Dialog.\n *       dialog: Props.instanceOf(Dialog).isRequired\n *     },\n *     render: function() { ... }\n *   });\n *\n * A more formal specification of how these methods are used:\n *\n *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)\n *   decl := ReactPropTypes.{type}(.isRequired)?\n *\n * Each and every declaration produces a function with the same signature. This\n * allows the creation of custom validation functions. For example:\n *\n *  var MyLink = React.createClass({\n *    propTypes: {\n *      // An optional string or URI prop named \"href\".\n *      href: function(props, propName, componentName) {\n *        var propValue = props[propName];\n *        if (propValue != null && typeof propValue !== 'string' &&\n *            !(propValue instanceof URI)) {\n *          return new Error(\n *            'Expected a string or an URI for ' + propName + ' in ' +\n *            componentName\n *          );\n *        }\n *      }\n *    },\n *    render: function() {...}\n *  });\n *\n * @internal\n */\n\nvar ANONYMOUS = '<<anonymous>>';\n\nvar ReactPropTypes = {\n  array: createPrimitiveTypeChecker('array'),\n  bool: createPrimitiveTypeChecker('boolean'),\n  func: createPrimitiveTypeChecker('function'),\n  number: createPrimitiveTypeChecker('number'),\n  object: createPrimitiveTypeChecker('object'),\n  string: createPrimitiveTypeChecker('string'),\n  symbol: createPrimitiveTypeChecker('symbol'),\n\n  any: createAnyTypeChecker(),\n  arrayOf: createArrayOfTypeChecker,\n  element: createElementTypeChecker(),\n  instanceOf: createInstanceTypeChecker,\n  node: createNodeChecker(),\n  objectOf: createObjectOfTypeChecker,\n  oneOf: createEnumTypeChecker,\n  oneOfType: createUnionTypeChecker,\n  shape: createShapeTypeChecker\n};\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n/*eslint-disable no-self-compare*/\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n/*eslint-enable no-self-compare*/\n\nfunction createChainableTypeChecker(validate) {\n  function checkType(isRequired, props, propName, componentName, location, propFullName) {\n    componentName = componentName || ANONYMOUS;\n    propFullName = propFullName || propName;\n    if (props[propName] == null) {\n      var locationName = ReactPropTypeLocationNames[location];\n      if (isRequired) {\n        return new Error('Required ' + locationName + ' `' + propFullName + '` was not specified in ' + ('`' + componentName + '`.'));\n      }\n      return null;\n    } else {\n      return validate(props, propName, componentName, location, propFullName);\n    }\n  }\n\n  var chainedCheckType = checkType.bind(null, false);\n  chainedCheckType.isRequired = checkType.bind(null, true);\n\n  return chainedCheckType;\n}\n\nfunction createPrimitiveTypeChecker(expectedType) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== expectedType) {\n      var locationName = ReactPropTypeLocationNames[location];\n      // `propValue` being instance of, say, date/regexp, pass the 'object'\n      // check, but we can offer a more precise error message here rather than\n      // 'of type `object`'.\n      var preciseType = getPreciseType(propValue);\n\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createAnyTypeChecker() {\n  return createChainableTypeChecker(emptyFunction.thatReturns(null));\n}\n\nfunction createArrayOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');\n    }\n    var propValue = props[propName];\n    if (!Array.isArray(propValue)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var propType = getPropType(propValue);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));\n    }\n    for (var i = 0; i < propValue.length; i++) {\n      var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']');\n      if (error instanceof Error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createElementTypeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!ReactElement.isValidElement(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a single ReactElement.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createInstanceTypeChecker(expectedClass) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!(props[propName] instanceof expectedClass)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var expectedClassName = expectedClass.name || ANONYMOUS;\n      var actualClassName = getClassName(props[propName]);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createEnumTypeChecker(expectedValues) {\n  if (!Array.isArray(expectedValues)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOf, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    for (var i = 0; i < expectedValues.length; i++) {\n      if (is(propValue, expectedValues[i])) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    var valuesString = JSON.stringify(expectedValues);\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createObjectOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');\n    }\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));\n    }\n    for (var key in propValue) {\n      if (propValue.hasOwnProperty(key)) {\n        var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key);\n        if (error instanceof Error) {\n          return error;\n        }\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createUnionTypeChecker(arrayOfTypeCheckers) {\n  if (!Array.isArray(arrayOfTypeCheckers)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOfType, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n      var checker = arrayOfTypeCheckers[i];\n      if (checker(props, propName, componentName, location, propFullName) == null) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createNodeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!isNode(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createShapeTypeChecker(shapeTypes) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n    }\n    for (var key in shapeTypes) {\n      var checker = shapeTypes[key];\n      if (!checker) {\n        continue;\n      }\n      var error = checker(propValue, key, componentName, location, propFullName + '.' + key);\n      if (error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction isNode(propValue) {\n  switch (typeof propValue) {\n    case 'number':\n    case 'string':\n    case 'undefined':\n      return true;\n    case 'boolean':\n      return !propValue;\n    case 'object':\n      if (Array.isArray(propValue)) {\n        return propValue.every(isNode);\n      }\n      if (propValue === null || ReactElement.isValidElement(propValue)) {\n        return true;\n      }\n\n      var iteratorFn = getIteratorFn(propValue);\n      if (iteratorFn) {\n        var iterator = iteratorFn.call(propValue);\n        var step;\n        if (iteratorFn !== propValue.entries) {\n          while (!(step = iterator.next()).done) {\n            if (!isNode(step.value)) {\n              return false;\n            }\n          }\n        } else {\n          // Iterator will provide entry [k,v] tuples rather than values.\n          while (!(step = iterator.next()).done) {\n            var entry = step.value;\n            if (entry) {\n              if (!isNode(entry[1])) {\n                return false;\n              }\n            }\n          }\n        }\n      } else {\n        return false;\n      }\n\n      return true;\n    default:\n      return false;\n  }\n}\n\nfunction isSymbol(propType, propValue) {\n  // Native Symbol.\n  if (propType === 'symbol') {\n    return true;\n  }\n\n  // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'\n  if (propValue['@@toStringTag'] === 'Symbol') {\n    return true;\n  }\n\n  // Fallback for non-spec compliant Symbols which are polyfilled.\n  if (typeof Symbol === 'function' && propValue instanceof Symbol) {\n    return true;\n  }\n\n  return false;\n}\n\n// Equivalent of `typeof` but with special handling for array and regexp.\nfunction getPropType(propValue) {\n  var propType = typeof propValue;\n  if (Array.isArray(propValue)) {\n    return 'array';\n  }\n  if (propValue instanceof RegExp) {\n    // Old webkits (at least until Android 4.0) return 'function' rather than\n    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/\n    // passes PropTypes.object.\n    return 'object';\n  }\n  if (isSymbol(propType, propValue)) {\n    return 'symbol';\n  }\n  return propType;\n}\n\n// This handles more types than `getPropType`. Only used for error messages.\n// See `createPrimitiveTypeChecker`.\nfunction getPreciseType(propValue) {\n  var propType = getPropType(propValue);\n  if (propType === 'object') {\n    if (propValue instanceof Date) {\n      return 'date';\n    } else if (propValue instanceof RegExp) {\n      return 'regexp';\n    }\n  }\n  return propType;\n}\n\n// Returns class name of the object, if any.\nfunction getClassName(propValue) {\n  if (!propValue.constructor || !propValue.constructor.name) {\n    return ANONYMOUS;\n  }\n  return propValue.constructor.name;\n}\n\nmodule.exports = ReactPropTypes;\n},{\"130\":130,\"153\":153,\"62\":62,\"83\":83}],86:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconcileTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactInputSelection = _dereq_(72);\nvar ReactInstrumentation = _dereq_(74);\nvar Transaction = _dereq_(113);\nvar ReactUpdateQueue = _dereq_(94);\n\n/**\n * Ensures that, when possible, the selection range (currently selected text\n * input) is not disturbed by performing the transaction.\n */\nvar SELECTION_RESTORATION = {\n  /**\n   * @return {Selection} Selection information.\n   */\n  initialize: ReactInputSelection.getSelectionInformation,\n  /**\n   * @param {Selection} sel Selection information returned from `initialize`.\n   */\n  close: ReactInputSelection.restoreSelection\n};\n\n/**\n * Suppresses events (blur/focus) that could be inadvertently dispatched due to\n * high level DOM manipulations (like temporarily removing a text input from the\n * DOM).\n */\nvar EVENT_SUPPRESSION = {\n  /**\n   * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before\n   * the reconciliation.\n   */\n  initialize: function () {\n    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();\n    ReactBrowserEventEmitter.setEnabled(false);\n    return currentlyEnabled;\n  },\n\n  /**\n   * @param {boolean} previouslyEnabled Enabled status of\n   *   `ReactBrowserEventEmitter` before the reconciliation occurred. `close`\n   *   restores the previous value.\n   */\n  close: function (previouslyEnabled) {\n    ReactBrowserEventEmitter.setEnabled(previouslyEnabled);\n  }\n};\n\n/**\n * Provides a queue for collecting `componentDidMount` and\n * `componentDidUpdate` callbacks during the transaction.\n */\nvar ON_DOM_READY_QUEUEING = {\n  /**\n   * Initializes the internal `onDOMReady` queue.\n   */\n  initialize: function () {\n    this.reactMountReady.reset();\n  },\n\n  /**\n   * After DOM is flushed, invoke all registered `onDOMReady` callbacks.\n   */\n  close: function () {\n    this.reactMountReady.notifyAll();\n  }\n};\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\n/**\n * Currently:\n * - The order that these are listed in the transaction is critical:\n * - Suppresses events.\n * - Restores selection range.\n *\n * Future:\n * - Restore document/overflow scroll positions that were unintentionally\n *   modified via DOM insertions above the top viewport boundary.\n * - Implement/integrate with customized constraint based layout system and keep\n *   track of which dimensions must be remeasured.\n *\n * @class ReactReconcileTransaction\n */\nfunction ReactReconcileTransaction(useCreateElement) {\n  this.reinitializeTransaction();\n  // Only server-side rendering really needs this option (see\n  // `ReactServerRendering`), but server-side uses\n  // `ReactServerRenderingTransaction` instead. This option is here so that it's\n  // accessible and defaults to false when `ReactDOMComponent` and\n  // `ReactDOMTextComponent` checks it in `mountComponent`.`\n  this.renderToStaticMarkup = false;\n  this.reactMountReady = CallbackQueue.getPooled(null);\n  this.useCreateElement = useCreateElement;\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array<object>} List of operation wrap procedures.\n   *   TODO: convert to array<TransactionWrapper>\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return this.reactMountReady;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return ReactUpdateQueue;\n  },\n\n  /**\n   * Save current transaction state -- if the return value from this method is\n   * passed to `rollback`, the transaction will be reset to that state.\n   */\n  checkpoint: function () {\n    // reactMountReady is the our only stateful wrapper\n    return this.reactMountReady.checkpoint();\n  },\n\n  rollback: function (checkpoint) {\n    this.reactMountReady.rollback(checkpoint);\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {\n    CallbackQueue.release(this.reactMountReady);\n    this.reactMountReady = null;\n  }\n};\n\n_assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactReconcileTransaction);\n\nmodule.exports = ReactReconcileTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"27\":27,\"5\":5,\"72\":72,\"74\":74,\"94\":94}],87:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconciler\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactRef = _dereq_(88);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\n\n/**\n * Helper to call ReactRef.attachRefs with this composite component, split out\n * to avoid allocations in the transaction mount-ready queue.\n */\nfunction attachRefs() {\n  ReactRef.attachRefs(this, this._currentElement);\n}\n\nvar ReactReconciler = {\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} the containing host component instance\n   * @param {?object} info about the host container\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (internalInstance, transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeMountComponent(internalInstance._debugID, internalInstance._currentElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'mountComponent');\n      }\n    }\n    var markup = internalInstance.mountComponent(transaction, hostParent, hostContainerInfo, context);\n    if (internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'mountComponent');\n        ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID);\n      }\n    }\n    return markup;\n  },\n\n  /**\n   * Returns a value that can be passed to\n   * ReactComponentEnvironment.replaceNodeWithMarkup.\n   */\n  getHostNode: function (internalInstance) {\n    return internalInstance.getHostNode();\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (internalInstance, safely) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n      }\n    }\n    ReactRef.detachRefs(internalInstance, internalInstance._currentElement);\n    internalInstance.unmountComponent(safely);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n        ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Update a component using a new element.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @internal\n   */\n  receiveComponent: function (internalInstance, nextElement, transaction, context) {\n    var prevElement = internalInstance._currentElement;\n\n    if (nextElement === prevElement && context === internalInstance._context) {\n      // Since elements are immutable after the owner is rendered,\n      // we can do a cheap identity compare here to determine if this is a\n      // superfluous reconcile. It's possible for state to be mutable but such\n      // change should trigger an update of the owner which would recreate\n      // the element. We explicitly check for the existence of an owner since\n      // it's possible for an element created outside a composite to be\n      // deeply mutated and reused.\n\n      // TODO: Bailing out early is just a perf optimization right?\n      // TODO: Removing the return statement should affect correctness?\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, nextElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n      }\n    }\n\n    var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);\n\n    if (refsChanged) {\n      ReactRef.detachRefs(internalInstance, prevElement);\n    }\n\n    internalInstance.receiveComponent(nextElement, transaction, context);\n\n    if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Flush any dirty changes in a component.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (internalInstance, transaction, updateBatchNumber) {\n    if (internalInstance._updateBatchNumber !== updateBatchNumber) {\n      // The component's enqueued batch number should always be the current\n      // batch or the following one.\n      !(internalInstance._updateBatchNumber == null || internalInstance._updateBatchNumber === updateBatchNumber + 1) ? \"development\" !== 'production' ? invariant(false, 'performUpdateIfNecessary: Unexpected batch number (current %s, pending %s)', updateBatchNumber, internalInstance._updateBatchNumber) : _prodInvariant('121', updateBatchNumber, internalInstance._updateBatchNumber) : void 0;\n      return;\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, internalInstance._currentElement);\n      }\n    }\n    internalInstance.performUpdateIfNecessary(transaction);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactReconciler;\n},{\"139\":139,\"161\":161,\"74\":74,\"88\":88}],88:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactRef\n */\n\n'use strict';\n\nvar ReactOwner = _dereq_(82);\n\nvar ReactRef = {};\n\nfunction attachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(component.getPublicInstance());\n  } else {\n    // Legacy ref\n    ReactOwner.addComponentAsRefTo(component, ref, owner);\n  }\n}\n\nfunction detachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(null);\n  } else {\n    // Legacy ref\n    ReactOwner.removeComponentAsRefFrom(component, ref, owner);\n  }\n}\n\nReactRef.attachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    attachRef(ref, instance, element._owner);\n  }\n};\n\nReactRef.shouldUpdateRefs = function (prevElement, nextElement) {\n  // If either the owner or a `ref` has changed, make sure the newest owner\n  // has stored a reference to `this`, and the previous owner (if different)\n  // has forgotten the reference to `this`. We use the element instead\n  // of the public this.props because the post processing cannot determine\n  // a ref. The ref conceptually lives on the element.\n\n  // TODO: Should this even be possible? The owner cannot change because\n  // it's forbidden by shouldUpdateReactComponent. The ref can change\n  // if you swap the keys of but not the refs. Reconsider where this check\n  // is made. It probably belongs where the key checking and\n  // instantiateReactComponent is done.\n\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n\n  return(\n    // This has a few false positives w/r/t empty components.\n    prevEmpty || nextEmpty || nextElement._owner !== prevElement._owner || nextElement.ref !== prevElement.ref\n  );\n};\n\nReactRef.detachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    detachRef(ref, instance, element._owner);\n  }\n};\n\nmodule.exports = ReactRef;\n},{\"82\":82}],89:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerBatchingStrategy\n */\n\n'use strict';\n\nvar ReactServerBatchingStrategy = {\n  isBatchingUpdates: false,\n  batchedUpdates: function (callback) {\n    // Don't do anything here. During the server rendering we don't want to\n    // schedule any updates. We will simply ignore them.\n  }\n};\n\nmodule.exports = ReactServerBatchingStrategy;\n},{}],90:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRendering\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactElement = _dereq_(62);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactServerBatchingStrategy = _dereq_(89);\nvar ReactServerRenderingTransaction = _dereq_(91);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\n\n/**\n * @param {ReactElement} element\n * @return {string} the HTML markup\n */\nfunction renderToStringImpl(element, makeStaticMarkup) {\n  var transaction;\n  try {\n    ReactUpdates.injection.injectBatchingStrategy(ReactServerBatchingStrategy);\n\n    transaction = ReactServerRenderingTransaction.getPooled(makeStaticMarkup);\n\n    return transaction.perform(function () {\n      var componentInstance = instantiateReactComponent(element, true);\n      var markup = ReactReconciler.mountComponent(componentInstance, transaction, null, ReactDOMContainerInfo(), emptyObject);\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onUnmountComponent(componentInstance._debugID);\n      }\n      if (!makeStaticMarkup) {\n        markup = ReactMarkupChecksum.addChecksumToMarkup(markup);\n      }\n      return markup;\n    }, null);\n  } finally {\n    ReactServerRenderingTransaction.release(transaction);\n    // Revert to the DOM batching strategy since these two renderers\n    // currently share these stateful modules.\n    ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n  }\n}\n\n/**\n * Render a ReactElement to its initial HTML. This should only be used on the\n * server.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostring\n */\nfunction renderToString(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToString(): You must pass a valid ReactElement.') : _prodInvariant('46') : void 0;\n  return renderToStringImpl(element, false);\n}\n\n/**\n * Similar to renderToString, except this doesn't create extra DOM attributes\n * such as data-react-id that React uses internally.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostaticmarkup\n */\nfunction renderToStaticMarkup(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToStaticMarkup(): You must pass a valid ReactElement.') : _prodInvariant('47') : void 0;\n  return renderToStringImpl(element, true);\n}\n\nmodule.exports = {\n  renderToString: renderToString,\n  renderToStaticMarkup: renderToStaticMarkup\n};\n},{\"134\":134,\"139\":139,\"154\":154,\"161\":161,\"42\":42,\"60\":60,\"62\":62,\"74\":74,\"76\":76,\"87\":87,\"89\":89,\"91\":91,\"95\":95}],91:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRenderingTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\nvar Transaction = _dereq_(113);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactServerUpdateQueue = _dereq_(92);\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\nvar noopCallbackQueue = {\n  enqueue: function () {}\n};\n\n/**\n * @class ReactServerRenderingTransaction\n * @param {boolean} renderToStaticMarkup\n */\nfunction ReactServerRenderingTransaction(renderToStaticMarkup) {\n  this.reinitializeTransaction();\n  this.renderToStaticMarkup = renderToStaticMarkup;\n  this.useCreateElement = false;\n  this.updateQueue = new ReactServerUpdateQueue(this);\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array} Empty list of operation wrap procedures.\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return noopCallbackQueue;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return this.updateQueue;\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {},\n\n  checkpoint: function () {},\n\n  rollback: function () {}\n};\n\n_assign(ReactServerRenderingTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactServerRenderingTransaction);\n\nmodule.exports = ReactServerRenderingTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"74\":74,\"92\":92}],92:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerUpdateQueue\n * \n */\n\n'use strict';\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar ReactUpdateQueue = _dereq_(94);\nvar Transaction = _dereq_(113);\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounting component. ' + 'This usually means you called %s() outside componentWillMount() on the server. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the update queue used for server rendering.\n * It delegates to ReactUpdateQueue while server rendering is in progress and\n * switches to ReactNoopUpdateQueue after the transaction has completed.\n * @class ReactServerUpdateQueue\n * @param {Transaction} transaction\n */\n\nvar ReactServerUpdateQueue = function () {\n  /* :: transaction: Transaction; */\n\n  function ReactServerUpdateQueue(transaction) {\n    _classCallCheck(this, ReactServerUpdateQueue);\n\n    this.transaction = transaction;\n  }\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n\n\n  ReactServerUpdateQueue.prototype.isMounted = function isMounted(publicInstance) {\n    return false;\n  };\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueCallback = function enqueueCallback(publicInstance, callback, callerName) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueCallback(publicInstance, callback, callerName);\n    }\n  };\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueForceUpdate = function enqueueForceUpdate(publicInstance) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueForceUpdate(publicInstance);\n    } else {\n      warnNoop(publicInstance, 'forceUpdate');\n    }\n  };\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} completeState Next state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueReplaceState = function enqueueReplaceState(publicInstance, completeState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueReplaceState(publicInstance, completeState);\n    } else {\n      warnNoop(publicInstance, 'replaceState');\n    }\n  };\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} partialState Next partial state to be merged with state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueSetState = function enqueueSetState(publicInstance, partialState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueSetState(publicInstance, partialState);\n    } else {\n      warnNoop(publicInstance, 'setState');\n    }\n  };\n\n  return ReactServerUpdateQueue;\n}();\n\nmodule.exports = ReactServerUpdateQueue;\n},{\"113\":113,\"171\":171,\"94\":94}],93:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUMDEntry\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactDOM = _dereq_(37);\nvar ReactDOMServer = _dereq_(54);\nvar React = _dereq_(26);\n\n// `version` will be added here by ReactIsomorphic.\nvar ReactUMDEntry = _assign({\n  __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOM,\n  __SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOMServer\n}, React);\n\nmodule.exports = ReactUMDEntry;\n},{\"172\":172,\"26\":26,\"37\":37,\"54\":54}],94:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdateQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nfunction enqueueUpdate(internalInstance) {\n  ReactUpdates.enqueueUpdate(internalInstance);\n}\n\nfunction formatUnexpectedArgument(arg) {\n  var type = typeof arg;\n  if (type !== 'object') {\n    return type;\n  }\n  var displayName = arg.constructor && arg.constructor.name || type;\n  var keys = Object.keys(arg);\n  if (keys.length > 0 && keys.length < 20) {\n    return displayName + ' (keys: ' + keys.join(', ') + ')';\n  }\n  return displayName;\n}\n\nfunction getInternalInstanceReadyForUpdate(publicInstance, callerName) {\n  var internalInstance = ReactInstanceMap.get(publicInstance);\n  if (!internalInstance) {\n    if (\"development\" !== 'production') {\n      // Only warn when we have a callerName. Otherwise we should be silent.\n      // We're probably calling from enqueueCallback. We don't want to warn\n      // there because we already warned for the corresponding lifecycle method.\n      \"development\" !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor.displayName) : void 0;\n    }\n    return null;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition (such as ' + 'within `render` or another component\\'s constructor). Render methods ' + 'should be a pure function of props and state; constructor ' + 'side-effects are an anti-pattern, but can be moved to ' + '`componentWillMount`.', callerName) : void 0;\n  }\n\n  return internalInstance;\n}\n\n/**\n * ReactUpdateQueue allows for state updates to be scheduled into a later\n * reconciliation step.\n */\nvar ReactUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    if (\"development\" !== 'production') {\n      var owner = ReactCurrentOwner.current;\n      if (owner !== null) {\n        \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n        owner._warnedAboutRefsInRender = true;\n      }\n    }\n    var internalInstance = ReactInstanceMap.get(publicInstance);\n    if (internalInstance) {\n      // During componentWillMount and render this will still be null but after\n      // that will always render to something. At least for now. So we can use\n      // this hack.\n      return !!internalInstance._renderedComponent;\n    } else {\n      return false;\n    }\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @param {string} callerName Name of the calling function in the public API.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback, callerName) {\n    ReactUpdateQueue.validateCallback(callback, callerName);\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);\n\n    // Previously we would throw an error if we didn't have an internal\n    // instance. Since we want to make it a no-op instead, we mirror the same\n    // behavior we have in other enqueue* methods.\n    // We also need to ignore callbacks in componentWillMount. See\n    // enqueueUpdates.\n    if (!internalInstance) {\n      return null;\n    }\n\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    // TODO: The callback here is ignored when setState is called from\n    // componentWillMount. Either fix it or disallow doing so completely in\n    // favor of getInitialState. Alternatively, we can disallow\n    // componentWillMount during server-side rendering.\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueCallbackInternal: function (internalInstance, callback) {\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'forceUpdate');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingForceUpdate = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingStateQueue = [completeState];\n    internalInstance._pendingReplaceState = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetState();\n      \"development\" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;\n    }\n\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);\n    queue.push(partialState);\n\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueElementInternal: function (internalInstance, nextElement, nextContext) {\n    internalInstance._pendingElement = nextElement;\n    // TODO: introduce _pendingContext instead of setting it directly.\n    internalInstance._context = nextContext;\n    enqueueUpdate(internalInstance);\n  },\n\n  validateCallback: function (callback, callerName) {\n    !(!callback || typeof callback === 'function') ? \"development\" !== 'production' ? invariant(false, '%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.', callerName, formatUnexpectedArgument(callback)) : _prodInvariant('122', callerName, formatUnexpectedArgument(callback)) : void 0;\n  }\n\n};\n\nmodule.exports = ReactUpdateQueue;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"73\":73,\"74\":74,\"95\":95}],95:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdates\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactReconciler = _dereq_(87);\nvar Transaction = _dereq_(113);\n\nvar invariant = _dereq_(161);\n\nvar dirtyComponents = [];\nvar updateBatchNumber = 0;\nvar asapCallbackQueue = CallbackQueue.getPooled();\nvar asapEnqueued = false;\n\nvar batchingStrategy = null;\n\nfunction ensureInjected() {\n  !(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching strategy') : _prodInvariant('123') : void 0;\n}\n\nvar NESTED_UPDATES = {\n  initialize: function () {\n    this.dirtyComponentsLength = dirtyComponents.length;\n  },\n  close: function () {\n    if (this.dirtyComponentsLength !== dirtyComponents.length) {\n      // Additional updates were enqueued by componentDidUpdate handlers or\n      // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run\n      // these new updates so that if A's componentDidUpdate calls setState on\n      // B, B will update before the callback A's updater provided when calling\n      // setState.\n      dirtyComponents.splice(0, this.dirtyComponentsLength);\n      flushBatchedUpdates();\n    } else {\n      dirtyComponents.length = 0;\n    }\n  }\n};\n\nvar UPDATE_QUEUEING = {\n  initialize: function () {\n    this.callbackQueue.reset();\n  },\n  close: function () {\n    this.callbackQueue.notifyAll();\n  }\n};\n\nvar TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];\n\nfunction ReactUpdatesFlushTransaction() {\n  this.reinitializeTransaction();\n  this.dirtyComponentsLength = null;\n  this.callbackQueue = CallbackQueue.getPooled();\n  this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */true);\n}\n\n_assign(ReactUpdatesFlushTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  destructor: function () {\n    this.dirtyComponentsLength = null;\n    CallbackQueue.release(this.callbackQueue);\n    this.callbackQueue = null;\n    ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);\n    this.reconcileTransaction = null;\n  },\n\n  perform: function (method, scope, a) {\n    // Essentially calls `this.reconcileTransaction.perform(method, scope, a)`\n    // with this transaction's wrappers around it.\n    return Transaction.Mixin.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a);\n  }\n});\n\nPooledClass.addPoolingTo(ReactUpdatesFlushTransaction);\n\nfunction batchedUpdates(callback, a, b, c, d, e) {\n  ensureInjected();\n  batchingStrategy.batchedUpdates(callback, a, b, c, d, e);\n}\n\n/**\n * Array comparator for ReactComponents by mount ordering.\n *\n * @param {ReactComponent} c1 first component you're comparing\n * @param {ReactComponent} c2 second component you're comparing\n * @return {number} Return value usable by Array.prototype.sort().\n */\nfunction mountOrderComparator(c1, c2) {\n  return c1._mountOrder - c2._mountOrder;\n}\n\nfunction runBatchedUpdates(transaction) {\n  var len = transaction.dirtyComponentsLength;\n  !(len === dirtyComponents.length) ? \"development\" !== 'production' ? invariant(false, 'Expected flush transaction\\'s stored dirty-components length (%s) to match dirty-components array length (%s).', len, dirtyComponents.length) : _prodInvariant('124', len, dirtyComponents.length) : void 0;\n\n  // Since reconciling a component higher in the owner hierarchy usually (not\n  // always -- see shouldComponentUpdate()) will reconcile children, reconcile\n  // them before their children by sorting the array.\n  dirtyComponents.sort(mountOrderComparator);\n\n  // Any updates enqueued while reconciling must be performed after this entire\n  // batch. Otherwise, if dirtyComponents is [A, B] where A has children B and\n  // C, B could update twice in a single batch if C's render enqueues an update\n  // to B (since B would have already updated, we should skip it, and the only\n  // way we can know to do so is by checking the batch counter).\n  updateBatchNumber++;\n\n  for (var i = 0; i < len; i++) {\n    // If a component is unmounted before pending changes apply, it will still\n    // be here, but we assume that it has cleared its _pendingCallbacks and\n    // that performUpdateIfNecessary is a noop.\n    var component = dirtyComponents[i];\n\n    // If performUpdateIfNecessary happens to enqueue any new updates, we\n    // shouldn't execute the callbacks until the next render happens, so\n    // stash the callbacks first\n    var callbacks = component._pendingCallbacks;\n    component._pendingCallbacks = null;\n\n    var markerName;\n    if (ReactFeatureFlags.logTopLevelRenders) {\n      var namedComponent = component;\n      // Duck type TopLevelWrapper. This is probably always true.\n      if (component._currentElement.props === component._renderedComponent._currentElement) {\n        namedComponent = component._renderedComponent;\n      }\n      markerName = 'React update: ' + namedComponent.getName();\n      console.time(markerName);\n    }\n\n    ReactReconciler.performUpdateIfNecessary(component, transaction.reconcileTransaction, updateBatchNumber);\n\n    if (markerName) {\n      console.timeEnd(markerName);\n    }\n\n    if (callbacks) {\n      for (var j = 0; j < callbacks.length; j++) {\n        transaction.callbackQueue.enqueue(callbacks[j], component.getPublicInstance());\n      }\n    }\n  }\n}\n\nvar flushBatchedUpdates = function () {\n  // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents\n  // array and perform any updates enqueued by mount-ready handlers (i.e.,\n  // componentDidUpdate) but we need to check here too in order to catch\n  // updates enqueued by setState callbacks and asap calls.\n  while (dirtyComponents.length || asapEnqueued) {\n    if (dirtyComponents.length) {\n      var transaction = ReactUpdatesFlushTransaction.getPooled();\n      transaction.perform(runBatchedUpdates, null, transaction);\n      ReactUpdatesFlushTransaction.release(transaction);\n    }\n\n    if (asapEnqueued) {\n      asapEnqueued = false;\n      var queue = asapCallbackQueue;\n      asapCallbackQueue = CallbackQueue.getPooled();\n      queue.notifyAll();\n      CallbackQueue.release(queue);\n    }\n  }\n};\n\n/**\n * Mark a component as needing a rerender, adding an optional callback to a\n * list of functions which will be executed once the rerender occurs.\n */\nfunction enqueueUpdate(component) {\n  ensureInjected();\n\n  // Various parts of our code (such as ReactCompositeComponent's\n  // _renderValidatedComponent) assume that calls to render aren't nested;\n  // verify that that's the case. (This is called by each top-level update\n  // function, like setState, forceUpdate, etc.; creation and\n  // destruction of top-level components is guarded in ReactMount.)\n\n  if (!batchingStrategy.isBatchingUpdates) {\n    batchingStrategy.batchedUpdates(enqueueUpdate, component);\n    return;\n  }\n\n  dirtyComponents.push(component);\n  if (component._updateBatchNumber == null) {\n    component._updateBatchNumber = updateBatchNumber + 1;\n  }\n}\n\n/**\n * Enqueue a callback to be run at the end of the current batching cycle. Throws\n * if no updates are currently being performed.\n */\nfunction asap(callback, context) {\n  !batchingStrategy.isBatchingUpdates ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates.asap: Can\\'t enqueue an asap callback in a context whereupdates are not being batched.') : _prodInvariant('125') : void 0;\n  asapCallbackQueue.enqueue(callback, context);\n  asapEnqueued = true;\n}\n\nvar ReactUpdatesInjection = {\n  injectReconcileTransaction: function (ReconcileTransaction) {\n    !ReconcileTransaction ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : _prodInvariant('126') : void 0;\n    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;\n  },\n\n  injectBatchingStrategy: function (_batchingStrategy) {\n    !_batchingStrategy ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : _prodInvariant('127') : void 0;\n    !(typeof _batchingStrategy.batchedUpdates === 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : _prodInvariant('128') : void 0;\n    !(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : _prodInvariant('129') : void 0;\n    batchingStrategy = _batchingStrategy;\n  }\n};\n\nvar ReactUpdates = {\n  /**\n   * React references `ReactReconcileTransaction` using this property in order\n   * to allow dependency injection.\n   *\n   * @internal\n   */\n  ReactReconcileTransaction: null,\n\n  batchedUpdates: batchedUpdates,\n  enqueueUpdate: enqueueUpdate,\n  flushBatchedUpdates: flushBatchedUpdates,\n  injection: ReactUpdatesInjection,\n  asap: asap\n};\n\nmodule.exports = ReactUpdates;\n},{\"113\":113,\"139\":139,\"161\":161,\"172\":172,\"25\":25,\"5\":5,\"68\":68,\"87\":87}],96:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactVersion\n */\n\n'use strict';\n\nmodule.exports = '15.2.1';\n},{}],97:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SVGDOMPropertyConfig\n */\n\n'use strict';\n\nvar NS = {\n  xlink: 'http://www.w3.org/1999/xlink',\n  xml: 'http://www.w3.org/XML/1998/namespace'\n};\n\n// We use attributes for everything SVG so let's avoid some duplication and run\n// code instead.\n// The following are all specified in the HTML config already so we exclude here.\n// - class (as className)\n// - color\n// - height\n// - id\n// - lang\n// - max\n// - media\n// - method\n// - min\n// - name\n// - style\n// - target\n// - type\n// - width\nvar ATTRS = {\n  accentHeight: 'accent-height',\n  accumulate: 0,\n  additive: 0,\n  alignmentBaseline: 'alignment-baseline',\n  allowReorder: 'allowReorder',\n  alphabetic: 0,\n  amplitude: 0,\n  arabicForm: 'arabic-form',\n  ascent: 0,\n  attributeName: 'attributeName',\n  attributeType: 'attributeType',\n  autoReverse: 'autoReverse',\n  azimuth: 0,\n  baseFrequency: 'baseFrequency',\n  baseProfile: 'baseProfile',\n  baselineShift: 'baseline-shift',\n  bbox: 0,\n  begin: 0,\n  bias: 0,\n  by: 0,\n  calcMode: 'calcMode',\n  capHeight: 'cap-height',\n  clip: 0,\n  clipPath: 'clip-path',\n  clipRule: 'clip-rule',\n  clipPathUnits: 'clipPathUnits',\n  colorInterpolation: 'color-interpolation',\n  colorInterpolationFilters: 'color-interpolation-filters',\n  colorProfile: 'color-profile',\n  colorRendering: 'color-rendering',\n  contentScriptType: 'contentScriptType',\n  contentStyleType: 'contentStyleType',\n  cursor: 0,\n  cx: 0,\n  cy: 0,\n  d: 0,\n  decelerate: 0,\n  descent: 0,\n  diffuseConstant: 'diffuseConstant',\n  direction: 0,\n  display: 0,\n  divisor: 0,\n  dominantBaseline: 'dominant-baseline',\n  dur: 0,\n  dx: 0,\n  dy: 0,\n  edgeMode: 'edgeMode',\n  elevation: 0,\n  enableBackground: 'enable-background',\n  end: 0,\n  exponent: 0,\n  externalResourcesRequired: 'externalResourcesRequired',\n  fill: 0,\n  fillOpacity: 'fill-opacity',\n  fillRule: 'fill-rule',\n  filter: 0,\n  filterRes: 'filterRes',\n  filterUnits: 'filterUnits',\n  floodColor: 'flood-color',\n  floodOpacity: 'flood-opacity',\n  focusable: 0,\n  fontFamily: 'font-family',\n  fontSize: 'font-size',\n  fontSizeAdjust: 'font-size-adjust',\n  fontStretch: 'font-stretch',\n  fontStyle: 'font-style',\n  fontVariant: 'font-variant',\n  fontWeight: 'font-weight',\n  format: 0,\n  from: 0,\n  fx: 0,\n  fy: 0,\n  g1: 0,\n  g2: 0,\n  glyphName: 'glyph-name',\n  glyphOrientationHorizontal: 'glyph-orientation-horizontal',\n  glyphOrientationVertical: 'glyph-orientation-vertical',\n  glyphRef: 'glyphRef',\n  gradientTransform: 'gradientTransform',\n  gradientUnits: 'gradientUnits',\n  hanging: 0,\n  horizAdvX: 'horiz-adv-x',\n  horizOriginX: 'horiz-origin-x',\n  ideographic: 0,\n  imageRendering: 'image-rendering',\n  'in': 0,\n  in2: 0,\n  intercept: 0,\n  k: 0,\n  k1: 0,\n  k2: 0,\n  k3: 0,\n  k4: 0,\n  kernelMatrix: 'kernelMatrix',\n  kernelUnitLength: 'kernelUnitLength',\n  kerning: 0,\n  keyPoints: 'keyPoints',\n  keySplines: 'keySplines',\n  keyTimes: 'keyTimes',\n  lengthAdjust: 'lengthAdjust',\n  letterSpacing: 'letter-spacing',\n  lightingColor: 'lighting-color',\n  limitingConeAngle: 'limitingConeAngle',\n  local: 0,\n  markerEnd: 'marker-end',\n  markerMid: 'marker-mid',\n  markerStart: 'marker-start',\n  markerHeight: 'markerHeight',\n  markerUnits: 'markerUnits',\n  markerWidth: 'markerWidth',\n  mask: 0,\n  maskContentUnits: 'maskContentUnits',\n  maskUnits: 'maskUnits',\n  mathematical: 0,\n  mode: 0,\n  numOctaves: 'numOctaves',\n  offset: 0,\n  opacity: 0,\n  operator: 0,\n  order: 0,\n  orient: 0,\n  orientation: 0,\n  origin: 0,\n  overflow: 0,\n  overlinePosition: 'overline-position',\n  overlineThickness: 'overline-thickness',\n  paintOrder: 'paint-order',\n  panose1: 'panose-1',\n  pathLength: 'pathLength',\n  patternContentUnits: 'patternContentUnits',\n  patternTransform: 'patternTransform',\n  patternUnits: 'patternUnits',\n  pointerEvents: 'pointer-events',\n  points: 0,\n  pointsAtX: 'pointsAtX',\n  pointsAtY: 'pointsAtY',\n  pointsAtZ: 'pointsAtZ',\n  preserveAlpha: 'preserveAlpha',\n  preserveAspectRatio: 'preserveAspectRatio',\n  primitiveUnits: 'primitiveUnits',\n  r: 0,\n  radius: 0,\n  refX: 'refX',\n  refY: 'refY',\n  renderingIntent: 'rendering-intent',\n  repeatCount: 'repeatCount',\n  repeatDur: 'repeatDur',\n  requiredExtensions: 'requiredExtensions',\n  requiredFeatures: 'requiredFeatures',\n  restart: 0,\n  result: 0,\n  rotate: 0,\n  rx: 0,\n  ry: 0,\n  scale: 0,\n  seed: 0,\n  shapeRendering: 'shape-rendering',\n  slope: 0,\n  spacing: 0,\n  specularConstant: 'specularConstant',\n  specularExponent: 'specularExponent',\n  speed: 0,\n  spreadMethod: 'spreadMethod',\n  startOffset: 'startOffset',\n  stdDeviation: 'stdDeviation',\n  stemh: 0,\n  stemv: 0,\n  stitchTiles: 'stitchTiles',\n  stopColor: 'stop-color',\n  stopOpacity: 'stop-opacity',\n  strikethroughPosition: 'strikethrough-position',\n  strikethroughThickness: 'strikethrough-thickness',\n  string: 0,\n  stroke: 0,\n  strokeDasharray: 'stroke-dasharray',\n  strokeDashoffset: 'stroke-dashoffset',\n  strokeLinecap: 'stroke-linecap',\n  strokeLinejoin: 'stroke-linejoin',\n  strokeMiterlimit: 'stroke-miterlimit',\n  strokeOpacity: 'stroke-opacity',\n  strokeWidth: 'stroke-width',\n  surfaceScale: 'surfaceScale',\n  systemLanguage: 'systemLanguage',\n  tableValues: 'tableValues',\n  targetX: 'targetX',\n  targetY: 'targetY',\n  textAnchor: 'text-anchor',\n  textDecoration: 'text-decoration',\n  textRendering: 'text-rendering',\n  textLength: 'textLength',\n  to: 0,\n  transform: 0,\n  u1: 0,\n  u2: 0,\n  underlinePosition: 'underline-position',\n  underlineThickness: 'underline-thickness',\n  unicode: 0,\n  unicodeBidi: 'unicode-bidi',\n  unicodeRange: 'unicode-range',\n  unitsPerEm: 'units-per-em',\n  vAlphabetic: 'v-alphabetic',\n  vHanging: 'v-hanging',\n  vIdeographic: 'v-ideographic',\n  vMathematical: 'v-mathematical',\n  values: 0,\n  vectorEffect: 'vector-effect',\n  version: 0,\n  vertAdvY: 'vert-adv-y',\n  vertOriginX: 'vert-origin-x',\n  vertOriginY: 'vert-origin-y',\n  viewBox: 'viewBox',\n  viewTarget: 'viewTarget',\n  visibility: 0,\n  widths: 0,\n  wordSpacing: 'word-spacing',\n  writingMode: 'writing-mode',\n  x: 0,\n  xHeight: 'x-height',\n  x1: 0,\n  x2: 0,\n  xChannelSelector: 'xChannelSelector',\n  xlinkActuate: 'xlink:actuate',\n  xlinkArcrole: 'xlink:arcrole',\n  xlinkHref: 'xlink:href',\n  xlinkRole: 'xlink:role',\n  xlinkShow: 'xlink:show',\n  xlinkTitle: 'xlink:title',\n  xlinkType: 'xlink:type',\n  xmlBase: 'xml:base',\n  xmlLang: 'xml:lang',\n  xmlSpace: 'xml:space',\n  y: 0,\n  y1: 0,\n  y2: 0,\n  yChannelSelector: 'yChannelSelector',\n  z: 0,\n  zoomAndPan: 'zoomAndPan'\n};\n\nvar SVGDOMPropertyConfig = {\n  Properties: {},\n  DOMAttributeNamespaces: {\n    xlinkActuate: NS.xlink,\n    xlinkArcrole: NS.xlink,\n    xlinkHref: NS.xlink,\n    xlinkRole: NS.xlink,\n    xlinkShow: NS.xlink,\n    xlinkTitle: NS.xlink,\n    xlinkType: NS.xlink,\n    xmlBase: NS.xml,\n    xmlLang: NS.xml,\n    xmlSpace: NS.xml\n  },\n  DOMAttributeNames: {}\n};\n\nObject.keys(ATTRS).forEach(function (key) {\n  SVGDOMPropertyConfig.Properties[key] = 0;\n  if (ATTRS[key]) {\n    SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key];\n  }\n});\n\nmodule.exports = SVGDOMPropertyConfig;\n},{}],98:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SelectEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInputSelection = _dereq_(72);\nvar SyntheticEvent = _dereq_(104);\n\nvar getActiveElement = _dereq_(156);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11;\n\nvar eventTypes = {\n  select: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSelect: null }),\n      captured: keyOf({ onSelectCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange]\n  }\n};\n\nvar activeElement = null;\nvar activeElementInst = null;\nvar lastSelection = null;\nvar mouseDown = false;\n\n// Track whether a listener exists for this plugin. If none exist, we do\n// not extract events. See #3639.\nvar hasListener = false;\nvar ON_SELECT_KEY = keyOf({ onSelect: null });\n\n/**\n * Get an object which is a unique representation of the current selection.\n *\n * The return value will not be consistent across nodes or browsers, but\n * two identical selections on the same node will return identical objects.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getSelection(node) {\n  if ('selectionStart' in node && ReactInputSelection.hasSelectionCapabilities(node)) {\n    return {\n      start: node.selectionStart,\n      end: node.selectionEnd\n    };\n  } else if (window.getSelection) {\n    var selection = window.getSelection();\n    return {\n      anchorNode: selection.anchorNode,\n      anchorOffset: selection.anchorOffset,\n      focusNode: selection.focusNode,\n      focusOffset: selection.focusOffset\n    };\n  } else if (document.selection) {\n    var range = document.selection.createRange();\n    return {\n      parentElement: range.parentElement(),\n      text: range.text,\n      top: range.boundingTop,\n      left: range.boundingLeft\n    };\n  }\n}\n\n/**\n * Poll selection to see whether it's changed.\n *\n * @param {object} nativeEvent\n * @return {?SyntheticEvent}\n */\nfunction constructSelectEvent(nativeEvent, nativeEventTarget) {\n  // Ensure we have the right element, and that the user is not dragging a\n  // selection (this matches native `select` event behavior). In HTML5, select\n  // fires only on input and textarea thus if there's no focused element we\n  // won't dispatch.\n  if (mouseDown || activeElement == null || activeElement !== getActiveElement()) {\n    return null;\n  }\n\n  // Only fire when selection has actually changed.\n  var currentSelection = getSelection(activeElement);\n  if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {\n    lastSelection = currentSelection;\n\n    var syntheticEvent = SyntheticEvent.getPooled(eventTypes.select, activeElementInst, nativeEvent, nativeEventTarget);\n\n    syntheticEvent.type = 'select';\n    syntheticEvent.target = activeElement;\n\n    EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent);\n\n    return syntheticEvent;\n  }\n\n  return null;\n}\n\n/**\n * This plugin creates an `onSelect` event that normalizes select events\n * across form elements.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - contentEditable\n *\n * This differs from native browser implementations in the following ways:\n * - Fires on contentEditable fields as well as inputs.\n * - Fires for collapsed selection.\n * - Fires after user input.\n */\nvar SelectEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (!hasListener) {\n      return null;\n    }\n\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    switch (topLevelType) {\n      // Track the input node that has focus.\n      case topLevelTypes.topFocus:\n        if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {\n          activeElement = targetNode;\n          activeElementInst = targetInst;\n          lastSelection = null;\n        }\n        break;\n      case topLevelTypes.topBlur:\n        activeElement = null;\n        activeElementInst = null;\n        lastSelection = null;\n        break;\n\n      // Don't fire the event while the user is dragging. This matches the\n      // semantics of the native select event.\n      case topLevelTypes.topMouseDown:\n        mouseDown = true;\n        break;\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topMouseUp:\n        mouseDown = false;\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n\n      // Chrome and IE fire non-standard event when selection is changed (and\n      // sometimes when it hasn't). IE's event fires out of order with respect\n      // to key and input events on deletion, so we discard it.\n      //\n      // Firefox doesn't support selectionchange, so check selection status\n      // after each key entry. The selection changes after keydown and before\n      // keyup, but we check on keydown as well in the case of holding down a\n      // key, when multiple keydown events are fired but only one keyup is.\n      // This is also our approach for IE handling, for the reason above.\n      case topLevelTypes.topSelectionChange:\n        if (skipSelectionChangeEvent) {\n          break;\n        }\n      // falls through\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n    }\n\n    return null;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    if (registrationName === ON_SELECT_KEY) {\n      hasListener = true;\n    }\n  }\n};\n\nmodule.exports = SelectEventPlugin;\n},{\"104\":104,\"136\":136,\"147\":147,\"156\":156,\"16\":16,\"165\":165,\"170\":170,\"20\":20,\"41\":41,\"72\":72}],99:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SimpleEventPlugin\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar EventListener = _dereq_(146);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticAnimationEvent = _dereq_(100);\nvar SyntheticClipboardEvent = _dereq_(101);\nvar SyntheticEvent = _dereq_(104);\nvar SyntheticFocusEvent = _dereq_(105);\nvar SyntheticKeyboardEvent = _dereq_(107);\nvar SyntheticMouseEvent = _dereq_(108);\nvar SyntheticDragEvent = _dereq_(103);\nvar SyntheticTouchEvent = _dereq_(109);\nvar SyntheticTransitionEvent = _dereq_(110);\nvar SyntheticUIEvent = _dereq_(111);\nvar SyntheticWheelEvent = _dereq_(112);\n\nvar emptyFunction = _dereq_(153);\nvar getEventCharCode = _dereq_(125);\nvar invariant = _dereq_(161);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  abort: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAbort: true }),\n      captured: keyOf({ onAbortCapture: true })\n    }\n  },\n  animationEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationEnd: true }),\n      captured: keyOf({ onAnimationEndCapture: true })\n    }\n  },\n  animationIteration: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationIteration: true }),\n      captured: keyOf({ onAnimationIterationCapture: true })\n    }\n  },\n  animationStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationStart: true }),\n      captured: keyOf({ onAnimationStartCapture: true })\n    }\n  },\n  blur: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBlur: true }),\n      captured: keyOf({ onBlurCapture: true })\n    }\n  },\n  canPlay: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlay: true }),\n      captured: keyOf({ onCanPlayCapture: true })\n    }\n  },\n  canPlayThrough: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlayThrough: true }),\n      captured: keyOf({ onCanPlayThroughCapture: true })\n    }\n  },\n  click: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onClick: true }),\n      captured: keyOf({ onClickCapture: true })\n    }\n  },\n  contextMenu: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onContextMenu: true }),\n      captured: keyOf({ onContextMenuCapture: true })\n    }\n  },\n  copy: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCopy: true }),\n      captured: keyOf({ onCopyCapture: true })\n    }\n  },\n  cut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCut: true }),\n      captured: keyOf({ onCutCapture: true })\n    }\n  },\n  doubleClick: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDoubleClick: true }),\n      captured: keyOf({ onDoubleClickCapture: true })\n    }\n  },\n  drag: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrag: true }),\n      captured: keyOf({ onDragCapture: true })\n    }\n  },\n  dragEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnd: true }),\n      captured: keyOf({ onDragEndCapture: true })\n    }\n  },\n  dragEnter: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnter: true }),\n      captured: keyOf({ onDragEnterCapture: true })\n    }\n  },\n  dragExit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragExit: true }),\n      captured: keyOf({ onDragExitCapture: true })\n    }\n  },\n  dragLeave: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragLeave: true }),\n      captured: keyOf({ onDragLeaveCapture: true })\n    }\n  },\n  dragOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragOver: true }),\n      captured: keyOf({ onDragOverCapture: true })\n    }\n  },\n  dragStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragStart: true }),\n      captured: keyOf({ onDragStartCapture: true })\n    }\n  },\n  drop: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrop: true }),\n      captured: keyOf({ onDropCapture: true })\n    }\n  },\n  durationChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDurationChange: true }),\n      captured: keyOf({ onDurationChangeCapture: true })\n    }\n  },\n  emptied: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEmptied: true }),\n      captured: keyOf({ onEmptiedCapture: true })\n    }\n  },\n  encrypted: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEncrypted: true }),\n      captured: keyOf({ onEncryptedCapture: true })\n    }\n  },\n  ended: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEnded: true }),\n      captured: keyOf({ onEndedCapture: true })\n    }\n  },\n  error: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onError: true }),\n      captured: keyOf({ onErrorCapture: true })\n    }\n  },\n  focus: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onFocus: true }),\n      captured: keyOf({ onFocusCapture: true })\n    }\n  },\n  input: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInput: true }),\n      captured: keyOf({ onInputCapture: true })\n    }\n  },\n  invalid: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInvalid: true }),\n      captured: keyOf({ onInvalidCapture: true })\n    }\n  },\n  keyDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyDown: true }),\n      captured: keyOf({ onKeyDownCapture: true })\n    }\n  },\n  keyPress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyPress: true }),\n      captured: keyOf({ onKeyPressCapture: true })\n    }\n  },\n  keyUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyUp: true }),\n      captured: keyOf({ onKeyUpCapture: true })\n    }\n  },\n  load: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoad: true }),\n      captured: keyOf({ onLoadCapture: true })\n    }\n  },\n  loadedData: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedData: true }),\n      captured: keyOf({ onLoadedDataCapture: true })\n    }\n  },\n  loadedMetadata: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedMetadata: true }),\n      captured: keyOf({ onLoadedMetadataCapture: true })\n    }\n  },\n  loadStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadStart: true }),\n      captured: keyOf({ onLoadStartCapture: true })\n    }\n  },\n  // Note: We do not allow listening to mouseOver events. Instead, use the\n  // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`.\n  mouseDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseDown: true }),\n      captured: keyOf({ onMouseDownCapture: true })\n    }\n  },\n  mouseMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseMove: true }),\n      captured: keyOf({ onMouseMoveCapture: true })\n    }\n  },\n  mouseOut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOut: true }),\n      captured: keyOf({ onMouseOutCapture: true })\n    }\n  },\n  mouseOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOver: true }),\n      captured: keyOf({ onMouseOverCapture: true })\n    }\n  },\n  mouseUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseUp: true }),\n      captured: keyOf({ onMouseUpCapture: true })\n    }\n  },\n  paste: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPaste: true }),\n      captured: keyOf({ onPasteCapture: true })\n    }\n  },\n  pause: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPause: true }),\n      captured: keyOf({ onPauseCapture: true })\n    }\n  },\n  play: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlay: true }),\n      captured: keyOf({ onPlayCapture: true })\n    }\n  },\n  playing: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlaying: true }),\n      captured: keyOf({ onPlayingCapture: true })\n    }\n  },\n  progress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onProgress: true }),\n      captured: keyOf({ onProgressCapture: true })\n    }\n  },\n  rateChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onRateChange: true }),\n      captured: keyOf({ onRateChangeCapture: true })\n    }\n  },\n  reset: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onReset: true }),\n      captured: keyOf({ onResetCapture: true })\n    }\n  },\n  scroll: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onScroll: true }),\n      captured: keyOf({ onScrollCapture: true })\n    }\n  },\n  seeked: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeked: true }),\n      captured: keyOf({ onSeekedCapture: true })\n    }\n  },\n  seeking: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeking: true }),\n      captured: keyOf({ onSeekingCapture: true })\n    }\n  },\n  stalled: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onStalled: true }),\n      captured: keyOf({ onStalledCapture: true })\n    }\n  },\n  submit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSubmit: true }),\n      captured: keyOf({ onSubmitCapture: true })\n    }\n  },\n  suspend: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSuspend: true }),\n      captured: keyOf({ onSuspendCapture: true })\n    }\n  },\n  timeUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTimeUpdate: true }),\n      captured: keyOf({ onTimeUpdateCapture: true })\n    }\n  },\n  touchCancel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchCancel: true }),\n      captured: keyOf({ onTouchCancelCapture: true })\n    }\n  },\n  touchEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchEnd: true }),\n      captured: keyOf({ onTouchEndCapture: true })\n    }\n  },\n  touchMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchMove: true }),\n      captured: keyOf({ onTouchMoveCapture: true })\n    }\n  },\n  touchStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchStart: true }),\n      captured: keyOf({ onTouchStartCapture: true })\n    }\n  },\n  transitionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTransitionEnd: true }),\n      captured: keyOf({ onTransitionEndCapture: true })\n    }\n  },\n  volumeChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onVolumeChange: true }),\n      captured: keyOf({ onVolumeChangeCapture: true })\n    }\n  },\n  waiting: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWaiting: true }),\n      captured: keyOf({ onWaitingCapture: true })\n    }\n  },\n  wheel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWheel: true }),\n      captured: keyOf({ onWheelCapture: true })\n    }\n  }\n};\n\nvar topLevelEventsToDispatchConfig = {\n  topAbort: eventTypes.abort,\n  topAnimationEnd: eventTypes.animationEnd,\n  topAnimationIteration: eventTypes.animationIteration,\n  topAnimationStart: eventTypes.animationStart,\n  topBlur: eventTypes.blur,\n  topCanPlay: eventTypes.canPlay,\n  topCanPlayThrough: eventTypes.canPlayThrough,\n  topClick: eventTypes.click,\n  topContextMenu: eventTypes.contextMenu,\n  topCopy: eventTypes.copy,\n  topCut: eventTypes.cut,\n  topDoubleClick: eventTypes.doubleClick,\n  topDrag: eventTypes.drag,\n  topDragEnd: eventTypes.dragEnd,\n  topDragEnter: eventTypes.dragEnter,\n  topDragExit: eventTypes.dragExit,\n  topDragLeave: eventTypes.dragLeave,\n  topDragOver: eventTypes.dragOver,\n  topDragStart: eventTypes.dragStart,\n  topDrop: eventTypes.drop,\n  topDurationChange: eventTypes.durationChange,\n  topEmptied: eventTypes.emptied,\n  topEncrypted: eventTypes.encrypted,\n  topEnded: eventTypes.ended,\n  topError: eventTypes.error,\n  topFocus: eventTypes.focus,\n  topInput: eventTypes.input,\n  topInvalid: eventTypes.invalid,\n  topKeyDown: eventTypes.keyDown,\n  topKeyPress: eventTypes.keyPress,\n  topKeyUp: eventTypes.keyUp,\n  topLoad: eventTypes.load,\n  topLoadedData: eventTypes.loadedData,\n  topLoadedMetadata: eventTypes.loadedMetadata,\n  topLoadStart: eventTypes.loadStart,\n  topMouseDown: eventTypes.mouseDown,\n  topMouseMove: eventTypes.mouseMove,\n  topMouseOut: eventTypes.mouseOut,\n  topMouseOver: eventTypes.mouseOver,\n  topMouseUp: eventTypes.mouseUp,\n  topPaste: eventTypes.paste,\n  topPause: eventTypes.pause,\n  topPlay: eventTypes.play,\n  topPlaying: eventTypes.playing,\n  topProgress: eventTypes.progress,\n  topRateChange: eventTypes.rateChange,\n  topReset: eventTypes.reset,\n  topScroll: eventTypes.scroll,\n  topSeeked: eventTypes.seeked,\n  topSeeking: eventTypes.seeking,\n  topStalled: eventTypes.stalled,\n  topSubmit: eventTypes.submit,\n  topSuspend: eventTypes.suspend,\n  topTimeUpdate: eventTypes.timeUpdate,\n  topTouchCancel: eventTypes.touchCancel,\n  topTouchEnd: eventTypes.touchEnd,\n  topTouchMove: eventTypes.touchMove,\n  topTouchStart: eventTypes.touchStart,\n  topTransitionEnd: eventTypes.transitionEnd,\n  topVolumeChange: eventTypes.volumeChange,\n  topWaiting: eventTypes.waiting,\n  topWheel: eventTypes.wheel\n};\n\nfor (var type in topLevelEventsToDispatchConfig) {\n  topLevelEventsToDispatchConfig[type].dependencies = [type];\n}\n\nvar ON_CLICK_KEY = keyOf({ onClick: null });\nvar onClickListeners = {};\n\nvar SimpleEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];\n    if (!dispatchConfig) {\n      return null;\n    }\n    var EventConstructor;\n    switch (topLevelType) {\n      case topLevelTypes.topAbort:\n      case topLevelTypes.topCanPlay:\n      case topLevelTypes.topCanPlayThrough:\n      case topLevelTypes.topDurationChange:\n      case topLevelTypes.topEmptied:\n      case topLevelTypes.topEncrypted:\n      case topLevelTypes.topEnded:\n      case topLevelTypes.topError:\n      case topLevelTypes.topInput:\n      case topLevelTypes.topInvalid:\n      case topLevelTypes.topLoad:\n      case topLevelTypes.topLoadedData:\n      case topLevelTypes.topLoadedMetadata:\n      case topLevelTypes.topLoadStart:\n      case topLevelTypes.topPause:\n      case topLevelTypes.topPlay:\n      case topLevelTypes.topPlaying:\n      case topLevelTypes.topProgress:\n      case topLevelTypes.topRateChange:\n      case topLevelTypes.topReset:\n      case topLevelTypes.topSeeked:\n      case topLevelTypes.topSeeking:\n      case topLevelTypes.topStalled:\n      case topLevelTypes.topSubmit:\n      case topLevelTypes.topSuspend:\n      case topLevelTypes.topTimeUpdate:\n      case topLevelTypes.topVolumeChange:\n      case topLevelTypes.topWaiting:\n        // HTML Events\n        // @see http://www.w3.org/TR/html5/index.html#events-0\n        EventConstructor = SyntheticEvent;\n        break;\n      case topLevelTypes.topKeyPress:\n        // Firefox creates a keypress event for function keys too. This removes\n        // the unwanted keypress events. Enter is however both printable and\n        // non-printable. One would expect Tab to be as well (but it isn't).\n        if (getEventCharCode(nativeEvent) === 0) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        EventConstructor = SyntheticKeyboardEvent;\n        break;\n      case topLevelTypes.topBlur:\n      case topLevelTypes.topFocus:\n        EventConstructor = SyntheticFocusEvent;\n        break;\n      case topLevelTypes.topClick:\n        // Firefox creates a click event on right mouse clicks. This removes the\n        // unwanted click events.\n        if (nativeEvent.button === 2) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topDoubleClick:\n      case topLevelTypes.topMouseDown:\n      case topLevelTypes.topMouseMove:\n      case topLevelTypes.topMouseOut:\n      case topLevelTypes.topMouseOver:\n      case topLevelTypes.topMouseUp:\n        EventConstructor = SyntheticMouseEvent;\n        break;\n      case topLevelTypes.topDrag:\n      case topLevelTypes.topDragEnd:\n      case topLevelTypes.topDragEnter:\n      case topLevelTypes.topDragExit:\n      case topLevelTypes.topDragLeave:\n      case topLevelTypes.topDragOver:\n      case topLevelTypes.topDragStart:\n      case topLevelTypes.topDrop:\n        EventConstructor = SyntheticDragEvent;\n        break;\n      case topLevelTypes.topTouchCancel:\n      case topLevelTypes.topTouchEnd:\n      case topLevelTypes.topTouchMove:\n      case topLevelTypes.topTouchStart:\n        EventConstructor = SyntheticTouchEvent;\n        break;\n      case topLevelTypes.topAnimationEnd:\n      case topLevelTypes.topAnimationIteration:\n      case topLevelTypes.topAnimationStart:\n        EventConstructor = SyntheticAnimationEvent;\n        break;\n      case topLevelTypes.topTransitionEnd:\n        EventConstructor = SyntheticTransitionEvent;\n        break;\n      case topLevelTypes.topScroll:\n        EventConstructor = SyntheticUIEvent;\n        break;\n      case topLevelTypes.topWheel:\n        EventConstructor = SyntheticWheelEvent;\n        break;\n      case topLevelTypes.topCopy:\n      case topLevelTypes.topCut:\n      case topLevelTypes.topPaste:\n        EventConstructor = SyntheticClipboardEvent;\n        break;\n    }\n    !EventConstructor ? \"development\" !== 'production' ? invariant(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : _prodInvariant('86', topLevelType) : void 0;\n    var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);\n    EventPropagators.accumulateTwoPhaseDispatches(event);\n    return event;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    // Mobile Safari does not fire properly bubble click events on\n    // non-interactive elements, which means delegated click listeners do not\n    // fire. The workaround for this bug involves attaching an empty click\n    // listener on the target node.\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      if (!onClickListeners[id]) {\n        onClickListeners[id] = EventListener.listen(node, 'click', emptyFunction);\n      }\n    }\n  },\n\n  willDeleteListener: function (inst, registrationName) {\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      onClickListeners[id].remove();\n      delete onClickListeners[id];\n    }\n  }\n\n};\n\nmodule.exports = SimpleEventPlugin;\n},{\"100\":100,\"101\":101,\"103\":103,\"104\":104,\"105\":105,\"107\":107,\"108\":108,\"109\":109,\"110\":110,\"111\":111,\"112\":112,\"125\":125,\"139\":139,\"146\":146,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"20\":20,\"41\":41}],100:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticAnimationEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface\n * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent\n */\nvar AnimationEventInterface = {\n  animationName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);\n\nmodule.exports = SyntheticAnimationEvent;\n},{\"104\":104}],101:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticClipboardEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/clipboard-apis/\n */\nvar ClipboardEventInterface = {\n  clipboardData: function (event) {\n    return 'clipboardData' in event ? event.clipboardData : window.clipboardData;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);\n\nmodule.exports = SyntheticClipboardEvent;\n},{\"104\":104}],102:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticCompositionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents\n */\nvar CompositionEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);\n\nmodule.exports = SyntheticCompositionEvent;\n},{\"104\":104}],103:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticDragEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface DragEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar DragEventInterface = {\n  dataTransfer: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);\n\nmodule.exports = SyntheticDragEvent;\n},{\"108\":108}],104:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticEvent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar didWarnForAddedNewProperty = false;\nvar isProxySupported = typeof Proxy === 'function';\n\nvar shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar EventInterface = {\n  type: null,\n  target: null,\n  // currentTarget is set when dispatching; no use in copying it here\n  currentTarget: emptyFunction.thatReturnsNull,\n  eventPhase: null,\n  bubbles: null,\n  cancelable: null,\n  timeStamp: function (event) {\n    return event.timeStamp || Date.now();\n  },\n  defaultPrevented: null,\n  isTrusted: null\n};\n\n/**\n * Synthetic events are dispatched by event plugins, typically in response to a\n * top-level event delegation handler.\n *\n * These systems should generally use pooling to reduce the frequency of garbage\n * collection. The system should check `isPersistent` to determine whether the\n * event should be released into the pool after being dispatched. Users that\n * need a persisted event should invoke `persist`.\n *\n * Synthetic events (and subclasses) implement the DOM Level 3 Events API by\n * normalizing browser quirks. Subclasses do not necessarily have to implement a\n * DOM interface; custom application-specific events can also subclass this.\n *\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {*} targetInst Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @param {DOMEventTarget} nativeEventTarget Target node.\n */\nfunction SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {\n  if (\"development\" !== 'production') {\n    // these have a getter/setter for warnings\n    delete this.nativeEvent;\n    delete this.preventDefault;\n    delete this.stopPropagation;\n  }\n\n  this.dispatchConfig = dispatchConfig;\n  this._targetInst = targetInst;\n  this.nativeEvent = nativeEvent;\n\n  var Interface = this.constructor.Interface;\n  for (var propName in Interface) {\n    if (!Interface.hasOwnProperty(propName)) {\n      continue;\n    }\n    if (\"development\" !== 'production') {\n      delete this[propName]; // this has a getter/setter for warnings\n    }\n    var normalize = Interface[propName];\n    if (normalize) {\n      this[propName] = normalize(nativeEvent);\n    } else {\n      if (propName === 'target') {\n        this.target = nativeEventTarget;\n      } else {\n        this[propName] = nativeEvent[propName];\n      }\n    }\n  }\n\n  var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;\n  if (defaultPrevented) {\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  } else {\n    this.isDefaultPrevented = emptyFunction.thatReturnsFalse;\n  }\n  this.isPropagationStopped = emptyFunction.thatReturnsFalse;\n  return this;\n}\n\n_assign(SyntheticEvent.prototype, {\n\n  preventDefault: function () {\n    this.defaultPrevented = true;\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.preventDefault) {\n      event.preventDefault();\n    } else {\n      event.returnValue = false;\n    }\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  },\n\n  stopPropagation: function () {\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.stopPropagation) {\n      event.stopPropagation();\n    } else {\n      event.cancelBubble = true;\n    }\n    this.isPropagationStopped = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * We release all dispatched `SyntheticEvent`s after each event loop, adding\n   * them back into the pool. This allows a way to hold onto a reference that\n   * won't be added back into the pool.\n   */\n  persist: function () {\n    this.isPersistent = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * Checks if this event should be released back into the pool.\n   *\n   * @return {boolean} True if this should not be released, false otherwise.\n   */\n  isPersistent: emptyFunction.thatReturnsFalse,\n\n  /**\n   * `PooledClass` looks for `destructor` on each instance it releases.\n   */\n  destructor: function () {\n    var Interface = this.constructor.Interface;\n    for (var propName in Interface) {\n      if (\"development\" !== 'production') {\n        Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));\n      } else {\n        this[propName] = null;\n      }\n    }\n    for (var i = 0; i < shouldBeReleasedProperties.length; i++) {\n      this[shouldBeReleasedProperties[i]] = null;\n    }\n    if (\"development\" !== 'production') {\n      Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));\n      Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction));\n      Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction));\n    }\n  }\n\n});\n\nSyntheticEvent.Interface = EventInterface;\n\nif (\"development\" !== 'production') {\n  if (isProxySupported) {\n    /*eslint-disable no-func-assign */\n    SyntheticEvent = new Proxy(SyntheticEvent, {\n      construct: function (target, args) {\n        return this.apply(target, Object.create(target.prototype), args);\n      },\n      apply: function (constructor, that, args) {\n        return new Proxy(constructor.apply(that, args), {\n          set: function (target, prop, value) {\n            if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {\n              \"development\" !== 'production' ? warning(didWarnForAddedNewProperty || target.isPersistent(), 'This synthetic event is reused for performance reasons. If you\\'re ' + 'seeing this, you\\'re adding a new property in the synthetic event object. ' + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;\n              didWarnForAddedNewProperty = true;\n            }\n            target[prop] = value;\n            return true;\n          }\n        });\n      }\n    });\n    /*eslint-enable no-func-assign */\n  }\n}\n/**\n * Helper to reduce boilerplate when creating subclasses.\n *\n * @param {function} Class\n * @param {?object} Interface\n */\nSyntheticEvent.augmentClass = function (Class, Interface) {\n  var Super = this;\n\n  var E = function () {};\n  E.prototype = Super.prototype;\n  var prototype = new E();\n\n  _assign(prototype, Class.prototype);\n  Class.prototype = prototype;\n  Class.prototype.constructor = Class;\n\n  Class.Interface = _assign({}, Super.Interface, Interface);\n  Class.augmentClass = Super.augmentClass;\n\n  PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);\n};\n\nPooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);\n\nmodule.exports = SyntheticEvent;\n\n/**\n  * Helper to nullify syntheticEvent instance properties when destructing\n  *\n  * @param {object} SyntheticEvent\n  * @param {String} propName\n  * @return {object} defineProperty object\n  */\nfunction getPooledWarningPropertyDefinition(propName, getVal) {\n  var isFunction = typeof getVal === 'function';\n  return {\n    configurable: true,\n    set: set,\n    get: get\n  };\n\n  function set(val) {\n    var action = isFunction ? 'setting the method' : 'setting the property';\n    warn(action, 'This is effectively a no-op');\n    return val;\n  }\n\n  function get() {\n    var action = isFunction ? 'accessing the method' : 'accessing the property';\n    var result = isFunction ? 'This is a no-op function' : 'This is set to null';\n    warn(action, result);\n    return getVal;\n  }\n\n  function warn(action, result) {\n    var warningCondition = false;\n    \"development\" !== 'production' ? warning(warningCondition, 'This synthetic event is reused for performance reasons. If you\\'re seeing this, ' + 'you\\'re %s `%s` on a released/nullified synthetic event. %s. ' + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;\n  }\n}\n},{\"153\":153,\"171\":171,\"172\":172,\"25\":25}],105:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticFocusEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\n/**\n * @interface FocusEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar FocusEventInterface = {\n  relatedTarget: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);\n\nmodule.exports = SyntheticFocusEvent;\n},{\"111\":111}],106:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticInputEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105\n *      /#events-inputevents\n */\nvar InputEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface);\n\nmodule.exports = SyntheticInputEvent;\n},{\"104\":104}],107:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticKeyboardEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventCharCode = _dereq_(125);\nvar getEventKey = _dereq_(126);\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface KeyboardEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar KeyboardEventInterface = {\n  key: getEventKey,\n  location: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  repeat: null,\n  locale: null,\n  getModifierState: getEventModifierState,\n  // Legacy Interface\n  charCode: function (event) {\n    // `charCode` is the result of a KeyPress event and represents the value of\n    // the actual printable character.\n\n    // KeyPress is deprecated, but its replacement is not yet final and not\n    // implemented in any major browser. Only KeyPress has charCode.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    return 0;\n  },\n  keyCode: function (event) {\n    // `keyCode` is the result of a KeyDown/Up event and represents the value of\n    // physical keyboard key.\n\n    // The actual meaning of the value depends on the users' keyboard layout\n    // which cannot be detected. Assuming that it is a US keyboard layout\n    // provides a surprisingly accurate mapping for US and European users.\n    // Due to this, it is left to the user to implement at this time.\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  },\n  which: function (event) {\n    // `which` is an alias for either `keyCode` or `charCode` depending on the\n    // type of the event.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);\n\nmodule.exports = SyntheticKeyboardEvent;\n},{\"111\":111,\"125\":125,\"126\":126,\"127\":127}],108:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticMouseEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\nvar ViewportMetrics = _dereq_(114);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface MouseEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar MouseEventInterface = {\n  screenX: null,\n  screenY: null,\n  clientX: null,\n  clientY: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  getModifierState: getEventModifierState,\n  button: function (event) {\n    // Webkit, Firefox, IE9+\n    // which:  1 2 3\n    // button: 0 1 2 (standard)\n    var button = event.button;\n    if ('which' in event) {\n      return button;\n    }\n    // IE<9\n    // which:  undefined\n    // button: 0 0 0\n    // button: 1 4 2 (onmouseup)\n    return button === 2 ? 2 : button === 4 ? 1 : 0;\n  },\n  buttons: null,\n  relatedTarget: function (event) {\n    return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);\n  },\n  // \"Proprietary\" Interface.\n  pageX: function (event) {\n    return 'pageX' in event ? event.pageX : event.clientX + ViewportMetrics.currentScrollLeft;\n  },\n  pageY: function (event) {\n    return 'pageY' in event ? event.pageY : event.clientY + ViewportMetrics.currentScrollTop;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);\n\nmodule.exports = SyntheticMouseEvent;\n},{\"111\":111,\"114\":114,\"127\":127}],109:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTouchEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface TouchEvent\n * @see http://www.w3.org/TR/touch-events/\n */\nvar TouchEventInterface = {\n  touches: null,\n  targetTouches: null,\n  changedTouches: null,\n  altKey: null,\n  metaKey: null,\n  ctrlKey: null,\n  shiftKey: null,\n  getModifierState: getEventModifierState\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);\n\nmodule.exports = SyntheticTouchEvent;\n},{\"111\":111,\"127\":127}],110:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTransitionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent\n */\nvar TransitionEventInterface = {\n  propertyName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);\n\nmodule.exports = SyntheticTransitionEvent;\n},{\"104\":104}],111:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticUIEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\n\n/**\n * @interface UIEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar UIEventInterface = {\n  view: function (event) {\n    if (event.view) {\n      return event.view;\n    }\n\n    var target = getEventTarget(event);\n    if (target.window === target) {\n      // target is a window object\n      return target;\n    }\n\n    var doc = target.ownerDocument;\n    // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n    if (doc) {\n      return doc.defaultView || doc.parentWindow;\n    } else {\n      return window;\n    }\n  },\n  detail: function (event) {\n    return event.detail || 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);\n\nmodule.exports = SyntheticUIEvent;\n},{\"104\":104,\"128\":128}],112:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticWheelEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface WheelEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar WheelEventInterface = {\n  deltaX: function (event) {\n    return 'deltaX' in event ? event.deltaX :\n    // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).\n    'wheelDeltaX' in event ? -event.wheelDeltaX : 0;\n  },\n  deltaY: function (event) {\n    return 'deltaY' in event ? event.deltaY :\n    // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).\n    'wheelDeltaY' in event ? -event.wheelDeltaY :\n    // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).\n    'wheelDelta' in event ? -event.wheelDelta : 0;\n  },\n  deltaZ: null,\n\n  // Browsers without \"deltaMode\" is reporting in raw wheel delta where one\n  // notch on the scroll is always +/- 120, roughly equivalent to pixels.\n  // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or\n  // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.\n  deltaMode: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticMouseEvent}\n */\nfunction SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);\n\nmodule.exports = SyntheticWheelEvent;\n},{\"108\":108}],113:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Transaction\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * `Transaction` creates a black box that is able to wrap any method such that\n * certain invariants are maintained before and after the method is invoked\n * (Even if an exception is thrown while invoking the wrapped method). Whoever\n * instantiates a transaction can provide enforcers of the invariants at\n * creation time. The `Transaction` class itself will supply one additional\n * automatic invariant for you - the invariant that any transaction instance\n * should not be run while it is already being run. You would typically create a\n * single instance of a `Transaction` for reuse multiple times, that potentially\n * is used to wrap several different methods. Wrappers are extremely simple -\n * they only require implementing two methods.\n *\n * <pre>\n *                       wrappers (injected at creation time)\n *                                      +        +\n *                                      |        |\n *                    +-----------------|--------|--------------+\n *                    |                 v        |              |\n *                    |      +---------------+   |              |\n *                    |   +--|    wrapper1   |---|----+         |\n *                    |   |  +---------------+   v    |         |\n *                    |   |          +-------------+  |         |\n *                    |   |     +----|   wrapper2  |--------+   |\n *                    |   |     |    +-------------+  |     |   |\n *                    |   |     |                     |     |   |\n *                    |   v     v                     v     v   | wrapper\n *                    | +---+ +---+   +---------+   +---+ +---+ | invariants\n * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained\n * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | +---+ +---+   +---------+   +---+ +---+ |\n *                    |  initialize                    close    |\n *                    +-----------------------------------------+\n * </pre>\n *\n * Use cases:\n * - Preserving the input selection ranges before/after reconciliation.\n *   Restoring selection even in the event of an unexpected error.\n * - Deactivating events while rearranging the DOM, preventing blurs/focuses,\n *   while guaranteeing that afterwards, the event system is reactivated.\n * - Flushing a queue of collected DOM mutations to the main UI thread after a\n *   reconciliation takes place in a worker thread.\n * - Invoking any collected `componentDidUpdate` callbacks after rendering new\n *   content.\n * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue\n *   to preserve the `scrollTop` (an automatic scroll aware DOM).\n * - (Future use case): Layout calculations before and after DOM updates.\n *\n * Transactional plugin API:\n * - A module that has an `initialize` method that returns any precomputation.\n * - and a `close` method that accepts the precomputation. `close` is invoked\n *   when the wrapped process is completed, or has failed.\n *\n * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules\n * that implement `initialize` and `close`.\n * @return {Transaction} Single transaction for reuse in thread.\n *\n * @class Transaction\n */\nvar Mixin = {\n  /**\n   * Sets up this instance so that it is prepared for collecting metrics. Does\n   * so such that this setup method may be used on an instance that is already\n   * initialized, in a way that does not consume additional memory upon reuse.\n   * That can be useful if you decide to make your subclass of this mixin a\n   * \"PooledClass\".\n   */\n  reinitializeTransaction: function () {\n    this.transactionWrappers = this.getTransactionWrappers();\n    if (this.wrapperInitData) {\n      this.wrapperInitData.length = 0;\n    } else {\n      this.wrapperInitData = [];\n    }\n    this._isInTransaction = false;\n  },\n\n  _isInTransaction: false,\n\n  /**\n   * @abstract\n   * @return {Array<TransactionWrapper>} Array of transaction wrappers.\n   */\n  getTransactionWrappers: null,\n\n  isInTransaction: function () {\n    return !!this._isInTransaction;\n  },\n\n  /**\n   * Executes the function within a safety window. Use this for the top level\n   * methods that result in large amounts of computation/mutations that would\n   * need to be safety checked. The optional arguments helps prevent the need\n   * to bind in many cases.\n   *\n   * @param {function} method Member of scope to call.\n   * @param {Object} scope Scope to invoke from.\n   * @param {Object?=} a Argument to pass to the method.\n   * @param {Object?=} b Argument to pass to the method.\n   * @param {Object?=} c Argument to pass to the method.\n   * @param {Object?=} d Argument to pass to the method.\n   * @param {Object?=} e Argument to pass to the method.\n   * @param {Object?=} f Argument to pass to the method.\n   *\n   * @return {*} Return value from `method`.\n   */\n  perform: function (method, scope, a, b, c, d, e, f) {\n    !!this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.perform(...): Cannot initialize a transaction when there is already an outstanding transaction.') : _prodInvariant('27') : void 0;\n    var errorThrown;\n    var ret;\n    try {\n      this._isInTransaction = true;\n      // Catching errors makes debugging more difficult, so we start with\n      // errorThrown set to true before setting it to false after calling\n      // close -- if it's still set to true in the finally block, it means\n      // one of these calls threw.\n      errorThrown = true;\n      this.initializeAll(0);\n      ret = method.call(scope, a, b, c, d, e, f);\n      errorThrown = false;\n    } finally {\n      try {\n        if (errorThrown) {\n          // If `method` throws, prefer to show that stack trace over any thrown\n          // by invoking `closeAll`.\n          try {\n            this.closeAll(0);\n          } catch (err) {}\n        } else {\n          // Since `method` didn't throw, we don't want to silence the exception\n          // here.\n          this.closeAll(0);\n        }\n      } finally {\n        this._isInTransaction = false;\n      }\n    }\n    return ret;\n  },\n\n  initializeAll: function (startIndex) {\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      try {\n        // Catching errors makes debugging more difficult, so we start with the\n        // OBSERVED_ERROR state before overwriting it with the real return value\n        // of initialize -- if it's still set to OBSERVED_ERROR in the finally\n        // block, it means wrapper.initialize threw.\n        this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;\n        this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null;\n      } finally {\n        if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {\n          // The initializer for wrapper i threw an error; initialize the\n          // remaining wrappers but silence any exceptions from them to ensure\n          // that the first error is the one to bubble up.\n          try {\n            this.initializeAll(i + 1);\n          } catch (err) {}\n        }\n      }\n    }\n  },\n\n  /**\n   * Invokes each of `this.transactionWrappers.close[i]` functions, passing into\n   * them the respective return values of `this.transactionWrappers.init[i]`\n   * (`close`rs that correspond to initializers that failed will not be\n   * invoked).\n   */\n  closeAll: function (startIndex) {\n    !this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') : _prodInvariant('28') : void 0;\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      var initData = this.wrapperInitData[i];\n      var errorThrown;\n      try {\n        // Catching errors makes debugging more difficult, so we start with\n        // errorThrown set to true before setting it to false after calling\n        // close -- if it's still set to true in the finally block, it means\n        // wrapper.close threw.\n        errorThrown = true;\n        if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) {\n          wrapper.close.call(this, initData);\n        }\n        errorThrown = false;\n      } finally {\n        if (errorThrown) {\n          // The closer for wrapper i threw an error; close the remaining\n          // wrappers but silence any exceptions from them to ensure that the\n          // first error is the one to bubble up.\n          try {\n            this.closeAll(i + 1);\n          } catch (e) {}\n        }\n      }\n    }\n    this.wrapperInitData.length = 0;\n  }\n};\n\nvar Transaction = {\n\n  Mixin: Mixin,\n\n  /**\n   * Token to look for to determine if an error occurred.\n   */\n  OBSERVED_ERROR: {}\n\n};\n\nmodule.exports = Transaction;\n},{\"139\":139,\"161\":161}],114:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ViewportMetrics\n */\n\n'use strict';\n\nvar ViewportMetrics = {\n\n  currentScrollLeft: 0,\n\n  currentScrollTop: 0,\n\n  refreshScrollValues: function (scrollPosition) {\n    ViewportMetrics.currentScrollLeft = scrollPosition.x;\n    ViewportMetrics.currentScrollTop = scrollPosition.y;\n  }\n\n};\n\nmodule.exports = ViewportMetrics;\n},{}],115:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule accumulateInto\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Accumulates items that must not be null or undefined into the first one. This\n * is used to conserve memory by avoiding array allocations, and thus sacrifices\n * API cleanness. Since `current` can be null before being passed in and not\n * null after this function, make sure to assign it back to `current`:\n *\n * `a = accumulateInto(a, b);`\n *\n * This API should be sparingly used. Try `accumulate` for something cleaner.\n *\n * @return {*|array<*>} An accumulation of items.\n */\n\nfunction accumulateInto(current, next) {\n  !(next != null) ? \"development\" !== 'production' ? invariant(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : _prodInvariant('30') : void 0;\n\n  if (current == null) {\n    return next;\n  }\n\n  // Both are not empty. Warning: Never call x.concat(y) when you are not\n  // certain that x is an Array (x could be a string with concat method).\n  if (Array.isArray(current)) {\n    if (Array.isArray(next)) {\n      current.push.apply(current, next);\n      return current;\n    }\n    current.push(next);\n    return current;\n  }\n\n  if (Array.isArray(next)) {\n    // A bit too dangerous to mutate `next`.\n    return [current].concat(next);\n  }\n\n  return [current, next];\n}\n\nmodule.exports = accumulateInto;\n},{\"139\":139,\"161\":161}],116:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule adler32\n * \n */\n\n'use strict';\n\nvar MOD = 65521;\n\n// adler32 is not cryptographically strong, and is only used to sanity check that\n// markup generated on the server matches the markup generated on the client.\n// This implementation (a modified version of the SheetJS version) has been optimized\n// for our use case, at the expense of conforming to the adler32 specification\n// for non-ascii inputs.\nfunction adler32(data) {\n  var a = 1;\n  var b = 0;\n  var i = 0;\n  var l = data.length;\n  var m = l & ~0x3;\n  while (i < m) {\n    var n = Math.min(i + 4096, m);\n    for (; i < n; i += 4) {\n      b += (a += data.charCodeAt(i)) + (a += data.charCodeAt(i + 1)) + (a += data.charCodeAt(i + 2)) + (a += data.charCodeAt(i + 3));\n    }\n    a %= MOD;\n    b %= MOD;\n  }\n  for (; i < l; i++) {\n    b += a += data.charCodeAt(i);\n  }\n  a %= MOD;\n  b %= MOD;\n  return a | b << 16;\n}\n\nmodule.exports = adler32;\n},{}],117:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule canDefineProperty\n */\n\n'use strict';\n\nvar canDefineProperty = false;\nif (\"development\" !== 'production') {\n  try {\n    Object.defineProperty({}, 'x', { get: function () {} });\n    canDefineProperty = true;\n  } catch (x) {\n    // IE will fail on defineProperty\n  }\n}\n\nmodule.exports = canDefineProperty;\n},{}],118:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule checkReactTypeSpec\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar loggedTypeFailures = {};\n\n/**\n * Assert that the values match with the type specs.\n * Error messages are memorized and will only be shown once.\n *\n * @param {object} typeSpecs Map of name to a ReactPropType\n * @param {object} values Runtime values that need to be type-checked\n * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n * @param {string} componentName Name of the component for error messages.\n * @param {?object} element The React element that is being type-checked\n * @param {?number} debugID The React component instance that is being type-checked\n * @private\n */\nfunction checkReactTypeSpec(typeSpecs, values, location, componentName, element, debugID) {\n  for (var typeSpecName in typeSpecs) {\n    if (typeSpecs.hasOwnProperty(typeSpecName)) {\n      var error;\n      // Prop type validation may throw. In case they do, we don't want to\n      // fail the render phase where it didn't fail before. So we log it.\n      // After these have been cleaned up, we'll let them throw.\n      try {\n        // This is intentionally an invariant that gets caught. It's the same\n        // behavior as without this statement except with a better message.\n        !(typeof typeSpecs[typeSpecName] === 'function') ? \"development\" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : _prodInvariant('84', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : void 0;\n        error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location);\n      } catch (ex) {\n        error = ex;\n      }\n      \"development\" !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName, typeof error) : void 0;\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var componentStackInfo = '';\n\n        if (\"development\" !== 'production') {\n          var ReactComponentTreeDevtool = _dereq_(34);\n          if (debugID !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getStackAddendumByID(debugID);\n          } else if (element !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getCurrentStackAddendum(element);\n          }\n        }\n\n        \"development\" !== 'production' ? warning(false, 'Failed %s type: %s%s', location, error.message, componentStackInfo) : void 0;\n      }\n    }\n  }\n}\n\nmodule.exports = checkReactTypeSpec;\n},{\"139\":139,\"161\":161,\"171\":171,\"34\":34,\"83\":83}],119:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule createMicrosoftUnsafeLocalFunction\n */\n\n/* globals MSApp */\n\n'use strict';\n\n/**\n * Create a function which has 'unsafe' privileges (required by windows8 apps)\n */\n\nvar createMicrosoftUnsafeLocalFunction = function (func) {\n  if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {\n    return function (arg0, arg1, arg2, arg3) {\n      MSApp.execUnsafeLocalFunction(function () {\n        return func(arg0, arg1, arg2, arg3);\n      });\n    };\n  } else {\n    return func;\n  }\n};\n\nmodule.exports = createMicrosoftUnsafeLocalFunction;\n},{}],120:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule dangerousStyleValue\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar warning = _dereq_(171);\n\nvar isUnitlessNumber = CSSProperty.isUnitlessNumber;\nvar styleWarnings = {};\n\n/**\n * Convert a value into the proper css writable value. The style name `name`\n * should be logical (no hyphens), as specified\n * in `CSSProperty.isUnitlessNumber`.\n *\n * @param {string} name CSS property name such as `topMargin`.\n * @param {*} value CSS property value such as `10px`.\n * @param {ReactDOMComponent} component\n * @return {string} Normalized style value with dimensions applied.\n */\nfunction dangerousStyleValue(name, value, component) {\n  // Note that we've removed escapeTextForBrowser() calls here since the\n  // whole string will be escaped when the attribute is injected into\n  // the markup. If you provide unsafe user data here they can inject\n  // arbitrary CSS which may be problematic (I couldn't repro this):\n  // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet\n  // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/\n  // This is not an XSS hole but instead a potential CSS injection issue\n  // which has lead to a greater discussion about how we're going to\n  // trust URLs moving forward. See #2115901\n\n  var isEmpty = value == null || typeof value === 'boolean' || value === '';\n  if (isEmpty) {\n    return '';\n  }\n\n  var isNonNumeric = isNaN(value);\n  if (isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {\n    return '' + value; // cast to string\n  }\n\n  if (typeof value === 'string') {\n    if (\"development\" !== 'production') {\n      // Allow '0' to pass through without warning. 0 is already special and\n      // doesn't require units, so we don't need to warn about it.\n      if (component && value !== '0') {\n        var owner = component._currentElement._owner;\n        var ownerName = owner ? owner.getName() : null;\n        if (ownerName && !styleWarnings[ownerName]) {\n          styleWarnings[ownerName] = {};\n        }\n        var warned = false;\n        if (ownerName) {\n          var warnings = styleWarnings[ownerName];\n          warned = warnings[name];\n          if (!warned) {\n            warnings[name] = true;\n          }\n        }\n        if (!warned) {\n          \"development\" !== 'production' ? warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' + 'for CSS property `%s` (value: `%s`) which will be treated ' + 'as a unitless number in a future version of React.', component._currentElement.type, ownerName || 'unknown', name, value) : void 0;\n        }\n      }\n    }\n    value = value.trim();\n  }\n  return value + 'px';\n}\n\nmodule.exports = dangerousStyleValue;\n},{\"171\":171,\"3\":3}],121:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * Based on the escape-html library, which is used under the MIT License below:\n *\n * Copyright (c) 2012-2013 TJ Holowaychuk\n * Copyright (c) 2015 Andreas Lubbe\n * Copyright (c) 2015 Tiancheng \"Timothy\" Gu\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * @providesModule escapeTextContentForBrowser\n */\n\n'use strict';\n\n// code copied and modified from escape-html\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param  {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n  var str = '' + string;\n  var match = matchHtmlRegExp.exec(str);\n\n  if (!match) {\n    return str;\n  }\n\n  var escape;\n  var html = '';\n  var index = 0;\n  var lastIndex = 0;\n\n  for (index = match.index; index < str.length; index++) {\n    switch (str.charCodeAt(index)) {\n      case 34:\n        // \"\n        escape = '&quot;';\n        break;\n      case 38:\n        // &\n        escape = '&amp;';\n        break;\n      case 39:\n        // '\n        escape = '&#x27;'; // modified from escape-html; used to be '&#39'\n        break;\n      case 60:\n        // <\n        escape = '&lt;';\n        break;\n      case 62:\n        // >\n        escape = '&gt;';\n        break;\n      default:\n        continue;\n    }\n\n    if (lastIndex !== index) {\n      html += str.substring(lastIndex, index);\n    }\n\n    lastIndex = index + 1;\n    html += escape;\n  }\n\n  return lastIndex !== index ? html + str.substring(lastIndex, index) : html;\n}\n// end code copied and modified from escape-html\n\n/**\n * Escapes text to prevent scripting attacks.\n *\n * @param {*} text Text value to escape.\n * @return {string} An escaped string.\n */\nfunction escapeTextContentForBrowser(text) {\n  if (typeof text === 'boolean' || typeof text === 'number') {\n    // this shortcircuit helps perf for types that we know will never have\n    // special characters, especially given that this function is used often\n    // for numeric dom ids.\n    return '' + text;\n  }\n  return escapeHtml(text);\n}\n\nmodule.exports = escapeTextContentForBrowser;\n},{}],122:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule findDOMNode\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstanceMap = _dereq_(73);\n\nvar getHostComponentFromComposite = _dereq_(129);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Returns the DOM node rendered by this element.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode\n *\n * @param {ReactComponent|DOMElement} componentOrElement\n * @return {?DOMElement} The root node of this element.\n */\nfunction findDOMNode(componentOrElement) {\n  if (\"development\" !== 'production') {\n    var owner = ReactCurrentOwner.current;\n    if (owner !== null) {\n      \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n      owner._warnedAboutRefsInRender = true;\n    }\n  }\n  if (componentOrElement == null) {\n    return null;\n  }\n  if (componentOrElement.nodeType === 1) {\n    return componentOrElement;\n  }\n\n  var inst = ReactInstanceMap.get(componentOrElement);\n  if (inst) {\n    inst = getHostComponentFromComposite(inst);\n    return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null;\n  }\n\n  if (typeof componentOrElement.render === 'function') {\n    !false ? \"development\" !== 'production' ? invariant(false, 'findDOMNode was called on an unmounted component.') : _prodInvariant('44') : void 0;\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', Object.keys(componentOrElement)) : _prodInvariant('45', Object.keys(componentOrElement)) : void 0;\n  }\n}\n\nmodule.exports = findDOMNode;\n},{\"129\":129,\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"41\":41,\"73\":73}],123:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule flattenChildren\n * \n */\n\n'use strict';\n\nvar KeyEscapeUtils = _dereq_(23);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\n/**\n * @param {function} traverseContext Context passed through traversal.\n * @param {?ReactComponent} child React child component.\n * @param {!string} name String name of key path to child.\n * @param {number=} selfDebugID Optional debugID of the current internal instance.\n */\nfunction flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID) {\n  // We found a component instance.\n  if (traverseContext && typeof traverseContext === 'object') {\n    var result = traverseContext;\n    var keyUnique = result[name] === undefined;\n    if (\"development\" !== 'production') {\n      var ReactComponentTreeDevtool = _dereq_(34);\n      \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n    }\n    if (keyUnique && child != null) {\n      result[name] = child;\n    }\n  }\n}\n\n/**\n * Flattens children that are typically specified as `props.children`. Any null\n * children will not be included in the resulting object.\n * @return {!object} flattened children keyed by name.\n */\nfunction flattenChildren(children, selfDebugID) {\n  if (children == null) {\n    return children;\n  }\n  var result = {};\n\n  if (\"development\" !== 'production') {\n    traverseAllChildren(children, function (traverseContext, child, name) {\n      return flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID);\n    }, result);\n  } else {\n    traverseAllChildren(children, flattenSingleChildIntoContext, result);\n  }\n  return result;\n}\n\nmodule.exports = flattenChildren;\n},{\"144\":144,\"171\":171,\"23\":23,\"34\":34}],124:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule forEachAccumulated\n * \n */\n\n'use strict';\n\n/**\n * @param {array} arr an \"accumulation\" of items which is either an Array or\n * a single item. Useful when paired with the `accumulate` module. This is a\n * simple utility that allows us to reason about a collection of items, but\n * handling the case when there is exactly one item (and we do not need to\n * allocate an array).\n */\n\nfunction forEachAccumulated(arr, cb, scope) {\n  if (Array.isArray(arr)) {\n    arr.forEach(cb, scope);\n  } else if (arr) {\n    cb.call(scope, arr);\n  }\n}\n\nmodule.exports = forEachAccumulated;\n},{}],125:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventCharCode\n */\n\n'use strict';\n\n/**\n * `charCode` represents the actual \"character code\" and is safe to use with\n * `String.fromCharCode`. As such, only keys that correspond to printable\n * characters produce a valid `charCode`, the only exception to this is Enter.\n * The Tab-key is considered non-printable and does not have a `charCode`,\n * presumably because it does not produce a tab-character in browsers.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {number} Normalized `charCode` property.\n */\n\nfunction getEventCharCode(nativeEvent) {\n  var charCode;\n  var keyCode = nativeEvent.keyCode;\n\n  if ('charCode' in nativeEvent) {\n    charCode = nativeEvent.charCode;\n\n    // FF does not set `charCode` for the Enter-key, check against `keyCode`.\n    if (charCode === 0 && keyCode === 13) {\n      charCode = 13;\n    }\n  } else {\n    // IE8 does not implement `charCode`, but `keyCode` has the correct value.\n    charCode = keyCode;\n  }\n\n  // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.\n  // Must not discard the (non-)printable Enter-key.\n  if (charCode >= 32 || charCode === 13) {\n    return charCode;\n  }\n\n  return 0;\n}\n\nmodule.exports = getEventCharCode;\n},{}],126:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventKey\n */\n\n'use strict';\n\nvar getEventCharCode = _dereq_(125);\n\n/**\n * Normalization of deprecated HTML5 `key` values\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar normalizeKey = {\n  'Esc': 'Escape',\n  'Spacebar': ' ',\n  'Left': 'ArrowLeft',\n  'Up': 'ArrowUp',\n  'Right': 'ArrowRight',\n  'Down': 'ArrowDown',\n  'Del': 'Delete',\n  'Win': 'OS',\n  'Menu': 'ContextMenu',\n  'Apps': 'ContextMenu',\n  'Scroll': 'ScrollLock',\n  'MozPrintableKey': 'Unidentified'\n};\n\n/**\n * Translation from legacy `keyCode` to HTML5 `key`\n * Only special keys supported, all others depend on keyboard layout or browser\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar translateToKey = {\n  8: 'Backspace',\n  9: 'Tab',\n  12: 'Clear',\n  13: 'Enter',\n  16: 'Shift',\n  17: 'Control',\n  18: 'Alt',\n  19: 'Pause',\n  20: 'CapsLock',\n  27: 'Escape',\n  32: ' ',\n  33: 'PageUp',\n  34: 'PageDown',\n  35: 'End',\n  36: 'Home',\n  37: 'ArrowLeft',\n  38: 'ArrowUp',\n  39: 'ArrowRight',\n  40: 'ArrowDown',\n  45: 'Insert',\n  46: 'Delete',\n  112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',\n  118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12',\n  144: 'NumLock',\n  145: 'ScrollLock',\n  224: 'Meta'\n};\n\n/**\n * @param {object} nativeEvent Native browser event.\n * @return {string} Normalized `key` property.\n */\nfunction getEventKey(nativeEvent) {\n  if (nativeEvent.key) {\n    // Normalize inconsistent values reported by browsers due to\n    // implementations of a working draft specification.\n\n    // FireFox implements `key` but returns `MozPrintableKey` for all\n    // printable characters (normalized to `Unidentified`), ignore it.\n    var key = normalizeKey[nativeEvent.key] || nativeEvent.key;\n    if (key !== 'Unidentified') {\n      return key;\n    }\n  }\n\n  // Browser does not implement `key`, polyfill as much of it as we can.\n  if (nativeEvent.type === 'keypress') {\n    var charCode = getEventCharCode(nativeEvent);\n\n    // The enter-key is technically both printable and non-printable and can\n    // thus be captured by `keypress`, no other non-printable key should.\n    return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);\n  }\n  if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {\n    // While user keyboard layout determines the actual meaning of each\n    // `keyCode` value, almost all function keys have a universal value.\n    return translateToKey[nativeEvent.keyCode] || 'Unidentified';\n  }\n  return '';\n}\n\nmodule.exports = getEventKey;\n},{\"125\":125}],127:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventModifierState\n */\n\n'use strict';\n\n/**\n * Translation from modifier key to the associated property in the event.\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers\n */\n\nvar modifierKeyToProp = {\n  'Alt': 'altKey',\n  'Control': 'ctrlKey',\n  'Meta': 'metaKey',\n  'Shift': 'shiftKey'\n};\n\n// IE8 does not implement getModifierState so we simply map it to the only\n// modifier keys exposed by the event itself, does not support Lock-keys.\n// Currently, all major browsers except Chrome seems to support Lock-keys.\nfunction modifierStateGetter(keyArg) {\n  var syntheticEvent = this;\n  var nativeEvent = syntheticEvent.nativeEvent;\n  if (nativeEvent.getModifierState) {\n    return nativeEvent.getModifierState(keyArg);\n  }\n  var keyProp = modifierKeyToProp[keyArg];\n  return keyProp ? !!nativeEvent[keyProp] : false;\n}\n\nfunction getEventModifierState(nativeEvent) {\n  return modifierStateGetter;\n}\n\nmodule.exports = getEventModifierState;\n},{}],128:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventTarget\n */\n\n'use strict';\n\n/**\n * Gets the target node from a native browser event by accounting for\n * inconsistencies in browser DOM APIs.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {DOMEventTarget} Target node.\n */\n\nfunction getEventTarget(nativeEvent) {\n  var target = nativeEvent.target || nativeEvent.srcElement || window;\n\n  // Normalize SVG <use> element events #4963\n  if (target.correspondingUseElement) {\n    target = target.correspondingUseElement;\n  }\n\n  // Safari may fire events on text nodes (Node.TEXT_NODE is 3).\n  // @see http://www.quirksmode.org/js/events_properties.html\n  return target.nodeType === 3 ? target.parentNode : target;\n}\n\nmodule.exports = getEventTarget;\n},{}],129:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getHostComponentFromComposite\n */\n\n'use strict';\n\nvar ReactNodeTypes = _dereq_(80);\n\nfunction getHostComponentFromComposite(inst) {\n  var type;\n\n  while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {\n    inst = inst._renderedComponent;\n  }\n\n  if (type === ReactNodeTypes.HOST) {\n    return inst._renderedComponent;\n  } else if (type === ReactNodeTypes.EMPTY) {\n    return null;\n  }\n}\n\nmodule.exports = getHostComponentFromComposite;\n},{\"80\":80}],130:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getIteratorFn\n * \n */\n\n'use strict';\n\n/* global Symbol */\n\nvar ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.\n\n/**\n * Returns the iterator method function contained on the iterable object.\n *\n * Be sure to invoke the function with the iterable as context:\n *\n *     var iteratorFn = getIteratorFn(myIterable);\n *     if (iteratorFn) {\n *       var iterator = iteratorFn.call(myIterable);\n *       ...\n *     }\n *\n * @param {?object} maybeIterable\n * @return {?function}\n */\nfunction getIteratorFn(maybeIterable) {\n  var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);\n  if (typeof iteratorFn === 'function') {\n    return iteratorFn;\n  }\n}\n\nmodule.exports = getIteratorFn;\n},{}],131:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getNodeForCharacterOffset\n */\n\n'use strict';\n\n/**\n * Given any node return the first leaf node without children.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {DOMElement|DOMTextNode}\n */\n\nfunction getLeafNode(node) {\n  while (node && node.firstChild) {\n    node = node.firstChild;\n  }\n  return node;\n}\n\n/**\n * Get the next sibling within a container. This will walk up the\n * DOM if a node's siblings have been exhausted.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {?DOMElement|DOMTextNode}\n */\nfunction getSiblingNode(node) {\n  while (node) {\n    if (node.nextSibling) {\n      return node.nextSibling;\n    }\n    node = node.parentNode;\n  }\n}\n\n/**\n * Get object describing the nodes which contain characters at offset.\n *\n * @param {DOMElement|DOMTextNode} root\n * @param {number} offset\n * @return {?object}\n */\nfunction getNodeForCharacterOffset(root, offset) {\n  var node = getLeafNode(root);\n  var nodeStart = 0;\n  var nodeEnd = 0;\n\n  while (node) {\n    if (node.nodeType === 3) {\n      nodeEnd = nodeStart + node.textContent.length;\n\n      if (nodeStart <= offset && nodeEnd >= offset) {\n        return {\n          node: node,\n          offset: offset - nodeStart\n        };\n      }\n\n      nodeStart = nodeEnd;\n    }\n\n    node = getLeafNode(getSiblingNode(node));\n  }\n}\n\nmodule.exports = getNodeForCharacterOffset;\n},{}],132:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getTextContentAccessor\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar contentKey = null;\n\n/**\n * Gets the key used to access text content on a DOM node.\n *\n * @return {?string} Key used to access text content.\n * @internal\n */\nfunction getTextContentAccessor() {\n  if (!contentKey && ExecutionEnvironment.canUseDOM) {\n    // Prefer textContent to innerText because many browsers support both but\n    // SVG <text> elements don't support innerText even when <div> does.\n    contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';\n  }\n  return contentKey;\n}\n\nmodule.exports = getTextContentAccessor;\n},{\"147\":147}],133:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getVendorPrefixedEventName\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\n/**\n * Generate a mapping of standard vendor prefixes using the defined style property and event name.\n *\n * @param {string} styleProp\n * @param {string} eventName\n * @returns {object}\n */\nfunction makePrefixMap(styleProp, eventName) {\n  var prefixes = {};\n\n  prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();\n  prefixes['Webkit' + styleProp] = 'webkit' + eventName;\n  prefixes['Moz' + styleProp] = 'moz' + eventName;\n  prefixes['ms' + styleProp] = 'MS' + eventName;\n  prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();\n\n  return prefixes;\n}\n\n/**\n * A list of event names to a configurable list of vendor prefixes.\n */\nvar vendorPrefixes = {\n  animationend: makePrefixMap('Animation', 'AnimationEnd'),\n  animationiteration: makePrefixMap('Animation', 'AnimationIteration'),\n  animationstart: makePrefixMap('Animation', 'AnimationStart'),\n  transitionend: makePrefixMap('Transition', 'TransitionEnd')\n};\n\n/**\n * Event names that have already been detected and prefixed (if applicable).\n */\nvar prefixedEventNames = {};\n\n/**\n * Element to check for prefixes on.\n */\nvar style = {};\n\n/**\n * Bootstrap if a DOM exists.\n */\nif (ExecutionEnvironment.canUseDOM) {\n  style = document.createElement('div').style;\n\n  // On some platforms, in particular some releases of Android 4.x,\n  // the un-prefixed \"animation\" and \"transition\" properties are defined on the\n  // style object but the events that fire will still be prefixed, so we need\n  // to check if the un-prefixed events are usable, and if not remove them from the map.\n  if (!('AnimationEvent' in window)) {\n    delete vendorPrefixes.animationend.animation;\n    delete vendorPrefixes.animationiteration.animation;\n    delete vendorPrefixes.animationstart.animation;\n  }\n\n  // Same as above\n  if (!('TransitionEvent' in window)) {\n    delete vendorPrefixes.transitionend.transition;\n  }\n}\n\n/**\n * Attempts to determine the correct vendor prefixed event name.\n *\n * @param {string} eventName\n * @returns {string}\n */\nfunction getVendorPrefixedEventName(eventName) {\n  if (prefixedEventNames[eventName]) {\n    return prefixedEventNames[eventName];\n  } else if (!vendorPrefixes[eventName]) {\n    return eventName;\n  }\n\n  var prefixMap = vendorPrefixes[eventName];\n\n  for (var styleProp in prefixMap) {\n    if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {\n      return prefixedEventNames[eventName] = prefixMap[styleProp];\n    }\n  }\n\n  return '';\n}\n\nmodule.exports = getVendorPrefixedEventName;\n},{\"147\":147}],134:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule instantiateReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactCompositeComponent = _dereq_(35);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactHostComponent = _dereq_(69);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n// To avoid a cyclic dependency, we create the final class in this module\nvar ReactCompositeComponentWrapper = function (element) {\n  this.construct(element);\n};\n_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent.Mixin, {\n  _instantiateReactComponent: instantiateReactComponent\n});\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nfunction getDisplayName(instance) {\n  var element = instance._currentElement;\n  if (element == null) {\n    return '#empty';\n  } else if (typeof element === 'string' || typeof element === 'number') {\n    return '#text';\n  } else if (typeof element.type === 'string') {\n    return element.type;\n  } else if (instance.getName) {\n    return instance.getName() || 'Unknown';\n  } else {\n    return element.type.displayName || element.type.name || 'Unknown';\n  }\n}\n\n/**\n * Check if the type reference is a known internal type. I.e. not a user\n * provided composite type.\n *\n * @param {function} type\n * @return {boolean} Returns true if this is a valid internal type.\n */\nfunction isInternalComponentType(type) {\n  return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';\n}\n\nvar nextDebugID = 1;\n\n/**\n * Given a ReactNode, create an instance that will actually be mounted.\n *\n * @param {ReactNode} node\n * @param {boolean} shouldHaveDebugID\n * @return {object} A new instance of the element's constructor.\n * @protected\n */\nfunction instantiateReactComponent(node, shouldHaveDebugID) {\n  var instance;\n\n  if (node === null || node === false) {\n    instance = ReactEmptyComponent.create(instantiateReactComponent);\n  } else if (typeof node === 'object') {\n    var element = node;\n    !(element && (typeof element.type === 'function' || typeof element.type === 'string')) ? \"development\" !== 'production' ? invariant(false, 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : _prodInvariant('130', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : void 0;\n\n    // Special case string values\n    if (typeof element.type === 'string') {\n      instance = ReactHostComponent.createInternalComponent(element);\n    } else if (isInternalComponentType(element.type)) {\n      // This is temporarily available for custom components that are not string\n      // representations. I.e. ART. Once those are updated to use the string\n      // representation, we can drop this code path.\n      instance = new element.type(element);\n\n      // We renamed this. Allow the old name for compat. :(\n      if (!instance.getHostNode) {\n        instance.getHostNode = instance.getNativeNode;\n      }\n    } else {\n      instance = new ReactCompositeComponentWrapper(element);\n    }\n  } else if (typeof node === 'string' || typeof node === 'number') {\n    instance = ReactHostComponent.createInstanceForText(node);\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : _prodInvariant('131', typeof node) : void 0;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getHostNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;\n  }\n\n  // These two fields are used by the DOM and ART diffing algorithms\n  // respectively. Instead of using expandos on components, we should be\n  // storing the state needed by the diffing algorithms elsewhere.\n  instance._mountIndex = 0;\n  instance._mountImage = null;\n\n  if (\"development\" !== 'production') {\n    if (shouldHaveDebugID) {\n      var debugID = nextDebugID++;\n      instance._debugID = debugID;\n      var displayName = getDisplayName(instance);\n      ReactInstrumentation.debugTool.onSetDisplayName(debugID, displayName);\n      var owner = node && node._owner;\n      if (owner) {\n        ReactInstrumentation.debugTool.onSetOwner(debugID, owner._debugID);\n      }\n    } else {\n      instance._debugID = 0;\n    }\n  }\n\n  // Internal instances should fully constructed at this point, so they should\n  // not get any new fields added to them at this point.\n  if (\"development\" !== 'production') {\n    if (Object.preventExtensions) {\n      Object.preventExtensions(instance);\n    }\n  }\n\n  return instance;\n}\n\nmodule.exports = instantiateReactComponent;\n},{\"139\":139,\"161\":161,\"171\":171,\"172\":172,\"35\":35,\"64\":64,\"69\":69,\"74\":74}],135:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isEventSupported\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar useHasFeature;\nif (ExecutionEnvironment.canUseDOM) {\n  useHasFeature = document.implementation && document.implementation.hasFeature &&\n  // always returns true in newer browsers as per the standard.\n  // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature\n  document.implementation.hasFeature('', '') !== true;\n}\n\n/**\n * Checks if an event is supported in the current execution environment.\n *\n * NOTE: This will not work correctly for non-generic events such as `change`,\n * `reset`, `load`, `error`, and `select`.\n *\n * Borrows from Modernizr.\n *\n * @param {string} eventNameSuffix Event name, e.g. \"click\".\n * @param {?boolean} capture Check if the capture phase is supported.\n * @return {boolean} True if the event is supported.\n * @internal\n * @license Modernizr 3.0.0pre (Custom Build) | MIT\n */\nfunction isEventSupported(eventNameSuffix, capture) {\n  if (!ExecutionEnvironment.canUseDOM || capture && !('addEventListener' in document)) {\n    return false;\n  }\n\n  var eventName = 'on' + eventNameSuffix;\n  var isSupported = eventName in document;\n\n  if (!isSupported) {\n    var element = document.createElement('div');\n    element.setAttribute(eventName, 'return;');\n    isSupported = typeof element[eventName] === 'function';\n  }\n\n  if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {\n    // This is the only way to test support for the `wheel` event in IE9+.\n    isSupported = document.implementation.hasFeature('Events.wheel', '3.0');\n  }\n\n  return isSupported;\n}\n\nmodule.exports = isEventSupported;\n},{\"147\":147}],136:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isTextInputElement\n * \n */\n\n'use strict';\n\n/**\n * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary\n */\n\nvar supportedInputTypes = {\n  'color': true,\n  'date': true,\n  'datetime': true,\n  'datetime-local': true,\n  'email': true,\n  'month': true,\n  'number': true,\n  'password': true,\n  'range': true,\n  'search': true,\n  'tel': true,\n  'text': true,\n  'time': true,\n  'url': true,\n  'week': true\n};\n\nfunction isTextInputElement(elem) {\n  var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n\n  if (nodeName === 'input') {\n    return !!supportedInputTypes[elem.type];\n  }\n\n  if (nodeName === 'textarea') {\n    return true;\n  }\n\n  return false;\n}\n\nmodule.exports = isTextInputElement;\n},{}],137:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule onlyChild\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\n/**\n * Returns the first child in a collection of children and verifies that there\n * is only one child in the collection.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.only\n *\n * The current implementation of this function assumes that a single child gets\n * passed without a wrapper, but the purpose of this helper function is to\n * abstract away the particular structure of children.\n *\n * @param {?object} children Child collection structure.\n * @return {ReactElement} The first and only `ReactElement` contained in the\n * structure.\n */\nfunction onlyChild(children) {\n  !ReactElement.isValidElement(children) ? \"development\" !== 'production' ? invariant(false, 'onlyChild must be passed a children with exactly one child.') : _prodInvariant('23') : void 0;\n  return children;\n}\n\nmodule.exports = onlyChild;\n},{\"139\":139,\"161\":161,\"62\":62}],138:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule quoteAttributeValueForBrowser\n */\n\n'use strict';\n\nvar escapeTextContentForBrowser = _dereq_(121);\n\n/**\n * Escapes attribute value to prevent scripting attacks.\n *\n * @param {*} value Value to escape.\n * @return {string} An escaped string.\n */\nfunction quoteAttributeValueForBrowser(value) {\n  return '\"' + escapeTextContentForBrowser(value) + '\"';\n}\n\nmodule.exports = quoteAttributeValueForBrowser;\n},{\"121\":121}],139:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule reactProdInvariant\n * \n */\n'use strict';\n\n/**\n * WARNING: DO NOT manually require this module.\n * This is a replacement for `invariant(...)` used by the error code system\n * and will _only_ be required by the corresponding babel pass.\n * It always throws.\n */\n\nfunction reactProdInvariant(code) {\n  var argCount = arguments.length - 1;\n\n  var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;\n\n  for (var argIdx = 0; argIdx < argCount; argIdx++) {\n    message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);\n  }\n\n  message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';\n\n  var error = new Error(message);\n  error.name = 'Invariant Violation';\n  error.framesToPop = 1; // we don't care about reactProdInvariant's own frame\n\n  throw error;\n}\n\nmodule.exports = reactProdInvariant;\n},{}],140:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n* @providesModule renderSubtreeIntoContainer\n*/\n\n'use strict';\n\nvar ReactMount = _dereq_(77);\n\nmodule.exports = ReactMount.renderSubtreeIntoContainer;\n},{\"77\":77}],141:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setInnerHTML\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar DOMNamespaces = _dereq_(9);\n\nvar WHITESPACE_TEST = /^[ \\r\\n\\t\\f]/;\nvar NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \\r\\n\\t\\f\\/>]/;\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\n\n// SVG temp container for IE lacking innerHTML\nvar reusableSVGContainer;\n\n/**\n * Set the innerHTML property of a node, ensuring that whitespace is preserved\n * even in IE8.\n *\n * @param {DOMElement} node\n * @param {string} html\n * @internal\n */\nvar setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {\n  // IE does not have innerHTML for SVG nodes, so instead we inject the\n  // new markup in a temp node and then move the child nodes across into\n  // the target node\n  if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {\n    reusableSVGContainer = reusableSVGContainer || document.createElement('div');\n    reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';\n    var newNodes = reusableSVGContainer.firstChild.childNodes;\n    for (var i = 0; i < newNodes.length; i++) {\n      node.appendChild(newNodes[i]);\n    }\n  } else {\n    node.innerHTML = html;\n  }\n});\n\nif (ExecutionEnvironment.canUseDOM) {\n  // IE8: When updating a just created node with innerHTML only leading\n  // whitespace is removed. When updating an existing node with innerHTML\n  // whitespace in root TextNodes is also collapsed.\n  // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html\n\n  // Feature detection; only IE8 is known to behave improperly like this.\n  var testElement = document.createElement('div');\n  testElement.innerHTML = ' ';\n  if (testElement.innerHTML === '') {\n    setInnerHTML = function (node, html) {\n      // Magic theory: IE8 supposedly differentiates between added and updated\n      // nodes when processing innerHTML, innerHTML on updated nodes suffers\n      // from worse whitespace behavior. Re-adding a node like this triggers\n      // the initial and more favorable whitespace behavior.\n      // TODO: What to do on a detached node?\n      if (node.parentNode) {\n        node.parentNode.replaceChild(node, node);\n      }\n\n      // We also implement a workaround for non-visible tags disappearing into\n      // thin air on IE8, this only happens if there is no visible text\n      // in-front of the non-visible tags. Piggyback on the whitespace fix\n      // and simply check if any non-visible tags appear in the source.\n      if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {\n        // Recover leading whitespace by temporarily prepending any character.\n        // \\uFEFF has the potential advantage of being zero-width/invisible.\n        // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode\n        // in hopes that this is preserved even if \"\\uFEFF\" is transformed to\n        // the actual Unicode character (by Babel, for example).\n        // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216\n        node.innerHTML = String.fromCharCode(0xFEFF) + html;\n\n        // deleteData leaves an empty `TextNode` which offsets the index of all\n        // children. Definitely want to avoid this.\n        var textNode = node.firstChild;\n        if (textNode.data.length === 1) {\n          node.removeChild(textNode);\n        } else {\n          textNode.deleteData(0, 1);\n        }\n      } else {\n        node.innerHTML = html;\n      }\n    };\n  }\n  testElement = null;\n}\n\nmodule.exports = setInnerHTML;\n},{\"119\":119,\"147\":147,\"9\":9}],142:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setTextContent\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar setInnerHTML = _dereq_(141);\n\n/**\n * Set the textContent property of a node, ensuring that whitespace is preserved\n * even in IE8. innerText is a poor substitute for textContent and, among many\n * issues, inserts <br> instead of the literal newline chars. innerHTML behaves\n * as it should.\n *\n * @param {DOMElement} node\n * @param {string} text\n * @internal\n */\nvar setTextContent = function (node, text) {\n  if (text) {\n    var firstChild = node.firstChild;\n\n    if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {\n      firstChild.nodeValue = text;\n      return;\n    }\n  }\n  node.textContent = text;\n};\n\nif (ExecutionEnvironment.canUseDOM) {\n  if (!('textContent' in document.documentElement)) {\n    setTextContent = function (node, text) {\n      setInnerHTML(node, escapeTextContentForBrowser(text));\n    };\n  }\n}\n\nmodule.exports = setTextContent;\n},{\"121\":121,\"141\":141,\"147\":147}],143:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule shouldUpdateReactComponent\n */\n\n'use strict';\n\n/**\n * Given a `prevElement` and `nextElement`, determines if the existing\n * instance should be updated as opposed to being destroyed or replaced by a new\n * instance. Both arguments are elements. This ensures that this logic can\n * operate on stateless trees without any backing instance.\n *\n * @param {?object} prevElement\n * @param {?object} nextElement\n * @return {boolean} True if the existing instance should be updated.\n * @protected\n */\n\nfunction shouldUpdateReactComponent(prevElement, nextElement) {\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n  if (prevEmpty || nextEmpty) {\n    return prevEmpty === nextEmpty;\n  }\n\n  var prevType = typeof prevElement;\n  var nextType = typeof nextElement;\n  if (prevType === 'string' || prevType === 'number') {\n    return nextType === 'string' || nextType === 'number';\n  } else {\n    return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key;\n  }\n}\n\nmodule.exports = shouldUpdateReactComponent;\n},{}],144:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule traverseAllChildren\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\n\nvar getIteratorFn = _dereq_(130);\nvar invariant = _dereq_(161);\nvar KeyEscapeUtils = _dereq_(23);\nvar warning = _dereq_(171);\n\nvar SEPARATOR = '.';\nvar SUBSEPARATOR = ':';\n\n/**\n * TODO: Test that a single child and an array with one item have the same key\n * pattern.\n */\n\nvar didWarnAboutMaps = false;\n\n/**\n * Generate a key string that identifies a component within a set.\n *\n * @param {*} component A component that could contain a manual key.\n * @param {number} index Index that is used if a manual key is not provided.\n * @return {string}\n */\nfunction getComponentKey(component, index) {\n  // Do some typechecking here since we call this blindly. We want to ensure\n  // that we don't block potential future ES APIs.\n  if (component && typeof component === 'object' && component.key != null) {\n    // Explicit key\n    return KeyEscapeUtils.escape(component.key);\n  }\n  // Implicit key determined by the index in the set\n  return index.toString(36);\n}\n\n/**\n * @param {?*} children Children tree container.\n * @param {!string} nameSoFar Name of the key path so far.\n * @param {!function} callback Callback to invoke with each child found.\n * @param {?*} traverseContext Used to pass information throughout the traversal\n * process.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {\n  var type = typeof children;\n\n  if (type === 'undefined' || type === 'boolean') {\n    // All of the above are perceived as null.\n    children = null;\n  }\n\n  if (children === null || type === 'string' || type === 'number' || ReactElement.isValidElement(children)) {\n    callback(traverseContext, children,\n    // If it's the only child, treat the name as if it was wrapped in an array\n    // so that it's consistent if the number of children grows.\n    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);\n    return 1;\n  }\n\n  var child;\n  var nextName;\n  var subtreeCount = 0; // Count of children found in the current subtree.\n  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;\n\n  if (Array.isArray(children)) {\n    for (var i = 0; i < children.length; i++) {\n      child = children[i];\n      nextName = nextNamePrefix + getComponentKey(child, i);\n      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n    }\n  } else {\n    var iteratorFn = getIteratorFn(children);\n    if (iteratorFn) {\n      var iterator = iteratorFn.call(children);\n      var step;\n      if (iteratorFn !== children.entries) {\n        var ii = 0;\n        while (!(step = iterator.next()).done) {\n          child = step.value;\n          nextName = nextNamePrefix + getComponentKey(child, ii++);\n          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n        }\n      } else {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : void 0;\n          didWarnAboutMaps = true;\n        }\n        // Iterator will provide entry [k,v] tuples rather than values.\n        while (!(step = iterator.next()).done) {\n          var entry = step.value;\n          if (entry) {\n            child = entry[1];\n            nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);\n            subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n          }\n        }\n      }\n    } else if (type === 'object') {\n      var addendum = '';\n      if (\"development\" !== 'production') {\n        addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';\n        if (children._isReactElement) {\n          addendum = ' It looks like you\\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.';\n        }\n        if (ReactCurrentOwner.current) {\n          var name = ReactCurrentOwner.current.getName();\n          if (name) {\n            addendum += ' Check the render method of `' + name + '`.';\n          }\n        }\n      }\n      var childrenString = String(children);\n      !false ? \"development\" !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0;\n    }\n  }\n\n  return subtreeCount;\n}\n\n/**\n * Traverses children that are typically specified as `props.children`, but\n * might also be specified through attributes:\n *\n * - `traverseAllChildren(this.props.children, ...)`\n * - `traverseAllChildren(this.props.leftPanelChildren, ...)`\n *\n * The `traverseContext` is an optional argument that is passed through the\n * entire traversal. It can be used to store accumulations or anything else that\n * the callback might find relevant.\n *\n * @param {?*} children Children tree object.\n * @param {!function} callback To invoke upon traversing each child.\n * @param {?*} traverseContext Context for traversal.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildren(children, callback, traverseContext) {\n  if (children == null) {\n    return 0;\n  }\n\n  return traverseAllChildrenImpl(children, '', callback, traverseContext);\n}\n\nmodule.exports = traverseAllChildren;\n},{\"130\":130,\"139\":139,\"161\":161,\"171\":171,\"23\":23,\"36\":36,\"62\":62}],145:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule validateDOMNesting\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar validateDOMNesting = emptyFunction;\n\nif (\"development\" !== 'production') {\n  // This validation code was written based on the HTML5 parsing spec:\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  //\n  // Note: this does not catch all invalid nesting, nor does it try to (as it's\n  // not clear what practical benefit doing so provides); instead, we warn only\n  // for cases where the parser will give a parse tree differing from what React\n  // intended. For example, <b><div></div></b> is invalid but we don't warn\n  // because it still parses correctly; we do warn for other cases like nested\n  // <p> tags where the beginning of the second element implicitly closes the\n  // first, causing a confusing mess.\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#special\n  var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point\n  // TODO: Distinguish by namespace here -- for <title>, including it here\n  // errs on the side of fewer warnings\n  'foreignObject', 'desc', 'title'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope\n  var buttonScopeTags = inScopeTags.concat(['button']);\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags\n  var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];\n\n  var emptyAncestorInfo = {\n    current: null,\n\n    formTag: null,\n    aTagInScope: null,\n    buttonTagInScope: null,\n    nobrTagInScope: null,\n    pTagInButtonScope: null,\n\n    listItemTagAutoclosing: null,\n    dlItemTagAutoclosing: null\n  };\n\n  var updatedAncestorInfo = function (oldInfo, tag, instance) {\n    var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);\n    var info = { tag: tag, instance: instance };\n\n    if (inScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.aTagInScope = null;\n      ancestorInfo.buttonTagInScope = null;\n      ancestorInfo.nobrTagInScope = null;\n    }\n    if (buttonScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.pTagInButtonScope = null;\n    }\n\n    // See rules for 'li', 'dd', 'dt' start tags in\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {\n      ancestorInfo.listItemTagAutoclosing = null;\n      ancestorInfo.dlItemTagAutoclosing = null;\n    }\n\n    ancestorInfo.current = info;\n\n    if (tag === 'form') {\n      ancestorInfo.formTag = info;\n    }\n    if (tag === 'a') {\n      ancestorInfo.aTagInScope = info;\n    }\n    if (tag === 'button') {\n      ancestorInfo.buttonTagInScope = info;\n    }\n    if (tag === 'nobr') {\n      ancestorInfo.nobrTagInScope = info;\n    }\n    if (tag === 'p') {\n      ancestorInfo.pTagInButtonScope = info;\n    }\n    if (tag === 'li') {\n      ancestorInfo.listItemTagAutoclosing = info;\n    }\n    if (tag === 'dd' || tag === 'dt') {\n      ancestorInfo.dlItemTagAutoclosing = info;\n    }\n\n    return ancestorInfo;\n  };\n\n  /**\n   * Returns whether\n   */\n  var isTagValidWithParent = function (tag, parentTag) {\n    // First, let's check if we're in an unusual parsing mode...\n    switch (parentTag) {\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect\n      case 'select':\n        return tag === 'option' || tag === 'optgroup' || tag === '#text';\n      case 'optgroup':\n        return tag === 'option' || tag === '#text';\n      // Strictly speaking, seeing an <option> doesn't mean we're in a <select>\n      // but\n      case 'option':\n        return tag === '#text';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption\n      // No special behavior since these rules fall back to \"in body\" mode for\n      // all except special table nodes which cause bad parsing behavior anyway.\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr\n      case 'tr':\n        return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody\n      case 'tbody':\n      case 'thead':\n      case 'tfoot':\n        return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup\n      case 'colgroup':\n        return tag === 'col' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable\n      case 'table':\n        return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead\n      case 'head':\n        return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element\n      case 'html':\n        return tag === 'head' || tag === 'body';\n      case '#document':\n        return tag === 'html';\n    }\n\n    // Probably in the \"in body\" parsing mode, so we outlaw only tag combos\n    // where the parsing rules cause implicit opens or closes to be added.\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    switch (tag) {\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';\n\n      case 'rp':\n      case 'rt':\n        return impliedEndTags.indexOf(parentTag) === -1;\n\n      case 'body':\n      case 'caption':\n      case 'col':\n      case 'colgroup':\n      case 'frame':\n      case 'head':\n      case 'html':\n      case 'tbody':\n      case 'td':\n      case 'tfoot':\n      case 'th':\n      case 'thead':\n      case 'tr':\n        // These tags are only valid with a few parents that have special child\n        // parsing rules -- if we're down here, then none of those matched and\n        // so we allow it only if we don't know what the parent is, as all other\n        // cases are invalid.\n        return parentTag == null;\n    }\n\n    return true;\n  };\n\n  /**\n   * Returns whether\n   */\n  var findInvalidAncestorForTag = function (tag, ancestorInfo) {\n    switch (tag) {\n      case 'address':\n      case 'article':\n      case 'aside':\n      case 'blockquote':\n      case 'center':\n      case 'details':\n      case 'dialog':\n      case 'dir':\n      case 'div':\n      case 'dl':\n      case 'fieldset':\n      case 'figcaption':\n      case 'figure':\n      case 'footer':\n      case 'header':\n      case 'hgroup':\n      case 'main':\n      case 'menu':\n      case 'nav':\n      case 'ol':\n      case 'p':\n      case 'section':\n      case 'summary':\n      case 'ul':\n\n      case 'pre':\n      case 'listing':\n\n      case 'table':\n\n      case 'hr':\n\n      case 'xmp':\n\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return ancestorInfo.pTagInButtonScope;\n\n      case 'form':\n        return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;\n\n      case 'li':\n        return ancestorInfo.listItemTagAutoclosing;\n\n      case 'dd':\n      case 'dt':\n        return ancestorInfo.dlItemTagAutoclosing;\n\n      case 'button':\n        return ancestorInfo.buttonTagInScope;\n\n      case 'a':\n        // Spec says something about storing a list of markers, but it sounds\n        // equivalent to this check.\n        return ancestorInfo.aTagInScope;\n\n      case 'nobr':\n        return ancestorInfo.nobrTagInScope;\n    }\n\n    return null;\n  };\n\n  /**\n   * Given a ReactCompositeComponent instance, return a list of its recursive\n   * owners, starting at the root and ending with the instance itself.\n   */\n  var findOwnerStack = function (instance) {\n    if (!instance) {\n      return [];\n    }\n\n    var stack = [];\n    do {\n      stack.push(instance);\n    } while (instance = instance._currentElement._owner);\n    stack.reverse();\n    return stack;\n  };\n\n  var didWarn = {};\n\n  validateDOMNesting = function (childTag, childInstance, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n\n    var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;\n    var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);\n    var problematic = invalidParent || invalidAncestor;\n\n    if (problematic) {\n      var ancestorTag = problematic.tag;\n      var ancestorInstance = problematic.instance;\n\n      var childOwner = childInstance && childInstance._currentElement._owner;\n      var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;\n\n      var childOwners = findOwnerStack(childOwner);\n      var ancestorOwners = findOwnerStack(ancestorOwner);\n\n      var minStackLen = Math.min(childOwners.length, ancestorOwners.length);\n      var i;\n\n      var deepestCommon = -1;\n      for (i = 0; i < minStackLen; i++) {\n        if (childOwners[i] === ancestorOwners[i]) {\n          deepestCommon = i;\n        } else {\n          break;\n        }\n      }\n\n      var UNKNOWN = '(unknown)';\n      var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ownerInfo = [].concat(\n      // If the parent and child instances have a common owner ancestor, start\n      // with that -- otherwise we just start with the parent's owners.\n      deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,\n      // If we're warning about an invalid (non-parent) ancestry, add '...'\n      invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');\n\n      var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;\n      if (didWarn[warnKey]) {\n        return;\n      }\n      didWarn[warnKey] = true;\n\n      var tagDisplayName = childTag;\n      if (childTag !== '#text') {\n        tagDisplayName = '<' + childTag + '>';\n      }\n\n      if (invalidParent) {\n        var info = '';\n        if (ancestorTag === 'table' && childTag === 'tr') {\n          info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';\n        }\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>. ' + 'See %s.%s', tagDisplayName, ancestorTag, ownerInfo, info) : void 0;\n      } else {\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;\n      }\n    }\n  };\n\n  validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;\n\n  // For testing\n  validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n    return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);\n  };\n}\n\nmodule.exports = validateDOMNesting;\n},{\"153\":153,\"171\":171,\"172\":172}],146:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * @typechecks\n */\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Upstream version of event listener. Does not take into account specific\n * nature of platform.\n */\nvar EventListener = {\n  /**\n   * Listen to DOM events during the bubble phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  listen: function listen(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, false);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, false);\n        }\n      };\n    } else if (target.attachEvent) {\n      target.attachEvent('on' + eventType, callback);\n      return {\n        remove: function remove() {\n          target.detachEvent('on' + eventType, callback);\n        }\n      };\n    }\n  },\n\n  /**\n   * Listen to DOM events during the capture phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  capture: function capture(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, true);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, true);\n        }\n      };\n    } else {\n      if (\"development\" !== 'production') {\n        console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');\n      }\n      return {\n        remove: emptyFunction\n      };\n    }\n  },\n\n  registerDefault: function registerDefault() {}\n};\n\nmodule.exports = EventListener;\n},{\"153\":153}],147:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);\n\n/**\n * Simple, lightweight module assisting with the detection and context of\n * Worker. Helps avoid circular dependencies and allows code to reason about\n * whether or not they are in a Worker, even if they never include the main\n * `ReactWorker` dependency.\n */\nvar ExecutionEnvironment = {\n\n  canUseDOM: canUseDOM,\n\n  canUseWorkers: typeof Worker !== 'undefined',\n\n  canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),\n\n  canUseViewport: canUseDOM && !!window.screen,\n\n  isInWorker: !canUseDOM // For now, this is true - might change in the future.\n\n};\n\nmodule.exports = ExecutionEnvironment;\n},{}],148:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _hyphenPattern = /-(.)/g;\n\n/**\n * Camelcases a hyphenated string, for example:\n *\n *   > camelize('background-color')\n *   < \"backgroundColor\"\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelize(string) {\n  return string.replace(_hyphenPattern, function (_, character) {\n    return character.toUpperCase();\n  });\n}\n\nmodule.exports = camelize;\n},{}],149:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar camelize = _dereq_(148);\n\nvar msPattern = /^-ms-/;\n\n/**\n * Camelcases a hyphenated CSS property name, for example:\n *\n *   > camelizeStyleName('background-color')\n *   < \"backgroundColor\"\n *   > camelizeStyleName('-moz-transition')\n *   < \"MozTransition\"\n *   > camelizeStyleName('-ms-transition')\n *   < \"msTransition\"\n *\n * As Andi Smith suggests\n * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix\n * is converted to lowercase `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelizeStyleName(string) {\n  return camelize(string.replace(msPattern, 'ms-'));\n}\n\nmodule.exports = camelizeStyleName;\n},{\"148\":148}],150:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nvar isTextNode = _dereq_(163);\n\n/*eslint-disable no-bitwise */\n\n/**\n * Checks if a given DOM node contains or is another DOM node.\n */\nfunction containsNode(outerNode, innerNode) {\n  if (!outerNode || !innerNode) {\n    return false;\n  } else if (outerNode === innerNode) {\n    return true;\n  } else if (isTextNode(outerNode)) {\n    return false;\n  } else if (isTextNode(innerNode)) {\n    return containsNode(outerNode, innerNode.parentNode);\n  } else if ('contains' in outerNode) {\n    return outerNode.contains(innerNode);\n  } else if (outerNode.compareDocumentPosition) {\n    return !!(outerNode.compareDocumentPosition(innerNode) & 16);\n  } else {\n    return false;\n  }\n}\n\nmodule.exports = containsNode;\n},{\"163\":163}],151:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar invariant = _dereq_(161);\n\n/**\n * Convert array-like objects to arrays.\n *\n * This API assumes the caller knows the contents of the data type. For less\n * well defined inputs use createArrayFromMixed.\n *\n * @param {object|function|filelist} obj\n * @return {array}\n */\nfunction toArray(obj) {\n  var length = obj.length;\n\n  // Some browsers builtin objects can report typeof 'function' (e.g. NodeList\n  // in old versions of Safari).\n  !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? \"development\" !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0;\n\n  !(typeof length === 'number') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0;\n\n  !(length === 0 || length - 1 in obj) ? \"development\" !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0;\n\n  !(typeof obj.callee !== 'function') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object can\\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0;\n\n  // Old IE doesn't give collections access to hasOwnProperty. Assume inputs\n  // without method will throw during the slice call and skip straight to the\n  // fallback.\n  if (obj.hasOwnProperty) {\n    try {\n      return Array.prototype.slice.call(obj);\n    } catch (e) {\n      // IE < 9 does not support Array#slice on collections objects\n    }\n  }\n\n  // Fall back to copying key by key. This assumes all keys have a value,\n  // so will not preserve sparsely populated inputs.\n  var ret = Array(length);\n  for (var ii = 0; ii < length; ii++) {\n    ret[ii] = obj[ii];\n  }\n  return ret;\n}\n\n/**\n * Perform a heuristic test to determine if an object is \"array-like\".\n *\n *   A monk asked Joshu, a Zen master, \"Has a dog Buddha nature?\"\n *   Joshu replied: \"Mu.\"\n *\n * This function determines if its argument has \"array nature\": it returns\n * true if the argument is an actual array, an `arguments' object, or an\n * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).\n *\n * It will return false for other array-like objects like Filelist.\n *\n * @param {*} obj\n * @return {boolean}\n */\nfunction hasArrayNature(obj) {\n  return(\n    // not null/false\n    !!obj && (\n    // arrays are objects, NodeLists are functions in Safari\n    typeof obj == 'object' || typeof obj == 'function') &&\n    // quacks like an array\n    'length' in obj &&\n    // not window\n    !('setInterval' in obj) &&\n    // no DOM node should be considered an array-like\n    // a 'select' element has 'length' and 'item' properties on IE8\n    typeof obj.nodeType != 'number' && (\n    // a real array\n    Array.isArray(obj) ||\n    // arguments\n    'callee' in obj ||\n    // HTMLCollection/NodeList\n    'item' in obj)\n  );\n}\n\n/**\n * Ensure that the argument is an array by wrapping it in an array if it is not.\n * Creates a copy of the argument if it is already an array.\n *\n * This is mostly useful idiomatically:\n *\n *   var createArrayFromMixed = require('createArrayFromMixed');\n *\n *   function takesOneOrMoreThings(things) {\n *     things = createArrayFromMixed(things);\n *     ...\n *   }\n *\n * This allows you to treat `things' as an array, but accept scalars in the API.\n *\n * If you need to convert an array-like object, like `arguments`, into an array\n * use toArray instead.\n *\n * @param {*} obj\n * @return {array}\n */\nfunction createArrayFromMixed(obj) {\n  if (!hasArrayNature(obj)) {\n    return [obj];\n  } else if (Array.isArray(obj)) {\n    return obj.slice();\n  } else {\n    return toArray(obj);\n  }\n}\n\nmodule.exports = createArrayFromMixed;\n},{\"161\":161}],152:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/*eslint-disable fb-www/unsafe-html*/\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createArrayFromMixed = _dereq_(151);\nvar getMarkupWrap = _dereq_(157);\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to render all markup.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Pattern used by `getNodeName`.\n */\nvar nodeNamePattern = /^\\s*<(\\w+)/;\n\n/**\n * Extracts the `nodeName` of the first element in a string of markup.\n *\n * @param {string} markup String of markup.\n * @return {?string} Node name of the supplied markup.\n */\nfunction getNodeName(markup) {\n  var nodeNameMatch = markup.match(nodeNamePattern);\n  return nodeNameMatch && nodeNameMatch[1].toLowerCase();\n}\n\n/**\n * Creates an array containing the nodes rendered from the supplied markup. The\n * optionally supplied `handleScript` function will be invoked once for each\n * <script> element that is rendered. If no `handleScript` function is supplied,\n * an exception is thrown if any <script> elements are rendered.\n *\n * @param {string} markup A string of valid HTML markup.\n * @param {?function} handleScript Invoked once for each rendered <script>.\n * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.\n */\nfunction createNodesFromMarkup(markup, handleScript) {\n  var node = dummyNode;\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;\n  var nodeName = getNodeName(markup);\n\n  var wrap = nodeName && getMarkupWrap(nodeName);\n  if (wrap) {\n    node.innerHTML = wrap[1] + markup + wrap[2];\n\n    var wrapDepth = wrap[0];\n    while (wrapDepth--) {\n      node = node.lastChild;\n    }\n  } else {\n    node.innerHTML = markup;\n  }\n\n  var scripts = node.getElementsByTagName('script');\n  if (scripts.length) {\n    !handleScript ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;\n    createArrayFromMixed(scripts).forEach(handleScript);\n  }\n\n  var nodes = Array.from(node.childNodes);\n  while (node.lastChild) {\n    node.removeChild(node.lastChild);\n  }\n  return nodes;\n}\n\nmodule.exports = createNodesFromMarkup;\n},{\"147\":147,\"151\":151,\"157\":157,\"161\":161}],153:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nfunction makeEmptyFunction(arg) {\n  return function () {\n    return arg;\n  };\n}\n\n/**\n * This function accepts and discards inputs; it has no side effects. This is\n * primarily useful idiomatically for overridable function endpoints which\n * always need to be callable, since JS lacks a null-call idiom ala Cocoa.\n */\nvar emptyFunction = function emptyFunction() {};\n\nemptyFunction.thatReturns = makeEmptyFunction;\nemptyFunction.thatReturnsFalse = makeEmptyFunction(false);\nemptyFunction.thatReturnsTrue = makeEmptyFunction(true);\nemptyFunction.thatReturnsNull = makeEmptyFunction(null);\nemptyFunction.thatReturnsThis = function () {\n  return this;\n};\nemptyFunction.thatReturnsArgument = function (arg) {\n  return arg;\n};\n\nmodule.exports = emptyFunction;\n},{}],154:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyObject = {};\n\nif (\"development\" !== 'production') {\n  Object.freeze(emptyObject);\n}\n\nmodule.exports = emptyObject;\n},{}],155:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * @param {DOMElement} node input/textarea to focus\n */\n\nfunction focusNode(node) {\n  // IE8 can throw \"Can't move focus to the control because it is invisible,\n  // not enabled, or of a type that does not accept the focus.\" for all kinds of\n  // reasons that are too expensive and fragile to test.\n  try {\n    node.focus();\n  } catch (e) {}\n}\n\nmodule.exports = focusNode;\n},{}],156:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/* eslint-disable fb-www/typeof-undefined */\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n */\nfunction getActiveElement() /*?DOMElement*/{\n  if (typeof document === 'undefined') {\n    return null;\n  }\n  try {\n    return document.activeElement || document.body;\n  } catch (e) {\n    return document.body;\n  }\n}\n\nmodule.exports = getActiveElement;\n},{}],157:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/*eslint-disable fb-www/unsafe-html */\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to detect which wraps are necessary.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Some browsers cannot use `innerHTML` to render certain elements standalone,\n * so we wrap them, render the wrapped nodes, then extract the desired node.\n *\n * In IE8, certain elements cannot render alone, so wrap all elements ('*').\n */\n\nvar shouldWrap = {};\n\nvar selectWrap = [1, '<select multiple=\"true\">', '</select>'];\nvar tableWrap = [1, '<table>', '</table>'];\nvar trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];\n\nvar svgWrap = [1, '<svg xmlns=\"http://www.w3.org/2000/svg\">', '</svg>'];\n\nvar markupWrap = {\n  '*': [1, '?<div>', '</div>'],\n\n  'area': [1, '<map>', '</map>'],\n  'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],\n  'legend': [1, '<fieldset>', '</fieldset>'],\n  'param': [1, '<object>', '</object>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n\n  'optgroup': selectWrap,\n  'option': selectWrap,\n\n  'caption': tableWrap,\n  'colgroup': tableWrap,\n  'tbody': tableWrap,\n  'tfoot': tableWrap,\n  'thead': tableWrap,\n\n  'td': trWrap,\n  'th': trWrap\n};\n\n// Initialize the SVG elements since we know they'll always need to be wrapped\n// consistently. If they are created inside a <div> they will be initialized in\n// the wrong namespace (and will not display).\nvar svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];\nsvgElements.forEach(function (nodeName) {\n  markupWrap[nodeName] = svgWrap;\n  shouldWrap[nodeName] = true;\n});\n\n/**\n * Gets the markup wrap configuration for the supplied `nodeName`.\n *\n * NOTE: This lazily detects which wraps are necessary for the current browser.\n *\n * @param {string} nodeName Lowercase `nodeName`.\n * @return {?array} Markup wrap configuration, if applicable.\n */\nfunction getMarkupWrap(nodeName) {\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;\n  if (!markupWrap.hasOwnProperty(nodeName)) {\n    nodeName = '*';\n  }\n  if (!shouldWrap.hasOwnProperty(nodeName)) {\n    if (nodeName === '*') {\n      dummyNode.innerHTML = '<link />';\n    } else {\n      dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';\n    }\n    shouldWrap[nodeName] = !dummyNode.firstChild;\n  }\n  return shouldWrap[nodeName] ? markupWrap[nodeName] : null;\n}\n\nmodule.exports = getMarkupWrap;\n},{\"147\":147,\"161\":161}],158:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\n/**\n * Gets the scroll position of the supplied element or window.\n *\n * The return values are unbounded, unlike `getScrollPosition`. This means they\n * may be negative or exceed the element boundaries (which is possible using\n * inertial scrolling).\n *\n * @param {DOMWindow|DOMElement} scrollable\n * @return {object} Map with `x` and `y` keys.\n */\n\nfunction getUnboundedScrollPosition(scrollable) {\n  if (scrollable === window) {\n    return {\n      x: window.pageXOffset || document.documentElement.scrollLeft,\n      y: window.pageYOffset || document.documentElement.scrollTop\n    };\n  }\n  return {\n    x: scrollable.scrollLeft,\n    y: scrollable.scrollTop\n  };\n}\n\nmodule.exports = getUnboundedScrollPosition;\n},{}],159:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _uppercasePattern = /([A-Z])/g;\n\n/**\n * Hyphenates a camelcased string, for example:\n *\n *   > hyphenate('backgroundColor')\n *   < \"background-color\"\n *\n * For CSS style names, use `hyphenateStyleName` instead which works properly\n * with all vendor prefixes, including `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenate(string) {\n  return string.replace(_uppercasePattern, '-$1').toLowerCase();\n}\n\nmodule.exports = hyphenate;\n},{}],160:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar hyphenate = _dereq_(159);\n\nvar msPattern = /^ms-/;\n\n/**\n * Hyphenates a camelcased CSS property name, for example:\n *\n *   > hyphenateStyleName('backgroundColor')\n *   < \"background-color\"\n *   > hyphenateStyleName('MozTransition')\n *   < \"-moz-transition\"\n *   > hyphenateStyleName('msTransition')\n *   < \"-ms-transition\"\n *\n * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix\n * is converted to `-ms-`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenateStyleName(string) {\n  return hyphenate(string).replace(msPattern, '-ms-');\n}\n\nmodule.exports = hyphenateStyleName;\n},{\"159\":159}],161:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * Use invariant() to assert state which your program assumes to be true.\n *\n * Provide sprintf-style format (only %s is supported) and arguments\n * to provide information about what broke and what you were\n * expecting.\n *\n * The invariant message will be stripped in production, but the invariant\n * will remain to ensure logic does not differ in production.\n */\n\nfunction invariant(condition, format, a, b, c, d, e, f) {\n  if (\"development\" !== 'production') {\n    if (format === undefined) {\n      throw new Error('invariant requires an error message argument');\n    }\n  }\n\n  if (!condition) {\n    var error;\n    if (format === undefined) {\n      error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');\n    } else {\n      var args = [a, b, c, d, e, f];\n      var argIndex = 0;\n      error = new Error(format.replace(/%s/g, function () {\n        return args[argIndex++];\n      }));\n      error.name = 'Invariant Violation';\n    }\n\n    error.framesToPop = 1; // we don't care about invariant's own frame\n    throw error;\n  }\n}\n\nmodule.exports = invariant;\n},{}],162:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM node.\n */\nfunction isNode(object) {\n  return !!(object && (typeof Node === 'function' ? object instanceof Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));\n}\n\nmodule.exports = isNode;\n},{}],163:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar isNode = _dereq_(162);\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM text node.\n */\nfunction isTextNode(object) {\n  return isNode(object) && object.nodeType == 3;\n}\n\nmodule.exports = isTextNode;\n},{\"162\":162}],164:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks static-only\n */\n\n'use strict';\n\nvar invariant = _dereq_(161);\n\n/**\n * Constructs an enumeration with keys equal to their value.\n *\n * For example:\n *\n *   var COLORS = keyMirror({blue: null, red: null});\n *   var myColor = COLORS.blue;\n *   var isColorValid = !!COLORS[myColor];\n *\n * The last line could not be performed if the values of the generated enum were\n * not equal to their keys.\n *\n *   Input:  {key1: val1, key2: val2}\n *   Output: {key1: key1, key2: key2}\n *\n * @param {object} obj\n * @return {object}\n */\nvar keyMirror = function keyMirror(obj) {\n  var ret = {};\n  var key;\n  !(obj instanceof Object && !Array.isArray(obj)) ? \"development\" !== 'production' ? invariant(false, 'keyMirror(...): Argument must be an object.') : invariant(false) : void 0;\n  for (key in obj) {\n    if (!obj.hasOwnProperty(key)) {\n      continue;\n    }\n    ret[key] = key;\n  }\n  return ret;\n};\n\nmodule.exports = keyMirror;\n},{\"161\":161}],165:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/**\n * Allows extraction of a minified key. Let's the build system minify keys\n * without losing the ability to dynamically use key strings as values\n * themselves. Pass in an object with a single key/val pair and it will return\n * you the string key of that single record. Suppose you want to grab the\n * value for a key 'className' inside of an object. Key/val minification may\n * have aliased that key to be 'xa12'. keyOf({className: null}) will return\n * 'xa12' in that case. Resolve keys you want to use once at startup time, then\n * reuse those resolutions.\n */\nvar keyOf = function keyOf(oneKeyObj) {\n  var key;\n  for (key in oneKeyObj) {\n    if (!oneKeyObj.hasOwnProperty(key)) {\n      continue;\n    }\n    return key;\n  }\n  return null;\n};\n\nmodule.exports = keyOf;\n},{}],166:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Executes the provided `callback` once for each enumerable own property in the\n * object and constructs a new object from the results. The `callback` is\n * invoked with three arguments:\n *\n *  - the property value\n *  - the property name\n *  - the object being traversed\n *\n * Properties that are added after the call to `mapObject` will not be visited\n * by `callback`. If the values of existing properties are changed, the value\n * passed to `callback` will be the value at the time `mapObject` visits them.\n * Properties that are deleted before being visited are not visited.\n *\n * @grep function objectMap()\n * @grep function objMap()\n *\n * @param {?object} object\n * @param {function} callback\n * @param {*} context\n * @return {?object}\n */\nfunction mapObject(object, callback, context) {\n  if (!object) {\n    return null;\n  }\n  var result = {};\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result[name] = callback.call(context, object[name], name, object);\n    }\n  }\n  return result;\n}\n\nmodule.exports = mapObject;\n},{}],167:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n * @typechecks static-only\n */\n\n'use strict';\n\n/**\n * Memoizes the return value of a function that accepts one string argument.\n */\n\nfunction memoizeStringOnly(callback) {\n  var cache = {};\n  return function (string) {\n    if (!cache.hasOwnProperty(string)) {\n      cache[string] = callback.call(this, string);\n    }\n    return cache[string];\n  };\n}\n\nmodule.exports = memoizeStringOnly;\n},{}],168:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performance;\n\nif (ExecutionEnvironment.canUseDOM) {\n  performance = window.performance || window.msPerformance || window.webkitPerformance;\n}\n\nmodule.exports = performance || {};\n},{\"147\":147}],169:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar performance = _dereq_(168);\n\nvar performanceNow;\n\n/**\n * Detect if we can use `window.performance.now()` and gracefully fallback to\n * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now\n * because of Facebook's testing infrastructure.\n */\nif (performance.now) {\n  performanceNow = function performanceNow() {\n    return performance.now();\n  };\n} else {\n  performanceNow = function performanceNow() {\n    return Date.now();\n  };\n}\n\nmodule.exports = performanceNow;\n},{\"168\":168}],170:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n * \n */\n\n/*eslint-disable no-self-compare */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n\n/**\n * Performs equality by iterating through keys on an object and returning false\n * when any key has values which are not strictly equal between the arguments.\n * Returns true when the values of all keys are strictly equal.\n */\nfunction shallowEqual(objA, objB) {\n  if (is(objA, objB)) {\n    return true;\n  }\n\n  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n    return false;\n  }\n\n  var keysA = Object.keys(objA);\n  var keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (var i = 0; i < keysA.length; i++) {\n    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nmodule.exports = shallowEqual;\n},{}],171:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-2015, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Similar to invariant but only logs a warning if the condition is not met.\n * This can be used to log issues in development environments in critical\n * paths. Removing the logging code for production environments will keep the\n * same logic and follow the same code paths.\n */\n\nvar warning = emptyFunction;\n\nif (\"development\" !== 'production') {\n  warning = function warning(condition, format) {\n    for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n      args[_key - 2] = arguments[_key];\n    }\n\n    if (format === undefined) {\n      throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');\n    }\n\n    if (format.indexOf('Failed Composite propType: ') === 0) {\n      return; // Ignore CompositeComponent proptype check.\n    }\n\n    if (!condition) {\n      var argIndex = 0;\n      var message = 'Warning: ' + format.replace(/%s/g, function () {\n        return args[argIndex++];\n      });\n      if (typeof console !== 'undefined') {\n        console.error(message);\n      }\n      try {\n        // --- Welcome to debugging React ---\n        // This error was thrown as a convenience so that you can use this stack\n        // to find the callsite that caused this warning to fire.\n        throw new Error(message);\n      } catch (x) {}\n    }\n  };\n}\n\nmodule.exports = warning;\n},{\"153\":153}],172:[function(_dereq_,module,exports){\n'use strict';\n/* eslint-disable no-unused-vars */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc');  // eslint-disable-line\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (e) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (Object.getOwnPropertySymbols) {\n\t\t\tsymbols = Object.getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n\n},{}]},{},[93])(93)\n});"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/.babelrc",
    "content": "{\n  \"presets\": [ \"es2015\", \"stage-0\", \"react\"],\n\n  /* if you want to use babel runtime, uncomment the following line */\n  // \"plugins\": [\"transform-runtime\"],\n\n  \"plugins\": [\"transform-decorators-legacy\"],\n\n  \"env\": {\n    \"build\": {\n      \"optional\": [\"optimisation\", \"minification\"]\n    }\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/.eslintignore",
    "content": "node_modules/**\n**/*.css\n**/*.html\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/.eslintrc",
    "content": "{\n  \"env\": {\n    \"node\": true\n  },\n  ecmaFeatures: {\n    jsx: true\n  },\n  \"globals\": {\n  },\n  \"plugins\": [\n  ],\n  \"extends\": \"eslint-config-airbnb\",\n  \"rules\": {\n    \"comma-dangle\": 0,\n    \"no-console\": 0,\n    \"id-length\": 0,\n    \"react/prop-types\": 0\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/.gitignore",
    "content": "node_modules\nbuild/\nnpm-debug.log\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/.jshintignore",
    "content": "node_modules\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/.jshintrc",
    "content": "{\n  \"node\": true,\n\n  \"curly\": true,\n  \"latedef\": true,\n  \"quotmark\": true,\n  \"undef\": true,\n  \"unused\": true,\n  \"trailing\": true\n}\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/app/index.html",
    "content": "<html>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"main.css\">\n  <title>React-Babel-Webpack Boileplate</title>\n  <body>\n    <script type=\"text/javascript\" src=\"bundle.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/app/main.css",
    "content": ""
  },
  {
    "path": "30-jstraining/demos/mobx-demo/app/main.jsx",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { observer } from 'mobx-react';\n\nimport Store from './store';\n\n@observer\nclass App extends React.Component {\n  render() {\n    return (\n      <div className=\"index\">\n        <p>{this.props.store.decorated}</p>\n        <input defaultValue={this.props.store.name} onChange={(event) => this.props.store.name = event.currentTarget.value}\n        />\n      </div>\n    );\n  }\n}\n\nconst store = new Store();\n\nReactDOM.render(\n  <App store={store} />,\n  document.body.appendChild(document.createElement('div'))\n);\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/app/store.js",
    "content": "import { observable, computed } from 'mobx';\n\nclass Store {\n  @observable name = 'Bartek';\n  @computed get decorated() {\n    return `${this.name} is awesome!`;\n  }\n}\n\nexport default Store;\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/package.json",
    "content": "{\n  \"name\": \"mobx-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app/main.jsx\",\n  \"scripts\": {\n    \"lint\": \"eslint 'app/**/*.@(js|jsx)'\",\n    \"lint:msg\": \"validate-commit-msg\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"build\": \"webpack\",\n    \"start\": \"webpack-dev-server --devtool eval --progress --hot --content-base app\",\n    \"deploy\": \"NODE_ENV=production webpack -p --config webpack.production.config.js\",\n    \"deploy-windows\": \"SET NODE_ENV=production & webpack -p --config webpack.production.config.js\",\n    \"validate\": \"npm ls\",\n    \"commit\": \"git cz\",\n    \"changelog\": \"conventional-changelog -p angular -i CHANGELOG.md -s -r 1\"\n  },\n  \"dependencies\": {\n    \"babel-plugin-transform-decorators-legacy\": \"^1.3.4\",\n    \"babel-runtime\": \"6.x\",\n    \"mobx\": \"^2.6.0\",\n    \"mobx-react\": \"^3.5.8\",\n    \"react\": \"15.x\",\n    \"react-dom\": \"15.x\"\n  },\n  \"devDependencies\": {\n    \"babel-core\": \"6.x\",\n    \"babel-eslint\": \"6.x\",\n    \"babel-loader\": \"6.x\",\n    \"babel-plugin-transform-runtime\": \"6.x\",\n    \"babel-preset-es2015\": \"6.x\",\n    \"babel-preset-react\": \"6.x\",\n    \"babel-preset-stage-0\": \"6.x\",\n    \"commitizen\": \"^2.5.0\",\n    \"conventional-changelog-cli\": \"1.x\",\n    \"copy-webpack-plugin\": \"latest\",\n    \"css-loader\": \"~0.23.0\",\n    \"cz-conventional-changelog\": \"^1.1.5\",\n    \"eslint\": \"latest\",\n    \"eslint-config-airbnb\": \"latest\",\n    \"eslint-plugin-import\": \"^1.9.2\",\n    \"eslint-plugin-jsx-a11y\": \"latest\",\n    \"eslint-plugin-react\": \"latest\",\n    \"ghooks\": \"^1.0.3\",\n    \"open-browser-webpack-plugin\": \"0.0.2\",\n    \"style-loader\": \"~0.13.0\",\n    \"validate-commit-msg\": \"2.x\",\n    \"webpack\": \"latest\",\n    \"webpack-dev-server\": \"latest\"\n  },\n  \"keywords\": [\n    \"es6\",\n    \"web app\",\n    \"boilerplate\"\n  ],\n  \"author\": \"Ruan Yifeng\",\n  \"license\": \"MIT\",\n  \"config\": {\n    \"ghooks\": {\n      \"pre-commit\": \"npm run lint\",\n      \"commit-msg\": \"npm run lint:msg\"\n    },\n    \"validate-commit-msg\": {\n      \"types\": [\n        \"feat\",\n        \"fix\",\n        \"docs\",\n        \"style\",\n        \"refactor\",\n        \"perf\",\n        \"test\",\n        \"chore\",\n        \"revert\"\n      ],\n      \"warnOnFail\": false,\n      \"maxSubjectLength\": 100\n    },\n    \"commitizen\": {\n      \"path\": \"node_modules/cz-conventional-changelog\"\n    }\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/webpack.config.js",
    "content": "var webpack = require('webpack');\nvar path = require('path');\nvar OpenBrowserPlugin = require('open-browser-webpack-plugin');\n\nmodule.exports = {\n  devServer: {\n    historyApiFallback: true,\n    hot: true,\n    inline: true,\n    progress: true,\n    contentBase: './app',\n    port: 8080\n  },\n  entry: [\n    'webpack/hot/dev-server',\n    'webpack-dev-server/client?http://localhost:8080',\n    path.resolve(__dirname, 'app/main.jsx')\n  ],\n  output: {\n    path: __dirname + '/build',\n    publicPath: '/',\n    filename: './bundle.js'\n  },\n  module: {\n    loaders:[\n      { test: /\\.css$/, include: path.resolve(__dirname, 'app'), loader: 'style-loader!css-loader' },\n      { test: /\\.js[x]?$/, include: path.resolve(__dirname, 'app'), exclude: /node_modules/, loader: 'babel-loader' },\n    ]\n  },\n  resolve: {\n    extensions: ['', '.js', '.jsx'],\n  },\n  plugins: [\n    new webpack.HotModuleReplacementPlugin(),\n    new OpenBrowserPlugin({ url: 'http://localhost:8080' })\n  ]\n};\n"
  },
  {
    "path": "30-jstraining/demos/mobx-demo/webpack.production.config.js",
    "content": "var webpack = require('webpack');\nvar path = require('path');\nvar uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;\nvar CopyWebpackPlugin = require('copy-webpack-plugin');\n\nmodule.exports = {\n  devtool: 'cheap-source-map',\n  entry: [\n    path.resolve(__dirname, 'app/main.jsx'),\n  ],\n  output: {\n    path: __dirname + '/build',\n    publicPath: '/',\n    filename: './bundle.js'\n  },\n  module: {\n    loaders:[\n      { test: /\\.css$/, include: path.resolve(__dirname, 'app'), loader: 'style-loader!css-loader' },\n      { test: /\\.js[x]?$/, include: path.resolve(__dirname, 'app'), exclude: /node_modules/, loader: 'babel-loader' },\n    ]\n  },\n  resolve: {\n    extensions: ['', '.js', '.jsx'],\n  },\n  plugins: [\n    new webpack.optimize.DedupePlugin(),\n    new uglifyJsPlugin({\n      compress: {\n        warnings: false\n      }\n    }),\n    new CopyWebpackPlugin([\n      { from: './app/index.html', to: 'index.html' },\n      { from: './app/main.css', to: 'main.css' }\n    ]),\n  ]\n};\n"
  },
  {
    "path": "30-jstraining/demos/mocha-demo/add.js",
    "content": "function add(x, y) {\n  return x + y;\n}\n\nmodule.exports = add;\n"
  },
  {
    "path": "30-jstraining/demos/mocha-demo/package.json",
    "content": "{\n  \"name\": \"mocha-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"chai\": \"^3.5.0\",\n    \"mocha\": \"^3.1.2\"\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/nightmare-demo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\"></div>\n    <script type=\"text/babel\">\n  class MyTitle extends React.Component {\n    constructor(...args) {\n      super(...args);\n      this.state = {\n        text: 'World'\n      };\n    }\n\n    handleClick() {\n      this.setState({\n        text: 'Clicked'\n      });\n    }\n\n    render() {\n      return <h1\n        onClick={this.handleClick.bind(this)}\n        style={{color: 'red'}}\n      >\n        {'Hello ' + this.state.text}\n      </h1>;\n    }\n  };\n\n  ReactDOM.render(\n    <MyTitle/>,\n    document.getElementById('example')\n  );\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/nightmare-demo/package.json",
    "content": "{\n  \"name\": \"nightmare-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"babel.min.js\",\n  \"scripts\": {\n    \"test\": \"mocha -t 15000 test.js\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"chai\": \"^3.5.0\",\n    \"http-server\": \"^0.9.0\",\n    \"mocha\": \"^3.1.2\",\n    \"nightmare\": \"^2.8.1\"\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/nightmare-demo/react-dom.js",
    "content": "/**\n * ReactDOM v15.2.1\n *\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js\n;(function(f) {\n  // CommonJS\n  if (typeof exports === \"object\" && typeof module !== \"undefined\") {\n    module.exports = f(require('react'));\n\n  // RequireJS\n  } else if (typeof define === \"function\" && define.amd) {\n    define(['react'], f);\n\n  // <script>\n  } else {\n    var g;\n    if (typeof window !== \"undefined\") {\n      g = window;\n    } else if (typeof global !== \"undefined\") {\n      g = global;\n    } else if (typeof self !== \"undefined\") {\n      g = self;\n    } else {\n      // works providing we're not in \"use strict\";\n      // needed for Java 8 Nashorn\n      // see https://github.com/facebook/react/issues/3037\n      g = this;\n    }\n    g.ReactDOM = f(g.React);\n  }\n\n})(function(React) {\n  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n});\n"
  },
  {
    "path": "30-jstraining/demos/nightmare-demo/react.js",
    "content": " /**\n  * React v15.2.1\n  */\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule AutoFocusUtils\n */\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar focusNode = _dereq_(155);\n\nvar AutoFocusUtils = {\n  focusDOMComponent: function () {\n    focusNode(ReactDOMComponentTree.getNodeFromInstance(this));\n  }\n};\n\nmodule.exports = AutoFocusUtils;\n},{\"155\":155,\"41\":41}],2:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule BeforeInputEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar FallbackCompositionState = _dereq_(21);\nvar SyntheticCompositionEvent = _dereq_(102);\nvar SyntheticInputEvent = _dereq_(106);\n\nvar keyOf = _dereq_(165);\n\nvar END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space\nvar START_KEYCODE = 229;\n\nvar canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;\n\nvar documentMode = null;\nif (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {\n  documentMode = document.documentMode;\n}\n\n// Webkit offers a very useful `textInput` event that can be used to\n// directly represent `beforeInput`. The IE `textinput` event is not as\n// useful, so we don't use it.\nvar canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();\n\n// In IE9+, we have access to composition events, but the data supplied\n// by the native compositionend event may be incorrect. Japanese ideographic\n// spaces, for instance (\\u3000) are not recorded correctly.\nvar useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);\n\n/**\n * Opera <= 12 includes TextEvent in window, but does not fire\n * text input events. Rely on keypress instead.\n */\nfunction isPresto() {\n  var opera = window.opera;\n  return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;\n}\n\nvar SPACEBAR_CODE = 32;\nvar SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\n// Events and their corresponding property names.\nvar eventTypes = {\n  beforeInput: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBeforeInput: null }),\n      captured: keyOf({ onBeforeInputCapture: null })\n    },\n    dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste]\n  },\n  compositionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionEnd: null }),\n      captured: keyOf({ onCompositionEndCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionStart: null }),\n      captured: keyOf({ onCompositionStartCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionUpdate: null }),\n      captured: keyOf({ onCompositionUpdateCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  }\n};\n\n// Track whether we've ever handled a keypress on the space key.\nvar hasSpaceKeypress = false;\n\n/**\n * Return whether a native keypress event is assumed to be a command.\n * This is required because Firefox fires `keypress` events for key commands\n * (cut, copy, select-all, etc.) even though no character is inserted.\n */\nfunction isKeypressCommand(nativeEvent) {\n  return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&\n  // ctrlKey && altKey is equivalent to AltGr, and is not a command.\n  !(nativeEvent.ctrlKey && nativeEvent.altKey);\n}\n\n/**\n * Translate native top level events into event types.\n *\n * @param {string} topLevelType\n * @return {object}\n */\nfunction getCompositionEventType(topLevelType) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionStart:\n      return eventTypes.compositionStart;\n    case topLevelTypes.topCompositionEnd:\n      return eventTypes.compositionEnd;\n    case topLevelTypes.topCompositionUpdate:\n      return eventTypes.compositionUpdate;\n  }\n}\n\n/**\n * Does our fallback best-guess model think this event signifies that\n * composition has begun?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionStart(topLevelType, nativeEvent) {\n  return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE;\n}\n\n/**\n * Does our fallback mode think that this event is the end of composition?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionEnd(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topKeyUp:\n      // Command keys insert or clear IME input.\n      return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;\n    case topLevelTypes.topKeyDown:\n      // Expect IME keyCode on each keydown. If we get any other\n      // code we must have exited earlier.\n      return nativeEvent.keyCode !== START_KEYCODE;\n    case topLevelTypes.topKeyPress:\n    case topLevelTypes.topMouseDown:\n    case topLevelTypes.topBlur:\n      // Events are not possible without cancelling IME.\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Google Input Tools provides composition data via a CustomEvent,\n * with the `data` property populated in the `detail` object. If this\n * is available on the event object, use it. If not, this is a plain\n * composition event and we have nothing special to extract.\n *\n * @param {object} nativeEvent\n * @return {?string}\n */\nfunction getDataFromCustomEvent(nativeEvent) {\n  var detail = nativeEvent.detail;\n  if (typeof detail === 'object' && 'data' in detail) {\n    return detail.data;\n  }\n  return null;\n}\n\n// Track the current IME composition fallback object, if any.\nvar currentComposition = null;\n\n/**\n * @return {?object} A SyntheticCompositionEvent.\n */\nfunction extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var eventType;\n  var fallbackData;\n\n  if (canUseCompositionEvent) {\n    eventType = getCompositionEventType(topLevelType);\n  } else if (!currentComposition) {\n    if (isFallbackCompositionStart(topLevelType, nativeEvent)) {\n      eventType = eventTypes.compositionStart;\n    }\n  } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n    eventType = eventTypes.compositionEnd;\n  }\n\n  if (!eventType) {\n    return null;\n  }\n\n  if (useFallbackCompositionData) {\n    // The current composition is stored statically and must not be\n    // overwritten while composition continues.\n    if (!currentComposition && eventType === eventTypes.compositionStart) {\n      currentComposition = FallbackCompositionState.getPooled(nativeEventTarget);\n    } else if (eventType === eventTypes.compositionEnd) {\n      if (currentComposition) {\n        fallbackData = currentComposition.getData();\n      }\n    }\n  }\n\n  var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);\n\n  if (fallbackData) {\n    // Inject data generated from fallback path into the synthetic event.\n    // This matches the property of native CompositionEventInterface.\n    event.data = fallbackData;\n  } else {\n    var customData = getDataFromCustomEvent(nativeEvent);\n    if (customData !== null) {\n      event.data = customData;\n    }\n  }\n\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The string corresponding to this `beforeInput` event.\n */\nfunction getNativeBeforeInputChars(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionEnd:\n      return getDataFromCustomEvent(nativeEvent);\n    case topLevelTypes.topKeyPress:\n      /**\n       * If native `textInput` events are available, our goal is to make\n       * use of them. However, there is a special case: the spacebar key.\n       * In Webkit, preventing default on a spacebar `textInput` event\n       * cancels character insertion, but it *also* causes the browser\n       * to fall back to its default spacebar behavior of scrolling the\n       * page.\n       *\n       * Tracking at:\n       * https://code.google.com/p/chromium/issues/detail?id=355103\n       *\n       * To avoid this issue, use the keypress event as if no `textInput`\n       * event is available.\n       */\n      var which = nativeEvent.which;\n      if (which !== SPACEBAR_CODE) {\n        return null;\n      }\n\n      hasSpaceKeypress = true;\n      return SPACEBAR_CHAR;\n\n    case topLevelTypes.topTextInput:\n      // Record the characters to be added to the DOM.\n      var chars = nativeEvent.data;\n\n      // If it's a spacebar character, assume that we have already handled\n      // it at the keypress level and bail immediately. Android Chrome\n      // doesn't give us keycodes, so we need to blacklist it.\n      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {\n        return null;\n      }\n\n      return chars;\n\n    default:\n      // For other native event types, do nothing.\n      return null;\n  }\n}\n\n/**\n * For browsers that do not provide the `textInput` event, extract the\n * appropriate string to use for SyntheticInputEvent.\n *\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The fallback string for this `beforeInput` event.\n */\nfunction getFallbackBeforeInputChars(topLevelType, nativeEvent) {\n  // If we are currently composing (IME) and using a fallback to do so,\n  // try to extract the composed characters from the fallback object.\n  if (currentComposition) {\n    if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n      var chars = currentComposition.getData();\n      FallbackCompositionState.release(currentComposition);\n      currentComposition = null;\n      return chars;\n    }\n    return null;\n  }\n\n  switch (topLevelType) {\n    case topLevelTypes.topPaste:\n      // If a paste event occurs after a keypress, throw out the input\n      // chars. Paste events should not lead to BeforeInput events.\n      return null;\n    case topLevelTypes.topKeyPress:\n      /**\n       * As of v27, Firefox may fire keypress events even when no character\n       * will be inserted. A few possibilities:\n       *\n       * - `which` is `0`. Arrow keys, Esc key, etc.\n       *\n       * - `which` is the pressed key code, but no char is available.\n       *   Ex: 'AltGr + d` in Polish. There is no modified character for\n       *   this key combination and no character is inserted into the\n       *   document, but FF fires the keypress for char code `100` anyway.\n       *   No `input` event will occur.\n       *\n       * - `which` is the pressed key code, but a command combination is\n       *   being used. Ex: `Cmd+C`. No character is inserted, and no\n       *   `input` event will occur.\n       */\n      if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {\n        return String.fromCharCode(nativeEvent.which);\n      }\n      return null;\n    case topLevelTypes.topCompositionEnd:\n      return useFallbackCompositionData ? null : nativeEvent.data;\n    default:\n      return null;\n  }\n}\n\n/**\n * Extract a SyntheticInputEvent for `beforeInput`, based on either native\n * `textInput` or fallback behavior.\n *\n * @return {?object} A SyntheticInputEvent.\n */\nfunction extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var chars;\n\n  if (canUseTextInputEvent) {\n    chars = getNativeBeforeInputChars(topLevelType, nativeEvent);\n  } else {\n    chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);\n  }\n\n  // If no characters are being inserted, no BeforeInput event should\n  // be fired.\n  if (!chars) {\n    return null;\n  }\n\n  var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);\n\n  event.data = chars;\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * Create an `onBeforeInput` event to match\n * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.\n *\n * This event plugin is based on the native `textInput` event\n * available in Chrome, Safari, Opera, and IE. This event fires after\n * `onKeyPress` and `onCompositionEnd`, but before `onInput`.\n *\n * `beforeInput` is spec'd but not implemented in any browsers, and\n * the `input` event does not provide any useful information about what has\n * actually been added, contrary to the spec. Thus, `textInput` is the best\n * available event to identify the characters that have actually been inserted\n * into the target node.\n *\n * This plugin is also responsible for emitting `composition` events, thus\n * allowing us to share composition fallback code for both `beforeInput` and\n * `composition` event types.\n */\nvar BeforeInputEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];\n  }\n};\n\nmodule.exports = BeforeInputEventPlugin;\n},{\"102\":102,\"106\":106,\"147\":147,\"16\":16,\"165\":165,\"20\":20,\"21\":21}],3:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSProperty\n */\n\n'use strict';\n\n/**\n * CSS properties which accept numbers but are not in units of \"px\".\n */\n\nvar isUnitlessNumber = {\n  animationIterationCount: true,\n  borderImageOutset: true,\n  borderImageSlice: true,\n  borderImageWidth: true,\n  boxFlex: true,\n  boxFlexGroup: true,\n  boxOrdinalGroup: true,\n  columnCount: true,\n  flex: true,\n  flexGrow: true,\n  flexPositive: true,\n  flexShrink: true,\n  flexNegative: true,\n  flexOrder: true,\n  gridRow: true,\n  gridColumn: true,\n  fontWeight: true,\n  lineClamp: true,\n  lineHeight: true,\n  opacity: true,\n  order: true,\n  orphans: true,\n  tabSize: true,\n  widows: true,\n  zIndex: true,\n  zoom: true,\n\n  // SVG-related properties\n  fillOpacity: true,\n  floodOpacity: true,\n  stopOpacity: true,\n  strokeDasharray: true,\n  strokeDashoffset: true,\n  strokeMiterlimit: true,\n  strokeOpacity: true,\n  strokeWidth: true\n};\n\n/**\n * @param {string} prefix vendor-specific prefix, eg: Webkit\n * @param {string} key style name, eg: transitionDuration\n * @return {string} style name prefixed with `prefix`, properly camelCased, eg:\n * WebkitTransitionDuration\n */\nfunction prefixKey(prefix, key) {\n  return prefix + key.charAt(0).toUpperCase() + key.substring(1);\n}\n\n/**\n * Support style names that may come passed in prefixed by adding permutations\n * of vendor prefixes.\n */\nvar prefixes = ['Webkit', 'ms', 'Moz', 'O'];\n\n// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an\n// infinite loop, because it iterates over the newly added props too.\nObject.keys(isUnitlessNumber).forEach(function (prop) {\n  prefixes.forEach(function (prefix) {\n    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];\n  });\n});\n\n/**\n * Most style properties can be unset by doing .style[prop] = '' but IE8\n * doesn't like doing that with shorthand properties so for the properties that\n * IE8 breaks on, which are listed here, we instead unset each of the\n * individual properties. See http://bugs.jquery.com/ticket/12385.\n * The 4-value 'clock' properties like margin, padding, border-width seem to\n * behave without any problems. Curiously, list-style works too without any\n * special prodding.\n */\nvar shorthandPropertyExpansions = {\n  background: {\n    backgroundAttachment: true,\n    backgroundColor: true,\n    backgroundImage: true,\n    backgroundPositionX: true,\n    backgroundPositionY: true,\n    backgroundRepeat: true\n  },\n  backgroundPosition: {\n    backgroundPositionX: true,\n    backgroundPositionY: true\n  },\n  border: {\n    borderWidth: true,\n    borderStyle: true,\n    borderColor: true\n  },\n  borderBottom: {\n    borderBottomWidth: true,\n    borderBottomStyle: true,\n    borderBottomColor: true\n  },\n  borderLeft: {\n    borderLeftWidth: true,\n    borderLeftStyle: true,\n    borderLeftColor: true\n  },\n  borderRight: {\n    borderRightWidth: true,\n    borderRightStyle: true,\n    borderRightColor: true\n  },\n  borderTop: {\n    borderTopWidth: true,\n    borderTopStyle: true,\n    borderTopColor: true\n  },\n  font: {\n    fontStyle: true,\n    fontVariant: true,\n    fontWeight: true,\n    fontSize: true,\n    lineHeight: true,\n    fontFamily: true\n  },\n  outline: {\n    outlineWidth: true,\n    outlineStyle: true,\n    outlineColor: true\n  }\n};\n\nvar CSSProperty = {\n  isUnitlessNumber: isUnitlessNumber,\n  shorthandPropertyExpansions: shorthandPropertyExpansions\n};\n\nmodule.exports = CSSProperty;\n},{}],4:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSPropertyOperations\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactInstrumentation = _dereq_(74);\n\nvar camelizeStyleName = _dereq_(149);\nvar dangerousStyleValue = _dereq_(120);\nvar hyphenateStyleName = _dereq_(160);\nvar memoizeStringOnly = _dereq_(167);\nvar warning = _dereq_(171);\n\nvar processStyleName = memoizeStringOnly(function (styleName) {\n  return hyphenateStyleName(styleName);\n});\n\nvar hasShorthandPropertyBug = false;\nvar styleFloatAccessor = 'cssFloat';\nif (ExecutionEnvironment.canUseDOM) {\n  var tempStyle = document.createElement('div').style;\n  try {\n    // IE8 throws \"Invalid argument.\" if resetting shorthand style properties.\n    tempStyle.font = '';\n  } catch (e) {\n    hasShorthandPropertyBug = true;\n  }\n  // IE8 only supports accessing cssFloat (standard) as styleFloat\n  if (document.documentElement.style.cssFloat === undefined) {\n    styleFloatAccessor = 'styleFloat';\n  }\n}\n\nif (\"development\" !== 'production') {\n  // 'msTransform' is correct, but the other prefixes should be capitalized\n  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;\n\n  // style values shouldn't contain a semicolon\n  var badStyleValueWithSemicolonPattern = /;\\s*$/;\n\n  var warnedStyleNames = {};\n  var warnedStyleValues = {};\n  var warnedForNaNValue = false;\n\n  var warnHyphenatedStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnBadVendoredStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnStyleValueWithSemicolon = function (name, value, owner) {\n    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {\n      return;\n    }\n\n    warnedStyleValues[value] = true;\n    \"development\" !== 'production' ? warning(false, 'Style property values shouldn\\'t contain a semicolon.%s ' + 'Try \"%s: %s\" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;\n  };\n\n  var warnStyleValueIsNaN = function (name, value, owner) {\n    if (warnedForNaNValue) {\n      return;\n    }\n\n    warnedForNaNValue = true;\n    \"development\" !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0;\n  };\n\n  var checkRenderMessage = function (owner) {\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' Check the render method of `' + name + '`.';\n      }\n    }\n    return '';\n  };\n\n  /**\n   * @param {string} name\n   * @param {*} value\n   * @param {ReactDOMComponent} component\n   */\n  var warnValidStyle = function (name, value, component) {\n    var owner;\n    if (component) {\n      owner = component._currentElement._owner;\n    }\n    if (name.indexOf('-') > -1) {\n      warnHyphenatedStyleName(name, owner);\n    } else if (badVendoredStyleNamePattern.test(name)) {\n      warnBadVendoredStyleName(name, owner);\n    } else if (badStyleValueWithSemicolonPattern.test(value)) {\n      warnStyleValueWithSemicolon(name, value, owner);\n    }\n\n    if (typeof value === 'number' && isNaN(value)) {\n      warnStyleValueIsNaN(name, value, owner);\n    }\n  };\n}\n\n/**\n * Operations for dealing with CSS properties.\n */\nvar CSSPropertyOperations = {\n\n  /**\n   * Serializes a mapping of style properties for use as inline styles:\n   *\n   *   > createMarkupForStyles({width: '200px', height: 0})\n   *   \"width:200px;height:0;\"\n   *\n   * Undefined values are ignored so that declarative programming is easier.\n   * The result should be HTML-escaped before insertion into the DOM.\n   *\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   * @return {?string}\n   */\n  createMarkupForStyles: function (styles, component) {\n    var serialized = '';\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      var styleValue = styles[styleName];\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styleValue, component);\n      }\n      if (styleValue != null) {\n        serialized += processStyleName(styleName) + ':';\n        serialized += dangerousStyleValue(styleName, styleValue, component) + ';';\n      }\n    }\n    return serialized || null;\n  },\n\n  /**\n   * Sets the value for multiple styles on a node.  If a value is specified as\n   * '' (empty string), the corresponding style property will be unset.\n   *\n   * @param {DOMElement} node\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   */\n  setValueForStyles: function (node, styles, component) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onHostOperation(component._debugID, 'update styles', styles);\n    }\n\n    var style = node.style;\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styles[styleName], component);\n      }\n      var styleValue = dangerousStyleValue(styleName, styles[styleName], component);\n      if (styleName === 'float' || styleName === 'cssFloat') {\n        styleName = styleFloatAccessor;\n      }\n      if (styleValue) {\n        style[styleName] = styleValue;\n      } else {\n        var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];\n        if (expansion) {\n          // Shorthand property that IE8 won't like unsetting, so unset each\n          // component to placate it\n          for (var individualStyleName in expansion) {\n            style[individualStyleName] = '';\n          }\n        } else {\n          style[styleName] = '';\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = CSSPropertyOperations;\n},{\"120\":120,\"147\":147,\"149\":149,\"160\":160,\"167\":167,\"171\":171,\"3\":3,\"74\":74}],5:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CallbackQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar invariant = _dereq_(161);\n\n/**\n * A specialized pseudo-event module to help keep track of components waiting to\n * be notified when their DOM representations are available for use.\n *\n * This implements `PooledClass`, so you should never need to instantiate this.\n * Instead, use `CallbackQueue.getPooled()`.\n *\n * @class ReactMountReady\n * @implements PooledClass\n * @internal\n */\nfunction CallbackQueue() {\n  this._callbacks = null;\n  this._contexts = null;\n}\n\n_assign(CallbackQueue.prototype, {\n\n  /**\n   * Enqueues a callback to be invoked when `notifyAll` is invoked.\n   *\n   * @param {function} callback Invoked when `notifyAll` is invoked.\n   * @param {?object} context Context to call `callback` with.\n   * @internal\n   */\n  enqueue: function (callback, context) {\n    this._callbacks = this._callbacks || [];\n    this._contexts = this._contexts || [];\n    this._callbacks.push(callback);\n    this._contexts.push(context);\n  },\n\n  /**\n   * Invokes all enqueued callbacks and clears the queue. This is invoked after\n   * the DOM representation of a component has been created or updated.\n   *\n   * @internal\n   */\n  notifyAll: function () {\n    var callbacks = this._callbacks;\n    var contexts = this._contexts;\n    if (callbacks) {\n      !(callbacks.length === contexts.length) ? \"development\" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : _prodInvariant('24') : void 0;\n      this._callbacks = null;\n      this._contexts = null;\n      for (var i = 0; i < callbacks.length; i++) {\n        callbacks[i].call(contexts[i]);\n      }\n      callbacks.length = 0;\n      contexts.length = 0;\n    }\n  },\n\n  checkpoint: function () {\n    return this._callbacks ? this._callbacks.length : 0;\n  },\n\n  rollback: function (len) {\n    if (this._callbacks) {\n      this._callbacks.length = len;\n      this._contexts.length = len;\n    }\n  },\n\n  /**\n   * Resets the internal queue.\n   *\n   * @internal\n   */\n  reset: function () {\n    this._callbacks = null;\n    this._contexts = null;\n  },\n\n  /**\n   * `PooledClass` looks for this.\n   */\n  destructor: function () {\n    this.reset();\n  }\n\n});\n\nPooledClass.addPoolingTo(CallbackQueue);\n\nmodule.exports = CallbackQueue;\n},{\"139\":139,\"161\":161,\"172\":172,\"25\":25}],6:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ChangeEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\nvar isEventSupported = _dereq_(135);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  change: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onChange: null }),\n      captured: keyOf({ onChangeCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topSelectionChange]\n  }\n};\n\n/**\n * For IE shims\n */\nvar activeElement = null;\nvar activeElementInst = null;\nvar activeElementValue = null;\nvar activeElementValueProp = null;\n\n/**\n * SECTION: handle `change` event\n */\nfunction shouldUseChangeEvent(elem) {\n  var nodeName = elem.nodeName && elem.nodeName.toLowerCase();\n  return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';\n}\n\nvar doesChangeEventBubble = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // See `handleChange` comment below\n  doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8);\n}\n\nfunction manualDispatchChangeEvent(nativeEvent) {\n  var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent));\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n\n  // If change and propertychange bubbled, we'd just bind to it like all the\n  // other events and have it go through ReactBrowserEventEmitter. Since it\n  // doesn't, we manually listen for the events and so we have to enqueue and\n  // process the abstract event manually.\n  //\n  // Batching is necessary here in order to ensure that all event handlers run\n  // before the next rerender (including event handlers attached to ancestor\n  // elements instead of directly on the input). Without this, controlled\n  // components don't work properly in conjunction with event bubbling because\n  // the component is rerendered and the value reverted before all the event\n  // handlers can run. See https://github.com/facebook/react/issues/708.\n  ReactUpdates.batchedUpdates(runEventInBatch, event);\n}\n\nfunction runEventInBatch(event) {\n  EventPluginHub.enqueueEvents(event);\n  EventPluginHub.processEventQueue(false);\n}\n\nfunction startWatchingForChangeEventIE8(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElement.attachEvent('onchange', manualDispatchChangeEvent);\n}\n\nfunction stopWatchingForChangeEventIE8() {\n  if (!activeElement) {\n    return;\n  }\n  activeElement.detachEvent('onchange', manualDispatchChangeEvent);\n  activeElement = null;\n  activeElementInst = null;\n}\n\nfunction getTargetInstForChangeEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topChange) {\n    return targetInst;\n  }\n}\nfunction handleEventsForChangeEventIE8(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForChangeEventIE8();\n    startWatchingForChangeEventIE8(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForChangeEventIE8();\n  }\n}\n\n/**\n * SECTION: handle `input` event\n */\nvar isInputEventSupported = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // IE9 claims to support the input event but fails to trigger it when\n  // deleting text, so we ignore its input events.\n  // IE10+ fire input events to often, such when a placeholder\n  // changes or when an input with a placeholder is focused.\n  isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11);\n}\n\n/**\n * (For IE <=11) Replacement getter/setter for the `value` property that gets\n * set on the active element.\n */\nvar newValueProp = {\n  get: function () {\n    return activeElementValueProp.get.call(this);\n  },\n  set: function (val) {\n    // Cast to a string so we can do equality checks.\n    activeElementValue = '' + val;\n    activeElementValueProp.set.call(this, val);\n  }\n};\n\n/**\n * (For IE <=11) Starts tracking propertychange events on the passed-in element\n * and override the value property so that we can distinguish user events from\n * value changes in JS.\n */\nfunction startWatchingForValueChange(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElementValue = target.value;\n  activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value');\n\n  // Not guarded in a canDefineProperty check: IE8 supports defineProperty only\n  // on DOM elements\n  Object.defineProperty(activeElement, 'value', newValueProp);\n  if (activeElement.attachEvent) {\n    activeElement.attachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.addEventListener('propertychange', handlePropertyChange, false);\n  }\n}\n\n/**\n * (For IE <=11) Removes the event listeners from the currently-tracked element,\n * if any exists.\n */\nfunction stopWatchingForValueChange() {\n  if (!activeElement) {\n    return;\n  }\n\n  // delete restores the original property definition\n  delete activeElement.value;\n\n  if (activeElement.detachEvent) {\n    activeElement.detachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.removeEventListener('propertychange', handlePropertyChange, false);\n  }\n\n  activeElement = null;\n  activeElementInst = null;\n  activeElementValue = null;\n  activeElementValueProp = null;\n}\n\n/**\n * (For IE <=11) Handles a propertychange event, sending a `change` event if\n * the value of the active element has changed.\n */\nfunction handlePropertyChange(nativeEvent) {\n  if (nativeEvent.propertyName !== 'value') {\n    return;\n  }\n  var value = nativeEvent.srcElement.value;\n  if (value === activeElementValue) {\n    return;\n  }\n  activeElementValue = value;\n\n  manualDispatchChangeEvent(nativeEvent);\n}\n\n/**\n * If a `change` event should be fired, returns the target's ID.\n */\nfunction getTargetInstForInputEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topInput) {\n    // In modern browsers (i.e., not IE8 or IE9), the input event is exactly\n    // what we want so fall through here and trigger an abstract event\n    return targetInst;\n  }\n}\n\nfunction handleEventsForInputEventIE(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // In IE8, we can capture almost all .value changes by adding a\n    // propertychange handler and looking for events with propertyName\n    // equal to 'value'\n    // In IE9-11, propertychange fires for most input events but is buggy and\n    // doesn't fire when text is deleted, but conveniently, selectionchange\n    // appears to fire in all of the remaining cases so we catch those and\n    // forward the event if the value has changed\n    // In either case, we don't want to call the event handler if the value\n    // is changed from JS so we redefine a setter for `.value` that updates\n    // our activeElementValue variable, allowing us to ignore those changes\n    //\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForValueChange();\n    startWatchingForValueChange(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForValueChange();\n  }\n}\n\n// For IE8 and IE9.\nfunction getTargetInstForInputEventIE(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) {\n    // On the selectionchange event, the target is just document which isn't\n    // helpful for us so just check activeElement instead.\n    //\n    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire\n    // propertychange on the first input event after setting `value` from a\n    // script and fires only keydown, keypress, keyup. Catching keyup usually\n    // gets it and catching keydown lets us fire an event for the first\n    // keystroke if user does a key repeat (it'll be a little delayed: right\n    // before the second keystroke). Other input methods (e.g., paste) seem to\n    // fire selectionchange normally.\n    if (activeElement && activeElement.value !== activeElementValue) {\n      activeElementValue = activeElement.value;\n      return activeElementInst;\n    }\n  }\n}\n\n/**\n * SECTION: handle `click` event\n */\nfunction shouldUseClickEvent(elem) {\n  // Use the `click` event to detect changes to checkbox and radio inputs.\n  // This approach works across all browsers, whereas `change` does not fire\n  // until `blur` in IE8.\n  return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');\n}\n\nfunction getTargetInstForClickEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topClick) {\n    return targetInst;\n  }\n}\n\n/**\n * This plugin creates an `onChange` event that normalizes change events\n * across form elements. This event fires at a time when it's possible to\n * change the element's value without seeing a flicker.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - select\n */\nvar ChangeEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    var getTargetInstFunc, handleEventFunc;\n    if (shouldUseChangeEvent(targetNode)) {\n      if (doesChangeEventBubble) {\n        getTargetInstFunc = getTargetInstForChangeEvent;\n      } else {\n        handleEventFunc = handleEventsForChangeEventIE8;\n      }\n    } else if (isTextInputElement(targetNode)) {\n      if (isInputEventSupported) {\n        getTargetInstFunc = getTargetInstForInputEvent;\n      } else {\n        getTargetInstFunc = getTargetInstForInputEventIE;\n        handleEventFunc = handleEventsForInputEventIE;\n      }\n    } else if (shouldUseClickEvent(targetNode)) {\n      getTargetInstFunc = getTargetInstForClickEvent;\n    }\n\n    if (getTargetInstFunc) {\n      var inst = getTargetInstFunc(topLevelType, targetInst);\n      if (inst) {\n        var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget);\n        event.type = 'change';\n        EventPropagators.accumulateTwoPhaseDispatches(event);\n        return event;\n      }\n    }\n\n    if (handleEventFunc) {\n      handleEventFunc(topLevelType, targetNode, targetInst);\n    }\n  }\n\n};\n\nmodule.exports = ChangeEventPlugin;\n},{\"104\":104,\"128\":128,\"135\":135,\"136\":136,\"147\":147,\"16\":16,\"165\":165,\"17\":17,\"20\":20,\"41\":41,\"95\":95}],7:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMChildrenOperations\n */\n\n'use strict';\n\nvar DOMLazyTree = _dereq_(8);\nvar Danger = _dereq_(12);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setInnerHTML = _dereq_(141);\nvar setTextContent = _dereq_(142);\n\nfunction getNodeAfter(parentNode, node) {\n  // Special case for text components, which return [open, close] comments\n  // from getHostNode.\n  if (Array.isArray(node)) {\n    node = node[1];\n  }\n  return node ? node.nextSibling : parentNode.firstChild;\n}\n\n/**\n * Inserts `childNode` as a child of `parentNode` at the `index`.\n *\n * @param {DOMElement} parentNode Parent node in which to insert.\n * @param {DOMElement} childNode Child node to insert.\n * @param {number} index Index at which to insert the child.\n * @internal\n */\nvar insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) {\n  // We rely exclusively on `insertBefore(node, null)` instead of also using\n  // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so\n  // we are careful to use `null`.)\n  parentNode.insertBefore(childNode, referenceNode);\n});\n\nfunction insertLazyTreeChildAt(parentNode, childTree, referenceNode) {\n  DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);\n}\n\nfunction moveChild(parentNode, childNode, referenceNode) {\n  if (Array.isArray(childNode)) {\n    moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);\n  } else {\n    insertChildAt(parentNode, childNode, referenceNode);\n  }\n}\n\nfunction removeChild(parentNode, childNode) {\n  if (Array.isArray(childNode)) {\n    var closingComment = childNode[1];\n    childNode = childNode[0];\n    removeDelimitedText(parentNode, childNode, closingComment);\n    parentNode.removeChild(closingComment);\n  }\n  parentNode.removeChild(childNode);\n}\n\nfunction moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) {\n  var node = openingComment;\n  while (true) {\n    var nextNode = node.nextSibling;\n    insertChildAt(parentNode, node, referenceNode);\n    if (node === closingComment) {\n      break;\n    }\n    node = nextNode;\n  }\n}\n\nfunction removeDelimitedText(parentNode, startNode, closingComment) {\n  while (true) {\n    var node = startNode.nextSibling;\n    if (node === closingComment) {\n      // The closing comment is removed by ReactMultiChild.\n      break;\n    } else {\n      parentNode.removeChild(node);\n    }\n  }\n}\n\nfunction replaceDelimitedText(openingComment, closingComment, stringText) {\n  var parentNode = openingComment.parentNode;\n  var nodeAfterComment = openingComment.nextSibling;\n  if (nodeAfterComment === closingComment) {\n    // There are no text nodes between the opening and closing comments; insert\n    // a new one if stringText isn't empty.\n    if (stringText) {\n      insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment);\n    }\n  } else {\n    if (stringText) {\n      // Set the text content of the first node after the opening comment, and\n      // remove all following nodes up until the closing comment.\n      setTextContent(nodeAfterComment, stringText);\n      removeDelimitedText(parentNode, nodeAfterComment, closingComment);\n    } else {\n      removeDelimitedText(parentNode, openingComment, closingComment);\n    }\n  }\n\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID, 'replace text', stringText);\n  }\n}\n\nvar dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup;\nif (\"development\" !== 'production') {\n  dangerouslyReplaceNodeWithMarkup = function (oldChild, markup, prevInstance) {\n    Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup);\n    if (prevInstance._debugID !== 0) {\n      ReactInstrumentation.debugTool.onHostOperation(prevInstance._debugID, 'replace with', markup.toString());\n    } else {\n      var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node);\n      if (nextInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(nextInstance._debugID, 'mount', markup.toString());\n      }\n    }\n  };\n}\n\n/**\n * Operations for updating with DOM children.\n */\nvar DOMChildrenOperations = {\n\n  dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,\n\n  replaceDelimitedText: replaceDelimitedText,\n\n  /**\n   * Updates a component's children by processing a series of updates. The\n   * update configurations are each expected to have a `parentNode` property.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  processUpdates: function (parentNode, updates) {\n    if (\"development\" !== 'production') {\n      var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID;\n    }\n\n    for (var k = 0; k < updates.length; k++) {\n      var update = updates[k];\n      switch (update.type) {\n        case ReactMultiChildUpdateTypes.INSERT_MARKUP:\n          insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'insert child', { toIndex: update.toIndex, content: update.content.toString() });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.MOVE_EXISTING:\n          moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'move child', { fromIndex: update.fromIndex, toIndex: update.toIndex });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.SET_MARKUP:\n          setInnerHTML(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace children', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.TEXT_CONTENT:\n          setTextContent(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace text', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.REMOVE_NODE:\n          removeChild(parentNode, update.fromNode);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'remove child', { fromIndex: update.fromIndex });\n          }\n          break;\n      }\n    }\n  }\n\n};\n\nmodule.exports = DOMChildrenOperations;\n},{\"119\":119,\"12\":12,\"141\":141,\"142\":142,\"41\":41,\"74\":74,\"79\":79,\"8\":8}],8:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMLazyTree\n */\n\n'use strict';\n\nvar DOMNamespaces = _dereq_(9);\nvar setInnerHTML = _dereq_(141);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setTextContent = _dereq_(142);\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\n/**\n * In IE (8-11) and Edge, appending nodes with no children is dramatically\n * faster than appending a full subtree, so we essentially queue up the\n * .appendChild calls here and apply them so each node is added to its parent\n * before any children are added.\n *\n * In other browsers, doing so is slower or neutral compared to the other order\n * (in Firefox, twice as slow) so we only do this inversion in IE.\n *\n * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.\n */\nvar enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\\bEdge\\/\\d/.test(navigator.userAgent);\n\nfunction insertTreeChildren(tree) {\n  if (!enableLazy) {\n    return;\n  }\n  var node = tree.node;\n  var children = tree.children;\n  if (children.length) {\n    for (var i = 0; i < children.length; i++) {\n      insertTreeBefore(node, children[i], null);\n    }\n  } else if (tree.html != null) {\n    setInnerHTML(node, tree.html);\n  } else if (tree.text != null) {\n    setTextContent(node, tree.text);\n  }\n}\n\nvar insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {\n  // DocumentFragments aren't actually part of the DOM after insertion so\n  // appending children won't update the DOM. We need to ensure the fragment\n  // is properly populated first, breaking out of our lazy approach for just\n  // this level. Also, some <object> plugins (like Flash Player) will read\n  // <param> nodes immediately upon insertion into the DOM, so <object>\n  // must also be populated prior to insertion into the DOM.\n  if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) {\n    insertTreeChildren(tree);\n    parentNode.insertBefore(tree.node, referenceNode);\n  } else {\n    parentNode.insertBefore(tree.node, referenceNode);\n    insertTreeChildren(tree);\n  }\n});\n\nfunction replaceChildWithTree(oldNode, newTree) {\n  oldNode.parentNode.replaceChild(newTree.node, oldNode);\n  insertTreeChildren(newTree);\n}\n\nfunction queueChild(parentTree, childTree) {\n  if (enableLazy) {\n    parentTree.children.push(childTree);\n  } else {\n    parentTree.node.appendChild(childTree.node);\n  }\n}\n\nfunction queueHTML(tree, html) {\n  if (enableLazy) {\n    tree.html = html;\n  } else {\n    setInnerHTML(tree.node, html);\n  }\n}\n\nfunction queueText(tree, text) {\n  if (enableLazy) {\n    tree.text = text;\n  } else {\n    setTextContent(tree.node, text);\n  }\n}\n\nfunction toString() {\n  return this.node.nodeName;\n}\n\nfunction DOMLazyTree(node) {\n  return {\n    node: node,\n    children: [],\n    html: null,\n    text: null,\n    toString: toString\n  };\n}\n\nDOMLazyTree.insertTreeBefore = insertTreeBefore;\nDOMLazyTree.replaceChildWithTree = replaceChildWithTree;\nDOMLazyTree.queueChild = queueChild;\nDOMLazyTree.queueHTML = queueHTML;\nDOMLazyTree.queueText = queueText;\n\nmodule.exports = DOMLazyTree;\n},{\"119\":119,\"141\":141,\"142\":142,\"9\":9}],9:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMNamespaces\n */\n\n'use strict';\n\nvar DOMNamespaces = {\n  html: 'http://www.w3.org/1999/xhtml',\n  mathml: 'http://www.w3.org/1998/Math/MathML',\n  svg: 'http://www.w3.org/2000/svg'\n};\n\nmodule.exports = DOMNamespaces;\n},{}],10:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMProperty\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nfunction checkMask(value, bitmask) {\n  return (value & bitmask) === bitmask;\n}\n\nvar DOMPropertyInjection = {\n  /**\n   * Mapping from normalized, camelcased property names to a configuration that\n   * specifies how the associated DOM property should be accessed or rendered.\n   */\n  MUST_USE_PROPERTY: 0x1,\n  HAS_BOOLEAN_VALUE: 0x4,\n  HAS_NUMERIC_VALUE: 0x8,\n  HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,\n  HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,\n\n  /**\n   * Inject some specialized knowledge about the DOM. This takes a config object\n   * with the following properties:\n   *\n   * isCustomAttribute: function that given an attribute name will return true\n   * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*\n   * attributes where it's impossible to enumerate all of the possible\n   * attribute names,\n   *\n   * Properties: object mapping DOM property name to one of the\n   * DOMPropertyInjection constants or null. If your attribute isn't in here,\n   * it won't get written to the DOM.\n   *\n   * DOMAttributeNames: object mapping React attribute name to the DOM\n   * attribute name. Attribute names not specified use the **lowercase**\n   * normalized name.\n   *\n   * DOMAttributeNamespaces: object mapping React attribute name to the DOM\n   * attribute namespace URL. (Attribute names not specified use no namespace.)\n   *\n   * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.\n   * Property names not specified use the normalized name.\n   *\n   * DOMMutationMethods: Properties that require special mutation methods. If\n   * `value` is undefined, the mutation method should unset the property.\n   *\n   * @param {object} domPropertyConfig the config as described above.\n   */\n  injectDOMPropertyConfig: function (domPropertyConfig) {\n    var Injection = DOMPropertyInjection;\n    var Properties = domPropertyConfig.Properties || {};\n    var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};\n    var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};\n    var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};\n    var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};\n\n    if (domPropertyConfig.isCustomAttribute) {\n      DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute);\n    }\n\n    for (var propName in Properties) {\n      !!DOMProperty.properties.hasOwnProperty(propName) ? \"development\" !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\\'re trying to inject DOM property \\'%s\\' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.', propName) : _prodInvariant('48', propName) : void 0;\n\n      var lowerCased = propName.toLowerCase();\n      var propConfig = Properties[propName];\n\n      var propertyInfo = {\n        attributeName: lowerCased,\n        attributeNamespace: null,\n        propertyName: propName,\n        mutationMethod: null,\n\n        mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),\n        hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),\n        hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),\n        hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),\n        hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE)\n      };\n      !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? \"development\" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : _prodInvariant('50', propName) : void 0;\n\n      if (\"development\" !== 'production') {\n        DOMProperty.getPossibleStandardName[lowerCased] = propName;\n      }\n\n      if (DOMAttributeNames.hasOwnProperty(propName)) {\n        var attributeName = DOMAttributeNames[propName];\n        propertyInfo.attributeName = attributeName;\n        if (\"development\" !== 'production') {\n          DOMProperty.getPossibleStandardName[attributeName] = propName;\n        }\n      }\n\n      if (DOMAttributeNamespaces.hasOwnProperty(propName)) {\n        propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];\n      }\n\n      if (DOMPropertyNames.hasOwnProperty(propName)) {\n        propertyInfo.propertyName = DOMPropertyNames[propName];\n      }\n\n      if (DOMMutationMethods.hasOwnProperty(propName)) {\n        propertyInfo.mutationMethod = DOMMutationMethods[propName];\n      }\n\n      DOMProperty.properties[propName] = propertyInfo;\n    }\n  }\n};\n\n/* eslint-disable max-len */\nvar ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\n/* eslint-enable max-len */\n\n/**\n * DOMProperty exports lookup objects that can be used like functions:\n *\n *   > DOMProperty.isValid['id']\n *   true\n *   > DOMProperty.isValid['foobar']\n *   undefined\n *\n * Although this may be confusing, it performs better in general.\n *\n * @see http://jsperf.com/key-exists\n * @see http://jsperf.com/key-missing\n */\nvar DOMProperty = {\n\n  ID_ATTRIBUTE_NAME: 'data-reactid',\n  ROOT_ATTRIBUTE_NAME: 'data-reactroot',\n\n  ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,\n  ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\\\-.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040',\n\n  /**\n   * Map from property \"standard name\" to an object with info about how to set\n   * the property in the DOM. Each object contains:\n   *\n   * attributeName:\n   *   Used when rendering markup or with `*Attribute()`.\n   * attributeNamespace\n   * propertyName:\n   *   Used on DOM node instances. (This includes properties that mutate due to\n   *   external factors.)\n   * mutationMethod:\n   *   If non-null, used instead of the property or `setAttribute()` after\n   *   initial render.\n   * mustUseProperty:\n   *   Whether the property must be accessed and mutated as an object property.\n   * hasBooleanValue:\n   *   Whether the property should be removed when set to a falsey value.\n   * hasNumericValue:\n   *   Whether the property must be numeric or parse as a numeric and should be\n   *   removed when set to a falsey value.\n   * hasPositiveNumericValue:\n   *   Whether the property must be positive numeric or parse as a positive\n   *   numeric and should be removed when set to a falsey value.\n   * hasOverloadedBooleanValue:\n   *   Whether the property can be used as a flag as well as with a value.\n   *   Removed when strictly equal to false; present without a value when\n   *   strictly equal to true; present with a value otherwise.\n   */\n  properties: {},\n\n  /**\n   * Mapping from lowercase property names to the properly cased version, used\n   * to warn in the case of missing properties. Available only in __DEV__.\n   * @type {Object}\n   */\n  getPossibleStandardName: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * All of the isCustomAttribute() functions that have been injected.\n   */\n  _isCustomAttributeFunctions: [],\n\n  /**\n   * Checks whether a property name is a custom attribute.\n   * @method\n   */\n  isCustomAttribute: function (attributeName) {\n    for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {\n      var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];\n      if (isCustomAttributeFn(attributeName)) {\n        return true;\n      }\n    }\n    return false;\n  },\n\n  injection: DOMPropertyInjection\n};\n\nmodule.exports = DOMProperty;\n},{\"139\":139,\"161\":161}],11:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMPropertyOperations\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInstrumentation = _dereq_(49);\nvar ReactInstrumentation = _dereq_(74);\n\nvar quoteAttributeValueForBrowser = _dereq_(138);\nvar warning = _dereq_(171);\n\nvar VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');\nvar illegalAttributeNameCache = {};\nvar validatedAttributeNameCache = {};\n\nfunction isAttributeNameSafe(attributeName) {\n  if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {\n    return true;\n  }\n  if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {\n    return false;\n  }\n  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {\n    validatedAttributeNameCache[attributeName] = true;\n    return true;\n  }\n  illegalAttributeNameCache[attributeName] = true;\n  \"development\" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;\n  return false;\n}\n\nfunction shouldIgnoreValue(propertyInfo, value) {\n  return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;\n}\n\n/**\n * Operations for dealing with DOM properties.\n */\nvar DOMPropertyOperations = {\n\n  /**\n   * Creates markup for the ID property.\n   *\n   * @param {string} id Unescaped ID.\n   * @return {string} Markup string.\n   */\n  createMarkupForID: function (id) {\n    return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);\n  },\n\n  setAttributeForID: function (node, id) {\n    node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);\n  },\n\n  createMarkupForRoot: function () {\n    return DOMProperty.ROOT_ATTRIBUTE_NAME + '=\"\"';\n  },\n\n  setAttributeForRoot: function (node) {\n    node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');\n  },\n\n  /**\n   * Creates markup for a property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {?string} Markup string, or null if the property was invalid.\n   */\n  createMarkupForProperty: function (name, value) {\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onCreateMarkupForProperty(name, value);\n    }\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      if (shouldIgnoreValue(propertyInfo, value)) {\n        return '';\n      }\n      var attributeName = propertyInfo.attributeName;\n      if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n        return attributeName + '=\"\"';\n      }\n      return attributeName + '=' + quoteAttributeValueForBrowser(value);\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      if (value == null) {\n        return '';\n      }\n      return name + '=' + quoteAttributeValueForBrowser(value);\n    }\n    return null;\n  },\n\n  /**\n   * Creates markup for a custom property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {string} Markup string, or empty string if the property was invalid.\n   */\n  createMarkupForCustomAttribute: function (name, value) {\n    if (!isAttributeNameSafe(name) || value == null) {\n      return '';\n    }\n    return name + '=' + quoteAttributeValueForBrowser(value);\n  },\n\n  /**\n   * Sets the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   * @param {*} value\n   */\n  setValueForProperty: function (node, name, value) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, value);\n      } else if (shouldIgnoreValue(propertyInfo, value)) {\n        this.deleteValueForProperty(node, name);\n        return;\n      } else if (propertyInfo.mustUseProperty) {\n        // Contrary to `setAttribute`, object properties are properly\n        // `toString`ed by IE8/9.\n        node[propertyInfo.propertyName] = value;\n      } else {\n        var attributeName = propertyInfo.attributeName;\n        var namespace = propertyInfo.attributeNamespace;\n        // `setAttribute` with objects becomes only `[object]` in IE8/9,\n        // ('' + value) makes it output the correct toString()-value.\n        if (namespace) {\n          node.setAttributeNS(namespace, attributeName, '' + value);\n        } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n          node.setAttribute(attributeName, '');\n        } else {\n          node.setAttribute(attributeName, '' + value);\n        }\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      DOMPropertyOperations.setValueForAttribute(node, name, value);\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onSetValueForProperty(node, name, value);\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  setValueForAttribute: function (node, name, value) {\n    if (!isAttributeNameSafe(name)) {\n      return;\n    }\n    if (value == null) {\n      node.removeAttribute(name);\n    } else {\n      node.setAttribute(name, '' + value);\n    }\n\n    if (\"development\" !== 'production') {\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  /**\n   * Deletes an attributes from a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForAttribute: function (node, name) {\n    node.removeAttribute(name);\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  },\n\n  /**\n   * Deletes the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForProperty: function (node, name) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, undefined);\n      } else if (propertyInfo.mustUseProperty) {\n        var propName = propertyInfo.propertyName;\n        if (propertyInfo.hasBooleanValue) {\n          node[propName] = false;\n        } else {\n          node[propName] = '';\n        }\n      } else {\n        node.removeAttribute(propertyInfo.attributeName);\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      node.removeAttribute(name);\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  }\n\n};\n\nmodule.exports = DOMPropertyOperations;\n},{\"10\":10,\"138\":138,\"171\":171,\"41\":41,\"49\":49,\"74\":74}],12:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Danger\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createNodesFromMarkup = _dereq_(152);\nvar emptyFunction = _dereq_(153);\nvar invariant = _dereq_(161);\n\nvar Danger = {\n\n  /**\n   * Replaces a node with a string of markup at its current position within its\n   * parent. The markup must render into a single root node.\n   *\n   * @param {DOMElement} oldChild Child node to replace.\n   * @param {string} markup Markup to render in place of the child node.\n   * @internal\n   */\n  dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) {\n    !ExecutionEnvironment.canUseDOM ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('56') : void 0;\n    !markup ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : _prodInvariant('57') : void 0;\n    !(oldChild.nodeName !== 'HTML') ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().') : _prodInvariant('58') : void 0;\n\n    if (typeof markup === 'string') {\n      var newChild = createNodesFromMarkup(markup, emptyFunction)[0];\n      oldChild.parentNode.replaceChild(newChild, oldChild);\n    } else {\n      DOMLazyTree.replaceChildWithTree(oldChild, markup);\n    }\n  }\n\n};\n\nmodule.exports = Danger;\n},{\"139\":139,\"147\":147,\"152\":152,\"153\":153,\"161\":161,\"8\":8}],13:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DefaultEventPluginOrder\n */\n\n'use strict';\n\nvar keyOf = _dereq_(165);\n\n/**\n * Module that is injectable into `EventPluginHub`, that specifies a\n * deterministic ordering of `EventPlugin`s. A convenient way to reason about\n * plugins, without having to package every one of them. This is better than\n * having plugins be ordered in the same order that they are injected because\n * that ordering would be influenced by the packaging order.\n * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that\n * preventing default on events is convenient in `SimpleEventPlugin` handlers.\n */\nvar DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })];\n\nmodule.exports = DefaultEventPluginOrder;\n},{\"165\":165}],14:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DisabledInputUtils\n */\n\n'use strict';\n\nvar disableableMouseListenerNames = {\n  onClick: true,\n  onDoubleClick: true,\n  onMouseDown: true,\n  onMouseMove: true,\n  onMouseUp: true,\n\n  onClickCapture: true,\n  onDoubleClickCapture: true,\n  onMouseDownCapture: true,\n  onMouseMoveCapture: true,\n  onMouseUpCapture: true\n};\n\n/**\n * Implements a host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar DisabledInputUtils = {\n  getHostProps: function (inst, props) {\n    if (!props.disabled) {\n      return props;\n    }\n\n    // Copy the props, except the mouse listeners\n    var hostProps = {};\n    for (var key in props) {\n      if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) {\n        hostProps[key] = props[key];\n      }\n    }\n\n    return hostProps;\n  }\n};\n\nmodule.exports = DisabledInputUtils;\n},{}],15:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EnterLeaveEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticMouseEvent = _dereq_(108);\n\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  mouseEnter: {\n    registrationName: keyOf({ onMouseEnter: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  },\n  mouseLeave: {\n    registrationName: keyOf({ onMouseLeave: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  }\n};\n\nvar EnterLeaveEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  /**\n   * For almost every interaction we care about, there will be both a top-level\n   * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that\n   * we do not extract duplicate events. However, moving the mouse into the\n   * browser from outside will not fire a `mouseout` event. In this case, we use\n   * the `mouseover` top-level event.\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {\n      return null;\n    }\n    if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) {\n      // Must not be a mouse in or mouse out - ignoring.\n      return null;\n    }\n\n    var win;\n    if (nativeEventTarget.window === nativeEventTarget) {\n      // `nativeEventTarget` is probably a window object.\n      win = nativeEventTarget;\n    } else {\n      // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n      var doc = nativeEventTarget.ownerDocument;\n      if (doc) {\n        win = doc.defaultView || doc.parentWindow;\n      } else {\n        win = window;\n      }\n    }\n\n    var from;\n    var to;\n    if (topLevelType === topLevelTypes.topMouseOut) {\n      from = targetInst;\n      var related = nativeEvent.relatedTarget || nativeEvent.toElement;\n      to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;\n    } else {\n      // Moving to a node from outside the window.\n      from = null;\n      to = targetInst;\n    }\n\n    if (from === to) {\n      // Nothing pertains to our managed components.\n      return null;\n    }\n\n    var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);\n    var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);\n\n    var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);\n    leave.type = 'mouseleave';\n    leave.target = fromNode;\n    leave.relatedTarget = toNode;\n\n    var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);\n    enter.type = 'mouseenter';\n    enter.target = toNode;\n    enter.relatedTarget = fromNode;\n\n    EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);\n\n    return [leave, enter];\n  }\n\n};\n\nmodule.exports = EnterLeaveEventPlugin;\n},{\"108\":108,\"16\":16,\"165\":165,\"20\":20,\"41\":41}],16:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventConstants\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar PropagationPhases = keyMirror({ bubbled: null, captured: null });\n\n/**\n * Types of raw signals from the browser caught at the top level.\n */\nvar topLevelTypes = keyMirror({\n  topAbort: null,\n  topAnimationEnd: null,\n  topAnimationIteration: null,\n  topAnimationStart: null,\n  topBlur: null,\n  topCanPlay: null,\n  topCanPlayThrough: null,\n  topChange: null,\n  topClick: null,\n  topCompositionEnd: null,\n  topCompositionStart: null,\n  topCompositionUpdate: null,\n  topContextMenu: null,\n  topCopy: null,\n  topCut: null,\n  topDoubleClick: null,\n  topDrag: null,\n  topDragEnd: null,\n  topDragEnter: null,\n  topDragExit: null,\n  topDragLeave: null,\n  topDragOver: null,\n  topDragStart: null,\n  topDrop: null,\n  topDurationChange: null,\n  topEmptied: null,\n  topEncrypted: null,\n  topEnded: null,\n  topError: null,\n  topFocus: null,\n  topInput: null,\n  topInvalid: null,\n  topKeyDown: null,\n  topKeyPress: null,\n  topKeyUp: null,\n  topLoad: null,\n  topLoadedData: null,\n  topLoadedMetadata: null,\n  topLoadStart: null,\n  topMouseDown: null,\n  topMouseMove: null,\n  topMouseOut: null,\n  topMouseOver: null,\n  topMouseUp: null,\n  topPaste: null,\n  topPause: null,\n  topPlay: null,\n  topPlaying: null,\n  topProgress: null,\n  topRateChange: null,\n  topReset: null,\n  topScroll: null,\n  topSeeked: null,\n  topSeeking: null,\n  topSelectionChange: null,\n  topStalled: null,\n  topSubmit: null,\n  topSuspend: null,\n  topTextInput: null,\n  topTimeUpdate: null,\n  topTouchCancel: null,\n  topTouchEnd: null,\n  topTouchMove: null,\n  topTouchStart: null,\n  topTransitionEnd: null,\n  topVolumeChange: null,\n  topWaiting: null,\n  topWheel: null\n});\n\nvar EventConstants = {\n  topLevelTypes: topLevelTypes,\n  PropagationPhases: PropagationPhases\n};\n\nmodule.exports = EventConstants;\n},{\"164\":164}],17:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginHub\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventPluginRegistry = _dereq_(18);\nvar EventPluginUtils = _dereq_(19);\nvar ReactErrorUtils = _dereq_(65);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar invariant = _dereq_(161);\n\n/**\n * Internal store for event listeners\n */\nvar listenerBank = {};\n\n/**\n * Internal queue of events that have accumulated their dispatches and are\n * waiting to have their dispatches executed.\n */\nvar eventQueue = null;\n\n/**\n * Dispatches an event and releases it back into the pool, unless persistent.\n *\n * @param {?object} event Synthetic event to be dispatched.\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @private\n */\nvar executeDispatchesAndRelease = function (event, simulated) {\n  if (event) {\n    EventPluginUtils.executeDispatchesInOrder(event, simulated);\n\n    if (!event.isPersistent()) {\n      event.constructor.release(event);\n    }\n  }\n};\nvar executeDispatchesAndReleaseSimulated = function (e) {\n  return executeDispatchesAndRelease(e, true);\n};\nvar executeDispatchesAndReleaseTopLevel = function (e) {\n  return executeDispatchesAndRelease(e, false);\n};\n\n/**\n * This is a unified interface for event plugins to be installed and configured.\n *\n * Event plugins can implement the following properties:\n *\n *   `extractEvents` {function(string, DOMEventTarget, string, object): *}\n *     Required. When a top-level event is fired, this method is expected to\n *     extract synthetic events that will in turn be queued and dispatched.\n *\n *   `eventTypes` {object}\n *     Optional, plugins that fire events must publish a mapping of registration\n *     names that are used to register listeners. Values of this mapping must\n *     be objects that contain `registrationName` or `phasedRegistrationNames`.\n *\n *   `executeDispatch` {function(object, function, string)}\n *     Optional, allows plugins to override how an event gets dispatched. By\n *     default, the listener is simply invoked.\n *\n * Each plugin that is injected into `EventsPluginHub` is immediately operable.\n *\n * @public\n */\nvar EventPluginHub = {\n\n  /**\n   * Methods for injecting dependencies.\n   */\n  injection: {\n\n    /**\n     * @param {array} InjectedEventPluginOrder\n     * @public\n     */\n    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,\n\n    /**\n     * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n     */\n    injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName\n\n  },\n\n  /**\n   * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {function} listener The callback to store.\n   */\n  putListener: function (inst, registrationName, listener) {\n    !(typeof listener === 'function') ? \"development\" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : _prodInvariant('94', registrationName, typeof listener) : void 0;\n\n    var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});\n    bankForRegistrationName[inst._rootNodeID] = listener;\n\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.didPutListener) {\n      PluginModule.didPutListener(inst, registrationName, listener);\n    }\n  },\n\n  /**\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @return {?function} The stored callback.\n   */\n  getListener: function (inst, registrationName) {\n    var bankForRegistrationName = listenerBank[registrationName];\n    return bankForRegistrationName && bankForRegistrationName[inst._rootNodeID];\n  },\n\n  /**\n   * Deletes a listener from the registration bank.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   */\n  deleteListener: function (inst, registrationName) {\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.willDeleteListener) {\n      PluginModule.willDeleteListener(inst, registrationName);\n    }\n\n    var bankForRegistrationName = listenerBank[registrationName];\n    // TODO: This should never be null -- when is it?\n    if (bankForRegistrationName) {\n      delete bankForRegistrationName[inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Deletes all listeners for the DOM element with the supplied ID.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   */\n  deleteAllListeners: function (inst) {\n    for (var registrationName in listenerBank) {\n      if (!listenerBank.hasOwnProperty(registrationName)) {\n        continue;\n      }\n\n      if (!listenerBank[registrationName][inst._rootNodeID]) {\n        continue;\n      }\n\n      var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n      if (PluginModule && PluginModule.willDeleteListener) {\n        PluginModule.willDeleteListener(inst, registrationName);\n      }\n\n      delete listenerBank[registrationName][inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Allows registered plugins an opportunity to extract events from top-level\n   * native browser events.\n   *\n   * @return {*} An accumulation of synthetic events.\n   * @internal\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events;\n    var plugins = EventPluginRegistry.plugins;\n    for (var i = 0; i < plugins.length; i++) {\n      // Not every plugin in the ordering may be loaded at runtime.\n      var possiblePlugin = plugins[i];\n      if (possiblePlugin) {\n        var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n        if (extractedEvents) {\n          events = accumulateInto(events, extractedEvents);\n        }\n      }\n    }\n    return events;\n  },\n\n  /**\n   * Enqueues a synthetic event that should be dispatched when\n   * `processEventQueue` is invoked.\n   *\n   * @param {*} events An accumulation of synthetic events.\n   * @internal\n   */\n  enqueueEvents: function (events) {\n    if (events) {\n      eventQueue = accumulateInto(eventQueue, events);\n    }\n  },\n\n  /**\n   * Dispatches all synthetic events on the event queue.\n   *\n   * @internal\n   */\n  processEventQueue: function (simulated) {\n    // Set `eventQueue` to null before processing it so that we can tell if more\n    // events get enqueued while processing.\n    var processingEventQueue = eventQueue;\n    eventQueue = null;\n    if (simulated) {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);\n    } else {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);\n    }\n    !!eventQueue ? \"development\" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : _prodInvariant('95') : void 0;\n    // This would be a good time to rethrow if any of the event handlers threw.\n    ReactErrorUtils.rethrowCaughtError();\n  },\n\n  /**\n   * These are needed for tests only. Do not use!\n   */\n  __purge: function () {\n    listenerBank = {};\n  },\n\n  __getListenerBank: function () {\n    return listenerBank;\n  }\n\n};\n\nmodule.exports = EventPluginHub;\n},{\"115\":115,\"124\":124,\"139\":139,\"161\":161,\"18\":18,\"19\":19,\"65\":65}],18:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginRegistry\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Injectable ordering of event plugins.\n */\nvar EventPluginOrder = null;\n\n/**\n * Injectable mapping from names to event plugin modules.\n */\nvar namesToPlugins = {};\n\n/**\n * Recomputes the plugin list using the injected plugins and plugin ordering.\n *\n * @private\n */\nfunction recomputePluginOrdering() {\n  if (!EventPluginOrder) {\n    // Wait until an `EventPluginOrder` is injected.\n    return;\n  }\n  for (var pluginName in namesToPlugins) {\n    var PluginModule = namesToPlugins[pluginName];\n    var pluginIndex = EventPluginOrder.indexOf(pluginName);\n    !(pluginIndex > -1) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0;\n    if (EventPluginRegistry.plugins[pluginIndex]) {\n      continue;\n    }\n    !PluginModule.extractEvents ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0;\n    EventPluginRegistry.plugins[pluginIndex] = PluginModule;\n    var publishedEvents = PluginModule.eventTypes;\n    for (var eventName in publishedEvents) {\n      !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('98', eventName, pluginName) : void 0;\n    }\n  }\n}\n\n/**\n * Publishes an event so that it can be dispatched by the supplied plugin.\n *\n * @param {object} dispatchConfig Dispatch configuration for the event.\n * @param {object} PluginModule Plugin publishing the event.\n * @return {boolean} True if the event was successfully published.\n * @private\n */\nfunction publishEventForPlugin(dispatchConfig, PluginModule, eventName) {\n  !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0;\n  EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;\n\n  var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;\n  if (phasedRegistrationNames) {\n    for (var phaseName in phasedRegistrationNames) {\n      if (phasedRegistrationNames.hasOwnProperty(phaseName)) {\n        var phasedRegistrationName = phasedRegistrationNames[phaseName];\n        publishRegistrationName(phasedRegistrationName, PluginModule, eventName);\n      }\n    }\n    return true;\n  } else if (dispatchConfig.registrationName) {\n    publishRegistrationName(dispatchConfig.registrationName, PluginModule, eventName);\n    return true;\n  }\n  return false;\n}\n\n/**\n * Publishes a registration name that is used to identify dispatched events and\n * can be used with `EventPluginHub.putListener` to register listeners.\n *\n * @param {string} registrationName Registration name to add.\n * @param {object} PluginModule Plugin publishing the event.\n * @private\n */\nfunction publishRegistrationName(registrationName, PluginModule, eventName) {\n  !!EventPluginRegistry.registrationNameModules[registrationName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0;\n  EventPluginRegistry.registrationNameModules[registrationName] = PluginModule;\n  EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies;\n\n  if (\"development\" !== 'production') {\n    var lowerCasedName = registrationName.toLowerCase();\n    EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;\n\n    if (registrationName === 'onDoubleClick') {\n      EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;\n    }\n  }\n}\n\n/**\n * Registers plugins so that they can extract and dispatch events.\n *\n * @see {EventPluginHub}\n */\nvar EventPluginRegistry = {\n\n  /**\n   * Ordered list of injected plugins.\n   */\n  plugins: [],\n\n  /**\n   * Mapping from event name to dispatch config\n   */\n  eventNameDispatchConfigs: {},\n\n  /**\n   * Mapping from registration name to plugin module\n   */\n  registrationNameModules: {},\n\n  /**\n   * Mapping from registration name to event name\n   */\n  registrationNameDependencies: {},\n\n  /**\n   * Mapping from lowercase registration names to the properly cased version,\n   * used to warn in the case of missing event handlers. Available\n   * only in __DEV__.\n   * @type {Object}\n   */\n  possibleRegistrationNames: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * Injects an ordering of plugins (by plugin name). This allows the ordering\n   * to be decoupled from injection of the actual plugins so that ordering is\n   * always deterministic regardless of packaging, on-the-fly injection, etc.\n   *\n   * @param {array} InjectedEventPluginOrder\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginOrder}\n   */\n  injectEventPluginOrder: function (InjectedEventPluginOrder) {\n    !!EventPluginOrder ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : _prodInvariant('101') : void 0;\n    // Clone the ordering so it cannot be dynamically mutated.\n    EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);\n    recomputePluginOrdering();\n  },\n\n  /**\n   * Injects plugins to be used by `EventPluginHub`. The plugin names must be\n   * in the ordering injected by `injectEventPluginOrder`.\n   *\n   * Plugins can be injected as part of page initialization or on-the-fly.\n   *\n   * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginsByName}\n   */\n  injectEventPluginsByName: function (injectedNamesToPlugins) {\n    var isOrderingDirty = false;\n    for (var pluginName in injectedNamesToPlugins) {\n      if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {\n        continue;\n      }\n      var PluginModule = injectedNamesToPlugins[pluginName];\n      if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== PluginModule) {\n        !!namesToPlugins[pluginName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0;\n        namesToPlugins[pluginName] = PluginModule;\n        isOrderingDirty = true;\n      }\n    }\n    if (isOrderingDirty) {\n      recomputePluginOrdering();\n    }\n  },\n\n  /**\n   * Looks up the plugin for the supplied event.\n   *\n   * @param {object} event A synthetic event.\n   * @return {?object} The plugin that created the supplied event.\n   * @internal\n   */\n  getPluginModuleForEvent: function (event) {\n    var dispatchConfig = event.dispatchConfig;\n    if (dispatchConfig.registrationName) {\n      return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null;\n    }\n    for (var phase in dispatchConfig.phasedRegistrationNames) {\n      if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) {\n        continue;\n      }\n      var PluginModule = EventPluginRegistry.registrationNameModules[dispatchConfig.phasedRegistrationNames[phase]];\n      if (PluginModule) {\n        return PluginModule;\n      }\n    }\n    return null;\n  },\n\n  /**\n   * Exposed for unit testing.\n   * @private\n   */\n  _resetEventPlugins: function () {\n    EventPluginOrder = null;\n    for (var pluginName in namesToPlugins) {\n      if (namesToPlugins.hasOwnProperty(pluginName)) {\n        delete namesToPlugins[pluginName];\n      }\n    }\n    EventPluginRegistry.plugins.length = 0;\n\n    var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs;\n    for (var eventName in eventNameDispatchConfigs) {\n      if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {\n        delete eventNameDispatchConfigs[eventName];\n      }\n    }\n\n    var registrationNameModules = EventPluginRegistry.registrationNameModules;\n    for (var registrationName in registrationNameModules) {\n      if (registrationNameModules.hasOwnProperty(registrationName)) {\n        delete registrationNameModules[registrationName];\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames;\n      for (var lowerCasedName in possibleRegistrationNames) {\n        if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) {\n          delete possibleRegistrationNames[lowerCasedName];\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = EventPluginRegistry;\n},{\"139\":139,\"161\":161}],19:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar ReactErrorUtils = _dereq_(65);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Injected dependencies:\n */\n\n/**\n * - `ComponentTree`: [required] Module that can convert between React instances\n *   and actual node references.\n */\nvar ComponentTree;\nvar TreeTraversal;\nvar injection = {\n  injectComponentTree: function (Injected) {\n    ComponentTree = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;\n    }\n  },\n  injectTreeTraversal: function (Injected) {\n    TreeTraversal = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;\n    }\n  }\n};\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nfunction isEndish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel;\n}\n\nfunction isMoveish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove;\n}\nfunction isStartish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart;\n}\n\nvar validateEventDispatches;\nif (\"development\" !== 'production') {\n  validateEventDispatches = function (event) {\n    var dispatchListeners = event._dispatchListeners;\n    var dispatchInstances = event._dispatchInstances;\n\n    var listenersIsArr = Array.isArray(dispatchListeners);\n    var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;\n\n    var instancesIsArr = Array.isArray(dispatchInstances);\n    var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;\n\n    \"development\" !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;\n  };\n}\n\n/**\n * Dispatch the event to the listener.\n * @param {SyntheticEvent} event SyntheticEvent to handle\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @param {function} listener Application-level callback\n * @param {*} inst Internal component instance\n */\nfunction executeDispatch(event, simulated, listener, inst) {\n  var type = event.type || 'unknown-event';\n  event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);\n  if (simulated) {\n    ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);\n  } else {\n    ReactErrorUtils.invokeGuardedCallback(type, listener, event);\n  }\n  event.currentTarget = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches.\n */\nfunction executeDispatchesInOrder(event, simulated) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);\n    }\n  } else if (dispatchListeners) {\n    executeDispatch(event, simulated, dispatchListeners, dispatchInstances);\n  }\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches, but stops\n * at the first dispatch execution returning true, and returns that id.\n *\n * @return {?string} id of the first dispatch execution who's listener returns\n * true, or null if no listener returned true.\n */\nfunction executeDispatchesInOrderStopAtTrueImpl(event) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      if (dispatchListeners[i](event, dispatchInstances[i])) {\n        return dispatchInstances[i];\n      }\n    }\n  } else if (dispatchListeners) {\n    if (dispatchListeners(event, dispatchInstances)) {\n      return dispatchInstances;\n    }\n  }\n  return null;\n}\n\n/**\n * @see executeDispatchesInOrderStopAtTrueImpl\n */\nfunction executeDispatchesInOrderStopAtTrue(event) {\n  var ret = executeDispatchesInOrderStopAtTrueImpl(event);\n  event._dispatchInstances = null;\n  event._dispatchListeners = null;\n  return ret;\n}\n\n/**\n * Execution of a \"direct\" dispatch - there must be at most one dispatch\n * accumulated on the event or it is considered an error. It doesn't really make\n * sense for an event with multiple dispatches (bubbled) to keep track of the\n * return values at each dispatch execution, but it does tend to make sense when\n * dealing with \"direct\" dispatches.\n *\n * @return {*} The return value of executing the single dispatch.\n */\nfunction executeDirectDispatch(event) {\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  var dispatchListener = event._dispatchListeners;\n  var dispatchInstance = event._dispatchInstances;\n  !!Array.isArray(dispatchListener) ? \"development\" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0;\n  event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;\n  var res = dispatchListener ? dispatchListener(event) : null;\n  event.currentTarget = null;\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n  return res;\n}\n\n/**\n * @param {SyntheticEvent} event\n * @return {boolean} True iff number of dispatches accumulated is greater than 0.\n */\nfunction hasDispatches(event) {\n  return !!event._dispatchListeners;\n}\n\n/**\n * General utilities that are useful in creating custom Event Plugins.\n */\nvar EventPluginUtils = {\n  isEndish: isEndish,\n  isMoveish: isMoveish,\n  isStartish: isStartish,\n\n  executeDirectDispatch: executeDirectDispatch,\n  executeDispatchesInOrder: executeDispatchesInOrder,\n  executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,\n  hasDispatches: hasDispatches,\n\n  getInstanceFromNode: function (node) {\n    return ComponentTree.getInstanceFromNode(node);\n  },\n  getNodeFromInstance: function (node) {\n    return ComponentTree.getNodeFromInstance(node);\n  },\n  isAncestor: function (a, b) {\n    return TreeTraversal.isAncestor(a, b);\n  },\n  getLowestCommonAncestor: function (a, b) {\n    return TreeTraversal.getLowestCommonAncestor(a, b);\n  },\n  getParentInstance: function (inst) {\n    return TreeTraversal.getParentInstance(inst);\n  },\n  traverseTwoPhase: function (target, fn, arg) {\n    return TreeTraversal.traverseTwoPhase(target, fn, arg);\n  },\n  traverseEnterLeave: function (from, to, fn, argFrom, argTo) {\n    return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);\n  },\n\n  injection: injection\n};\n\nmodule.exports = EventPluginUtils;\n},{\"139\":139,\"16\":16,\"161\":161,\"171\":171,\"65\":65}],20:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPropagators\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar warning = _dereq_(171);\n\nvar PropagationPhases = EventConstants.PropagationPhases;\nvar getListener = EventPluginHub.getListener;\n\n/**\n * Some event types have a notion of different registration names for different\n * \"phases\" of propagation. This finds listeners by a given phase.\n */\nfunction listenerAtPhase(inst, event, propagationPhase) {\n  var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];\n  return getListener(inst, registrationName);\n}\n\n/**\n * Tags a `SyntheticEvent` with dispatched listeners. Creating this function\n * here, allows us to not have to bind or create functions for each event.\n * Mutating the event's members allows us to not have to create a wrapping\n * \"dispatch\" object that pairs the event with the listener.\n */\nfunction accumulateDirectionalDispatches(inst, upwards, event) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;\n  }\n  var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured;\n  var listener = listenerAtPhase(inst, event, phase);\n  if (listener) {\n    event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n  }\n}\n\n/**\n * Collect dispatches (must be entirely collected before dispatching - see unit\n * tests). Lazily allocate the array to conserve memory.  We must loop through\n * each event and perform the traversal for each one. We cannot perform a\n * single traversal for the entire collection of events because each event may\n * have a different target.\n */\nfunction accumulateTwoPhaseDispatchesSingle(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.\n */\nfunction accumulateTwoPhaseDispatchesSingleSkipTarget(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    var targetInst = event._targetInst;\n    var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;\n    EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Accumulates without regard to direction, does not look for phased\n * registration names. Same as `accumulateDirectDispatchesSingle` but without\n * requiring that the `dispatchMarker` be the same as the dispatched ID.\n */\nfunction accumulateDispatches(inst, ignoredDirection, event) {\n  if (event && event.dispatchConfig.registrationName) {\n    var registrationName = event.dispatchConfig.registrationName;\n    var listener = getListener(inst, registrationName);\n    if (listener) {\n      event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n    }\n  }\n}\n\n/**\n * Accumulates dispatches on an `SyntheticEvent`, but only for the\n * `dispatchMarker`.\n * @param {SyntheticEvent} event\n */\nfunction accumulateDirectDispatchesSingle(event) {\n  if (event && event.dispatchConfig.registrationName) {\n    accumulateDispatches(event._targetInst, null, event);\n  }\n}\n\nfunction accumulateTwoPhaseDispatches(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);\n}\n\nfunction accumulateTwoPhaseDispatchesSkipTarget(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);\n}\n\nfunction accumulateEnterLeaveDispatches(leave, enter, from, to) {\n  EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);\n}\n\nfunction accumulateDirectDispatches(events) {\n  forEachAccumulated(events, accumulateDirectDispatchesSingle);\n}\n\n/**\n * A small set of propagation patterns, each of which will accept a small amount\n * of information, and generate a set of \"dispatch ready event objects\" - which\n * are sets of events that have already been annotated with a set of dispatched\n * listener functions/ids. The API is designed this way to discourage these\n * propagation strategies from actually executing the dispatches, since we\n * always want to collect the entire set of dispatches before executing event a\n * single one.\n *\n * @constructor EventPropagators\n */\nvar EventPropagators = {\n  accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,\n  accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,\n  accumulateDirectDispatches: accumulateDirectDispatches,\n  accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches\n};\n\nmodule.exports = EventPropagators;\n},{\"115\":115,\"124\":124,\"16\":16,\"17\":17,\"171\":171,\"19\":19}],21:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule FallbackCompositionState\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * This helper class stores information about text content of a target node,\n * allowing comparison of content before and after a given event.\n *\n * Identify the node where selection currently begins, then observe\n * both its text content and its current position in the DOM. Since the\n * browser may natively replace the target node during composition, we can\n * use its position to find its replacement.\n *\n * @param {DOMEventTarget} root\n */\nfunction FallbackCompositionState(root) {\n  this._root = root;\n  this._startText = this.getText();\n  this._fallbackText = null;\n}\n\n_assign(FallbackCompositionState.prototype, {\n  destructor: function () {\n    this._root = null;\n    this._startText = null;\n    this._fallbackText = null;\n  },\n\n  /**\n   * Get current text of input.\n   *\n   * @return {string}\n   */\n  getText: function () {\n    if ('value' in this._root) {\n      return this._root.value;\n    }\n    return this._root[getTextContentAccessor()];\n  },\n\n  /**\n   * Determine the differing substring between the initially stored\n   * text content and the current content.\n   *\n   * @return {string}\n   */\n  getData: function () {\n    if (this._fallbackText) {\n      return this._fallbackText;\n    }\n\n    var start;\n    var startValue = this._startText;\n    var startLength = startValue.length;\n    var end;\n    var endValue = this.getText();\n    var endLength = endValue.length;\n\n    for (start = 0; start < startLength; start++) {\n      if (startValue[start] !== endValue[start]) {\n        break;\n      }\n    }\n\n    var minEnd = startLength - start;\n    for (end = 1; end <= minEnd; end++) {\n      if (startValue[startLength - end] !== endValue[endLength - end]) {\n        break;\n      }\n    }\n\n    var sliceTail = end > 1 ? 1 - end : undefined;\n    this._fallbackText = endValue.slice(start, sliceTail);\n    return this._fallbackText;\n  }\n});\n\nPooledClass.addPoolingTo(FallbackCompositionState);\n\nmodule.exports = FallbackCompositionState;\n},{\"132\":132,\"172\":172,\"25\":25}],22:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule HTMLDOMPropertyConfig\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\n\nvar MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;\nvar HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;\nvar HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;\nvar HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;\nvar HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;\n\nvar HTMLDOMPropertyConfig = {\n  isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')),\n  Properties: {\n    /**\n     * Standard Properties\n     */\n    accept: 0,\n    acceptCharset: 0,\n    accessKey: 0,\n    action: 0,\n    allowFullScreen: HAS_BOOLEAN_VALUE,\n    allowTransparency: 0,\n    alt: 0,\n    async: HAS_BOOLEAN_VALUE,\n    autoComplete: 0,\n    // autoFocus is polyfilled/normalized by AutoFocusUtils\n    // autoFocus: HAS_BOOLEAN_VALUE,\n    autoPlay: HAS_BOOLEAN_VALUE,\n    capture: HAS_BOOLEAN_VALUE,\n    cellPadding: 0,\n    cellSpacing: 0,\n    charSet: 0,\n    challenge: 0,\n    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    cite: 0,\n    classID: 0,\n    className: 0,\n    cols: HAS_POSITIVE_NUMERIC_VALUE,\n    colSpan: 0,\n    content: 0,\n    contentEditable: 0,\n    contextMenu: 0,\n    controls: HAS_BOOLEAN_VALUE,\n    coords: 0,\n    crossOrigin: 0,\n    data: 0, // For `<object />` acts as `src`.\n    dateTime: 0,\n    'default': HAS_BOOLEAN_VALUE,\n    defer: HAS_BOOLEAN_VALUE,\n    dir: 0,\n    disabled: HAS_BOOLEAN_VALUE,\n    download: HAS_OVERLOADED_BOOLEAN_VALUE,\n    draggable: 0,\n    encType: 0,\n    form: 0,\n    formAction: 0,\n    formEncType: 0,\n    formMethod: 0,\n    formNoValidate: HAS_BOOLEAN_VALUE,\n    formTarget: 0,\n    frameBorder: 0,\n    headers: 0,\n    height: 0,\n    hidden: HAS_BOOLEAN_VALUE,\n    high: 0,\n    href: 0,\n    hrefLang: 0,\n    htmlFor: 0,\n    httpEquiv: 0,\n    icon: 0,\n    id: 0,\n    inputMode: 0,\n    integrity: 0,\n    is: 0,\n    keyParams: 0,\n    keyType: 0,\n    kind: 0,\n    label: 0,\n    lang: 0,\n    list: 0,\n    loop: HAS_BOOLEAN_VALUE,\n    low: 0,\n    manifest: 0,\n    marginHeight: 0,\n    marginWidth: 0,\n    max: 0,\n    maxLength: 0,\n    media: 0,\n    mediaGroup: 0,\n    method: 0,\n    min: 0,\n    minLength: 0,\n    // Caution; `option.selected` is not updated if `select.multiple` is\n    // disabled with `removeAttribute`.\n    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    name: 0,\n    nonce: 0,\n    noValidate: HAS_BOOLEAN_VALUE,\n    open: HAS_BOOLEAN_VALUE,\n    optimum: 0,\n    pattern: 0,\n    placeholder: 0,\n    poster: 0,\n    preload: 0,\n    profile: 0,\n    radioGroup: 0,\n    readOnly: HAS_BOOLEAN_VALUE,\n    rel: 0,\n    required: HAS_BOOLEAN_VALUE,\n    reversed: HAS_BOOLEAN_VALUE,\n    role: 0,\n    rows: HAS_POSITIVE_NUMERIC_VALUE,\n    rowSpan: HAS_NUMERIC_VALUE,\n    sandbox: 0,\n    scope: 0,\n    scoped: HAS_BOOLEAN_VALUE,\n    scrolling: 0,\n    seamless: HAS_BOOLEAN_VALUE,\n    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    shape: 0,\n    size: HAS_POSITIVE_NUMERIC_VALUE,\n    sizes: 0,\n    span: HAS_POSITIVE_NUMERIC_VALUE,\n    spellCheck: 0,\n    src: 0,\n    srcDoc: 0,\n    srcLang: 0,\n    srcSet: 0,\n    start: HAS_NUMERIC_VALUE,\n    step: 0,\n    style: 0,\n    summary: 0,\n    tabIndex: 0,\n    target: 0,\n    title: 0,\n    // Setting .type throws on non-<input> tags\n    type: 0,\n    useMap: 0,\n    value: 0,\n    width: 0,\n    wmode: 0,\n    wrap: 0,\n\n    /**\n     * RDFa Properties\n     */\n    about: 0,\n    datatype: 0,\n    inlist: 0,\n    prefix: 0,\n    // property is also supported for OpenGraph in meta tags.\n    property: 0,\n    resource: 0,\n    'typeof': 0,\n    vocab: 0,\n\n    /**\n     * Non-standard Properties\n     */\n    // autoCapitalize and autoCorrect are supported in Mobile Safari for\n    // keyboard hints.\n    autoCapitalize: 0,\n    autoCorrect: 0,\n    // autoSave allows WebKit/Blink to persist values of input fields on page reloads\n    autoSave: 0,\n    // color is for Safari mask-icon link\n    color: 0,\n    // itemProp, itemScope, itemType are for\n    // Microdata support. See http://schema.org/docs/gs.html\n    itemProp: 0,\n    itemScope: HAS_BOOLEAN_VALUE,\n    itemType: 0,\n    // itemID and itemRef are for Microdata support as well but\n    // only specified in the WHATWG spec document. See\n    // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api\n    itemID: 0,\n    itemRef: 0,\n    // results show looking glass icon and recent searches on input\n    // search fields in WebKit/Blink\n    results: 0,\n    // IE-only attribute that specifies security restrictions on an iframe\n    // as an alternative to the sandbox attribute on IE<10\n    security: 0,\n    // IE-only attribute that controls focus behavior\n    unselectable: 0\n  },\n  DOMAttributeNames: {\n    acceptCharset: 'accept-charset',\n    className: 'class',\n    htmlFor: 'for',\n    httpEquiv: 'http-equiv'\n  },\n  DOMPropertyNames: {}\n};\n\nmodule.exports = HTMLDOMPropertyConfig;\n},{\"10\":10}],23:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule KeyEscapeUtils\n * \n */\n\n'use strict';\n\n/**\n * Escape and wrap key so it is safe to use as a reactid\n *\n * @param {string} key to be escaped.\n * @return {string} the escaped key.\n */\n\nfunction escape(key) {\n  var escapeRegex = /[=:]/g;\n  var escaperLookup = {\n    '=': '=0',\n    ':': '=2'\n  };\n  var escapedString = ('' + key).replace(escapeRegex, function (match) {\n    return escaperLookup[match];\n  });\n\n  return '$' + escapedString;\n}\n\n/**\n * Unescape and unwrap key for human-readable display\n *\n * @param {string} key to unescape.\n * @return {string} the unescaped key.\n */\nfunction unescape(key) {\n  var unescapeRegex = /(=0|=2)/g;\n  var unescaperLookup = {\n    '=0': '=',\n    '=2': ':'\n  };\n  var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);\n\n  return ('' + keySubstring).replace(unescapeRegex, function (match) {\n    return unescaperLookup[match];\n  });\n}\n\nvar KeyEscapeUtils = {\n  escape: escape,\n  unescape: unescape\n};\n\nmodule.exports = KeyEscapeUtils;\n},{}],24:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule LinkedValueUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypes = _dereq_(85);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar hasReadOnlyValue = {\n  'button': true,\n  'checkbox': true,\n  'image': true,\n  'hidden': true,\n  'radio': true,\n  'reset': true,\n  'submit': true\n};\n\nfunction _assertSingleLink(inputProps) {\n  !(inputProps.checkedLink == null || inputProps.valueLink == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don\\'t want to use valueLink and vice versa.') : _prodInvariant('87') : void 0;\n}\nfunction _assertValueLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.value == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don\\'t want to use valueLink.') : _prodInvariant('88') : void 0;\n}\n\nfunction _assertCheckedLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.checked == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don\\'t want to use checkedLink') : _prodInvariant('89') : void 0;\n}\n\nvar propTypes = {\n  value: function (props, propName, componentName) {\n    if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  checked: function (props, propName, componentName) {\n    if (!props[propName] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  onChange: ReactPropTypes.func\n};\n\nvar loggedTypeFailures = {};\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Provide a linked `value` attribute for controlled forms. You should not use\n * this outside of the ReactDOM controlled form components.\n */\nvar LinkedValueUtils = {\n  checkPropTypes: function (tagName, props, owner) {\n    for (var propName in propTypes) {\n      if (propTypes.hasOwnProperty(propName)) {\n        var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop);\n      }\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var addendum = getDeclarationErrorAddendum(owner);\n        \"development\" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0;\n      }\n    }\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current value of the input either from value prop or link.\n   */\n  getValue: function (inputProps) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.value;\n    }\n    return inputProps.value;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current checked status of the input either from checked prop\n   *             or link.\n   */\n  getChecked: function (inputProps) {\n    if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.value;\n    }\n    return inputProps.checked;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @param {SyntheticEvent} event change event to handle\n   */\n  executeOnChange: function (inputProps, event) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.requestChange(event.target.value);\n    } else if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.requestChange(event.target.checked);\n    } else if (inputProps.onChange) {\n      return inputProps.onChange.call(undefined, event);\n    }\n  }\n};\n\nmodule.exports = LinkedValueUtils;\n},{\"139\":139,\"161\":161,\"171\":171,\"84\":84,\"85\":85}],25:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule PooledClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Static poolers. Several custom versions for each potential number of\n * arguments. A completely generic pooler is easy to implement, but would\n * require accessing the `arguments` object. In each of these, `this` refers to\n * the Class itself, not an instance. If any others are needed, simply add them\n * here, or in their own files.\n */\nvar oneArgumentPooler = function (copyFieldsFrom) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, copyFieldsFrom);\n    return instance;\n  } else {\n    return new Klass(copyFieldsFrom);\n  }\n};\n\nvar twoArgumentPooler = function (a1, a2) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2);\n    return instance;\n  } else {\n    return new Klass(a1, a2);\n  }\n};\n\nvar threeArgumentPooler = function (a1, a2, a3) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3);\n  }\n};\n\nvar fourArgumentPooler = function (a1, a2, a3, a4) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4);\n  }\n};\n\nvar fiveArgumentPooler = function (a1, a2, a3, a4, a5) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4, a5);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4, a5);\n  }\n};\n\nvar standardReleaser = function (instance) {\n  var Klass = this;\n  !(instance instanceof Klass) ? \"development\" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0;\n  instance.destructor();\n  if (Klass.instancePool.length < Klass.poolSize) {\n    Klass.instancePool.push(instance);\n  }\n};\n\nvar DEFAULT_POOL_SIZE = 10;\nvar DEFAULT_POOLER = oneArgumentPooler;\n\n/**\n * Augments `CopyConstructor` to be a poolable class, augmenting only the class\n * itself (statically) not adding any prototypical fields. Any CopyConstructor\n * you give this may have a `poolSize` property, and will look for a\n * prototypical `destructor` on instances.\n *\n * @param {Function} CopyConstructor Constructor that can be used to reset.\n * @param {Function} pooler Customizable pooler.\n */\nvar addPoolingTo = function (CopyConstructor, pooler) {\n  var NewKlass = CopyConstructor;\n  NewKlass.instancePool = [];\n  NewKlass.getPooled = pooler || DEFAULT_POOLER;\n  if (!NewKlass.poolSize) {\n    NewKlass.poolSize = DEFAULT_POOL_SIZE;\n  }\n  NewKlass.release = standardReleaser;\n  return NewKlass;\n};\n\nvar PooledClass = {\n  addPoolingTo: addPoolingTo,\n  oneArgumentPooler: oneArgumentPooler,\n  twoArgumentPooler: twoArgumentPooler,\n  threeArgumentPooler: threeArgumentPooler,\n  fourArgumentPooler: fourArgumentPooler,\n  fiveArgumentPooler: fiveArgumentPooler\n};\n\nmodule.exports = PooledClass;\n},{\"139\":139,\"161\":161}],26:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule React\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactComponent = _dereq_(31);\nvar ReactClass = _dereq_(30);\nvar ReactDOMFactories = _dereq_(45);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypes = _dereq_(85);\nvar ReactVersion = _dereq_(96);\n\nvar onlyChild = _dereq_(137);\nvar warning = _dereq_(171);\n\nvar createElement = ReactElement.createElement;\nvar createFactory = ReactElement.createFactory;\nvar cloneElement = ReactElement.cloneElement;\n\nif (\"development\" !== 'production') {\n  var ReactElementValidator = _dereq_(63);\n  createElement = ReactElementValidator.createElement;\n  createFactory = ReactElementValidator.createFactory;\n  cloneElement = ReactElementValidator.cloneElement;\n}\n\nvar __spread = _assign;\n\nif (\"development\" !== 'production') {\n  var warned = false;\n  __spread = function () {\n    \"development\" !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;\n    warned = true;\n    return _assign.apply(null, arguments);\n  };\n}\n\nvar React = {\n\n  // Modern\n\n  Children: {\n    map: ReactChildren.map,\n    forEach: ReactChildren.forEach,\n    count: ReactChildren.count,\n    toArray: ReactChildren.toArray,\n    only: onlyChild\n  },\n\n  Component: ReactComponent,\n\n  createElement: createElement,\n  cloneElement: cloneElement,\n  isValidElement: ReactElement.isValidElement,\n\n  // Classic\n\n  PropTypes: ReactPropTypes,\n  createClass: ReactClass.createClass,\n  createFactory: createFactory,\n  createMixin: function (mixin) {\n    // Currently a noop. Will be used to validate and trace mixins.\n    return mixin;\n  },\n\n  // This looks DOM specific but these are actually isomorphic helpers\n  // since they are just generating DOM strings.\n  DOM: ReactDOMFactories,\n\n  version: ReactVersion,\n\n  // Deprecated hook for JSX spread, don't use this for anything.\n  __spread: __spread\n};\n\nmodule.exports = React;\n},{\"137\":137,\"171\":171,\"172\":172,\"29\":29,\"30\":30,\"31\":31,\"45\":45,\"62\":62,\"63\":63,\"85\":85,\"96\":96}],27:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactBrowserEventEmitter\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventConstants = _dereq_(16);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactEventEmitterMixin = _dereq_(66);\nvar ViewportMetrics = _dereq_(114);\n\nvar getVendorPrefixedEventName = _dereq_(133);\nvar isEventSupported = _dereq_(135);\n\n/**\n * Summary of `ReactBrowserEventEmitter` event handling:\n *\n *  - Top-level delegation is used to trap most native browser events. This\n *    may only occur in the main thread and is the responsibility of\n *    ReactEventListener, which is injected and can therefore support pluggable\n *    event sources. This is the only work that occurs in the main thread.\n *\n *  - We normalize and de-duplicate events to account for browser quirks. This\n *    may be done in the worker thread.\n *\n *  - Forward these native events (with the associated top-level type used to\n *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want\n *    to extract any synthetic events.\n *\n *  - The `EventPluginHub` will then process each event by annotating them with\n *    \"dispatches\", a sequence of listeners and IDs that care about that event.\n *\n *  - The `EventPluginHub` then dispatches the events.\n *\n * Overview of React and the event system:\n *\n * +------------+    .\n * |    DOM     |    .\n * +------------+    .\n *       |           .\n *       v           .\n * +------------+    .\n * | ReactEvent |    .\n * |  Listener  |    .\n * +------------+    .                         +-----------+\n *       |           .               +--------+|SimpleEvent|\n *       |           .               |         |Plugin     |\n * +-----|------+    .               v         +-----------+\n * |     |      |    .    +--------------+                    +------------+\n * |     +-----------.--->|EventPluginHub|                    |    Event   |\n * |            |    .    |              |     +-----------+  | Propagators|\n * | ReactEvent |    .    |              |     |TapEvent   |  |------------|\n * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|\n * |            |    .    |              |     +-----------+  |  utilities |\n * |     +-----------.--->|              |                    +------------+\n * |     |      |    .    +--------------+\n * +-----|------+    .                ^        +-----------+\n *       |           .                |        |Enter/Leave|\n *       +           .                +-------+|Plugin     |\n * +-------------+   .                         +-----------+\n * | application |   .\n * |-------------|   .\n * |             |   .\n * |             |   .\n * +-------------+   .\n *                   .\n *    React Core     .  General Purpose Event Plugin System\n */\n\nvar hasEventPageXY;\nvar alreadyListeningTo = {};\nvar isMonitoringScrollValue = false;\nvar reactTopListenersCounter = 0;\n\n// For events like 'submit' which don't consistently bubble (which we trap at a\n// lower node than `document`), binding at `document` would cause duplicate\n// events so we don't include them here\nvar topEventMapping = {\n  topAbort: 'abort',\n  topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',\n  topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',\n  topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',\n  topBlur: 'blur',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topChange: 'change',\n  topClick: 'click',\n  topCompositionEnd: 'compositionend',\n  topCompositionStart: 'compositionstart',\n  topCompositionUpdate: 'compositionupdate',\n  topContextMenu: 'contextmenu',\n  topCopy: 'copy',\n  topCut: 'cut',\n  topDoubleClick: 'dblclick',\n  topDrag: 'drag',\n  topDragEnd: 'dragend',\n  topDragEnter: 'dragenter',\n  topDragExit: 'dragexit',\n  topDragLeave: 'dragleave',\n  topDragOver: 'dragover',\n  topDragStart: 'dragstart',\n  topDrop: 'drop',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topFocus: 'focus',\n  topInput: 'input',\n  topKeyDown: 'keydown',\n  topKeyPress: 'keypress',\n  topKeyUp: 'keyup',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topMouseDown: 'mousedown',\n  topMouseMove: 'mousemove',\n  topMouseOut: 'mouseout',\n  topMouseOver: 'mouseover',\n  topMouseUp: 'mouseup',\n  topPaste: 'paste',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topScroll: 'scroll',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topSelectionChange: 'selectionchange',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTextInput: 'textInput',\n  topTimeUpdate: 'timeupdate',\n  topTouchCancel: 'touchcancel',\n  topTouchEnd: 'touchend',\n  topTouchMove: 'touchmove',\n  topTouchStart: 'touchstart',\n  topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting',\n  topWheel: 'wheel'\n};\n\n/**\n * To ensure no conflicts with other potential React instances on the page\n */\nvar topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2);\n\nfunction getListeningForDocument(mountAt) {\n  // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`\n  // directly.\n  if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {\n    mountAt[topListenersIDKey] = reactTopListenersCounter++;\n    alreadyListeningTo[mountAt[topListenersIDKey]] = {};\n  }\n  return alreadyListeningTo[mountAt[topListenersIDKey]];\n}\n\n/**\n * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For\n * example:\n *\n *   EventPluginHub.putListener('myID', 'onClick', myFunction);\n *\n * This would allocate a \"registration\" of `('onClick', myFunction)` on 'myID'.\n *\n * @internal\n */\nvar ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {\n\n  /**\n   * Injectable event backend\n   */\n  ReactEventListener: null,\n\n  injection: {\n    /**\n     * @param {object} ReactEventListener\n     */\n    injectReactEventListener: function (ReactEventListener) {\n      ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel);\n      ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;\n    }\n  },\n\n  /**\n   * Sets whether or not any created callbacks should be enabled.\n   *\n   * @param {boolean} enabled True if callbacks should be enabled.\n   */\n  setEnabled: function (enabled) {\n    if (ReactBrowserEventEmitter.ReactEventListener) {\n      ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled);\n    }\n  },\n\n  /**\n   * @return {boolean} True if callbacks are enabled.\n   */\n  isEnabled: function () {\n    return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled());\n  },\n\n  /**\n   * We listen for bubbled touch events on the document object.\n   *\n   * Firefox v8.01 (and possibly others) exhibited strange behavior when\n   * mounting `onmousemove` events at some node that was not the document\n   * element. The symptoms were that if your mouse is not moving over something\n   * contained within that mount point (for example on the background) the\n   * top-level listeners for `onmousemove` won't be called. However, if you\n   * register the `mousemove` on the document object, then it will of course\n   * catch all `mousemove`s. This along with iOS quirks, justifies restricting\n   * top-level listeners to the document object only, at least for these\n   * movement types of events and possibly all events.\n   *\n   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html\n   *\n   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but\n   * they bubble to document.\n   *\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {object} contentDocumentHandle Document which owns the container\n   */\n  listenTo: function (registrationName, contentDocumentHandle) {\n    var mountAt = contentDocumentHandle;\n    var isListening = getListeningForDocument(mountAt);\n    var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName];\n\n    var topLevelTypes = EventConstants.topLevelTypes;\n    for (var i = 0; i < dependencies.length; i++) {\n      var dependency = dependencies[i];\n      if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {\n        if (dependency === topLevelTypes.topWheel) {\n          if (isEventSupported('wheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);\n          } else if (isEventSupported('mousewheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);\n          } else {\n            // Firefox needs to capture a different mouse scroll event.\n            // @see http://www.quirksmode.org/dom/events/tests/scroll.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt);\n          }\n        } else if (dependency === topLevelTypes.topScroll) {\n\n          if (isEventSupported('scroll', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);\n          } else {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE);\n          }\n        } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) {\n\n          if (isEventSupported('focus', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);\n          } else if (isEventSupported('focusin')) {\n            // IE has `focusin` and `focusout` events which bubble.\n            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);\n          }\n\n          // to make sure blur and focus event listeners are only attached once\n          isListening[topLevelTypes.topBlur] = true;\n          isListening[topLevelTypes.topFocus] = true;\n        } else if (topEventMapping.hasOwnProperty(dependency)) {\n          ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt);\n        }\n\n        isListening[dependency] = true;\n      }\n    }\n  },\n\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  /**\n   * Listens to window scroll and resize events. We cache scroll values so that\n   * application code can access them without triggering reflows.\n   *\n   * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when\n   * pageX/pageY isn't supported (legacy browsers).\n   *\n   * NOTE: Scroll events do not bubble.\n   *\n   * @see http://www.quirksmode.org/dom/events/scroll.html\n   */\n  ensureScrollValueMonitoring: function () {\n    if (hasEventPageXY === undefined) {\n      hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent');\n    }\n    if (!hasEventPageXY && !isMonitoringScrollValue) {\n      var refresh = ViewportMetrics.refreshScrollValues;\n      ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);\n      isMonitoringScrollValue = true;\n    }\n  }\n\n});\n\nmodule.exports = ReactBrowserEventEmitter;\n},{\"114\":114,\"133\":133,\"135\":135,\"16\":16,\"172\":172,\"18\":18,\"66\":66}],28:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildReconciler\n */\n\n'use strict';\n\nvar ReactReconciler = _dereq_(87);\n\nvar instantiateReactComponent = _dereq_(134);\nvar KeyEscapeUtils = _dereq_(23);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\nfunction instantiateChild(childInstances, child, name, selfDebugID) {\n  // We found a component instance.\n  var keyUnique = childInstances[name] === undefined;\n  if (\"development\" !== 'production') {\n    var ReactComponentTreeDevtool = _dereq_(34);\n    \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n  }\n  if (child != null && keyUnique) {\n    childInstances[name] = instantiateReactComponent(child, true);\n  }\n}\n\n/**\n * ReactChildReconciler provides helpers for initializing or updating a set of\n * children. Its output is suitable for passing it onto ReactMultiChild which\n * does diffed reordering and insertion.\n */\nvar ReactChildReconciler = {\n  /**\n   * Generates a \"mount image\" for each of the supplied children. In the case\n   * of `ReactDOMComponent`, a mount image is a string of markup.\n   *\n   * @param {?object} nestedChildNodes Nested child maps.\n   * @return {?object} A set of child instances.\n   * @internal\n   */\n  instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID // __DEV__ only\n  ) {\n    if (nestedChildNodes == null) {\n      return null;\n    }\n    var childInstances = {};\n\n    if (\"development\" !== 'production') {\n      traverseAllChildren(nestedChildNodes, function (childInsts, child, name) {\n        return instantiateChild(childInsts, child, name, selfDebugID);\n      }, childInstances);\n    } else {\n      traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);\n    }\n    return childInstances;\n  },\n\n  /**\n   * Updates the rendered children and returns a new set of children.\n   *\n   * @param {?object} prevChildren Previously initialized set of children.\n   * @param {?object} nextChildren Flat child element maps.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @return {?object} A new set of child instances.\n   * @internal\n   */\n  updateChildren: function (prevChildren, nextChildren, removedNodes, transaction, context) {\n    // We currently don't have a way to track moves here but if we use iterators\n    // instead of for..in we can zip the iterators and check if an item has\n    // moved.\n    // TODO: If nothing has changed, return the prevChildren object so that we\n    // can quickly bailout if nothing has changed.\n    if (!nextChildren && !prevChildren) {\n      return;\n    }\n    var name;\n    var prevChild;\n    for (name in nextChildren) {\n      if (!nextChildren.hasOwnProperty(name)) {\n        continue;\n      }\n      prevChild = prevChildren && prevChildren[name];\n      var prevElement = prevChild && prevChild._currentElement;\n      var nextElement = nextChildren[name];\n      if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {\n        ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);\n        nextChildren[name] = prevChild;\n      } else {\n        if (prevChild) {\n          removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n          ReactReconciler.unmountComponent(prevChild, false);\n        }\n        // The child must be instantiated before it's mounted.\n        var nextChildInstance = instantiateReactComponent(nextElement, true);\n        nextChildren[name] = nextChildInstance;\n      }\n    }\n    // Unmount children that are no longer present.\n    for (name in prevChildren) {\n      if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {\n        prevChild = prevChildren[name];\n        removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n        ReactReconciler.unmountComponent(prevChild, false);\n      }\n    }\n  },\n\n  /**\n   * Unmounts all rendered children. This should be used to clean up children\n   * when this component is unmounted.\n   *\n   * @param {?object} renderedChildren Previously initialized set of children.\n   * @internal\n   */\n  unmountChildren: function (renderedChildren, safely) {\n    for (var name in renderedChildren) {\n      if (renderedChildren.hasOwnProperty(name)) {\n        var renderedChild = renderedChildren[name];\n        ReactReconciler.unmountComponent(renderedChild, safely);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactChildReconciler;\n},{\"134\":134,\"143\":143,\"144\":144,\"171\":171,\"23\":23,\"34\":34,\"87\":87}],29:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildren\n */\n\n'use strict';\n\nvar PooledClass = _dereq_(25);\nvar ReactElement = _dereq_(62);\n\nvar emptyFunction = _dereq_(153);\nvar traverseAllChildren = _dereq_(144);\n\nvar twoArgumentPooler = PooledClass.twoArgumentPooler;\nvar fourArgumentPooler = PooledClass.fourArgumentPooler;\n\nvar userProvidedKeyEscapeRegex = /\\/+/g;\nfunction escapeUserProvidedKey(text) {\n  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * traversal. Allows avoiding binding callbacks.\n *\n * @constructor ForEachBookKeeping\n * @param {!function} forEachFunction Function to perform traversal with.\n * @param {?*} forEachContext Context to perform context with.\n */\nfunction ForEachBookKeeping(forEachFunction, forEachContext) {\n  this.func = forEachFunction;\n  this.context = forEachContext;\n  this.count = 0;\n}\nForEachBookKeeping.prototype.destructor = function () {\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);\n\nfunction forEachSingleChild(bookKeeping, child, name) {\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n  func.call(context, child, bookKeeping.count++);\n}\n\n/**\n * Iterates through children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach\n *\n * The provided forEachFunc(child, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} forEachFunc\n * @param {*} forEachContext Context for forEachContext.\n */\nfunction forEachChildren(children, forEachFunc, forEachContext) {\n  if (children == null) {\n    return children;\n  }\n  var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);\n  traverseAllChildren(children, forEachSingleChild, traverseContext);\n  ForEachBookKeeping.release(traverseContext);\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * mapping. Allows avoiding binding callbacks.\n *\n * @constructor MapBookKeeping\n * @param {!*} mapResult Object containing the ordered map of results.\n * @param {!function} mapFunction Function to perform mapping with.\n * @param {?*} mapContext Context to perform mapping with.\n */\nfunction MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {\n  this.result = mapResult;\n  this.keyPrefix = keyPrefix;\n  this.func = mapFunction;\n  this.context = mapContext;\n  this.count = 0;\n}\nMapBookKeeping.prototype.destructor = function () {\n  this.result = null;\n  this.keyPrefix = null;\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);\n\nfunction mapSingleChildIntoContext(bookKeeping, child, childKey) {\n  var result = bookKeeping.result;\n  var keyPrefix = bookKeeping.keyPrefix;\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n\n  var mappedChild = func.call(context, child, bookKeeping.count++);\n  if (Array.isArray(mappedChild)) {\n    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);\n  } else if (mappedChild != null) {\n    if (ReactElement.isValidElement(mappedChild)) {\n      mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,\n      // Keep both the (mapped) and old keys if they differ, just as\n      // traverseAllChildren used to do for objects as children\n      keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);\n    }\n    result.push(mappedChild);\n  }\n}\n\nfunction mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {\n  var escapedPrefix = '';\n  if (prefix != null) {\n    escapedPrefix = escapeUserProvidedKey(prefix) + '/';\n  }\n  var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);\n  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);\n  MapBookKeeping.release(traverseContext);\n}\n\n/**\n * Maps children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.map\n *\n * The provided mapFunction(child, key, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} func The map function.\n * @param {*} context Context for mapFunction.\n * @return {object} Object containing the ordered map of results.\n */\nfunction mapChildren(children, func, context) {\n  if (children == null) {\n    return children;\n  }\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, func, context);\n  return result;\n}\n\nfunction forEachSingleChildDummy(traverseContext, child, name) {\n  return null;\n}\n\n/**\n * Count the number of children that are typically specified as\n * `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.count\n *\n * @param {?*} children Children tree container.\n * @return {number} The number of children.\n */\nfunction countChildren(children, context) {\n  return traverseAllChildren(children, forEachSingleChildDummy, null);\n}\n\n/**\n * Flatten a children object (typically specified as `props.children`) and\n * return an array with appropriately re-keyed children.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray\n */\nfunction toArray(children) {\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);\n  return result;\n}\n\nvar ReactChildren = {\n  forEach: forEachChildren,\n  map: mapChildren,\n  mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,\n  count: countChildren,\n  toArray: toArray\n};\n\nmodule.exports = ReactChildren;\n},{\"144\":144,\"153\":153,\"25\":25,\"62\":62}],30:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponent = _dereq_(31);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactPropTypeLocationNames = _dereq_(83);\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar keyMirror = _dereq_(164);\nvar keyOf = _dereq_(165);\nvar warning = _dereq_(171);\n\nvar MIXINS_KEY = keyOf({ mixins: null });\n\n/**\n * Policies that describe methods in `ReactClassInterface`.\n */\nvar SpecPolicy = keyMirror({\n  /**\n   * These methods may be defined only once by the class specification or mixin.\n   */\n  DEFINE_ONCE: null,\n  /**\n   * These methods may be defined by both the class specification and mixins.\n   * Subsequent definitions will be chained. These methods must return void.\n   */\n  DEFINE_MANY: null,\n  /**\n   * These methods are overriding the base class.\n   */\n  OVERRIDE_BASE: null,\n  /**\n   * These methods are similar to DEFINE_MANY, except we assume they return\n   * objects. We try to merge the keys of the return values of all the mixed in\n   * functions. If there is a key conflict we throw.\n   */\n  DEFINE_MANY_MERGED: null\n});\n\nvar injectedMixins = [];\n\n/**\n * Composite components are higher-level components that compose other composite\n * or host components.\n *\n * To create a new type of `ReactClass`, pass a specification of\n * your new class to `React.createClass`. The only requirement of your class\n * specification is that you implement a `render` method.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return <div>Hello World</div>;\n *     }\n *   });\n *\n * The class specification supports a specific protocol of methods that have\n * special meaning (e.g. `render`). See `ReactClassInterface` for\n * more the comprehensive protocol. Any other properties and methods in the\n * class specification will be available on the prototype.\n *\n * @interface ReactClassInterface\n * @internal\n */\nvar ReactClassInterface = {\n\n  /**\n   * An array of Mixin objects to include when defining your component.\n   *\n   * @type {array}\n   * @optional\n   */\n  mixins: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * An object containing properties and methods that should be defined on\n   * the component's constructor instead of its prototype (static methods).\n   *\n   * @type {object}\n   * @optional\n   */\n  statics: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of prop types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  propTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  contextTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types this component sets for its children.\n   *\n   * @type {object}\n   * @optional\n   */\n  childContextTypes: SpecPolicy.DEFINE_MANY,\n\n  // ==== Definition methods ====\n\n  /**\n   * Invoked when the component is mounted. Values in the mapping will be set on\n   * `this.props` if that prop is not specified (i.e. using an `in` check).\n   *\n   * This method is invoked before `getInitialState` and therefore cannot rely\n   * on `this.state` or use `this.setState`.\n   *\n   * @return {object}\n   * @optional\n   */\n  getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Invoked once before the component is mounted. The return value will be used\n   * as the initial value of `this.state`.\n   *\n   *   getInitialState: function() {\n   *     return {\n   *       isOn: false,\n   *       fooBaz: new BazFoo()\n   *     }\n   *   }\n   *\n   * @return {object}\n   * @optional\n   */\n  getInitialState: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * @return {object}\n   * @optional\n   */\n  getChildContext: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Uses props from `this.props` and state from `this.state` to render the\n   * structure of the component.\n   *\n   * No guarantees are made about when or how often this method is invoked, so\n   * it must not have side effects.\n   *\n   *   render: function() {\n   *     var name = this.props.name;\n   *     return <div>Hello, {name}!</div>;\n   *   }\n   *\n   * @return {ReactComponent}\n   * @nosideeffects\n   * @required\n   */\n  render: SpecPolicy.DEFINE_ONCE,\n\n  // ==== Delegate methods ====\n\n  /**\n   * Invoked when the component is initially created and about to be mounted.\n   * This may have side effects, but any external subscriptions or data created\n   * by this method must be cleaned up in `componentWillUnmount`.\n   *\n   * @optional\n   */\n  componentWillMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component has been mounted and has a DOM representation.\n   * However, there is no guarantee that the DOM node is in the document.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been mounted (initialized and rendered) for the first time.\n   *\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked before the component receives new props.\n   *\n   * Use this as an opportunity to react to a prop transition by updating the\n   * state using `this.setState`. Current props are accessed via `this.props`.\n   *\n   *   componentWillReceiveProps: function(nextProps, nextContext) {\n   *     this.setState({\n   *       likesIncreasing: nextProps.likeCount > this.props.likeCount\n   *     });\n   *   }\n   *\n   * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop\n   * transition may cause a state change, but the opposite is not true. If you\n   * need it, you are probably looking for `componentWillUpdate`.\n   *\n   * @param {object} nextProps\n   * @optional\n   */\n  componentWillReceiveProps: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked while deciding if the component should be updated as a result of\n   * receiving new props, state and/or context.\n   *\n   * Use this as an opportunity to `return false` when you're certain that the\n   * transition to the new props/state/context will not require a component\n   * update.\n   *\n   *   shouldComponentUpdate: function(nextProps, nextState, nextContext) {\n   *     return !equal(nextProps, this.props) ||\n   *       !equal(nextState, this.state) ||\n   *       !equal(nextContext, this.context);\n   *   }\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @return {boolean} True if the component should update.\n   * @optional\n   */\n  shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,\n\n  /**\n   * Invoked when the component is about to update due to a transition from\n   * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`\n   * and `nextContext`.\n   *\n   * Use this as an opportunity to perform preparation before an update occurs.\n   *\n   * NOTE: You **cannot** use `this.setState()` in this method.\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @param {ReactReconcileTransaction} transaction\n   * @optional\n   */\n  componentWillUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component's DOM representation has been updated.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been updated.\n   *\n   * @param {object} prevProps\n   * @param {?object} prevState\n   * @param {?object} prevContext\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component is about to be removed from its parent and have\n   * its DOM representation destroyed.\n   *\n   * Use this as an opportunity to deallocate any external resources.\n   *\n   * NOTE: There is no `componentDidUnmount` since your component will have been\n   * destroyed by that point.\n   *\n   * @optional\n   */\n  componentWillUnmount: SpecPolicy.DEFINE_MANY,\n\n  // ==== Advanced methods ====\n\n  /**\n   * Updates the component's currently mounted DOM representation.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   * @overridable\n   */\n  updateComponent: SpecPolicy.OVERRIDE_BASE\n\n};\n\n/**\n * Mapping from class specification keys to special processing functions.\n *\n * Although these are declared like instance properties in the specification\n * when defining classes using `React.createClass`, they are actually static\n * and are accessible on the constructor instead of the prototype. Despite\n * being static, they must be defined outside of the \"statics\" key under\n * which all other static methods are defined.\n */\nvar RESERVED_SPEC_KEYS = {\n  displayName: function (Constructor, displayName) {\n    Constructor.displayName = displayName;\n  },\n  mixins: function (Constructor, mixins) {\n    if (mixins) {\n      for (var i = 0; i < mixins.length; i++) {\n        mixSpecIntoComponent(Constructor, mixins[i]);\n      }\n    }\n  },\n  childContextTypes: function (Constructor, childContextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext);\n    }\n    Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes);\n  },\n  contextTypes: function (Constructor, contextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context);\n    }\n    Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes);\n  },\n  /**\n   * Special case getDefaultProps which should move into statics but requires\n   * automatic merging.\n   */\n  getDefaultProps: function (Constructor, getDefaultProps) {\n    if (Constructor.getDefaultProps) {\n      Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps);\n    } else {\n      Constructor.getDefaultProps = getDefaultProps;\n    }\n  },\n  propTypes: function (Constructor, propTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop);\n    }\n    Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes);\n  },\n  statics: function (Constructor, statics) {\n    mixStaticSpecIntoComponent(Constructor, statics);\n  },\n  autobind: function () {} };\n\n// noop\nfunction validateTypeDef(Constructor, typeDef, location) {\n  for (var propName in typeDef) {\n    if (typeDef.hasOwnProperty(propName)) {\n      // use a warning instead of an invariant so components\n      // don't show up in prod but only in __DEV__\n      \"development\" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0;\n    }\n  }\n}\n\nfunction validateMethodOverride(isAlreadyDefined, name) {\n  var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null;\n\n  // Disallow overriding of base class methods unless explicitly allowed.\n  if (ReactClassMixin.hasOwnProperty(name)) {\n    !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.', name) : _prodInvariant('73', name) : void 0;\n  }\n\n  // Disallow defining methods more than once unless explicitly allowed.\n  if (isAlreadyDefined) {\n    !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('74', name) : void 0;\n  }\n}\n\n/**\n * Mixin helper which handles policy validation and reserved\n * specification keys when building React classes.\n */\nfunction mixSpecIntoComponent(Constructor, spec) {\n  if (!spec) {\n    return;\n  }\n\n  !(typeof spec !== 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component class or function as a mixin. Instead, just use a regular object.') : _prodInvariant('75') : void 0;\n  !!ReactElement.isValidElement(spec) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component as a mixin. Instead, just use a regular object.') : _prodInvariant('76') : void 0;\n\n  var proto = Constructor.prototype;\n  var autoBindPairs = proto.__reactAutoBindPairs;\n\n  // By handling mixins before any other properties, we ensure the same\n  // chaining order is applied to methods with DEFINE_MANY policy, whether\n  // mixins are listed before or after these methods in the spec.\n  if (spec.hasOwnProperty(MIXINS_KEY)) {\n    RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);\n  }\n\n  for (var name in spec) {\n    if (!spec.hasOwnProperty(name)) {\n      continue;\n    }\n\n    if (name === MIXINS_KEY) {\n      // We have already handled mixins in a special case above.\n      continue;\n    }\n\n    var property = spec[name];\n    var isAlreadyDefined = proto.hasOwnProperty(name);\n    validateMethodOverride(isAlreadyDefined, name);\n\n    if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {\n      RESERVED_SPEC_KEYS[name](Constructor, property);\n    } else {\n      // Setup methods on prototype:\n      // The following member methods should not be automatically bound:\n      // 1. Expected ReactClass methods (in the \"interface\").\n      // 2. Overridden methods (that were mixed in).\n      var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);\n      var isFunction = typeof property === 'function';\n      var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;\n\n      if (shouldAutoBind) {\n        autoBindPairs.push(name, property);\n        proto[name] = property;\n      } else {\n        if (isAlreadyDefined) {\n          var specPolicy = ReactClassInterface[name];\n\n          // These cases should already be caught by validateMethodOverride.\n          !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.', specPolicy, name) : _prodInvariant('77', specPolicy, name) : void 0;\n\n          // For methods which are defined more than once, call the existing\n          // methods before calling the new property, merging if appropriate.\n          if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {\n            proto[name] = createMergedResultFunction(proto[name], property);\n          } else if (specPolicy === SpecPolicy.DEFINE_MANY) {\n            proto[name] = createChainedFunction(proto[name], property);\n          }\n        } else {\n          proto[name] = property;\n          if (\"development\" !== 'production') {\n            // Add verbose displayName to the function, which helps when looking\n            // at profiling tools.\n            if (typeof property === 'function' && spec.displayName) {\n              proto[name].displayName = spec.displayName + '_' + name;\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction mixStaticSpecIntoComponent(Constructor, statics) {\n  if (!statics) {\n    return;\n  }\n  for (var name in statics) {\n    var property = statics[name];\n    if (!statics.hasOwnProperty(name)) {\n      continue;\n    }\n\n    var isReserved = name in RESERVED_SPEC_KEYS;\n    !!isReserved ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved property, `%s`, that shouldn\\'t be on the \"statics\" key. Define it as an instance property instead; it will still be accessible on the constructor.', name) : _prodInvariant('78', name) : void 0;\n\n    var isInherited = name in Constructor;\n    !!isInherited ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('79', name) : void 0;\n    Constructor[name] = property;\n  }\n}\n\n/**\n * Merge two objects, but throw if both contain the same key.\n *\n * @param {object} one The first object, which is mutated.\n * @param {object} two The second object\n * @return {object} one after it has been mutated to contain everything in two.\n */\nfunction mergeIntoWithNoDuplicateKeys(one, two) {\n  !(one && two && typeof one === 'object' && typeof two === 'object') ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : _prodInvariant('80') : void 0;\n\n  for (var key in two) {\n    if (two.hasOwnProperty(key)) {\n      !(one[key] === undefined) ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.', key) : _prodInvariant('81', key) : void 0;\n      one[key] = two[key];\n    }\n  }\n  return one;\n}\n\n/**\n * Creates a function that invokes two functions and merges their return values.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createMergedResultFunction(one, two) {\n  return function mergedResult() {\n    var a = one.apply(this, arguments);\n    var b = two.apply(this, arguments);\n    if (a == null) {\n      return b;\n    } else if (b == null) {\n      return a;\n    }\n    var c = {};\n    mergeIntoWithNoDuplicateKeys(c, a);\n    mergeIntoWithNoDuplicateKeys(c, b);\n    return c;\n  };\n}\n\n/**\n * Creates a function that invokes two functions and ignores their return vales.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createChainedFunction(one, two) {\n  return function chainedFunction() {\n    one.apply(this, arguments);\n    two.apply(this, arguments);\n  };\n}\n\n/**\n * Binds a method to the component.\n *\n * @param {object} component Component whose method is going to be bound.\n * @param {function} method Method to be bound.\n * @return {function} The bound method.\n */\nfunction bindAutoBindMethod(component, method) {\n  var boundMethod = method.bind(component);\n  if (\"development\" !== 'production') {\n    boundMethod.__reactBoundContext = component;\n    boundMethod.__reactBoundMethod = method;\n    boundMethod.__reactBoundArguments = null;\n    var componentName = component.constructor.displayName;\n    var _bind = boundMethod.bind;\n    boundMethod.bind = function (newThis) {\n      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n        args[_key - 1] = arguments[_key];\n      }\n\n      // User is trying to bind() an autobound method; we effectively will\n      // ignore the value of \"this\" that the user is trying to use, so\n      // let's warn.\n      if (newThis !== component && newThis !== null) {\n        \"development\" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0;\n      } else if (!args.length) {\n        \"development\" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0;\n        return boundMethod;\n      }\n      var reboundMethod = _bind.apply(boundMethod, arguments);\n      reboundMethod.__reactBoundContext = component;\n      reboundMethod.__reactBoundMethod = method;\n      reboundMethod.__reactBoundArguments = args;\n      return reboundMethod;\n    };\n  }\n  return boundMethod;\n}\n\n/**\n * Binds all auto-bound methods in a component.\n *\n * @param {object} component Component whose method is going to be bound.\n */\nfunction bindAutoBindMethods(component) {\n  var pairs = component.__reactAutoBindPairs;\n  for (var i = 0; i < pairs.length; i += 2) {\n    var autoBindKey = pairs[i];\n    var method = pairs[i + 1];\n    component[autoBindKey] = bindAutoBindMethod(component, method);\n  }\n}\n\n/**\n * Add more to the ReactClass base class. These are all legacy features and\n * therefore not already part of the modern ReactComponent.\n */\nvar ReactClassMixin = {\n\n  /**\n   * TODO: This will be deprecated because state should always keep a consistent\n   * type signature and the only use case for this, is to avoid that.\n   */\n  replaceState: function (newState, callback) {\n    this.updater.enqueueReplaceState(this, newState);\n    if (callback) {\n      this.updater.enqueueCallback(this, callback, 'replaceState');\n    }\n  },\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function () {\n    return this.updater.isMounted(this);\n  }\n};\n\nvar ReactClassComponent = function () {};\n_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);\n\n/**\n * Module for creating composite components.\n *\n * @class ReactClass\n */\nvar ReactClass = {\n\n  /**\n   * Creates a composite component class given a class specification.\n   * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass\n   *\n   * @param {object} spec Class specification (which must define `render`).\n   * @return {function} Component constructor function.\n   * @public\n   */\n  createClass: function (spec) {\n    var Constructor = function (props, context, updater) {\n      // This constructor gets overridden by mocks. The argument is used\n      // by mocks to assert on what gets mounted.\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0;\n      }\n\n      // Wire up auto-binding\n      if (this.__reactAutoBindPairs.length) {\n        bindAutoBindMethods(this);\n      }\n\n      this.props = props;\n      this.context = context;\n      this.refs = emptyObject;\n      this.updater = updater || ReactNoopUpdateQueue;\n\n      this.state = null;\n\n      // ReactClasses doesn't have constructors. Instead, they use the\n      // getInitialState and componentWillMount methods for initialization.\n\n      var initialState = this.getInitialState ? this.getInitialState() : null;\n      if (\"development\" !== 'production') {\n        // We allow auto-mocks to proceed as if they're returning null.\n        if (initialState === undefined && this.getInitialState._isMockFunction) {\n          // This is probably bad practice. Consider warning here and\n          // deprecating this convenience.\n          initialState = null;\n        }\n      }\n      !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : _prodInvariant('82', Constructor.displayName || 'ReactCompositeComponent') : void 0;\n\n      this.state = initialState;\n    };\n    Constructor.prototype = new ReactClassComponent();\n    Constructor.prototype.constructor = Constructor;\n    Constructor.prototype.__reactAutoBindPairs = [];\n\n    injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));\n\n    mixSpecIntoComponent(Constructor, spec);\n\n    // Initialize the defaultProps property after all mixins have been merged.\n    if (Constructor.getDefaultProps) {\n      Constructor.defaultProps = Constructor.getDefaultProps();\n    }\n\n    if (\"development\" !== 'production') {\n      // This is a tag to indicate that the use of these method names is ok,\n      // since it's used with createClass. If it's not, then it's likely a\n      // mistake so we'll warn you to use the static property, property\n      // initializer or constructor respectively.\n      if (Constructor.getDefaultProps) {\n        Constructor.getDefaultProps.isReactClassApproved = {};\n      }\n      if (Constructor.prototype.getInitialState) {\n        Constructor.prototype.getInitialState.isReactClassApproved = {};\n      }\n    }\n\n    !Constructor.prototype.render ? \"development\" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : _prodInvariant('83') : void 0;\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0;\n    }\n\n    // Reduce time spent doing lookups by setting these on the prototype.\n    for (var methodName in ReactClassInterface) {\n      if (!Constructor.prototype[methodName]) {\n        Constructor.prototype[methodName] = null;\n      }\n    }\n\n    return Constructor;\n  },\n\n  injection: {\n    injectMixin: function (mixin) {\n      injectedMixins.push(mixin);\n    }\n  }\n\n};\n\nmodule.exports = ReactClass;\n},{\"139\":139,\"154\":154,\"161\":161,\"164\":164,\"165\":165,\"171\":171,\"172\":172,\"31\":31,\"62\":62,\"81\":81,\"83\":83,\"84\":84}],31:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar canDefineProperty = _dereq_(117);\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Base class helpers for the updating state of a component.\n */\nfunction ReactComponent(props, context, updater) {\n  this.props = props;\n  this.context = context;\n  this.refs = emptyObject;\n  // We initialize the default updater but the real one gets injected by the\n  // renderer.\n  this.updater = updater || ReactNoopUpdateQueue;\n}\n\nReactComponent.prototype.isReactComponent = {};\n\n/**\n * Sets a subset of the state. Always use this to mutate\n * state. You should treat `this.state` as immutable.\n *\n * There is no guarantee that `this.state` will be immediately updated, so\n * accessing `this.state` after calling this method may return the old value.\n *\n * There is no guarantee that calls to `setState` will run synchronously,\n * as they may eventually be batched together.  You can provide an optional\n * callback that will be executed when the call to setState is actually\n * completed.\n *\n * When a function is provided to setState, it will be called at some point in\n * the future (not synchronously). It will be called with the up to date\n * component arguments (state, props, context). These values can be different\n * from this.* because your function may be called after receiveProps but before\n * shouldComponentUpdate, and this new state, props, and context will not yet be\n * assigned to this.\n *\n * @param {object|function} partialState Next partial state or function to\n *        produce next partial state to be merged with current state.\n * @param {?function} callback Called after state is updated.\n * @final\n * @protected\n */\nReactComponent.prototype.setState = function (partialState, callback) {\n  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? \"development\" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;\n  this.updater.enqueueSetState(this, partialState);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'setState');\n  }\n};\n\n/**\n * Forces an update. This should only be invoked when it is known with\n * certainty that we are **not** in a DOM transaction.\n *\n * You may want to call this when you know that some deeper aspect of the\n * component's state has changed but `setState` was not called.\n *\n * This will not invoke `shouldComponentUpdate`, but it will invoke\n * `componentWillUpdate` and `componentDidUpdate`.\n *\n * @param {?function} callback Called after update is complete.\n * @final\n * @protected\n */\nReactComponent.prototype.forceUpdate = function (callback) {\n  this.updater.enqueueForceUpdate(this);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'forceUpdate');\n  }\n};\n\n/**\n * Deprecated APIs. These APIs used to exist on classic React classes but since\n * we would like to deprecate them, we're not going to move them over to this\n * modern base class. Instead, we define a getter that warns if it's accessed.\n */\nif (\"development\" !== 'production') {\n  var deprecatedAPIs = {\n    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],\n    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']\n  };\n  var defineDeprecationWarning = function (methodName, info) {\n    if (canDefineProperty) {\n      Object.defineProperty(ReactComponent.prototype, methodName, {\n        get: function () {\n          \"development\" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0;\n          return undefined;\n        }\n      });\n    }\n  };\n  for (var fnName in deprecatedAPIs) {\n    if (deprecatedAPIs.hasOwnProperty(fnName)) {\n      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);\n    }\n  }\n}\n\nmodule.exports = ReactComponent;\n},{\"117\":117,\"139\":139,\"154\":154,\"161\":161,\"171\":171,\"81\":81}],32:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentBrowserEnvironment\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMIDOperations = _dereq_(47);\n\n/**\n * Abstracts away all functionality of the reconciler that requires knowledge of\n * the browser context. TODO: These callers should be refactored to avoid the\n * need for this injection.\n */\nvar ReactComponentBrowserEnvironment = {\n\n  processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,\n\n  replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup,\n\n  /**\n   * If a particular environment requires that some resources be cleaned up,\n   * specify this in the injected Mixin. In the DOM, we would likely want to\n   * purge any cached node ID lookups.\n   *\n   * @private\n   */\n  unmountIDFromEnvironment: function (rootNodeID) {}\n\n};\n\nmodule.exports = ReactComponentBrowserEnvironment;\n},{\"47\":47,\"7\":7}],33:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentEnvironment\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nvar injected = false;\n\nvar ReactComponentEnvironment = {\n\n  /**\n   * Optionally injectable environment dependent cleanup hook. (server vs.\n   * browser etc). Example: A browser system caches DOM nodes based on component\n   * ID and must remove that cache entry when this instance is unmounted.\n   */\n  unmountIDFromEnvironment: null,\n\n  /**\n   * Optionally injectable hook for swapping out mount images in the middle of\n   * the tree.\n   */\n  replaceNodeWithMarkup: null,\n\n  /**\n   * Optionally injectable hook for processing a queue of child updates. Will\n   * later move into MultiChildComponents.\n   */\n  processChildrenUpdates: null,\n\n  injection: {\n    injectEnvironment: function (environment) {\n      !!injected ? \"development\" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0;\n      ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment;\n      ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;\n      ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;\n      injected = true;\n    }\n  }\n\n};\n\nmodule.exports = ReactComponentEnvironment;\n},{\"139\":139,\"161\":161}],34:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentTreeDevtool\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar tree = {};\nvar unmountedIDs = {};\nvar rootIDs = {};\n\nfunction updateTree(id, update) {\n  if (!tree[id]) {\n    tree[id] = {\n      element: null,\n      parentID: null,\n      ownerID: null,\n      text: null,\n      childIDs: [],\n      displayName: 'Unknown',\n      isMounted: false,\n      updateCount: 0\n    };\n  }\n  update(tree[id]);\n}\n\nfunction purgeDeep(id) {\n  var item = tree[id];\n  if (item) {\n    var childIDs = item.childIDs;\n\n    delete tree[id];\n    childIDs.forEach(purgeDeep);\n  }\n}\n\nfunction describeComponentFrame(name, source, ownerName) {\n  return '\\n    in ' + name + (source ? ' (at ' + source.fileName.replace(/^.*[\\\\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');\n}\n\nfunction describeID(id) {\n  var name = ReactComponentTreeDevtool.getDisplayName(id);\n  var element = ReactComponentTreeDevtool.getElement(id);\n  var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n  var ownerName;\n  if (ownerID) {\n    ownerName = ReactComponentTreeDevtool.getDisplayName(ownerID);\n  }\n  \"development\" !== 'production' ? warning(element, 'ReactComponentTreeDevtool: Missing React element for debugID %s when ' + 'building stack', id) : void 0;\n  return describeComponentFrame(name, element && element._source, ownerName);\n}\n\nvar ReactComponentTreeDevtool = {\n  onSetDisplayName: function (id, displayName) {\n    updateTree(id, function (item) {\n      return item.displayName = displayName;\n    });\n  },\n  onSetChildren: function (id, nextChildIDs) {\n    updateTree(id, function (item) {\n      item.childIDs = nextChildIDs;\n\n      nextChildIDs.forEach(function (nextChildID) {\n        var nextChild = tree[nextChildID];\n        !nextChild ? \"development\" !== 'production' ? invariant(false, 'Expected devtool events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('68') : void 0;\n        !(nextChild.displayName != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('69') : void 0;\n        !(nextChild.childIDs != null || nextChild.text != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('70') : void 0;\n        !nextChild.isMounted ? \"development\" !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;\n        if (nextChild.parentID == null) {\n          nextChild.parentID = id;\n          // TODO: This shouldn't be necessary but mounting a new root during in\n          // componentWillMount currently causes not-yet-mounted components to\n          // be purged from our tree data so their parent ID is missing.\n        }\n        !(nextChild.parentID === id) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('72', nextChildID, nextChild.parentID, id) : void 0;\n      });\n    });\n  },\n  onSetOwner: function (id, ownerID) {\n    updateTree(id, function (item) {\n      return item.ownerID = ownerID;\n    });\n  },\n  onSetParent: function (id, parentID) {\n    updateTree(id, function (item) {\n      return item.parentID = parentID;\n    });\n  },\n  onSetText: function (id, text) {\n    updateTree(id, function (item) {\n      return item.text = text;\n    });\n  },\n  onBeforeMountComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onBeforeUpdateComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onMountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = true;\n    });\n  },\n  onMountRootComponent: function (id) {\n    rootIDs[id] = true;\n  },\n  onUpdateComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.updateCount++;\n    });\n  },\n  onUnmountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = false;\n    });\n    unmountedIDs[id] = true;\n    delete rootIDs[id];\n  },\n  purgeUnmountedComponents: function () {\n    if (ReactComponentTreeDevtool._preventPurging) {\n      // Should only be used for testing.\n      return;\n    }\n\n    for (var id in unmountedIDs) {\n      purgeDeep(id);\n    }\n    unmountedIDs = {};\n  },\n  isMounted: function (id) {\n    var item = tree[id];\n    return item ? item.isMounted : false;\n  },\n  getCurrentStackAddendum: function (topElement) {\n    var info = '';\n    if (topElement) {\n      var type = topElement.type;\n      var name = typeof type === 'function' ? type.displayName || type.name : type;\n      var owner = topElement._owner;\n      info += describeComponentFrame(name || 'Unknown', topElement._source, owner && owner.getName());\n    }\n\n    var currentOwner = ReactCurrentOwner.current;\n    var id = currentOwner && currentOwner._debugID;\n\n    info += ReactComponentTreeDevtool.getStackAddendumByID(id);\n    return info;\n  },\n  getStackAddendumByID: function (id) {\n    var info = '';\n    while (id) {\n      info += describeID(id);\n      id = ReactComponentTreeDevtool.getParentID(id);\n    }\n    return info;\n  },\n  getChildIDs: function (id) {\n    var item = tree[id];\n    return item ? item.childIDs : [];\n  },\n  getDisplayName: function (id) {\n    var item = tree[id];\n    return item ? item.displayName : 'Unknown';\n  },\n  getElement: function (id) {\n    var item = tree[id];\n    return item ? item.element : null;\n  },\n  getOwnerID: function (id) {\n    var item = tree[id];\n    return item ? item.ownerID : null;\n  },\n  getParentID: function (id) {\n    var item = tree[id];\n    return item ? item.parentID : null;\n  },\n  getSource: function (id) {\n    var item = tree[id];\n    var element = item ? item.element : null;\n    var source = element != null ? element._source : null;\n    return source;\n  },\n  getText: function (id) {\n    var item = tree[id];\n    return item ? item.text : null;\n  },\n  getUpdateCount: function (id) {\n    var item = tree[id];\n    return item ? item.updateCount : 0;\n  },\n  getRootIDs: function () {\n    return Object.keys(rootIDs);\n  },\n  getRegisteredIDs: function () {\n    return Object.keys(tree);\n  }\n};\n\nmodule.exports = ReactComponentTreeDevtool;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36}],35:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCompositeComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\nvar ReactErrorUtils = _dereq_(65);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactNodeTypes = _dereq_(80);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactReconciler = _dereq_(87);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nfunction StatelessComponent(Component) {}\nStatelessComponent.prototype.render = function () {\n  var Component = ReactInstanceMap.get(this)._currentElement.type;\n  var element = Component(this.props, this.context, this.updater);\n  warnIfInvalidElement(Component, element);\n  return element;\n};\n\nfunction warnIfInvalidElement(Component, element) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;\n    \"development\" !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0;\n  }\n}\n\nfunction invokeComponentDidMountWithTimer() {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n  publicInstance.componentDidMount();\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n}\n\nfunction invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n  publicInstance.componentDidUpdate(prevProps, prevState, prevContext);\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n}\n\nfunction shouldConstruct(Component) {\n  return Component.prototype && Component.prototype.isReactComponent;\n}\n\n/**\n * ------------------ The Life-Cycle of a Composite Component ------------------\n *\n * - constructor: Initialization of state. The instance is now retained.\n *   - componentWillMount\n *   - render\n *   - [children's constructors]\n *     - [children's componentWillMount and render]\n *     - [children's componentDidMount]\n *     - componentDidMount\n *\n *       Update Phases:\n *       - componentWillReceiveProps (only called if parent updated)\n *       - shouldComponentUpdate\n *         - componentWillUpdate\n *           - render\n *           - [children's constructors or receive props phases]\n *         - componentDidUpdate\n *\n *     - componentWillUnmount\n *     - [children's componentWillUnmount]\n *   - [children destroyed]\n * - (destroyed): The instance is now blank, released by React and ready for GC.\n *\n * -----------------------------------------------------------------------------\n */\n\n/**\n * An incrementing ID assigned to each component when it is mounted. This is\n * used to enforce the order in which `ReactUpdates` updates dirty components.\n *\n * @private\n */\nvar nextMountID = 1;\n\n/**\n * @lends {ReactCompositeComponent.prototype}\n */\nvar ReactCompositeComponentMixin = {\n\n  /**\n   * Base constructor for all composite component.\n   *\n   * @param {ReactElement} element\n   * @final\n   * @internal\n   */\n  construct: function (element) {\n    this._currentElement = element;\n    this._rootNodeID = null;\n    this._instance = null;\n    this._hostParent = null;\n    this._hostContainerInfo = null;\n\n    // See ReactUpdateQueue\n    this._updateBatchNumber = null;\n    this._pendingElement = null;\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    this._renderedNodeType = null;\n    this._renderedComponent = null;\n    this._context = null;\n    this._mountOrder = 0;\n    this._topLevelWrapper = null;\n\n    // See ReactUpdates and ReactUpdateQueue.\n    this._pendingCallbacks = null;\n\n    // ComponentWillUnmount shall only be called once\n    this._calledComponentWillUnmount = false;\n\n    if (\"development\" !== 'production') {\n      this._warnedAboutRefsInRender = false;\n    }\n  },\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} hostParent\n   * @param {?object} hostContainerInfo\n   * @param {?object} context\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._context = context;\n    this._mountOrder = nextMountID++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var publicProps = this._currentElement.props;\n    var publicContext = this._processContext(context);\n\n    var Component = this._currentElement.type;\n\n    var updateQueue = transaction.getUpdateQueue();\n\n    // Initialize the public class\n    var inst = this._constructComponent(publicProps, publicContext, updateQueue);\n    var renderedElement;\n\n    // Support functional components\n    if (!shouldConstruct(Component) && (inst == null || inst.render == null)) {\n      renderedElement = inst;\n      warnIfInvalidElement(Component, renderedElement);\n      !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? \"development\" !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0;\n      inst = new StatelessComponent(Component);\n    }\n\n    if (\"development\" !== 'production') {\n      // This will throw later in _renderValidatedComponent, but add an early\n      // warning now to help debugging\n      if (inst.render == null) {\n        \"development\" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0;\n      }\n\n      var propsMutated = inst.props !== publicProps;\n      var componentName = Component.displayName || Component.name || 'Component';\n\n      \"development\" !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\\'s constructor was passed.', componentName, componentName) : void 0;\n    }\n\n    // These should be set up in the constructor, but as a convenience for\n    // simpler class abstractions, we set them up after the fact.\n    inst.props = publicProps;\n    inst.context = publicContext;\n    inst.refs = emptyObject;\n    inst.updater = updateQueue;\n\n    this._instance = inst;\n\n    // Store a reference from the instance back to the internal representation\n    ReactInstanceMap.set(inst, this);\n\n    if (\"development\" !== 'production') {\n      // Since plain JS classes are defined without any special initialization\n      // logic, we can not catch common errors early. Therefore, we have to\n      // catch them here, at initialization time, instead.\n      \"development\" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0;\n    }\n\n    var initialState = inst.state;\n    if (initialState === undefined) {\n      inst.state = initialState = null;\n    }\n    !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    var markup;\n    if (inst.unstable_handleError) {\n      markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } else {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n\n    if (inst.componentDidMount) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);\n      }\n    }\n\n    return markup;\n  },\n\n  _constructComponent: function (publicProps, publicContext, updateQueue) {\n    if (\"development\" !== 'production') {\n      ReactCurrentOwner.current = this;\n      try {\n        return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n      } finally {\n        ReactCurrentOwner.current = null;\n      }\n    } else {\n      return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n    }\n  },\n\n  _constructComponentWithoutOwner: function (publicProps, publicContext, updateQueue) {\n    var Component = this._currentElement.type;\n    var instanceOrElement;\n    if (shouldConstruct(Component)) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n      instanceOrElement = new Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n    } else {\n      // This can still be an instance in case of factory components\n      // but we'll count this as time spent rendering as the more common case.\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n      instanceOrElement = Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n    }\n    return instanceOrElement;\n  },\n\n  performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var markup;\n    var checkpoint = transaction.checkpoint();\n    try {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } catch (e) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onError();\n        }\n      }\n      // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint\n      transaction.rollback(checkpoint);\n      this._instance.unstable_handleError(e);\n      if (this._pendingStateQueue) {\n        this._instance.state = this._processPendingState(this._instance.props, this._instance.context);\n      }\n      checkpoint = transaction.checkpoint();\n\n      this._renderedComponent.unmountComponent(true);\n      transaction.rollback(checkpoint);\n\n      // Try again - we've informed the component about the error, so they can render an error message this time.\n      // If this throws again, the error will bubble up (and can be caught by a higher error boundary).\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n    return markup;\n  },\n\n  performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var inst = this._instance;\n    if (inst.componentWillMount) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      inst.componentWillMount();\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      // When mounting, calls to `setState` by `componentWillMount` will set\n      // `this._pendingStateQueue` without triggering a re-render.\n      if (this._pendingStateQueue) {\n        inst.state = this._processPendingState(inst.props, inst.context);\n      }\n    }\n\n    // If not a stateless component, we now render\n    if (renderedElement === undefined) {\n      renderedElement = this._renderValidatedComponent();\n    }\n\n    var nodeType = ReactNodeTypes.getType(renderedElement);\n    this._renderedNodeType = nodeType;\n    var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n    );\n    this._renderedComponent = child;\n    if (\"development\" !== 'production') {\n      if (child._debugID !== 0 && this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n      }\n    }\n\n    var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context));\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n      }\n    }\n\n    return markup;\n  },\n\n  getHostNode: function () {\n    return ReactReconciler.getHostNode(this._renderedComponent);\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    if (!this._renderedComponent) {\n      return;\n    }\n    var inst = this._instance;\n\n    if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {\n      inst._calledComponentWillUnmount = true;\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n      if (safely) {\n        var name = this.getName() + '.componentWillUnmount()';\n        ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));\n      } else {\n        inst.componentWillUnmount();\n      }\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n    }\n\n    if (this._renderedComponent) {\n      ReactReconciler.unmountComponent(this._renderedComponent, safely);\n      this._renderedNodeType = null;\n      this._renderedComponent = null;\n      this._instance = null;\n    }\n\n    // Reset pending fields\n    // Even if this component is scheduled for another update in ReactUpdates,\n    // it would still be ignored because these fields are reset.\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n    this._pendingCallbacks = null;\n    this._pendingElement = null;\n\n    // These fields do not really need to be reset since this object is no\n    // longer accessible.\n    this._context = null;\n    this._rootNodeID = null;\n    this._topLevelWrapper = null;\n\n    // Delete the reference from the instance to this internal representation\n    // which allow the internals to be properly cleaned up even if the user\n    // leaks a reference to the public instance.\n    ReactInstanceMap.remove(inst);\n\n    // Some existing components rely on inst.props even after they've been\n    // destroyed (in event handlers).\n    // TODO: inst.props = null;\n    // TODO: inst.state = null;\n    // TODO: inst.context = null;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _maskContext: function (context) {\n    var Component = this._currentElement.type;\n    var contextTypes = Component.contextTypes;\n    if (!contextTypes) {\n      return emptyObject;\n    }\n    var maskedContext = {};\n    for (var contextName in contextTypes) {\n      maskedContext[contextName] = context[contextName];\n    }\n    return maskedContext;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`, and asserts that they are valid.\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _processContext: function (context) {\n    var maskedContext = this._maskContext(context);\n    if (\"development\" !== 'production') {\n      var Component = this._currentElement.type;\n      if (Component.contextTypes) {\n        this._checkContextTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);\n      }\n    }\n    return maskedContext;\n  },\n\n  /**\n   * @param {object} currentContext\n   * @return {object}\n   * @private\n   */\n  _processChildContext: function (currentContext) {\n    var Component = this._currentElement.type;\n    var inst = this._instance;\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onBeginProcessingChildContext();\n    }\n    var childContext = inst.getChildContext && inst.getChildContext();\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onEndProcessingChildContext();\n    }\n    if (childContext) {\n      !(typeof Component.childContextTypes === 'object') ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;\n      if (\"development\" !== 'production') {\n        this._checkContextTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);\n      }\n      for (var name in childContext) {\n        !(name in Component.childContextTypes) ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): key \"%s\" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0;\n      }\n      return _assign({}, currentContext, childContext);\n    }\n    return currentContext;\n  },\n\n  /**\n   * Assert that the context types are valid\n   *\n   * @param {object} typeSpecs Map of context field to a ReactPropType\n   * @param {object} values Runtime values that need to be type-checked\n   * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n   * @private\n   */\n  _checkContextTypes: function (typeSpecs, values, location) {\n    checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);\n  },\n\n  receiveComponent: function (nextElement, transaction, nextContext) {\n    var prevElement = this._currentElement;\n    var prevContext = this._context;\n\n    this._pendingElement = null;\n\n    this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);\n  },\n\n  /**\n   * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`\n   * is set, update the component.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (transaction) {\n    if (this._pendingElement != null) {\n      ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);\n    } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {\n      this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);\n    } else {\n      this._updateBatchNumber = null;\n    }\n  },\n\n  /**\n   * Perform an update to a mounted component. The componentWillReceiveProps and\n   * shouldComponentUpdate methods are called, then (assuming the update isn't\n   * skipped) the remaining update lifecycle methods are called and the DOM\n   * representation is updated.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevParentElement\n   * @param {ReactElement} nextParentElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {\n    var inst = this._instance;\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    var willReceive = false;\n    var nextContext;\n    var nextProps;\n\n    // Determine if the context has changed or not\n    if (this._context === nextUnmaskedContext) {\n      nextContext = inst.context;\n    } else {\n      nextContext = this._processContext(nextUnmaskedContext);\n      willReceive = true;\n    }\n\n    nextProps = nextParentElement.props;\n\n    // Not a simple state update but a props update\n    if (prevParentElement !== nextParentElement) {\n      willReceive = true;\n    }\n\n    // An update here will schedule an update but immediately set\n    // _pendingStateQueue which will ensure that any state updates gets\n    // immediately reconciled instead of waiting for the next batch.\n    if (willReceive && inst.componentWillReceiveProps) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n      inst.componentWillReceiveProps(nextProps, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n    }\n\n    var nextState = this._processPendingState(nextProps, nextContext);\n    var shouldUpdate = true;\n\n    if (!this._pendingForceUpdate && inst.shouldComponentUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n      shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;\n    }\n\n    this._updateBatchNumber = null;\n    if (shouldUpdate) {\n      this._pendingForceUpdate = false;\n      // Will set `this.props`, `this.state` and `this.context`.\n      this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);\n    } else {\n      // If it's determined that a component should not update, we still want\n      // to set props and state but we shortcut the rest of the update.\n      this._currentElement = nextParentElement;\n      this._context = nextUnmaskedContext;\n      inst.props = nextProps;\n      inst.state = nextState;\n      inst.context = nextContext;\n    }\n  },\n\n  _processPendingState: function (props, context) {\n    var inst = this._instance;\n    var queue = this._pendingStateQueue;\n    var replace = this._pendingReplaceState;\n    this._pendingReplaceState = false;\n    this._pendingStateQueue = null;\n\n    if (!queue) {\n      return inst.state;\n    }\n\n    if (replace && queue.length === 1) {\n      return queue[0];\n    }\n\n    var nextState = _assign({}, replace ? queue[0] : inst.state);\n    for (var i = replace ? 1 : 0; i < queue.length; i++) {\n      var partial = queue[i];\n      _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);\n    }\n\n    return nextState;\n  },\n\n  /**\n   * Merges new props and state, notifies delegate methods of update and\n   * performs update.\n   *\n   * @param {ReactElement} nextElement Next element\n   * @param {object} nextProps Next public object to set as properties.\n   * @param {?object} nextState Next object to set as state.\n   * @param {?object} nextContext Next public object to set as context.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {?object} unmaskedContext\n   * @private\n   */\n  _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {\n    var inst = this._instance;\n\n    var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);\n    var prevProps;\n    var prevState;\n    var prevContext;\n    if (hasComponentDidUpdate) {\n      prevProps = inst.props;\n      prevState = inst.state;\n      prevContext = inst.context;\n    }\n\n    if (inst.componentWillUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n      inst.componentWillUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n    }\n\n    this._currentElement = nextElement;\n    this._context = unmaskedContext;\n    inst.props = nextProps;\n    inst.state = nextState;\n    inst.context = nextContext;\n\n    this._updateRenderedComponent(transaction, unmaskedContext);\n\n    if (hasComponentDidUpdate) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);\n      }\n    }\n  },\n\n  /**\n   * Call the component's `render` method and update the DOM accordingly.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  _updateRenderedComponent: function (transaction, context) {\n    var prevComponentInstance = this._renderedComponent;\n    var prevRenderedElement = prevComponentInstance._currentElement;\n    var nextRenderedElement = this._renderValidatedComponent();\n    if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {\n      ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));\n    } else {\n      var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);\n      ReactReconciler.unmountComponent(prevComponentInstance, false);\n\n      var nodeType = ReactNodeTypes.getType(nextRenderedElement);\n      this._renderedNodeType = nodeType;\n      var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n      );\n      this._renderedComponent = child;\n      if (\"development\" !== 'production') {\n        if (child._debugID !== 0 && this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n        }\n      }\n\n      var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context));\n\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n        }\n      }\n\n      this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);\n    }\n  },\n\n  /**\n   * Overridden in shallow rendering.\n   *\n   * @protected\n   */\n  _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {\n    ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);\n  },\n\n  /**\n   * @protected\n   */\n  _renderValidatedComponentWithoutOwnerOrContext: function () {\n    var inst = this._instance;\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n    var renderedComponent = inst.render();\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      // We allow auto-mocks to proceed as if they're returning null.\n      if (renderedComponent === undefined && inst.render._isMockFunction) {\n        // This is probably bad practice. Consider warning here and\n        // deprecating this convenience.\n        renderedComponent = null;\n      }\n    }\n\n    return renderedComponent;\n  },\n\n  /**\n   * @private\n   */\n  _renderValidatedComponent: function () {\n    var renderedComponent;\n    ReactCurrentOwner.current = this;\n    try {\n      renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();\n    } finally {\n      ReactCurrentOwner.current = null;\n    }\n    !(\n    // TODO: An `isValidNode` function would probably be more appropriate\n    renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? \"development\" !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    return renderedComponent;\n  },\n\n  /**\n   * Lazily allocates the refs object and stores `component` as `ref`.\n   *\n   * @param {string} ref Reference name.\n   * @param {component} component Component to store as `ref`.\n   * @final\n   * @private\n   */\n  attachRef: function (ref, component) {\n    var inst = this.getPublicInstance();\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0;\n    var publicComponentInstance = component.getPublicInstance();\n    if (\"development\" !== 'production') {\n      var componentName = component && component.getName ? component.getName() : 'a component';\n      \"development\" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref \"%s\" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;\n    }\n    var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;\n    refs[ref] = publicComponentInstance;\n  },\n\n  /**\n   * Detaches a reference name.\n   *\n   * @param {string} ref Name to dereference.\n   * @final\n   * @private\n   */\n  detachRef: function (ref) {\n    var refs = this.getPublicInstance().refs;\n    delete refs[ref];\n  },\n\n  /**\n   * Get a text description of the component that can be used to identify it\n   * in error messages.\n   * @return {string} The name or null.\n   * @internal\n   */\n  getName: function () {\n    var type = this._currentElement.type;\n    var constructor = this._instance && this._instance.constructor;\n    return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;\n  },\n\n  /**\n   * Get the publicly accessible representation of this component - i.e. what\n   * is exposed by refs and returned by render. Can be null for stateless\n   * components.\n   *\n   * @return {ReactComponent} the public component instance.\n   * @internal\n   */\n  getPublicInstance: function () {\n    var inst = this._instance;\n    if (inst instanceof StatelessComponent) {\n      return null;\n    }\n    return inst;\n  },\n\n  // Stub\n  _instantiateReactComponent: null\n\n};\n\nvar ReactCompositeComponent = {\n\n  Mixin: ReactCompositeComponentMixin\n\n};\n\nmodule.exports = ReactCompositeComponent;\n},{\"118\":118,\"139\":139,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"172\":172,\"33\":33,\"36\":36,\"62\":62,\"65\":65,\"73\":73,\"74\":74,\"80\":80,\"84\":84,\"87\":87}],36:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCurrentOwner\n */\n\n'use strict';\n\n/**\n * Keeps track of the current owner.\n *\n * The current owner is the component who should own any components that are\n * currently being constructed.\n */\n\nvar ReactCurrentOwner = {\n\n  /**\n   * @internal\n   * @type {ReactComponent}\n   */\n  current: null\n\n};\n\nmodule.exports = ReactCurrentOwner;\n},{}],37:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOM\n */\n\n/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactMount = _dereq_(77);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdates = _dereq_(95);\nvar ReactVersion = _dereq_(96);\n\nvar findDOMNode = _dereq_(122);\nvar getHostComponentFromComposite = _dereq_(129);\nvar renderSubtreeIntoContainer = _dereq_(140);\nvar warning = _dereq_(171);\n\nReactDefaultInjection.inject();\n\nvar React = {\n  findDOMNode: findDOMNode,\n  render: ReactMount.render,\n  unmountComponentAtNode: ReactMount.unmountComponentAtNode,\n  version: ReactVersion,\n\n  /* eslint-disable camelcase */\n  unstable_batchedUpdates: ReactUpdates.batchedUpdates,\n  unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer\n};\n\n// Inject the runtime into a devtools global hook regardless of browser.\n// Allows for debugging when the hook is injected on the page.\n/* eslint-enable camelcase */\nif (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {\n  __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({\n    ComponentTree: {\n      getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,\n      getNodeFromInstance: function (inst) {\n        // inst is an internal instance (but could be a composite)\n        if (inst._renderedComponent) {\n          inst = getHostComponentFromComposite(inst);\n        }\n        if (inst) {\n          return ReactDOMComponentTree.getNodeFromInstance(inst);\n        } else {\n          return null;\n        }\n      }\n    },\n    Mount: ReactMount,\n    Reconciler: ReactReconciler\n  });\n}\n\nif (\"development\" !== 'production') {\n  var ExecutionEnvironment = _dereq_(147);\n  if (ExecutionEnvironment.canUseDOM && window.top === window.self) {\n\n    // First check if devtools is not installed\n    if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {\n      // If we're in Chrome or Firefox, provide a download link if not installed.\n      if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {\n        // Firefox does not have the issue with devtools loaded over file://\n        var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;\n        console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');\n      }\n    }\n\n    var testFunc = function testFn() {};\n    \"development\" !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;\n\n    // If we're in IE8, check to see if we are in compatibility mode and provide\n    // information on preventing compatibility mode\n    var ieCompatibilityMode = document.documentMode && document.documentMode < 8;\n\n    \"development\" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />') : void 0;\n\n    var expectedFeatures = [\n    // shims\n    Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim];\n\n    for (var i = 0; i < expectedFeatures.length; i++) {\n      if (!expectedFeatures[i]) {\n        \"development\" !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;\n        break;\n      }\n    }\n  }\n}\n\nmodule.exports = React;\n},{\"122\":122,\"129\":129,\"140\":140,\"147\":147,\"171\":171,\"41\":41,\"61\":61,\"77\":77,\"87\":87,\"95\":95,\"96\":96}],38:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMButton\n */\n\n'use strict';\n\nvar DisabledInputUtils = _dereq_(14);\n\n/**\n * Implements a <button> host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar ReactDOMButton = {\n  getHostProps: DisabledInputUtils.getHostProps\n};\n\nmodule.exports = ReactDOMButton;\n},{\"14\":14}],39:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponent\n */\n\n/* global hasOwnProperty:true */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar AutoFocusUtils = _dereq_(1);\nvar CSSPropertyOperations = _dereq_(4);\nvar DOMLazyTree = _dereq_(8);\nvar DOMNamespaces = _dereq_(9);\nvar DOMProperty = _dereq_(10);\nvar DOMPropertyOperations = _dereq_(11);\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMButton = _dereq_(38);\nvar ReactDOMComponentFlags = _dereq_(40);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInput = _dereq_(48);\nvar ReactDOMOption = _dereq_(51);\nvar ReactDOMSelect = _dereq_(52);\nvar ReactDOMTextarea = _dereq_(56);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChild = _dereq_(78);\nvar ReactServerRenderingTransaction = _dereq_(91);\n\nvar emptyFunction = _dereq_(153);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar isEventSupported = _dereq_(135);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\nvar validateDOMNesting = _dereq_(145);\nvar warning = _dereq_(171);\n\nvar Flags = ReactDOMComponentFlags;\nvar deleteListener = EventPluginHub.deleteListener;\nvar getNode = ReactDOMComponentTree.getNodeFromInstance;\nvar listenTo = ReactBrowserEventEmitter.listenTo;\nvar registrationNameModules = EventPluginRegistry.registrationNameModules;\n\n// For quickly matching children type, to test if can be treated as content.\nvar CONTENT_TYPES = { 'string': true, 'number': true };\n\nvar STYLE = keyOf({ style: null });\nvar HTML = keyOf({ __html: null });\nvar RESERVED_PROPS = {\n  children: null,\n  dangerouslySetInnerHTML: null,\n  suppressContentEditableWarning: null\n};\n\n// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).\nvar DOC_FRAGMENT_TYPE = 11;\n\nfunction getDeclarationErrorAddendum(internalInstance) {\n  if (internalInstance) {\n    var owner = internalInstance._currentElement._owner || null;\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' This DOM node was rendered by `' + name + '`.';\n      }\n    }\n  }\n  return '';\n}\n\nfunction friendlyStringify(obj) {\n  if (typeof obj === 'object') {\n    if (Array.isArray(obj)) {\n      return '[' + obj.map(friendlyStringify).join(', ') + ']';\n    } else {\n      var pairs = [];\n      for (var key in obj) {\n        if (Object.prototype.hasOwnProperty.call(obj, key)) {\n          var keyEscaped = /^[a-z$_][\\w$_]*$/i.test(key) ? key : JSON.stringify(key);\n          pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));\n        }\n      }\n      return '{' + pairs.join(', ') + '}';\n    }\n  } else if (typeof obj === 'string') {\n    return JSON.stringify(obj);\n  } else if (typeof obj === 'function') {\n    return '[function object]';\n  }\n  // Differs from JSON.stringify in that undefined because undefined and that\n  // inf and nan don't become null\n  return String(obj);\n}\n\nvar styleMutationWarning = {};\n\nfunction checkAndWarnForMutatedStyle(style1, style2, component) {\n  if (style1 == null || style2 == null) {\n    return;\n  }\n  if (shallowEqual(style1, style2)) {\n    return;\n  }\n\n  var componentName = component._tag;\n  var owner = component._currentElement._owner;\n  var ownerName;\n  if (owner) {\n    ownerName = owner.getName();\n  }\n\n  var hash = ownerName + '|' + componentName;\n\n  if (styleMutationWarning.hasOwnProperty(hash)) {\n    return;\n  }\n\n  styleMutationWarning[hash] = true;\n\n  \"development\" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;\n}\n\n/**\n * @param {object} component\n * @param {?object} props\n */\nfunction assertValidProps(component, props) {\n  if (!props) {\n    return;\n  }\n  // Note the use of `==` which checks for null or undefined.\n  if (voidElementTags[component._tag]) {\n    !(props.children == null && props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : _prodInvariant('137', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : void 0;\n  }\n  if (props.dangerouslySetInnerHTML != null) {\n    !(props.children == null) ? \"development\" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : _prodInvariant('60') : void 0;\n    !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? \"development\" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : _prodInvariant('61') : void 0;\n  }\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;\n    \"development\" !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0;\n    \"development\" !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;\n  }\n  !(props.style == null || typeof props.style === 'object') ? \"development\" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \\'em\\'}} when using JSX.%s', getDeclarationErrorAddendum(component)) : _prodInvariant('62', getDeclarationErrorAddendum(component)) : void 0;\n}\n\nfunction enqueuePutListener(inst, registrationName, listener, transaction) {\n  if (transaction instanceof ReactServerRenderingTransaction) {\n    return;\n  }\n  if (\"development\" !== 'production') {\n    // IE8 has no API for event capturing and the `onScroll` event doesn't\n    // bubble.\n    \"development\" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\\'t support the `onScroll` event') : void 0;\n  }\n  var containerInfo = inst._hostContainerInfo;\n  var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;\n  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;\n  listenTo(registrationName, doc);\n  transaction.getReactMountReady().enqueue(putListener, {\n    inst: inst,\n    registrationName: registrationName,\n    listener: listener\n  });\n}\n\nfunction putListener() {\n  var listenerToPut = this;\n  EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);\n}\n\nfunction inputPostMount() {\n  var inst = this;\n  ReactDOMInput.postMountWrapper(inst);\n}\n\nfunction textareaPostMount() {\n  var inst = this;\n  ReactDOMTextarea.postMountWrapper(inst);\n}\n\nfunction optionPostMount() {\n  var inst = this;\n  ReactDOMOption.postMountWrapper(inst);\n}\n\nvar setContentChildForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  setContentChildForInstrumentation = function (content) {\n    var hasExistingContent = this._contentDebugID != null;\n    var debugID = this._debugID;\n    var contentDebugID = debugID + '#text';\n\n    if (content == null) {\n      if (hasExistingContent) {\n        ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);\n      }\n      this._contentDebugID = null;\n      return;\n    }\n\n    this._contentDebugID = contentDebugID;\n    var text = '' + content;\n\n    ReactInstrumentation.debugTool.onSetDisplayName(contentDebugID, '#text');\n    ReactInstrumentation.debugTool.onSetParent(contentDebugID, debugID);\n    ReactInstrumentation.debugTool.onSetText(contentDebugID, text);\n\n    if (hasExistingContent) {\n      ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);\n    } else {\n      ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onMountComponent(contentDebugID);\n      ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);\n    }\n  };\n}\n\n// There are so many media events, it makes sense to just\n// maintain a list rather than create a `trapBubbledEvent` for each\nvar mediaEvents = {\n  topAbort: 'abort',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTimeUpdate: 'timeupdate',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting'\n};\n\nfunction trapBubbledEventsLocal() {\n  var inst = this;\n  // If a component renders to null or if another component fatals and causes\n  // the state of the tree to be corrupted, `node` here can be null.\n  !inst._rootNodeID ? \"development\" !== 'production' ? invariant(false, 'Must be mounted to trap events') : _prodInvariant('63') : void 0;\n  var node = getNode(inst);\n  !node ? \"development\" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : _prodInvariant('64') : void 0;\n\n  switch (inst._tag) {\n    case 'iframe':\n    case 'object':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'video':\n    case 'audio':\n\n      inst._wrapperState.listeners = [];\n      // Create listener for each media event\n      for (var event in mediaEvents) {\n        if (mediaEvents.hasOwnProperty(event)) {\n          inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));\n        }\n      }\n      break;\n    case 'source':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node)];\n      break;\n    case 'img':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'form':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];\n      break;\n    case 'input':\n    case 'select':\n    case 'textarea':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topInvalid, 'invalid', node)];\n      break;\n  }\n}\n\nfunction postUpdateSelectWrapper() {\n  ReactDOMSelect.postUpdateWrapper(this);\n}\n\n// For HTML, certain tags should omit their close tag. We keep a whitelist for\n// those special-case tags.\n\nvar omittedCloseTags = {\n  'area': true,\n  'base': true,\n  'br': true,\n  'col': true,\n  'embed': true,\n  'hr': true,\n  'img': true,\n  'input': true,\n  'keygen': true,\n  'link': true,\n  'meta': true,\n  'param': true,\n  'source': true,\n  'track': true,\n  'wbr': true\n};\n\n// NOTE: menuitem's close tag should be omitted, but that causes problems.\nvar newlineEatingTags = {\n  'listing': true,\n  'pre': true,\n  'textarea': true\n};\n\n// For HTML, certain tags cannot have children. This has the same purpose as\n// `omittedCloseTags` except that `menuitem` should still have its closing tag.\n\nvar voidElementTags = _assign({\n  'menuitem': true\n}, omittedCloseTags);\n\n// We accept any tag to be rendered but since this gets injected into arbitrary\n// HTML, we want to make sure that it's a safe tag.\n// http://www.w3.org/TR/REC-xml/#NT-Name\n\nvar VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\\.\\-\\d]*$/; // Simplified subset\nvar validatedTagCache = {};\nvar hasOwnProperty = {}.hasOwnProperty;\n\nfunction validateDangerousTag(tag) {\n  if (!hasOwnProperty.call(validatedTagCache, tag)) {\n    !VALID_TAG_REGEX.test(tag) ? \"development\" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : _prodInvariant('65', tag) : void 0;\n    validatedTagCache[tag] = true;\n  }\n}\n\nfunction isCustomComponent(tagName, props) {\n  return tagName.indexOf('-') >= 0 || props.is != null;\n}\n\nvar globalIdCounter = 1;\n\n/**\n * Creates a new React class that is idempotent and capable of containing other\n * React components. It accepts event listeners and DOM properties that are\n * valid according to `DOMProperty`.\n *\n *  - Event listeners: `onClick`, `onMouseDown`, etc.\n *  - DOM properties: `className`, `name`, `title`, etc.\n *\n * The `style` property functions differently from the DOM API. It accepts an\n * object mapping of style properties to values.\n *\n * @constructor ReactDOMComponent\n * @extends ReactMultiChild\n */\nfunction ReactDOMComponent(element) {\n  var tag = element.type;\n  validateDangerousTag(tag);\n  this._currentElement = element;\n  this._tag = tag.toLowerCase();\n  this._namespaceURI = null;\n  this._renderedChildren = null;\n  this._previousStyle = null;\n  this._previousStyleCopy = null;\n  this._hostNode = null;\n  this._hostParent = null;\n  this._rootNodeID = null;\n  this._domID = null;\n  this._hostContainerInfo = null;\n  this._wrapperState = null;\n  this._topLevelWrapper = null;\n  this._flags = 0;\n  if (\"development\" !== 'production') {\n    this._ancestorInfo = null;\n    setContentChildForInstrumentation.call(this, null);\n  }\n}\n\nReactDOMComponent.displayName = 'ReactDOMComponent';\n\nReactDOMComponent.Mixin = {\n\n  /**\n   * Generates root tag markup then recurses. This method has side effects and\n   * is not idempotent.\n   *\n   * @internal\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?ReactDOMComponent} the containing DOM component instance\n   * @param {?object} info about the host container\n   * @param {object} context\n   * @return {string} The computed markup.\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._rootNodeID = globalIdCounter++;\n    this._domID = hostContainerInfo._idCounter++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var props = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        this._wrapperState = {\n          listeners: null\n        };\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'button':\n        props = ReactDOMButton.getHostProps(this, props, hostParent);\n        break;\n      case 'input':\n        ReactDOMInput.mountWrapper(this, props, hostParent);\n        props = ReactDOMInput.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'option':\n        ReactDOMOption.mountWrapper(this, props, hostParent);\n        props = ReactDOMOption.getHostProps(this, props);\n        break;\n      case 'select':\n        ReactDOMSelect.mountWrapper(this, props, hostParent);\n        props = ReactDOMSelect.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.mountWrapper(this, props, hostParent);\n        props = ReactDOMTextarea.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n    }\n\n    assertValidProps(this, props);\n\n    // We create tags in the namespace of their parent container, except HTML\n    // tags get no namespace.\n    var namespaceURI;\n    var parentTag;\n    if (hostParent != null) {\n      namespaceURI = hostParent._namespaceURI;\n      parentTag = hostParent._tag;\n    } else if (hostContainerInfo._tag) {\n      namespaceURI = hostContainerInfo._namespaceURI;\n      parentTag = hostContainerInfo._tag;\n    }\n    if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {\n      namespaceURI = DOMNamespaces.html;\n    }\n    if (namespaceURI === DOMNamespaces.html) {\n      if (this._tag === 'svg') {\n        namespaceURI = DOMNamespaces.svg;\n      } else if (this._tag === 'math') {\n        namespaceURI = DOMNamespaces.mathml;\n      }\n    }\n    this._namespaceURI = namespaceURI;\n\n    if (\"development\" !== 'production') {\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo._tag) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting(this._tag, this, parentInfo);\n      }\n      this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);\n    }\n\n    var mountImage;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var el;\n      if (namespaceURI === DOMNamespaces.html) {\n        if (this._tag === 'script') {\n          // Create the script via .innerHTML so its \"parser-inserted\" flag is\n          // set to true and it does not execute\n          var div = ownerDocument.createElement('div');\n          var type = this._currentElement.type;\n          div.innerHTML = '<' + type + '></' + type + '>';\n          el = div.removeChild(div.firstChild);\n        } else if (props.is) {\n          el = ownerDocument.createElement(this._currentElement.type, props.is);\n        } else {\n          // Separate else branch instead of using `props.is || undefined` above becuase of a Firefox bug.\n          // See discussion in https://github.com/facebook/react/pull/6896\n          // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240\n          el = ownerDocument.createElement(this._currentElement.type);\n        }\n      } else {\n        el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);\n      }\n      ReactDOMComponentTree.precacheNode(this, el);\n      this._flags |= Flags.hasCachedChildNodes;\n      if (!this._hostParent) {\n        DOMPropertyOperations.setAttributeForRoot(el);\n      }\n      this._updateDOMProperties(null, props, transaction);\n      var lazyTree = DOMLazyTree(el);\n      this._createInitialChildren(transaction, props, context, lazyTree);\n      mountImage = lazyTree;\n    } else {\n      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);\n      var tagContent = this._createContentMarkup(transaction, props, context);\n      if (!tagContent && omittedCloseTags[this._tag]) {\n        mountImage = tagOpen + '/>';\n      } else {\n        mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';\n      }\n    }\n\n    switch (this._tag) {\n      case 'input':\n        transaction.getReactMountReady().enqueue(inputPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'textarea':\n        transaction.getReactMountReady().enqueue(textareaPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'select':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'button':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'option':\n        transaction.getReactMountReady().enqueue(optionPostMount, this);\n        break;\n    }\n\n    return mountImage;\n  },\n\n  /**\n   * Creates markup for the open tag and all attributes.\n   *\n   * This method has side effects because events get registered.\n   *\n   * Iterating over object properties is faster than iterating over arrays.\n   * @see http://jsperf.com/obj-vs-arr-iteration\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @return {string} Markup of opening tag.\n   */\n  _createOpenTagMarkupAndPutListeners: function (transaction, props) {\n    var ret = '<' + this._currentElement.type;\n\n    for (var propKey in props) {\n      if (!props.hasOwnProperty(propKey)) {\n        continue;\n      }\n      var propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (propValue) {\n          enqueuePutListener(this, propKey, propValue, transaction);\n        }\n      } else {\n        if (propKey === STYLE) {\n          if (propValue) {\n            if (\"development\" !== 'production') {\n              // See `_updateDOMProperties`. style block\n              this._previousStyle = propValue;\n            }\n            propValue = this._previousStyleCopy = _assign({}, props.style);\n          }\n          propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);\n        }\n        var markup = null;\n        if (this._tag != null && isCustomComponent(this._tag, props)) {\n          if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n            markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);\n          }\n        } else {\n          markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);\n        }\n        if (markup) {\n          ret += ' ' + markup;\n        }\n      }\n    }\n\n    // For static pages, no need to put React ID and checksum. Saves lots of\n    // bytes.\n    if (transaction.renderToStaticMarkup) {\n      return ret;\n    }\n\n    if (!this._hostParent) {\n      ret += ' ' + DOMPropertyOperations.createMarkupForRoot();\n    }\n    ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);\n    return ret;\n  },\n\n  /**\n   * Creates markup for the content between the tags.\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @param {object} context\n   * @return {string} Content markup.\n   */\n  _createContentMarkup: function (transaction, props, context) {\n    var ret = '';\n\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        ret = innerHTML.__html;\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        ret = escapeTextContentForBrowser(contentToUse);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        ret = mountImages.join('');\n      }\n    }\n    if (newlineEatingTags[this._tag] && ret.charAt(0) === '\\n') {\n      // text/html ignores the first character in these tags if it's a newline\n      // Prefer to break application/xml over text/html (for now) by adding\n      // a newline specifically to get eaten by the parser. (Alternately for\n      // textareas, replacing \"^\\n\" with \"\\r\\n\" doesn't get eaten, and the first\n      // \\r is normalized out by HTMLTextAreaElement#value.)\n      // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>\n      // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>\n      // See: <http://www.w3.org/TR/html5/syntax.html#newlines>\n      // See: Parsing of \"textarea\" \"listing\" and \"pre\" elements\n      //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>\n      return '\\n' + ret;\n    } else {\n      return ret;\n    }\n  },\n\n  _createInitialChildren: function (transaction, props, context, lazyTree) {\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n        DOMLazyTree.queueText(lazyTree, contentToUse);\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        for (var i = 0; i < mountImages.length; i++) {\n          DOMLazyTree.queueChild(lazyTree, mountImages[i]);\n        }\n      }\n    }\n  },\n\n  /**\n   * Receives a next element and updates the component.\n   *\n   * @internal\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} context\n   */\n  receiveComponent: function (nextElement, transaction, context) {\n    var prevElement = this._currentElement;\n    this._currentElement = nextElement;\n    this.updateComponent(transaction, prevElement, nextElement, context);\n  },\n\n  /**\n   * Updates a DOM component after it has already been allocated and\n   * attached to the DOM. Reconciles the root DOM node, then recurses.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevElement\n   * @param {ReactElement} nextElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevElement, nextElement, context) {\n    var lastProps = prevElement.props;\n    var nextProps = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'button':\n        lastProps = ReactDOMButton.getHostProps(this, lastProps);\n        nextProps = ReactDOMButton.getHostProps(this, nextProps);\n        break;\n      case 'input':\n        ReactDOMInput.updateWrapper(this);\n        lastProps = ReactDOMInput.getHostProps(this, lastProps);\n        nextProps = ReactDOMInput.getHostProps(this, nextProps);\n        break;\n      case 'option':\n        lastProps = ReactDOMOption.getHostProps(this, lastProps);\n        nextProps = ReactDOMOption.getHostProps(this, nextProps);\n        break;\n      case 'select':\n        lastProps = ReactDOMSelect.getHostProps(this, lastProps);\n        nextProps = ReactDOMSelect.getHostProps(this, nextProps);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.updateWrapper(this);\n        lastProps = ReactDOMTextarea.getHostProps(this, lastProps);\n        nextProps = ReactDOMTextarea.getHostProps(this, nextProps);\n        break;\n    }\n\n    assertValidProps(this, nextProps);\n    this._updateDOMProperties(lastProps, nextProps, transaction);\n    this._updateDOMChildren(lastProps, nextProps, transaction, context);\n\n    if (this._tag === 'select') {\n      // <select> value update needs to occur after <option> children\n      // reconciliation\n      transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);\n    }\n  },\n\n  /**\n   * Reconciles the properties by detecting differences in property values and\n   * updating the DOM as necessary. This function is probably the single most\n   * critical path for performance optimization.\n   *\n   * TODO: Benchmark whether checking for changed values in memory actually\n   *       improves performance (especially statically positioned elements).\n   * TODO: Benchmark the effects of putting this at the top since 99% of props\n   *       do not change for a given reconciliation.\n   * TODO: Benchmark areas that can be improved with caching.\n   *\n   * @private\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {?DOMElement} node\n   */\n  _updateDOMProperties: function (lastProps, nextProps, transaction) {\n    var propKey;\n    var styleName;\n    var styleUpdates;\n    for (propKey in lastProps) {\n      if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        var lastStyle = this._previousStyleCopy;\n        for (styleName in lastStyle) {\n          if (lastStyle.hasOwnProperty(styleName)) {\n            styleUpdates = styleUpdates || {};\n            styleUpdates[styleName] = '';\n          }\n        }\n        this._previousStyleCopy = null;\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (lastProps[propKey]) {\n          // Only call deleteListener if there was a listener previously or\n          // else willDeleteListener gets called when there wasn't actually a\n          // listener (e.g., onClick={null})\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, lastProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);\n      }\n    }\n    for (propKey in nextProps) {\n      var nextProp = nextProps[propKey];\n      var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;\n      if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        if (nextProp) {\n          if (\"development\" !== 'production') {\n            checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);\n            this._previousStyle = nextProp;\n          }\n          nextProp = this._previousStyleCopy = _assign({}, nextProp);\n        } else {\n          this._previousStyleCopy = null;\n        }\n        if (lastProp) {\n          // Unset styles on `lastProp` but not on `nextProp`.\n          for (styleName in lastProp) {\n            if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = '';\n            }\n          }\n          // Update styles that changed since `lastProp`.\n          for (styleName in nextProp) {\n            if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = nextProp[styleName];\n            }\n          }\n        } else {\n          // Relies on `updateStylesByID` not mutating `styleUpdates`.\n          styleUpdates = nextProp;\n        }\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (nextProp) {\n          enqueuePutListener(this, propKey, nextProp, transaction);\n        } else if (lastProp) {\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, nextProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        var node = getNode(this);\n        // If we're updating to null or undefined, we should remove the property\n        // from the DOM node instead of inadvertently setting to a string. This\n        // brings us in line with the same behavior we have on initial render.\n        if (nextProp != null) {\n          DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);\n        } else {\n          DOMPropertyOperations.deleteValueForProperty(node, propKey);\n        }\n      }\n    }\n    if (styleUpdates) {\n      CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);\n    }\n  },\n\n  /**\n   * Reconciles the children with the various properties that affect the\n   * children content.\n   *\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   */\n  _updateDOMChildren: function (lastProps, nextProps, transaction, context) {\n    var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;\n    var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;\n\n    var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;\n    var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;\n\n    // Note the use of `!=` which checks for null or undefined.\n    var lastChildren = lastContent != null ? null : lastProps.children;\n    var nextChildren = nextContent != null ? null : nextProps.children;\n\n    // If we're switching from children to content/html or vice versa, remove\n    // the old content\n    var lastHasContentOrHtml = lastContent != null || lastHtml != null;\n    var nextHasContentOrHtml = nextContent != null || nextHtml != null;\n    if (lastChildren != null && nextChildren == null) {\n      this.updateChildren(null, transaction, context);\n    } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {\n      this.updateTextContent('');\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    }\n\n    if (nextContent != null) {\n      if (lastContent !== nextContent) {\n        this.updateTextContent('' + nextContent);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, nextContent);\n        }\n      }\n    } else if (nextHtml != null) {\n      if (lastHtml !== nextHtml) {\n        this.updateMarkup('' + nextHtml);\n      }\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    } else if (nextChildren != null) {\n      if (\"development\" !== 'production') {\n        setContentChildForInstrumentation.call(this, null);\n      }\n\n      this.updateChildren(nextChildren, transaction, context);\n    }\n  },\n\n  getHostNode: function () {\n    return getNode(this);\n  },\n\n  /**\n   * Destroys all event registrations for this instance. Does not remove from\n   * the DOM. That must be done by the parent.\n   *\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        var listeners = this._wrapperState.listeners;\n        if (listeners) {\n          for (var i = 0; i < listeners.length; i++) {\n            listeners[i].remove();\n          }\n        }\n        break;\n      case 'html':\n      case 'head':\n      case 'body':\n        /**\n         * Components like <html> <head> and <body> can't be removed or added\n         * easily in a cross-browser way, however it's valuable to be able to\n         * take advantage of React's reconciliation for styling and <title>\n         * management. So we just document it and throw in dangerous cases.\n         */\n        !false ? \"development\" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.', this._tag) : _prodInvariant('66', this._tag) : void 0;\n        break;\n    }\n\n    this.unmountChildren(safely);\n    ReactDOMComponentTree.uncacheNode(this);\n    EventPluginHub.deleteAllListeners(this);\n    ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);\n    this._rootNodeID = null;\n    this._domID = null;\n    this._wrapperState = null;\n\n    if (\"development\" !== 'production') {\n      setContentChildForInstrumentation.call(this, null);\n    }\n  },\n\n  getPublicInstance: function () {\n    return getNode(this);\n  }\n\n};\n\n_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);\n\nmodule.exports = ReactDOMComponent;\n},{\"1\":1,\"10\":10,\"11\":11,\"121\":121,\"135\":135,\"139\":139,\"145\":145,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"17\":17,\"170\":170,\"171\":171,\"172\":172,\"18\":18,\"27\":27,\"32\":32,\"38\":38,\"4\":4,\"40\":40,\"41\":41,\"48\":48,\"51\":51,\"52\":52,\"56\":56,\"74\":74,\"78\":78,\"8\":8,\"9\":9,\"91\":91}],40:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentFlags\n */\n\n'use strict';\n\nvar ReactDOMComponentFlags = {\n  hasCachedChildNodes: 1 << 0\n};\n\nmodule.exports = ReactDOMComponentFlags;\n},{}],41:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentTree\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentFlags = _dereq_(40);\n\nvar invariant = _dereq_(161);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar Flags = ReactDOMComponentFlags;\n\nvar internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);\n\n/**\n * Drill down (through composites and empty components) until we get a host or\n * host text component.\n *\n * This is pretty polymorphic but unavoidable with the current structure we have\n * for `_renderedChildren`.\n */\nfunction getRenderedHostOrTextFromComponent(component) {\n  var rendered;\n  while (rendered = component._renderedComponent) {\n    component = rendered;\n  }\n  return component;\n}\n\n/**\n * Populate `_hostNode` on the rendered host/text component with the given\n * DOM node. The passed `inst` can be a composite.\n */\nfunction precacheNode(inst, node) {\n  var hostInst = getRenderedHostOrTextFromComponent(inst);\n  hostInst._hostNode = node;\n  node[internalInstanceKey] = hostInst;\n}\n\nfunction uncacheNode(inst) {\n  var node = inst._hostNode;\n  if (node) {\n    delete node[internalInstanceKey];\n    inst._hostNode = null;\n  }\n}\n\n/**\n * Populate `_hostNode` on each child of `inst`, assuming that the children\n * match up with the DOM (element) children of `node`.\n *\n * We cache entire levels at once to avoid an n^2 problem where we access the\n * children of a node sequentially and have to walk from the start to our target\n * node every time.\n *\n * Since we update `_renderedChildren` and the actual DOM at (slightly)\n * different times, we could race here and see a newer `_renderedChildren` than\n * the DOM nodes we see. To avoid this, ReactMultiChild calls\n * `prepareToManageChildren` before we change `_renderedChildren`, at which\n * time the container's child nodes are always cached (until it unmounts).\n */\nfunction precacheChildNodes(inst, node) {\n  if (inst._flags & Flags.hasCachedChildNodes) {\n    return;\n  }\n  var children = inst._renderedChildren;\n  var childNode = node.firstChild;\n  outer: for (var name in children) {\n    if (!children.hasOwnProperty(name)) {\n      continue;\n    }\n    var childInst = children[name];\n    var childID = getRenderedHostOrTextFromComponent(childInst)._domID;\n    if (childID == null) {\n      // We're currently unmounting this child in ReactMultiChild; skip it.\n      continue;\n    }\n    // We assume the child nodes are in the same order as the child instances.\n    for (; childNode !== null; childNode = childNode.nextSibling) {\n      if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') {\n        precacheNode(childInst, childNode);\n        continue outer;\n      }\n    }\n    // We reached the end of the DOM children without finding an ID match.\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : _prodInvariant('32', childID) : void 0;\n  }\n  inst._flags |= Flags.hasCachedChildNodes;\n}\n\n/**\n * Given a DOM node, return the closest ReactDOMComponent or\n * ReactDOMTextComponent instance ancestor.\n */\nfunction getClosestInstanceFromNode(node) {\n  if (node[internalInstanceKey]) {\n    return node[internalInstanceKey];\n  }\n\n  // Walk up the tree until we find an ancestor whose instance we have cached.\n  var parents = [];\n  while (!node[internalInstanceKey]) {\n    parents.push(node);\n    if (node.parentNode) {\n      node = node.parentNode;\n    } else {\n      // Top of the tree. This node must not be part of a React tree (or is\n      // unmounted, potentially).\n      return null;\n    }\n  }\n\n  var closest;\n  var inst;\n  for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {\n    closest = inst;\n    if (parents.length) {\n      precacheChildNodes(inst, node);\n    }\n  }\n\n  return closest;\n}\n\n/**\n * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent\n * instance, or null if the node was not rendered by this React.\n */\nfunction getInstanceFromNode(node) {\n  var inst = getClosestInstanceFromNode(node);\n  if (inst != null && inst._hostNode === node) {\n    return inst;\n  } else {\n    return null;\n  }\n}\n\n/**\n * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding\n * DOM node.\n */\nfunction getNodeFromInstance(inst) {\n  // Without this first invariant, passing a non-DOM-component triggers the next\n  // invariant for a missing parent, which is super confusing.\n  !(inst._hostNode !== undefined) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  if (inst._hostNode) {\n    return inst._hostNode;\n  }\n\n  // Walk up the tree until we find an ancestor whose DOM node we have cached.\n  var parents = [];\n  while (!inst._hostNode) {\n    parents.push(inst);\n    !inst._hostParent ? \"development\" !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') : _prodInvariant('34') : void 0;\n    inst = inst._hostParent;\n  }\n\n  // Now parents contains each ancestor that does *not* have a cached native\n  // node, and `inst` is the deepest ancestor that does.\n  for (; parents.length; inst = parents.pop()) {\n    precacheChildNodes(inst, inst._hostNode);\n  }\n\n  return inst._hostNode;\n}\n\nvar ReactDOMComponentTree = {\n  getClosestInstanceFromNode: getClosestInstanceFromNode,\n  getInstanceFromNode: getInstanceFromNode,\n  getNodeFromInstance: getNodeFromInstance,\n  precacheChildNodes: precacheChildNodes,\n  precacheNode: precacheNode,\n  uncacheNode: uncacheNode\n};\n\nmodule.exports = ReactDOMComponentTree;\n},{\"10\":10,\"139\":139,\"161\":161,\"40\":40}],42:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMContainerInfo\n */\n\n'use strict';\n\nvar validateDOMNesting = _dereq_(145);\n\nvar DOC_NODE_TYPE = 9;\n\nfunction ReactDOMContainerInfo(topLevelWrapper, node) {\n  var info = {\n    _topLevelWrapper: topLevelWrapper,\n    _idCounter: 1,\n    _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null,\n    _node: node,\n    _tag: node ? node.nodeName.toLowerCase() : null,\n    _namespaceURI: node ? node.namespaceURI : null\n  };\n  if (\"development\" !== 'production') {\n    info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null;\n  }\n  return info;\n}\n\nmodule.exports = ReactDOMContainerInfo;\n},{\"145\":145}],43:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMDebugTool\n */\n\n'use strict';\n\nvar ReactDOMNullInputValuePropDevtool = _dereq_(50);\nvar ReactDOMUnknownPropertyDevtool = _dereq_(58);\nvar ReactDebugTool = _dereq_(59);\n\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar ReactDOMDebugTool = {\n  addDevtool: function (devtool) {\n    ReactDebugTool.addDevtool(devtool);\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    ReactDebugTool.removeDevtool(devtool);\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  onCreateMarkupForProperty: function (name, value) {\n    emitEvent('onCreateMarkupForProperty', name, value);\n  },\n  onSetValueForProperty: function (node, name, value) {\n    emitEvent('onSetValueForProperty', node, name, value);\n  },\n  onDeleteValueForProperty: function (node, name) {\n    emitEvent('onDeleteValueForProperty', node, name);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool);\nReactDOMDebugTool.addDevtool(ReactDOMNullInputValuePropDevtool);\n\nmodule.exports = ReactDOMDebugTool;\n},{\"171\":171,\"50\":50,\"58\":58,\"59\":59}],44:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMEmptyComponent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar ReactDOMEmptyComponent = function (instantiate) {\n  // ReactCompositeComponent uses this:\n  this._currentElement = null;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n  this._hostContainerInfo = null;\n  this._domID = null;\n};\n_assign(ReactDOMEmptyComponent.prototype, {\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    var domID = hostContainerInfo._idCounter++;\n    this._domID = domID;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var nodeValue = ' react-empty: ' + this._domID + ' ';\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var node = ownerDocument.createComment(nodeValue);\n      ReactDOMComponentTree.precacheNode(this, node);\n      return DOMLazyTree(node);\n    } else {\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd insert a comment node, but since this is a situation\n        // where React won't take over (static pages), we can simply return\n        // nothing.\n        return '';\n      }\n      return '<!--' + nodeValue + '-->';\n    }\n  },\n  receiveComponent: function () {},\n  getHostNode: function () {\n    return ReactDOMComponentTree.getNodeFromInstance(this);\n  },\n  unmountComponent: function () {\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n});\n\nmodule.exports = ReactDOMEmptyComponent;\n},{\"172\":172,\"41\":41,\"8\":8}],45:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFactories\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\n\nvar mapObject = _dereq_(166);\n\n/**\n * Create a factory that creates HTML tag elements.\n *\n * @param {string} tag Tag name (e.g. `div`).\n * @private\n */\nfunction createDOMFactory(tag) {\n  if (\"development\" !== 'production') {\n    var ReactElementValidator = _dereq_(63);\n    return ReactElementValidator.createFactory(tag);\n  }\n  return ReactElement.createFactory(tag);\n}\n\n/**\n * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.\n * This is also accessible via `React.DOM`.\n *\n * @public\n */\nvar ReactDOMFactories = mapObject({\n  a: 'a',\n  abbr: 'abbr',\n  address: 'address',\n  area: 'area',\n  article: 'article',\n  aside: 'aside',\n  audio: 'audio',\n  b: 'b',\n  base: 'base',\n  bdi: 'bdi',\n  bdo: 'bdo',\n  big: 'big',\n  blockquote: 'blockquote',\n  body: 'body',\n  br: 'br',\n  button: 'button',\n  canvas: 'canvas',\n  caption: 'caption',\n  cite: 'cite',\n  code: 'code',\n  col: 'col',\n  colgroup: 'colgroup',\n  data: 'data',\n  datalist: 'datalist',\n  dd: 'dd',\n  del: 'del',\n  details: 'details',\n  dfn: 'dfn',\n  dialog: 'dialog',\n  div: 'div',\n  dl: 'dl',\n  dt: 'dt',\n  em: 'em',\n  embed: 'embed',\n  fieldset: 'fieldset',\n  figcaption: 'figcaption',\n  figure: 'figure',\n  footer: 'footer',\n  form: 'form',\n  h1: 'h1',\n  h2: 'h2',\n  h3: 'h3',\n  h4: 'h4',\n  h5: 'h5',\n  h6: 'h6',\n  head: 'head',\n  header: 'header',\n  hgroup: 'hgroup',\n  hr: 'hr',\n  html: 'html',\n  i: 'i',\n  iframe: 'iframe',\n  img: 'img',\n  input: 'input',\n  ins: 'ins',\n  kbd: 'kbd',\n  keygen: 'keygen',\n  label: 'label',\n  legend: 'legend',\n  li: 'li',\n  link: 'link',\n  main: 'main',\n  map: 'map',\n  mark: 'mark',\n  menu: 'menu',\n  menuitem: 'menuitem',\n  meta: 'meta',\n  meter: 'meter',\n  nav: 'nav',\n  noscript: 'noscript',\n  object: 'object',\n  ol: 'ol',\n  optgroup: 'optgroup',\n  option: 'option',\n  output: 'output',\n  p: 'p',\n  param: 'param',\n  picture: 'picture',\n  pre: 'pre',\n  progress: 'progress',\n  q: 'q',\n  rp: 'rp',\n  rt: 'rt',\n  ruby: 'ruby',\n  s: 's',\n  samp: 'samp',\n  script: 'script',\n  section: 'section',\n  select: 'select',\n  small: 'small',\n  source: 'source',\n  span: 'span',\n  strong: 'strong',\n  style: 'style',\n  sub: 'sub',\n  summary: 'summary',\n  sup: 'sup',\n  table: 'table',\n  tbody: 'tbody',\n  td: 'td',\n  textarea: 'textarea',\n  tfoot: 'tfoot',\n  th: 'th',\n  thead: 'thead',\n  time: 'time',\n  title: 'title',\n  tr: 'tr',\n  track: 'track',\n  u: 'u',\n  ul: 'ul',\n  'var': 'var',\n  video: 'video',\n  wbr: 'wbr',\n\n  // SVG\n  circle: 'circle',\n  clipPath: 'clipPath',\n  defs: 'defs',\n  ellipse: 'ellipse',\n  g: 'g',\n  image: 'image',\n  line: 'line',\n  linearGradient: 'linearGradient',\n  mask: 'mask',\n  path: 'path',\n  pattern: 'pattern',\n  polygon: 'polygon',\n  polyline: 'polyline',\n  radialGradient: 'radialGradient',\n  rect: 'rect',\n  stop: 'stop',\n  svg: 'svg',\n  text: 'text',\n  tspan: 'tspan'\n\n}, createDOMFactory);\n\nmodule.exports = ReactDOMFactories;\n},{\"166\":166,\"62\":62,\"63\":63}],46:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFeatureFlags\n */\n\n'use strict';\n\nvar ReactDOMFeatureFlags = {\n  useCreateElement: true\n};\n\nmodule.exports = ReactDOMFeatureFlags;\n},{}],47:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMIDOperations\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMComponentTree = _dereq_(41);\n\n/**\n * Operations used to process updates to DOM nodes.\n */\nvar ReactDOMIDOperations = {\n\n  /**\n   * Updates a component's children by processing a series of updates.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  dangerouslyProcessChildrenUpdates: function (parentInst, updates) {\n    var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);\n    DOMChildrenOperations.processUpdates(node, updates);\n  }\n};\n\nmodule.exports = ReactDOMIDOperations;\n},{\"41\":41,\"7\":7}],48:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInput\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar DOMPropertyOperations = _dereq_(11);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnCheckedLink = false;\nvar didWarnValueDefaultValue = false;\nvar didWarnCheckedDefaultChecked = false;\nvar didWarnControlledToUncontrolled = false;\nvar didWarnUncontrolledToControlled = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMInput.updateWrapper(this);\n  }\n}\n\nfunction isControlled(props) {\n  var usesChecked = props.type === 'checkbox' || props.type === 'radio';\n  return usesChecked ? props.checked !== undefined : props.value !== undefined;\n}\n\n/**\n * Implements an <input> host component that allows setting these optional\n * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.\n *\n * If `checked` or `value` are not supplied (or null/undefined), user actions\n * that affect the checked state or value will trigger updates to the element.\n *\n * If they are supplied (and not null/undefined), the rendered element will not\n * trigger updates to the element. Instead, the props must change in order for\n * the rendered element to be updated.\n *\n * The rendered element will be initialized as unchecked (or `defaultChecked`)\n * with an empty value (or `defaultValue`).\n *\n * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html\n */\nvar ReactDOMInput = {\n  getHostProps: function (inst, props) {\n    var value = LinkedValueUtils.getValue(props);\n    var checked = LinkedValueUtils.getChecked(props);\n\n    var hostProps = _assign({\n      // Make sure we set .type before any other properties (setting .value\n      // before .type means .value is lost in IE11 and below)\n      type: undefined\n    }, DisabledInputUtils.getHostProps(inst, props), {\n      defaultChecked: undefined,\n      defaultValue: undefined,\n      value: value != null ? value : inst._wrapperState.initialValue,\n      checked: checked != null ? checked : inst._wrapperState.initialChecked,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);\n\n      var owner = inst._currentElement._owner;\n\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.checkedLink !== undefined && !didWarnCheckedLink) {\n        \"development\" !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnCheckedLink = true;\n      }\n      if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnCheckedDefaultChecked = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnValueDefaultValue = true;\n      }\n    }\n\n    var defaultValue = props.defaultValue;\n    inst._wrapperState = {\n      initialChecked: props.checked != null ? props.checked : props.defaultChecked,\n      initialValue: props.value != null ? props.value : defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n\n    if (\"development\" !== 'production') {\n      inst._wrapperState.controlled = isControlled(props);\n    }\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    if (\"development\" !== 'production') {\n      var controlled = isControlled(props);\n      var owner = inst._currentElement._owner;\n\n      if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnUncontrolledToControlled = true;\n      }\n      if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnControlledToUncontrolled = true;\n      }\n    }\n\n    // TODO: Shouldn't this be getChecked(props)?\n    var checked = props.checked;\n    if (checked != null) {\n      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);\n    }\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n    } else {\n      if (props.value == null && props.defaultValue != null) {\n        node.defaultValue = '' + props.defaultValue;\n      }\n      if (props.checked == null && props.defaultChecked != null) {\n        node.defaultChecked = !!props.defaultChecked;\n      }\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Detach value from defaultValue. We won't do anything if we're working on\n    // submit or reset inputs as those values & defaultValues are linked. They\n    // are not resetable nodes so this operation doesn't matter and actually\n    // removes browser-default values (eg \"Submit Query\") when no value is\n    // provided.\n    if (props.type !== 'submit' && props.type !== 'reset') {\n      node.value = node.value;\n    }\n\n    // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug\n    // this is needed to work around a chrome bug where setting defaultChecked\n    // will sometimes influence the value of checked (even after detachment).\n    // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416\n    // We need to temporarily unset name to avoid disrupting radio button groups.\n    var name = node.name;\n    if (name !== '') {\n      node.name = '';\n    }\n    node.defaultChecked = !node.defaultChecked;\n    node.defaultChecked = !node.defaultChecked;\n    if (name !== '') {\n      node.name = name;\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  // Here we use asap to wait until all updates have propagated, which\n  // is important when using controlled components within layers:\n  // https://github.com/facebook/react/issues/1698\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n\n  var name = props.name;\n  if (props.type === 'radio' && name != null) {\n    var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);\n    var queryRoot = rootNode;\n\n    while (queryRoot.parentNode) {\n      queryRoot = queryRoot.parentNode;\n    }\n\n    // If `rootNode.form` was non-null, then we could try `form.elements`,\n    // but that sometimes behaves strangely in IE8. We could also try using\n    // `form.getElementsByName`, but that will only return direct children\n    // and won't include inputs that use the HTML5 `form=` attribute. Since\n    // the input might not even be in a form, let's just use the global\n    // `querySelectorAll` to ensure we don't miss anything.\n    var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type=\"radio\"]');\n\n    for (var i = 0; i < group.length; i++) {\n      var otherNode = group[i];\n      if (otherNode === rootNode || otherNode.form !== rootNode.form) {\n        continue;\n      }\n      // This will throw if radio buttons rendered by different copies of React\n      // and the same name are rendered into the same form (same as #1939).\n      // That's probably okay; we don't support it just as we don't support\n      // mixing React radio buttons with non-React ones.\n      var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);\n      !otherInstance ? \"development\" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;\n      // If this is a controlled radio button group, forcing the input that\n      // was previously checked to update will cause it to be come re-checked\n      // as appropriate.\n      ReactUpdates.asap(forceUpdateIfMounted, otherInstance);\n    }\n  }\n\n  return returnValue;\n}\n\nmodule.exports = ReactDOMInput;\n},{\"11\":11,\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],49:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDOMDebugTool = _dereq_(43);\n  debugTool = ReactDOMDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"43\":43}],50:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMNullInputValuePropDevtool\n */\n\n'use strict';\n\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueNull = false;\n\nfunction handleElement(debugID, element) {\n  if (element == null) {\n    return;\n  }\n  if (element.type !== 'input' && element.type !== 'textarea' && element.type !== 'select') {\n    return;\n  }\n  if (element.props != null && element.props.value === null && !didWarnValueNull) {\n    \"development\" !== 'production' ? warning(false, '`value` prop on `%s` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n\n    didWarnValueNull = true;\n  }\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"171\":171,\"34\":34}],51:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMOption\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMSelect = _dereq_(52);\n\nvar warning = _dereq_(171);\nvar didWarnInvalidOptionChildren = false;\n\nfunction flattenChildren(children) {\n  var content = '';\n\n  // Flatten children and warn if they aren't strings or numbers;\n  // invalid types are ignored.\n  ReactChildren.forEach(children, function (child) {\n    if (child == null) {\n      return;\n    }\n    if (typeof child === 'string' || typeof child === 'number') {\n      content += child;\n    } else if (!didWarnInvalidOptionChildren) {\n      didWarnInvalidOptionChildren = true;\n      \"development\" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;\n    }\n  });\n\n  return content;\n}\n\n/**\n * Implements an <option> host component that warns when `selected` is set.\n */\nvar ReactDOMOption = {\n  mountWrapper: function (inst, props, hostParent) {\n    // TODO (yungsters): Remove support for `selected` in <option>.\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;\n    }\n\n    // Look up whether this option is 'selected'\n    var selectValue = null;\n    if (hostParent != null) {\n      var selectParent = hostParent;\n\n      if (selectParent._tag === 'optgroup') {\n        selectParent = selectParent._hostParent;\n      }\n\n      if (selectParent != null && selectParent._tag === 'select') {\n        selectValue = ReactDOMSelect.getSelectValueContext(selectParent);\n      }\n    }\n\n    // If the value is null (e.g., no specified value or after initial mount)\n    // or missing (e.g., for <datalist>), we don't change props.selected\n    var selected = null;\n    if (selectValue != null) {\n      var value;\n      if (props.value != null) {\n        value = props.value + '';\n      } else {\n        value = flattenChildren(props.children);\n      }\n      selected = false;\n      if (Array.isArray(selectValue)) {\n        // multiple\n        for (var i = 0; i < selectValue.length; i++) {\n          if ('' + selectValue[i] === value) {\n            selected = true;\n            break;\n          }\n        }\n      } else {\n        selected = '' + selectValue === value;\n      }\n    }\n\n    inst._wrapperState = { selected: selected };\n  },\n\n  postMountWrapper: function (inst) {\n    // value=\"\" should make a value attribute (#6219)\n    var props = inst._currentElement.props;\n    if (props.value != null) {\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      node.setAttribute('value', props.value);\n    }\n  },\n\n  getHostProps: function (inst, props) {\n    var hostProps = _assign({ selected: undefined, children: undefined }, props);\n\n    // Read state only from initial mount because <select> updates value\n    // manually; we need the initial state only for server rendering\n    if (inst._wrapperState.selected != null) {\n      hostProps.selected = inst._wrapperState.selected;\n    }\n\n    var content = flattenChildren(props.children);\n\n    if (content) {\n      hostProps.children = content;\n    }\n\n    return hostProps;\n  }\n\n};\n\nmodule.exports = ReactDOMOption;\n},{\"171\":171,\"172\":172,\"29\":29,\"41\":41,\"52\":52}],52:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelect\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValueDefaultValue = false;\n\nfunction updateOptionsIfPendingUpdateAndMounted() {\n  if (this._rootNodeID && this._wrapperState.pendingUpdate) {\n    this._wrapperState.pendingUpdate = false;\n\n    var props = this._currentElement.props;\n    var value = LinkedValueUtils.getValue(props);\n\n    if (value != null) {\n      updateOptions(this, Boolean(props.multiple), value);\n    }\n  }\n}\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nvar valuePropNames = ['value', 'defaultValue'];\n\n/**\n * Validation function for `value` and `defaultValue`.\n * @private\n */\nfunction checkSelectPropTypes(inst, props) {\n  var owner = inst._currentElement._owner;\n  LinkedValueUtils.checkPropTypes('select', props, owner);\n\n  if (props.valueLink !== undefined && !didWarnValueLink) {\n    \"development\" !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;\n    didWarnValueLink = true;\n  }\n\n  for (var i = 0; i < valuePropNames.length; i++) {\n    var propName = valuePropNames[i];\n    if (props[propName] == null) {\n      continue;\n    }\n    if (props.multiple) {\n      \"development\" !== 'production' ? warning(Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    } else {\n      \"development\" !== 'production' ? warning(!Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    }\n  }\n}\n\n/**\n * @param {ReactDOMComponent} inst\n * @param {boolean} multiple\n * @param {*} propValue A stringable (with `multiple`, a list of stringables).\n * @private\n */\nfunction updateOptions(inst, multiple, propValue) {\n  var selectedValue, i;\n  var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;\n\n  if (multiple) {\n    selectedValue = {};\n    for (i = 0; i < propValue.length; i++) {\n      selectedValue['' + propValue[i]] = true;\n    }\n    for (i = 0; i < options.length; i++) {\n      var selected = selectedValue.hasOwnProperty(options[i].value);\n      if (options[i].selected !== selected) {\n        options[i].selected = selected;\n      }\n    }\n  } else {\n    // Do not set `select.value` as exact behavior isn't consistent across all\n    // browsers for all cases.\n    selectedValue = '' + propValue;\n    for (i = 0; i < options.length; i++) {\n      if (options[i].value === selectedValue) {\n        options[i].selected = true;\n        return;\n      }\n    }\n    if (options.length) {\n      options[0].selected = true;\n    }\n  }\n}\n\n/**\n * Implements a <select> host component that allows optionally setting the\n * props `value` and `defaultValue`. If `multiple` is false, the prop must be a\n * stringable. If `multiple` is true, the prop must be an array of stringables.\n *\n * If `value` is not supplied (or null/undefined), user actions that change the\n * selected option will trigger updates to the rendered options.\n *\n * If it is supplied (and not null/undefined), the rendered options will not\n * update in response to user actions. Instead, the `value` prop must change in\n * order for the rendered options to update.\n *\n * If `defaultValue` is provided, any options with the supplied values will be\n * selected.\n */\nvar ReactDOMSelect = {\n  getHostProps: function (inst, props) {\n    return _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      onChange: inst._wrapperState.onChange,\n      value: undefined\n    });\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      checkSelectPropTypes(inst, props);\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    inst._wrapperState = {\n      pendingUpdate: false,\n      initialValue: value != null ? value : props.defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst),\n      wasMultiple: Boolean(props.multiple)\n    };\n\n    if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n      \"development\" !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n      didWarnValueDefaultValue = true;\n    }\n  },\n\n  getSelectValueContext: function (inst) {\n    // ReactDOMOption looks at this initial value so the initial generated\n    // markup has correct `selected` attributes\n    return inst._wrapperState.initialValue;\n  },\n\n  postUpdateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // After the initial mount, we control selected-ness manually so don't pass\n    // this value down\n    inst._wrapperState.initialValue = undefined;\n\n    var wasMultiple = inst._wrapperState.wasMultiple;\n    inst._wrapperState.wasMultiple = Boolean(props.multiple);\n\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      inst._wrapperState.pendingUpdate = false;\n      updateOptions(inst, Boolean(props.multiple), value);\n    } else if (wasMultiple !== Boolean(props.multiple)) {\n      // For simplicity, reapply `defaultValue` if `multiple` is toggled.\n      if (props.defaultValue != null) {\n        updateOptions(inst, Boolean(props.multiple), props.defaultValue);\n      } else {\n        // Revert the select back to its default unselected state.\n        updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : '');\n      }\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  if (this._rootNodeID) {\n    this._wrapperState.pendingUpdate = true;\n  }\n  ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMSelect;\n},{\"14\":14,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],53:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelection\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar getNodeForCharacterOffset = _dereq_(131);\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * While `isCollapsed` is available on the Selection object and `collapsed`\n * is available on the Range object, IE11 sometimes gets them wrong.\n * If the anchor/focus nodes and offsets are the same, the range is collapsed.\n */\nfunction isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {\n  return anchorNode === focusNode && anchorOffset === focusOffset;\n}\n\n/**\n * Get the appropriate anchor and focus node/offset pairs for IE.\n *\n * The catch here is that IE's selection API doesn't provide information\n * about whether the selection is forward or backward, so we have to\n * behave as though it's always forward.\n *\n * IE text differs from modern selection in that it behaves as though\n * block elements end with a new line. This means character offsets will\n * differ between the two APIs.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getIEOffsets(node) {\n  var selection = document.selection;\n  var selectedRange = selection.createRange();\n  var selectedLength = selectedRange.text.length;\n\n  // Duplicate selection so we can move range without breaking user selection.\n  var fromStart = selectedRange.duplicate();\n  fromStart.moveToElementText(node);\n  fromStart.setEndPoint('EndToStart', selectedRange);\n\n  var startOffset = fromStart.text.length;\n  var endOffset = startOffset + selectedLength;\n\n  return {\n    start: startOffset,\n    end: endOffset\n  };\n}\n\n/**\n * @param {DOMElement} node\n * @return {?object}\n */\nfunction getModernOffsets(node) {\n  var selection = window.getSelection && window.getSelection();\n\n  if (!selection || selection.rangeCount === 0) {\n    return null;\n  }\n\n  var anchorNode = selection.anchorNode;\n  var anchorOffset = selection.anchorOffset;\n  var focusNode = selection.focusNode;\n  var focusOffset = selection.focusOffset;\n\n  var currentRange = selection.getRangeAt(0);\n\n  // In Firefox, range.startContainer and range.endContainer can be \"anonymous\n  // divs\", e.g. the up/down buttons on an <input type=\"number\">. Anonymous\n  // divs do not seem to expose properties, triggering a \"Permission denied\n  // error\" if any of its properties are accessed. The only seemingly possible\n  // way to avoid erroring is to access a property that typically works for\n  // non-anonymous divs and catch any error that may otherwise arise. See\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=208427\n  try {\n    /* eslint-disable no-unused-expressions */\n    currentRange.startContainer.nodeType;\n    currentRange.endContainer.nodeType;\n    /* eslint-enable no-unused-expressions */\n  } catch (e) {\n    return null;\n  }\n\n  // If the node and offset values are the same, the selection is collapsed.\n  // `Selection.isCollapsed` is available natively, but IE sometimes gets\n  // this value wrong.\n  var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);\n\n  var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;\n\n  var tempRange = currentRange.cloneRange();\n  tempRange.selectNodeContents(node);\n  tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);\n\n  var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset);\n\n  var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;\n  var end = start + rangeLength;\n\n  // Detect whether the selection is backward.\n  var detectionRange = document.createRange();\n  detectionRange.setStart(anchorNode, anchorOffset);\n  detectionRange.setEnd(focusNode, focusOffset);\n  var isBackward = detectionRange.collapsed;\n\n  return {\n    start: isBackward ? end : start,\n    end: isBackward ? start : end\n  };\n}\n\n/**\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setIEOffsets(node, offsets) {\n  var range = document.selection.createRange().duplicate();\n  var start, end;\n\n  if (offsets.end === undefined) {\n    start = offsets.start;\n    end = start;\n  } else if (offsets.start > offsets.end) {\n    start = offsets.end;\n    end = offsets.start;\n  } else {\n    start = offsets.start;\n    end = offsets.end;\n  }\n\n  range.moveToElementText(node);\n  range.moveStart('character', start);\n  range.setEndPoint('EndToStart', range);\n  range.moveEnd('character', end - start);\n  range.select();\n}\n\n/**\n * In modern non-IE browsers, we can support both forward and backward\n * selections.\n *\n * Note: IE10+ supports the Selection object, but it does not support\n * the `extend` method, which means that even in modern IE, it's not possible\n * to programmatically create a backward selection. Thus, for all IE\n * versions, we use the old IE API to create our selections.\n *\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setModernOffsets(node, offsets) {\n  if (!window.getSelection) {\n    return;\n  }\n\n  var selection = window.getSelection();\n  var length = node[getTextContentAccessor()].length;\n  var start = Math.min(offsets.start, length);\n  var end = offsets.end === undefined ? start : Math.min(offsets.end, length);\n\n  // IE 11 uses modern selection, but doesn't support the extend method.\n  // Flip backward selections, so we can set with a single range.\n  if (!selection.extend && start > end) {\n    var temp = end;\n    end = start;\n    start = temp;\n  }\n\n  var startMarker = getNodeForCharacterOffset(node, start);\n  var endMarker = getNodeForCharacterOffset(node, end);\n\n  if (startMarker && endMarker) {\n    var range = document.createRange();\n    range.setStart(startMarker.node, startMarker.offset);\n    selection.removeAllRanges();\n\n    if (start > end) {\n      selection.addRange(range);\n      selection.extend(endMarker.node, endMarker.offset);\n    } else {\n      range.setEnd(endMarker.node, endMarker.offset);\n      selection.addRange(range);\n    }\n  }\n}\n\nvar useIEOffsets = ExecutionEnvironment.canUseDOM && 'selection' in document && !('getSelection' in window);\n\nvar ReactDOMSelection = {\n  /**\n   * @param {DOMElement} node\n   */\n  getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,\n\n  /**\n   * @param {DOMElement|DOMTextNode} node\n   * @param {object} offsets\n   */\n  setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets\n};\n\nmodule.exports = ReactDOMSelection;\n},{\"131\":131,\"132\":132,\"147\":147}],54:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMServer\n */\n\n'use strict';\n\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactServerRendering = _dereq_(90);\nvar ReactVersion = _dereq_(96);\n\nReactDefaultInjection.inject();\n\nvar ReactDOMServer = {\n  renderToString: ReactServerRendering.renderToString,\n  renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup,\n  version: ReactVersion\n};\n\nmodule.exports = ReactDOMServer;\n},{\"61\":61,\"90\":90,\"96\":96}],55:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DOMChildrenOperations = _dereq_(7);\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar validateDOMNesting = _dereq_(145);\n\n/**\n * Text nodes violate a couple assumptions that React makes about components:\n *\n *  - When mounting text into the DOM, adjacent text nodes are merged.\n *  - Text nodes cannot be assigned a React root ID.\n *\n * This component is used to wrap strings between comment nodes so that they\n * can undergo the same reconciliation that is applied to elements.\n *\n * TODO: Investigate representing React components in the DOM with text nodes.\n *\n * @class ReactDOMTextComponent\n * @extends ReactComponent\n * @internal\n */\nvar ReactDOMTextComponent = function (text) {\n  // TODO: This is really a ReactText (ReactNode), not a ReactElement\n  this._currentElement = text;\n  this._stringText = '' + text;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n\n  // Properties\n  this._domID = null;\n  this._mountIndex = 0;\n  this._closingComment = null;\n  this._commentNodes = null;\n};\n\n_assign(ReactDOMTextComponent.prototype, {\n\n  /**\n   * Creates the markup for this text node. This node is not intended to have\n   * any features besides containing text content.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @return {string} Markup for this text node.\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetText(this._debugID, this._stringText);\n\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo != null) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting('#text', this, parentInfo);\n      }\n    }\n\n    var domID = hostContainerInfo._idCounter++;\n    var openingValue = ' react-text: ' + domID + ' ';\n    var closingValue = ' /react-text ';\n    this._domID = domID;\n    this._hostParent = hostParent;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var openingComment = ownerDocument.createComment(openingValue);\n      var closingComment = ownerDocument.createComment(closingValue);\n      var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment());\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment));\n      if (this._stringText) {\n        DOMLazyTree.queueChild(lazyTree, DOMLazyTree(ownerDocument.createTextNode(this._stringText)));\n      }\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment));\n      ReactDOMComponentTree.precacheNode(this, openingComment);\n      this._closingComment = closingComment;\n      return lazyTree;\n    } else {\n      var escapedText = escapeTextContentForBrowser(this._stringText);\n\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd wrap this between comment nodes for the reasons stated\n        // above, but since this is a situation where React won't take over\n        // (static pages), we can simply return the text as it is.\n        return escapedText;\n      }\n\n      return '<!--' + openingValue + '-->' + escapedText + '<!--' + closingValue + '-->';\n    }\n  },\n\n  /**\n   * Updates this component by updating the text content.\n   *\n   * @param {ReactText} nextText The next text content\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  receiveComponent: function (nextText, transaction) {\n    if (nextText !== this._currentElement) {\n      this._currentElement = nextText;\n      var nextStringText = '' + nextText;\n      if (nextStringText !== this._stringText) {\n        // TODO: Save this as pending props and use performUpdateIfNecessary\n        // and/or updateComponent to do the actual update for consistency with\n        // other component types?\n        this._stringText = nextStringText;\n        var commentNodes = this.getHostNode();\n        DOMChildrenOperations.replaceDelimitedText(commentNodes[0], commentNodes[1], nextStringText);\n\n        if (\"development\" !== 'production') {\n          ReactInstrumentation.debugTool.onSetText(this._debugID, nextStringText);\n        }\n      }\n    }\n  },\n\n  getHostNode: function () {\n    var hostNode = this._commentNodes;\n    if (hostNode) {\n      return hostNode;\n    }\n    if (!this._closingComment) {\n      var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);\n      var node = openingComment.nextSibling;\n      while (true) {\n        !(node != null) ? \"development\" !== 'production' ? invariant(false, 'Missing closing comment for text component %s', this._domID) : _prodInvariant('67', this._domID) : void 0;\n        if (node.nodeType === 8 && node.nodeValue === ' /react-text ') {\n          this._closingComment = node;\n          break;\n        }\n        node = node.nextSibling;\n      }\n    }\n    hostNode = [this._hostNode, this._closingComment];\n    this._commentNodes = hostNode;\n    return hostNode;\n  },\n\n  unmountComponent: function () {\n    this._closingComment = null;\n    this._commentNodes = null;\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n\n});\n\nmodule.exports = ReactDOMTextComponent;\n},{\"121\":121,\"139\":139,\"145\":145,\"161\":161,\"172\":172,\"41\":41,\"7\":7,\"74\":74,\"8\":8}],56:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextarea\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValDefaultVal = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMTextarea.updateWrapper(this);\n  }\n}\n\n/**\n * Implements a <textarea> host component that allows setting `value`, and\n * `defaultValue`. This differs from the traditional DOM API because value is\n * usually set as PCDATA children.\n *\n * If `value` is not supplied (or null/undefined), user actions that affect the\n * value will trigger updates to the element.\n *\n * If `value` is supplied (and not null/undefined), the rendered element will\n * not trigger updates to the element. Instead, the `value` prop must change in\n * order for the rendered element to be updated.\n *\n * The rendered element will be initialized with an empty value, the prop\n * `defaultValue` if specified, or the children content (deprecated).\n */\nvar ReactDOMTextarea = {\n  getHostProps: function (inst, props) {\n    !(props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : _prodInvariant('91') : void 0;\n\n    // Always set children to the same thing. In IE9, the selection range will\n    // get reset if `textContent` is mutated.  We could add a check in setTextContent\n    // to only set the value if/when the value differs from the node value (which would\n    // completely solve this IE9 bug), but Sebastian+Ben seemed to like this solution.\n    // The value can be a boolean or object so that's why it's forced to be a string.\n    var hostProps = _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      value: undefined,\n      defaultValue: undefined,\n      children: '' + inst._wrapperState.initialValue,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `textarea` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {\n        \"development\" !== 'production' ? warning(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n        didWarnValDefaultVal = true;\n      }\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    var initialValue = value;\n\n    // Only bother fetching default value if we're going to use it\n    if (value == null) {\n      var defaultValue = props.defaultValue;\n      // TODO (yungsters): Remove support for children content in <textarea>.\n      var children = props.children;\n      if (children != null) {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.') : void 0;\n        }\n        !(defaultValue == null) ? \"development\" !== 'production' ? invariant(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : _prodInvariant('92') : void 0;\n        if (Array.isArray(children)) {\n          !(children.length <= 1) ? \"development\" !== 'production' ? invariant(false, '<textarea> can only have at most one child.') : _prodInvariant('93') : void 0;\n          children = children[0];\n        }\n\n        defaultValue = '' + children;\n      }\n      if (defaultValue == null) {\n        defaultValue = '';\n      }\n      initialValue = defaultValue;\n    }\n\n    inst._wrapperState = {\n      initialValue: '' + initialValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n      if (props.defaultValue == null) {\n        node.defaultValue = newValue;\n      }\n    }\n    if (props.defaultValue != null) {\n      node.defaultValue = props.defaultValue;\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Warning: node.value may be the empty string at this point (IE11) if placeholder is set.\n    node.value = node.textContent; // Detach value from defaultValue\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMTextarea;\n},{\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],57:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTreeTraversal\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Return the lowest common ancestor of A and B, or null if they are in\n * different trees.\n */\nfunction getLowestCommonAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  var depthA = 0;\n  for (var tempA = instA; tempA; tempA = tempA._hostParent) {\n    depthA++;\n  }\n  var depthB = 0;\n  for (var tempB = instB; tempB; tempB = tempB._hostParent) {\n    depthB++;\n  }\n\n  // If A is deeper, crawl up.\n  while (depthA - depthB > 0) {\n    instA = instA._hostParent;\n    depthA--;\n  }\n\n  // If B is deeper, crawl up.\n  while (depthB - depthA > 0) {\n    instB = instB._hostParent;\n    depthB--;\n  }\n\n  // Walk in lockstep until we find a match.\n  var depth = depthA;\n  while (depth--) {\n    if (instA === instB) {\n      return instA;\n    }\n    instA = instA._hostParent;\n    instB = instB._hostParent;\n  }\n  return null;\n}\n\n/**\n * Return if A is an ancestor of B.\n */\nfunction isAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n\n  while (instB) {\n    if (instB === instA) {\n      return true;\n    }\n    instB = instB._hostParent;\n  }\n  return false;\n}\n\n/**\n * Return the parent instance of the passed-in instance.\n */\nfunction getParentInstance(inst) {\n  !('_hostNode' in inst) ? \"development\" !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : _prodInvariant('36') : void 0;\n\n  return inst._hostParent;\n}\n\n/**\n * Simulates the traversal of a two-phase, capture/bubble event dispatch.\n */\nfunction traverseTwoPhase(inst, fn, arg) {\n  var path = [];\n  while (inst) {\n    path.push(inst);\n    inst = inst._hostParent;\n  }\n  var i;\n  for (i = path.length; i-- > 0;) {\n    fn(path[i], false, arg);\n  }\n  for (i = 0; i < path.length; i++) {\n    fn(path[i], true, arg);\n  }\n}\n\n/**\n * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that\n * should would receive a `mouseEnter` or `mouseLeave` event.\n *\n * Does not invoke the callback on the nearest common ancestor because nothing\n * \"entered\" or \"left\" that element.\n */\nfunction traverseEnterLeave(from, to, fn, argFrom, argTo) {\n  var common = from && to ? getLowestCommonAncestor(from, to) : null;\n  var pathFrom = [];\n  while (from && from !== common) {\n    pathFrom.push(from);\n    from = from._hostParent;\n  }\n  var pathTo = [];\n  while (to && to !== common) {\n    pathTo.push(to);\n    to = to._hostParent;\n  }\n  var i;\n  for (i = 0; i < pathFrom.length; i++) {\n    fn(pathFrom[i], true, argFrom);\n  }\n  for (i = pathTo.length; i-- > 0;) {\n    fn(pathTo[i], false, argTo);\n  }\n}\n\nmodule.exports = {\n  isAncestor: isAncestor,\n  getLowestCommonAncestor: getLowestCommonAncestor,\n  getParentInstance: getParentInstance,\n  traverseTwoPhase: traverseTwoPhase,\n  traverseEnterLeave: traverseEnterLeave\n};\n},{\"139\":139,\"161\":161}],58:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMUnknownPropertyDevtool\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var reactProps = {\n    children: true,\n    dangerouslySetInnerHTML: true,\n    key: true,\n    ref: true,\n\n    autoFocus: true,\n    defaultValue: true,\n    valueLink: true,\n    defaultChecked: true,\n    checkedLink: true,\n    innerHTML: true,\n    suppressContentEditableWarning: true,\n    onFocusIn: true,\n    onFocusOut: true\n  };\n  var warnedProperties = {};\n\n  var validateProperty = function (tagName, name, debugID) {\n    if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) {\n      return true;\n    }\n    if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {\n      return true;\n    }\n    if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) {\n      return true;\n    }\n    warnedProperties[name] = true;\n    var lowerCasedName = name.toLowerCase();\n\n    // data-* attributes should be lowercase; suggest the lowercase version\n    var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;\n\n    var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : null;\n\n    if (standardName != null) {\n      \"development\" !== 'production' ? warning(standardName == null, 'Unknown DOM property %s. Did you mean %s?%s', name, standardName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else if (registrationName != null) {\n      \"development\" !== 'production' ? warning(registrationName == null, 'Unknown event handler property %s. Did you mean `%s`?%s', name, registrationName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else {\n      // We were unable to guess which prop the user intended.\n      // It is likely that the user was just blindly spreading/forwarding props\n      // Components should be careful to only render valid props/attributes.\n      // Warning will be invoked in warnUnknownProperties to allow grouping.\n      return false;\n    }\n  };\n}\n\nvar warnUnknownProperties = function (debugID, element) {\n  var unknownProps = [];\n  for (var key in element.props) {\n    var isValid = validateProperty(element.type, key, debugID);\n    if (!isValid) {\n      unknownProps.push(key);\n    }\n  }\n\n  var unknownPropString = unknownProps.map(function (prop) {\n    return '`' + prop + '`';\n  }).join(', ');\n\n  if (unknownProps.length === 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown prop %s on <%s> tag. Remove this prop from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  } else if (unknownProps.length > 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown props %s on <%s> tag. Remove these props from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  }\n};\n\nfunction handleElement(debugID, element) {\n  if (element == null || typeof element.type !== 'string') {\n    return;\n  }\n  if (element.type.indexOf('-') >= 0 || element.props.is) {\n    return;\n  }\n  warnUnknownProperties(debugID, element);\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"10\":10,\"171\":171,\"18\":18,\"34\":34}],59:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDebugTool\n */\n\n'use strict';\n\nvar ReactInvalidSetStateWarningDevTool = _dereq_(75);\nvar ReactHostOperationHistoryDevtool = _dereq_(70);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performanceNow = _dereq_(169);\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar isProfiling = false;\nvar flushHistory = [];\nvar lifeCycleTimerStack = [];\nvar currentFlushNesting = 0;\nvar currentFlushMeasurements = null;\nvar currentFlushStartTime = null;\nvar currentTimerDebugID = null;\nvar currentTimerStartTime = null;\nvar currentTimerNestedFlushDuration = null;\nvar currentTimerType = null;\n\nfunction clearHistory() {\n  ReactComponentTreeDevtool.purgeUnmountedComponents();\n  ReactHostOperationHistoryDevtool.clearHistory();\n}\n\nfunction getTreeSnapshot(registeredIDs) {\n  return registeredIDs.reduce(function (tree, id) {\n    var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n    var parentID = ReactComponentTreeDevtool.getParentID(id);\n    tree[id] = {\n      displayName: ReactComponentTreeDevtool.getDisplayName(id),\n      text: ReactComponentTreeDevtool.getText(id),\n      updateCount: ReactComponentTreeDevtool.getUpdateCount(id),\n      childIDs: ReactComponentTreeDevtool.getChildIDs(id),\n      // Text nodes don't have owners but this is close enough.\n      ownerID: ownerID || ReactComponentTreeDevtool.getOwnerID(parentID),\n      parentID: parentID\n    };\n    return tree;\n  }, {});\n}\n\nfunction resetMeasurements() {\n  var previousStartTime = currentFlushStartTime;\n  var previousMeasurements = currentFlushMeasurements || [];\n  var previousOperations = ReactHostOperationHistoryDevtool.getHistory();\n\n  if (currentFlushNesting === 0) {\n    currentFlushStartTime = null;\n    currentFlushMeasurements = null;\n    clearHistory();\n    return;\n  }\n\n  if (previousMeasurements.length || previousOperations.length) {\n    var registeredIDs = ReactComponentTreeDevtool.getRegisteredIDs();\n    flushHistory.push({\n      duration: performanceNow() - previousStartTime,\n      measurements: previousMeasurements || [],\n      operations: previousOperations || [],\n      treeSnapshot: getTreeSnapshot(registeredIDs)\n    });\n  }\n\n  clearHistory();\n  currentFlushStartTime = performanceNow();\n  currentFlushMeasurements = [];\n}\n\nfunction checkDebugID(debugID) {\n  \"development\" !== 'production' ? warning(debugID, 'ReactDebugTool: debugID may not be empty.') : void 0;\n}\n\nfunction beginLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(!currentTimerType, 'There is an internal error in the React performance measurement code. ' + 'Did not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  currentTimerStartTime = performanceNow();\n  currentTimerNestedFlushDuration = 0;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nfunction endLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(currentTimerType === timerType, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  if (isProfiling) {\n    currentFlushMeasurements.push({\n      timerType: timerType,\n      instanceID: debugID,\n      duration: performanceNow() - currentTimerStartTime - currentTimerNestedFlushDuration\n    });\n  }\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction pauseCurrentLifeCycleTimer() {\n  var currentTimer = {\n    startTime: currentTimerStartTime,\n    nestedFlushStartTime: performanceNow(),\n    debugID: currentTimerDebugID,\n    timerType: currentTimerType\n  };\n  lifeCycleTimerStack.push(currentTimer);\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction resumeCurrentLifeCycleTimer() {\n  var _lifeCycleTimerStack$ = lifeCycleTimerStack.pop();\n\n  var startTime = _lifeCycleTimerStack$.startTime;\n  var nestedFlushStartTime = _lifeCycleTimerStack$.nestedFlushStartTime;\n  var debugID = _lifeCycleTimerStack$.debugID;\n  var timerType = _lifeCycleTimerStack$.timerType;\n\n  var nestedFlushDuration = performanceNow() - nestedFlushStartTime;\n  currentTimerStartTime = startTime;\n  currentTimerNestedFlushDuration += nestedFlushDuration;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nvar ReactDebugTool = {\n  addDevtool: function (devtool) {\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  isProfiling: function () {\n    return isProfiling;\n  },\n  beginProfiling: function () {\n    if (isProfiling) {\n      return;\n    }\n\n    isProfiling = true;\n    flushHistory.length = 0;\n    resetMeasurements();\n    ReactDebugTool.addDevtool(ReactHostOperationHistoryDevtool);\n  },\n  endProfiling: function () {\n    if (!isProfiling) {\n      return;\n    }\n\n    isProfiling = false;\n    resetMeasurements();\n    ReactDebugTool.removeDevtool(ReactHostOperationHistoryDevtool);\n  },\n  getFlushHistory: function () {\n    return flushHistory;\n  },\n  onBeginFlush: function () {\n    currentFlushNesting++;\n    resetMeasurements();\n    pauseCurrentLifeCycleTimer();\n    emitEvent('onBeginFlush');\n  },\n  onEndFlush: function () {\n    resetMeasurements();\n    currentFlushNesting--;\n    resumeCurrentLifeCycleTimer();\n    emitEvent('onEndFlush');\n  },\n  onBeginLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginLifeCycleTimer', debugID, timerType);\n    beginLifeCycleTimer(debugID, timerType);\n  },\n  onEndLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    endLifeCycleTimer(debugID, timerType);\n    emitEvent('onEndLifeCycleTimer', debugID, timerType);\n  },\n  onBeginReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginReconcilerTimer', debugID, timerType);\n  },\n  onEndReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onEndReconcilerTimer', debugID, timerType);\n  },\n  onError: function (debugID) {\n    if (currentTimerDebugID != null) {\n      endLifeCycleTimer(currentTimerDebugID, currentTimerType);\n    }\n    emitEvent('onError', debugID);\n  },\n  onBeginProcessingChildContext: function () {\n    emitEvent('onBeginProcessingChildContext');\n  },\n  onEndProcessingChildContext: function () {\n    emitEvent('onEndProcessingChildContext');\n  },\n  onHostOperation: function (debugID, type, payload) {\n    checkDebugID(debugID);\n    emitEvent('onHostOperation', debugID, type, payload);\n  },\n  onSetState: function () {\n    emitEvent('onSetState');\n  },\n  onSetDisplayName: function (debugID, displayName) {\n    checkDebugID(debugID);\n    emitEvent('onSetDisplayName', debugID, displayName);\n  },\n  onSetChildren: function (debugID, childDebugIDs) {\n    checkDebugID(debugID);\n    childDebugIDs.forEach(checkDebugID);\n    emitEvent('onSetChildren', debugID, childDebugIDs);\n  },\n  onSetOwner: function (debugID, ownerDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetOwner', debugID, ownerDebugID);\n  },\n  onSetParent: function (debugID, parentDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetParent', debugID, parentDebugID);\n  },\n  onSetText: function (debugID, text) {\n    checkDebugID(debugID);\n    emitEvent('onSetText', debugID, text);\n  },\n  onMountRootComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountRootComponent', debugID);\n  },\n  onBeforeMountComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeMountComponent', debugID, element);\n  },\n  onMountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountComponent', debugID);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeUpdateComponent', debugID, element);\n  },\n  onUpdateComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUpdateComponent', debugID);\n  },\n  onUnmountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUnmountComponent', debugID);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool);\nReactDebugTool.addDevtool(ReactComponentTreeDevtool);\nvar url = ExecutionEnvironment.canUseDOM && window.location.href || '';\nif (/[?&]react_perf\\b/.test(url)) {\n  ReactDebugTool.beginProfiling();\n}\n\nmodule.exports = ReactDebugTool;\n},{\"147\":147,\"169\":169,\"171\":171,\"34\":34,\"70\":70,\"75\":75}],60:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultBatchingStrategy\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactUpdates = _dereq_(95);\nvar Transaction = _dereq_(113);\n\nvar emptyFunction = _dereq_(153);\n\nvar RESET_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: function () {\n    ReactDefaultBatchingStrategy.isBatchingUpdates = false;\n  }\n};\n\nvar FLUSH_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)\n};\n\nvar TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];\n\nfunction ReactDefaultBatchingStrategyTransaction() {\n  this.reinitializeTransaction();\n}\n\n_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  }\n});\n\nvar transaction = new ReactDefaultBatchingStrategyTransaction();\n\nvar ReactDefaultBatchingStrategy = {\n  isBatchingUpdates: false,\n\n  /**\n   * Call the provided function in a context within which calls to `setState`\n   * and friends are batched such that components aren't updated unnecessarily.\n   */\n  batchedUpdates: function (callback, a, b, c, d, e) {\n    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;\n\n    ReactDefaultBatchingStrategy.isBatchingUpdates = true;\n\n    // The code is written this way to avoid extra allocations\n    if (alreadyBatchingUpdates) {\n      callback(a, b, c, d, e);\n    } else {\n      transaction.perform(callback, null, a, b, c, d, e);\n    }\n  }\n};\n\nmodule.exports = ReactDefaultBatchingStrategy;\n},{\"113\":113,\"153\":153,\"172\":172,\"95\":95}],61:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultInjection\n */\n\n'use strict';\n\nvar BeforeInputEventPlugin = _dereq_(2);\nvar ChangeEventPlugin = _dereq_(6);\nvar DefaultEventPluginOrder = _dereq_(13);\nvar EnterLeaveEventPlugin = _dereq_(15);\nvar HTMLDOMPropertyConfig = _dereq_(22);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMComponent = _dereq_(39);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMEmptyComponent = _dereq_(44);\nvar ReactDOMTreeTraversal = _dereq_(57);\nvar ReactDOMTextComponent = _dereq_(55);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactEventListener = _dereq_(67);\nvar ReactInjection = _dereq_(71);\nvar ReactReconcileTransaction = _dereq_(86);\nvar SVGDOMPropertyConfig = _dereq_(97);\nvar SelectEventPlugin = _dereq_(98);\nvar SimpleEventPlugin = _dereq_(99);\n\nvar alreadyInjected = false;\n\nfunction inject() {\n  if (alreadyInjected) {\n    // TODO: This is currently true because these injections are shared between\n    // the client and the server package. They should be built independently\n    // and not share any injection state. Then this problem will be solved.\n    return;\n  }\n  alreadyInjected = true;\n\n  ReactInjection.EventEmitter.injectReactEventListener(ReactEventListener);\n\n  /**\n   * Inject modules for resolving DOM hierarchy and plugin ordering.\n   */\n  ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);\n  ReactInjection.EventPluginUtils.injectComponentTree(ReactDOMComponentTree);\n  ReactInjection.EventPluginUtils.injectTreeTraversal(ReactDOMTreeTraversal);\n\n  /**\n   * Some important event plugins included by default (without having to require\n   * them).\n   */\n  ReactInjection.EventPluginHub.injectEventPluginsByName({\n    SimpleEventPlugin: SimpleEventPlugin,\n    EnterLeaveEventPlugin: EnterLeaveEventPlugin,\n    ChangeEventPlugin: ChangeEventPlugin,\n    SelectEventPlugin: SelectEventPlugin,\n    BeforeInputEventPlugin: BeforeInputEventPlugin\n  });\n\n  ReactInjection.HostComponent.injectGenericComponentClass(ReactDOMComponent);\n\n  ReactInjection.HostComponent.injectTextComponentClass(ReactDOMTextComponent);\n\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);\n\n  ReactInjection.EmptyComponent.injectEmptyComponentFactory(function (instantiate) {\n    return new ReactDOMEmptyComponent(instantiate);\n  });\n\n  ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction);\n  ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n\n  ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);\n}\n\nmodule.exports = {\n  inject: inject\n};\n},{\"13\":13,\"15\":15,\"2\":2,\"22\":22,\"32\":32,\"39\":39,\"41\":41,\"44\":44,\"55\":55,\"57\":57,\"6\":6,\"60\":60,\"67\":67,\"71\":71,\"86\":86,\"97\":97,\"98\":98,\"99\":99}],62:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElement\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar warning = _dereq_(171);\nvar canDefineProperty = _dereq_(117);\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// The Symbol used to tag the ReactElement type. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;\n\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\n\nvar specialPropKeyWarningShown, specialPropRefWarningShown;\n\nfunction hasValidRef(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.key !== undefined;\n}\n\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, no instanceof check\n * will work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} key\n * @param {string|object} ref\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @param {*} owner\n * @param {*} props\n * @internal\n */\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allow us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  if (\"development\" !== 'production') {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {};\n\n    // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n    if (canDefineProperty) {\n      Object.defineProperty(element._store, 'validated', {\n        configurable: false,\n        enumerable: false,\n        writable: true,\n        value: false\n      });\n      // self and source are DEV only properties.\n      Object.defineProperty(element, '_self', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: self\n      });\n      // Two elements created in two different places should be considered\n      // equal for testing purposes and therefore we hide it from enumeration.\n      Object.defineProperty(element, '_source', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: source\n      });\n    } else {\n      element._store.validated = false;\n      element._self = self;\n      element._source = source;\n    }\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n\n/**\n * Create and return a new ReactElement of the given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createelement\n */\nReactElement.createElement = function (type, config, children) {\n  var propName;\n\n  // Reserved names are extracted\n  var props = {};\n\n  var key = null;\n  var ref = null;\n  var self = null;\n  var source = null;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.createElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    self = config.__self === undefined ? null : config.__self;\n    source = config.__source === undefined ? null : config.__source;\n    // Remaining properties are added to a new props object\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  // Resolve default props\n  if (type && type.defaultProps) {\n    var defaultProps = type.defaultProps;\n    for (propName in defaultProps) {\n      if (props[propName] === undefined) {\n        props[propName] = defaultProps[propName];\n      }\n    }\n  }\n  if (\"development\" !== 'production') {\n    var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n    // Create dummy `key` and `ref` property to `props` to warn users against its use\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingKey.isReactWarning = true;\n\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingRef.isReactWarning = true;\n\n    if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) {\n      if (!props.hasOwnProperty('key')) {\n        Object.defineProperty(props, 'key', {\n          get: warnAboutAccessingKey,\n          configurable: true\n        });\n      }\n      if (!props.hasOwnProperty('ref')) {\n        Object.defineProperty(props, 'ref', {\n          get: warnAboutAccessingRef,\n          configurable: true\n        });\n      }\n    }\n  }\n  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n};\n\n/**\n * Return a function that produces ReactElements of a given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createfactory\n */\nReactElement.createFactory = function (type) {\n  var factory = ReactElement.createElement.bind(null, type);\n  // Expose the type on the factory and the prototype so that it can be\n  // easily accessed on elements. E.g. `<Foo />.type === Foo`.\n  // This should not be named `constructor` since this may not be the function\n  // that created the element, and it may not even be a constructor.\n  // Legacy hook TODO: Warn if this is accessed\n  factory.type = type;\n  return factory;\n};\n\nReactElement.cloneAndReplaceKey = function (oldElement, newKey) {\n  var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);\n\n  return newElement;\n};\n\n/**\n * Clone and return a new ReactElement using element as the starting point.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement\n */\nReactElement.cloneElement = function (element, config, children) {\n  var propName;\n\n  // Original props are copied\n  var props = _assign({}, element.props);\n\n  // Reserved names are extracted\n  var key = element.key;\n  var ref = element.ref;\n  // Self is preserved since the owner is preserved.\n  var self = element._self;\n  // Source is preserved since cloneElement is unlikely to be targeted by a\n  // transpiler, and the original source is probably a better indicator of the\n  // true owner.\n  var source = element._source;\n\n  // Owner will be preserved, unless ref is overridden\n  var owner = element._owner;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.cloneElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      // Silently steal the ref from the parent.\n      ref = config.ref;\n      owner = ReactCurrentOwner.current;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    // Remaining properties override existing props\n    var defaultProps;\n    if (element.type && element.type.defaultProps) {\n      defaultProps = element.type.defaultProps;\n    }\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        if (config[propName] === undefined && defaultProps !== undefined) {\n          // Resolve default props\n          props[propName] = defaultProps[propName];\n        } else {\n          props[propName] = config[propName];\n        }\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  return ReactElement(element.type, key, ref, self, source, owner, props);\n};\n\n/**\n * Verifies the object is a ReactElement.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a valid component.\n * @final\n */\nReactElement.isValidElement = function (object) {\n  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n};\n\nReactElement.REACT_ELEMENT_TYPE = REACT_ELEMENT_TYPE;\n\nmodule.exports = ReactElement;\n},{\"117\":117,\"171\":171,\"172\":172,\"36\":36}],63:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElementValidator\n */\n\n/**\n * ReactElementValidator provides a wrapper around a element factory\n * which validates the props passed to the element. This is intended to be\n * used only in DEV and could be replaced by a static type checker for languages\n * that support it.\n */\n\n'use strict';\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar canDefineProperty = _dereq_(117);\nvar getIteratorFn = _dereq_(130);\nvar warning = _dereq_(171);\n\nfunction getDeclarationErrorAddendum() {\n  if (ReactCurrentOwner.current) {\n    var name = ReactCurrentOwner.current.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  var info = getDeclarationErrorAddendum();\n\n  if (!info) {\n    var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n    if (parentName) {\n      info = ' Check the top-level render call using <' + parentName + '>.';\n    }\n  }\n  return info;\n}\n\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\nfunction validateExplicitKey(element, parentType) {\n  if (!element._store || element._store.validated || element.key != null) {\n    return;\n  }\n  element._store.validated = true;\n\n  var memoizer = ownerHasKeyUseWarning.uniqueKey || (ownerHasKeyUseWarning.uniqueKey = {});\n\n  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n  if (memoizer[currentComponentErrorInfo]) {\n    return;\n  }\n  memoizer[currentComponentErrorInfo] = true;\n\n  // Usually the current owner is the offender, but if it accepts children as a\n  // property, it may be the creator of the child that's responsible for\n  // assigning it a key.\n  var childOwner = '';\n  if (element && element._owner && element._owner !== ReactCurrentOwner.current) {\n    // Give the component that originally created this child.\n    childOwner = ' It was passed a child from ' + element._owner.getName() + '.';\n  }\n\n  \"development\" !== 'production' ? warning(false, 'Each child in an array or iterator should have a unique \"key\" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.%s', currentComponentErrorInfo, childOwner, ReactComponentTreeDevtool.getCurrentStackAddendum(element)) : void 0;\n}\n\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\nfunction validateChildKeys(node, parentType) {\n  if (typeof node !== 'object') {\n    return;\n  }\n  if (Array.isArray(node)) {\n    for (var i = 0; i < node.length; i++) {\n      var child = node[i];\n      if (ReactElement.isValidElement(child)) {\n        validateExplicitKey(child, parentType);\n      }\n    }\n  } else if (ReactElement.isValidElement(node)) {\n    // This element was passed in a valid location.\n    if (node._store) {\n      node._store.validated = true;\n    }\n  } else if (node) {\n    var iteratorFn = getIteratorFn(node);\n    // Entry iterators provide implicit keys.\n    if (iteratorFn) {\n      if (iteratorFn !== node.entries) {\n        var iterator = iteratorFn.call(node);\n        var step;\n        while (!(step = iterator.next()).done) {\n          if (ReactElement.isValidElement(step.value)) {\n            validateExplicitKey(step.value, parentType);\n          }\n        }\n      }\n    }\n  }\n}\n\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\nfunction validatePropTypes(element) {\n  var componentClass = element.type;\n  if (typeof componentClass !== 'function') {\n    return;\n  }\n  var name = componentClass.displayName || componentClass.name;\n  if (componentClass.propTypes) {\n    checkReactTypeSpec(componentClass.propTypes, element.props, ReactPropTypeLocations.prop, name, element, null);\n  }\n  if (typeof componentClass.getDefaultProps === 'function') {\n    \"development\" !== 'production' ? warning(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0;\n  }\n}\n\nvar ReactElementValidator = {\n\n  createElement: function (type, props, children) {\n    var validType = typeof type === 'string' || typeof type === 'function';\n    // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n    \"development\" !== 'production' ? warning(validType, 'React.createElement: type should not be null, undefined, boolean, or ' + 'number. It should be a string (for DOM elements) or a ReactClass ' + '(for composite components).%s', getDeclarationErrorAddendum()) : void 0;\n\n    var element = ReactElement.createElement.apply(this, arguments);\n\n    // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n    if (element == null) {\n      return element;\n    }\n\n    // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n    if (validType) {\n      for (var i = 2; i < arguments.length; i++) {\n        validateChildKeys(arguments[i], type);\n      }\n    }\n\n    validatePropTypes(element);\n\n    return element;\n  },\n\n  createFactory: function (type) {\n    var validatedFactory = ReactElementValidator.createElement.bind(null, type);\n    // Legacy hook TODO: Warn if this is accessed\n    validatedFactory.type = type;\n\n    if (\"development\" !== 'production') {\n      if (canDefineProperty) {\n        Object.defineProperty(validatedFactory, 'type', {\n          enumerable: false,\n          get: function () {\n            \"development\" !== 'production' ? warning(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.') : void 0;\n            Object.defineProperty(this, 'type', {\n              value: type\n            });\n            return type;\n          }\n        });\n      }\n    }\n\n    return validatedFactory;\n  },\n\n  cloneElement: function (element, props, children) {\n    var newElement = ReactElement.cloneElement.apply(this, arguments);\n    for (var i = 2; i < arguments.length; i++) {\n      validateChildKeys(arguments[i], newElement.type);\n    }\n    validatePropTypes(newElement);\n    return newElement;\n  }\n\n};\n\nmodule.exports = ReactElementValidator;\n},{\"117\":117,\"118\":118,\"130\":130,\"171\":171,\"34\":34,\"36\":36,\"62\":62,\"84\":84}],64:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEmptyComponent\n */\n\n'use strict';\n\nvar emptyComponentFactory;\n\nvar ReactEmptyComponentInjection = {\n  injectEmptyComponentFactory: function (factory) {\n    emptyComponentFactory = factory;\n  }\n};\n\nvar ReactEmptyComponent = {\n  create: function (instantiate) {\n    return emptyComponentFactory(instantiate);\n  }\n};\n\nReactEmptyComponent.injection = ReactEmptyComponentInjection;\n\nmodule.exports = ReactEmptyComponent;\n},{}],65:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactErrorUtils\n */\n\n'use strict';\n\nvar caughtError = null;\n\n/**\n * Call a function while guarding against errors that happens within it.\n *\n * @param {?String} name of the guard to use for logging or debugging\n * @param {Function} func The function to invoke\n * @param {*} a First argument\n * @param {*} b Second argument\n */\nfunction invokeGuardedCallback(name, func, a, b) {\n  try {\n    return func(a, b);\n  } catch (x) {\n    if (caughtError === null) {\n      caughtError = x;\n    }\n    return undefined;\n  }\n}\n\nvar ReactErrorUtils = {\n  invokeGuardedCallback: invokeGuardedCallback,\n\n  /**\n   * Invoked by ReactTestUtils.Simulate so that any errors thrown by the event\n   * handler are sure to be rethrown by rethrowCaughtError.\n   */\n  invokeGuardedCallbackWithCatch: invokeGuardedCallback,\n\n  /**\n   * During execution of guarded functions we will capture the first error which\n   * we will rethrow to be handled by the top level error handler.\n   */\n  rethrowCaughtError: function () {\n    if (caughtError) {\n      var error = caughtError;\n      caughtError = null;\n      throw error;\n    }\n  }\n};\n\nif (\"development\" !== 'production') {\n  /**\n   * To help development we can get better devtools integration by simulating a\n   * real browser event.\n   */\n  if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {\n    var fakeNode = document.createElement('react');\n    ReactErrorUtils.invokeGuardedCallback = function (name, func, a, b) {\n      var boundFunc = func.bind(null, a, b);\n      var evtType = 'react-' + name;\n      fakeNode.addEventListener(evtType, boundFunc, false);\n      var evt = document.createEvent('Event');\n      evt.initEvent(evtType, false, false);\n      fakeNode.dispatchEvent(evt);\n      fakeNode.removeEventListener(evtType, boundFunc, false);\n    };\n  }\n}\n\nmodule.exports = ReactErrorUtils;\n},{}],66:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventEmitterMixin\n */\n\n'use strict';\n\nvar EventPluginHub = _dereq_(17);\n\nfunction runEventQueueInBatch(events) {\n  EventPluginHub.enqueueEvents(events);\n  EventPluginHub.processEventQueue(false);\n}\n\nvar ReactEventEmitterMixin = {\n\n  /**\n   * Streams a fired top-level event to `EventPluginHub` where plugins have the\n   * opportunity to create `ReactEvent`s to be dispatched.\n   */\n  handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events = EventPluginHub.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n    runEventQueueInBatch(events);\n  }\n};\n\nmodule.exports = ReactEventEmitterMixin;\n},{\"17\":17}],67:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventListener\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventListener = _dereq_(146);\nvar ExecutionEnvironment = _dereq_(147);\nvar PooledClass = _dereq_(25);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar getEventTarget = _dereq_(128);\nvar getUnboundedScrollPosition = _dereq_(158);\n\n/**\n * Find the deepest React component completely containing the root of the\n * passed-in instance (for use when entire React trees are nested within each\n * other). If React trees are not nested, returns null.\n */\nfunction findParent(inst) {\n  // TODO: It may be a good idea to cache this to prevent unnecessary DOM\n  // traversal, but caching is difficult to do correctly without using a\n  // mutation observer to listen for all DOM changes.\n  while (inst._hostParent) {\n    inst = inst._hostParent;\n  }\n  var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);\n  var container = rootNode.parentNode;\n  return ReactDOMComponentTree.getClosestInstanceFromNode(container);\n}\n\n// Used to store ancestor hierarchy in top level callback\nfunction TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {\n  this.topLevelType = topLevelType;\n  this.nativeEvent = nativeEvent;\n  this.ancestors = [];\n}\n_assign(TopLevelCallbackBookKeeping.prototype, {\n  destructor: function () {\n    this.topLevelType = null;\n    this.nativeEvent = null;\n    this.ancestors.length = 0;\n  }\n});\nPooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler);\n\nfunction handleTopLevelImpl(bookKeeping) {\n  var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);\n  var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);\n\n  // Loop through the hierarchy, in case there's any nested components.\n  // It's important that we build the array of ancestors before calling any\n  // event handlers, because event handlers can modify the DOM, leading to\n  // inconsistencies with ReactMount's node cache. See #1105.\n  var ancestor = targetInst;\n  do {\n    bookKeeping.ancestors.push(ancestor);\n    ancestor = ancestor && findParent(ancestor);\n  } while (ancestor);\n\n  for (var i = 0; i < bookKeeping.ancestors.length; i++) {\n    targetInst = bookKeeping.ancestors[i];\n    ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));\n  }\n}\n\nfunction scrollValueMonitor(cb) {\n  var scrollPosition = getUnboundedScrollPosition(window);\n  cb(scrollPosition);\n}\n\nvar ReactEventListener = {\n  _enabled: true,\n  _handleTopLevel: null,\n\n  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,\n\n  setHandleTopLevel: function (handleTopLevel) {\n    ReactEventListener._handleTopLevel = handleTopLevel;\n  },\n\n  setEnabled: function (enabled) {\n    ReactEventListener._enabled = !!enabled;\n  },\n\n  isEnabled: function () {\n    return ReactEventListener._enabled;\n  },\n\n  /**\n   * Traps top-level events by using event bubbling.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  /**\n   * Traps a top-level event by using event capturing.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  monitorScrollValue: function (refresh) {\n    var callback = scrollValueMonitor.bind(null, refresh);\n    EventListener.listen(window, 'scroll', callback);\n  },\n\n  dispatchEvent: function (topLevelType, nativeEvent) {\n    if (!ReactEventListener._enabled) {\n      return;\n    }\n\n    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);\n    try {\n      // Event queue being processed in the same cycle allows\n      // `preventDefault`.\n      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);\n    } finally {\n      TopLevelCallbackBookKeeping.release(bookKeeping);\n    }\n  }\n};\n\nmodule.exports = ReactEventListener;\n},{\"128\":128,\"146\":146,\"147\":147,\"158\":158,\"172\":172,\"25\":25,\"41\":41,\"95\":95}],68:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactFeatureFlags\n * \n */\n\n'use strict';\n\nvar ReactFeatureFlags = {\n  // When true, call console.time() before and .timeEnd() after each top-level\n  // render (both initial renders and updates). Useful when looking at prod-mode\n  // timeline profiles in Chrome, for example.\n  logTopLevelRenders: false\n};\n\nmodule.exports = ReactFeatureFlags;\n},{}],69:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar invariant = _dereq_(161);\n\nvar genericComponentClass = null;\n// This registry keeps track of wrapper classes around host tags.\nvar tagToComponentClass = {};\nvar textComponentClass = null;\n\nvar ReactHostComponentInjection = {\n  // This accepts a class that receives the tag string. This is a catch all\n  // that can render any kind of tag.\n  injectGenericComponentClass: function (componentClass) {\n    genericComponentClass = componentClass;\n  },\n  // This accepts a text component class that takes the text string to be\n  // rendered as props.\n  injectTextComponentClass: function (componentClass) {\n    textComponentClass = componentClass;\n  },\n  // This accepts a keyed object with classes as values. Each key represents a\n  // tag. That particular tag will use this class instead of the generic one.\n  injectComponentClasses: function (componentClasses) {\n    _assign(tagToComponentClass, componentClasses);\n  }\n};\n\n/**\n * Get a host internal component class for a specific tag.\n *\n * @param {ReactElement} element The element to create.\n * @return {function} The internal class constructor function.\n */\nfunction createInternalComponent(element) {\n  !genericComponentClass ? \"development\" !== 'production' ? invariant(false, 'There is no registered component for the tag %s', element.type) : _prodInvariant('111', element.type) : void 0;\n  return new genericComponentClass(element);\n}\n\n/**\n * @param {ReactText} text\n * @return {ReactComponent}\n */\nfunction createInstanceForText(text) {\n  return new textComponentClass(text);\n}\n\n/**\n * @param {ReactComponent} component\n * @return {boolean}\n */\nfunction isTextComponent(component) {\n  return component instanceof textComponentClass;\n}\n\nvar ReactHostComponent = {\n  createInternalComponent: createInternalComponent,\n  createInstanceForText: createInstanceForText,\n  isTextComponent: isTextComponent,\n  injection: ReactHostComponentInjection\n};\n\nmodule.exports = ReactHostComponent;\n},{\"139\":139,\"161\":161,\"172\":172}],70:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostOperationHistoryDevtool\n */\n\n'use strict';\n\nvar history = [];\n\nvar ReactHostOperationHistoryDevtool = {\n  onHostOperation: function (debugID, type, payload) {\n    history.push({\n      instanceID: debugID,\n      type: type,\n      payload: payload\n    });\n  },\n  clearHistory: function () {\n    if (ReactHostOperationHistoryDevtool._preventClearing) {\n      // Should only be used for tests.\n      return;\n    }\n\n    history = [];\n  },\n  getHistory: function () {\n    return history;\n  }\n};\n\nmodule.exports = ReactHostOperationHistoryDevtool;\n},{}],71:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInjection\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactClass = _dereq_(30);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactHostComponent = _dereq_(69);\nvar ReactUpdates = _dereq_(95);\n\nvar ReactInjection = {\n  Component: ReactComponentEnvironment.injection,\n  Class: ReactClass.injection,\n  DOMProperty: DOMProperty.injection,\n  EmptyComponent: ReactEmptyComponent.injection,\n  EventPluginHub: EventPluginHub.injection,\n  EventPluginUtils: EventPluginUtils.injection,\n  EventEmitter: ReactBrowserEventEmitter.injection,\n  HostComponent: ReactHostComponent.injection,\n  Updates: ReactUpdates.injection\n};\n\nmodule.exports = ReactInjection;\n},{\"10\":10,\"17\":17,\"19\":19,\"27\":27,\"30\":30,\"33\":33,\"64\":64,\"69\":69,\"95\":95}],72:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInputSelection\n */\n\n'use strict';\n\nvar ReactDOMSelection = _dereq_(53);\n\nvar containsNode = _dereq_(150);\nvar focusNode = _dereq_(155);\nvar getActiveElement = _dereq_(156);\n\nfunction isInDocument(node) {\n  return containsNode(document.documentElement, node);\n}\n\n/**\n * @ReactInputSelection: React input selection module. Based on Selection.js,\n * but modified to be suitable for react and has a couple of bug fixes (doesn't\n * assume buttons have range selections allowed).\n * Input selection module for React.\n */\nvar ReactInputSelection = {\n\n  hasSelectionCapabilities: function (elem) {\n    var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n    return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');\n  },\n\n  getSelectionInformation: function () {\n    var focusedElem = getActiveElement();\n    return {\n      focusedElem: focusedElem,\n      selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null\n    };\n  },\n\n  /**\n   * @restoreSelection: If any selection information was potentially lost,\n   * restore it. This is useful when performing operations that could remove dom\n   * nodes and place them back in, resulting in focus being lost.\n   */\n  restoreSelection: function (priorSelectionInformation) {\n    var curFocusedElem = getActiveElement();\n    var priorFocusedElem = priorSelectionInformation.focusedElem;\n    var priorSelectionRange = priorSelectionInformation.selectionRange;\n    if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {\n      if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {\n        ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);\n      }\n      focusNode(priorFocusedElem);\n    }\n  },\n\n  /**\n   * @getSelection: Gets the selection bounds of a focused textarea, input or\n   * contentEditable node.\n   * -@input: Look up selection bounds of this input\n   * -@return {start: selectionStart, end: selectionEnd}\n   */\n  getSelection: function (input) {\n    var selection;\n\n    if ('selectionStart' in input) {\n      // Modern browser with input or textarea.\n      selection = {\n        start: input.selectionStart,\n        end: input.selectionEnd\n      };\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      // IE8 input.\n      var range = document.selection.createRange();\n      // There can only be one selection per document in IE, so it must\n      // be in our element.\n      if (range.parentElement() === input) {\n        selection = {\n          start: -range.moveStart('character', -input.value.length),\n          end: -range.moveEnd('character', -input.value.length)\n        };\n      }\n    } else {\n      // Content editable or old IE textarea.\n      selection = ReactDOMSelection.getOffsets(input);\n    }\n\n    return selection || { start: 0, end: 0 };\n  },\n\n  /**\n   * @setSelection: Sets the selection bounds of a textarea or input and focuses\n   * the input.\n   * -@input     Set selection bounds of this input or textarea\n   * -@offsets   Object of same form that is returned from get*\n   */\n  setSelection: function (input, offsets) {\n    var start = offsets.start;\n    var end = offsets.end;\n    if (end === undefined) {\n      end = start;\n    }\n\n    if ('selectionStart' in input) {\n      input.selectionStart = start;\n      input.selectionEnd = Math.min(end, input.value.length);\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      var range = input.createTextRange();\n      range.collapse(true);\n      range.moveStart('character', start);\n      range.moveEnd('character', end - start);\n      range.select();\n    } else {\n      ReactDOMSelection.setOffsets(input, offsets);\n    }\n  }\n};\n\nmodule.exports = ReactInputSelection;\n},{\"150\":150,\"155\":155,\"156\":156,\"53\":53}],73:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstanceMap\n */\n\n'use strict';\n\n/**\n * `ReactInstanceMap` maintains a mapping from a public facing stateful\n * instance (key) and the internal representation (value). This allows public\n * methods to accept the user facing instance as an argument and map them back\n * to internal methods.\n */\n\n// TODO: Replace this with ES6: var ReactInstanceMap = new Map();\n\nvar ReactInstanceMap = {\n\n  /**\n   * This API should be called `delete` but we'd have to make sure to always\n   * transform these to strings for IE support. When this transform is fully\n   * supported we can rename it.\n   */\n  remove: function (key) {\n    key._reactInternalInstance = undefined;\n  },\n\n  get: function (key) {\n    return key._reactInternalInstance;\n  },\n\n  has: function (key) {\n    return key._reactInternalInstance !== undefined;\n  },\n\n  set: function (key, value) {\n    key._reactInternalInstance = value;\n  }\n\n};\n\nmodule.exports = ReactInstanceMap;\n},{}],74:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDebugTool = _dereq_(59);\n  debugTool = ReactDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"59\":59}],75:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInvalidSetStateWarningDevTool\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var processingChildContext = false;\n\n  var warnInvalidSetState = function () {\n    \"development\" !== 'production' ? warning(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()') : void 0;\n  };\n}\n\nvar ReactInvalidSetStateWarningDevTool = {\n  onBeginProcessingChildContext: function () {\n    processingChildContext = true;\n  },\n  onEndProcessingChildContext: function () {\n    processingChildContext = false;\n  },\n  onSetState: function () {\n    warnInvalidSetState();\n  }\n};\n\nmodule.exports = ReactInvalidSetStateWarningDevTool;\n},{\"171\":171}],76:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMarkupChecksum\n */\n\n'use strict';\n\nvar adler32 = _dereq_(116);\n\nvar TAG_END = /\\/?>/;\nvar COMMENT_START = /^<\\!\\-\\-/;\n\nvar ReactMarkupChecksum = {\n  CHECKSUM_ATTR_NAME: 'data-react-checksum',\n\n  /**\n   * @param {string} markup Markup string\n   * @return {string} Markup string with checksum attribute attached\n   */\n  addChecksumToMarkup: function (markup) {\n    var checksum = adler32(markup);\n\n    // Add checksum (handle both parent tags, comments and self-closing tags)\n    if (COMMENT_START.test(markup)) {\n      return markup;\n    } else {\n      return markup.replace(TAG_END, ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '=\"' + checksum + '\"$&');\n    }\n  },\n\n  /**\n   * @param {string} markup to use\n   * @param {DOMElement} element root React element\n   * @returns {boolean} whether or not the markup is the same\n   */\n  canReuseMarkup: function (markup, element) {\n    var existingChecksum = element.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n    existingChecksum = existingChecksum && parseInt(existingChecksum, 10);\n    var markupChecksum = adler32(markup);\n    return markupChecksum === existingChecksum;\n  }\n};\n\nmodule.exports = ReactMarkupChecksum;\n},{\"116\":116}],77:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMount\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar DOMProperty = _dereq_(10);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDOMFeatureFlags = _dereq_(46);\nvar ReactElement = _dereq_(62);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdateQueue = _dereq_(94);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\nvar setInnerHTML = _dereq_(141);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOC_NODE_TYPE = 9;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\nvar instancesByReactRootID = {};\n\n/**\n * Finds the index of the first character\n * that's not common between the two given strings.\n *\n * @return {number} the index of the character where the strings diverge\n */\nfunction firstDifferenceIndex(string1, string2) {\n  var minLen = Math.min(string1.length, string2.length);\n  for (var i = 0; i < minLen; i++) {\n    if (string1.charAt(i) !== string2.charAt(i)) {\n      return i;\n    }\n  }\n  return string1.length === string2.length ? -1 : minLen;\n}\n\n/**\n * @param {DOMElement|DOMDocument} container DOM element that may contain\n * a React component\n * @return {?*} DOM element that may have the reactRoot ID, or null.\n */\nfunction getReactRootElementInContainer(container) {\n  if (!container) {\n    return null;\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    return container.documentElement;\n  } else {\n    return container.firstChild;\n  }\n}\n\nfunction internalGetID(node) {\n  // If node is something like a window, document, or text node, none of\n  // which support attributes or a .getAttribute method, gracefully return\n  // the empty string, as if the attribute were missing.\n  return node.getAttribute && node.getAttribute(ATTR_NAME) || '';\n}\n\n/**\n * Mounts this component and inserts it into the DOM.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {ReactReconcileTransaction} transaction\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) {\n  var markerName;\n  if (ReactFeatureFlags.logTopLevelRenders) {\n    var wrappedElement = wrapperInstance._currentElement.props;\n    var type = wrappedElement.type;\n    markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name);\n    console.time(markerName);\n  }\n\n  var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context);\n\n  if (markerName) {\n    console.timeEnd(markerName);\n  }\n\n  wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;\n  ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction);\n}\n\n/**\n * Batched mount.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) {\n  var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */\n  !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement);\n  transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context);\n  ReactUpdates.ReactReconcileTransaction.release(transaction);\n}\n\n/**\n * Unmounts a component and removes it from the DOM.\n *\n * @param {ReactComponent} instance React component instance.\n * @param {DOMElement} container DOM element to unmount from.\n * @final\n * @internal\n * @see {ReactMount.unmountComponentAtNode}\n */\nfunction unmountComponentFromNode(instance, container, safely) {\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onBeginFlush();\n  }\n  ReactReconciler.unmountComponent(instance, safely);\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onEndFlush();\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    container = container.documentElement;\n  }\n\n  // http://jsperf.com/emptying-a-node\n  while (container.lastChild) {\n    container.removeChild(container.lastChild);\n  }\n}\n\n/**\n * True if the supplied DOM node has a direct React-rendered child that is\n * not a React root element. Useful for warning in `render`,\n * `unmountComponentAtNode`, etc.\n *\n * @param {?DOMElement} node The candidate DOM node.\n * @return {boolean} True if the DOM element contains a direct child that was\n * rendered by React but is not a root element.\n * @internal\n */\nfunction hasNonRootReactChild(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  if (rootEl) {\n    var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);\n    return !!(inst && inst._hostParent);\n  }\n}\n\nfunction getHostRootInstanceInContainer(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  var prevHostInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);\n  return prevHostInstance && !prevHostInstance._hostParent ? prevHostInstance : null;\n}\n\nfunction getTopLevelWrapperInContainer(container) {\n  var root = getHostRootInstanceInContainer(container);\n  return root ? root._hostContainerInfo._topLevelWrapper : null;\n}\n\n/**\n * Temporary (?) hack so that we can store all top-level pending updates on\n * composites instead of having to worry about different types of components\n * here.\n */\nvar topLevelRootCounter = 1;\nvar TopLevelWrapper = function () {\n  this.rootID = topLevelRootCounter++;\n};\nTopLevelWrapper.prototype.isReactComponent = {};\nif (\"development\" !== 'production') {\n  TopLevelWrapper.displayName = 'TopLevelWrapper';\n}\nTopLevelWrapper.prototype.render = function () {\n  // this.props is actually a ReactElement\n  return this.props;\n};\n\n/**\n * Mounting is the process of initializing a React component by creating its\n * representative DOM elements and inserting them into a supplied `container`.\n * Any prior content inside `container` is destroyed in the process.\n *\n *   ReactMount.render(\n *     component,\n *     document.getElementById('container')\n *   );\n *\n *   <div id=\"container\">                   <-- Supplied `container`.\n *     <div data-reactid=\".3\">              <-- Rendered reactRoot of React\n *       // ...                                 component.\n *     </div>\n *   </div>\n *\n * Inside of `container`, the first element rendered is the \"reactRoot\".\n */\nvar ReactMount = {\n\n  TopLevelWrapper: TopLevelWrapper,\n\n  /**\n   * Used by devtools. The keys are not important.\n   */\n  _instancesByReactRootID: instancesByReactRootID,\n\n  /**\n   * This is a hook provided to support rendering React components while\n   * ensuring that the apparent scroll position of its `container` does not\n   * change.\n   *\n   * @param {DOMElement} container The `container` being rendered into.\n   * @param {function} renderCallback This must be called once to do the render.\n   */\n  scrollMonitor: function (container, renderCallback) {\n    renderCallback();\n  },\n\n  /**\n   * Take a component that's already mounted into the DOM and replace its props\n   * @param {ReactComponent} prevComponent component instance already in the DOM\n   * @param {ReactElement} nextElement component instance to render\n   * @param {DOMElement} container container to render into\n   * @param {?function} callback function triggered on completion\n   */\n  _updateRootComponent: function (prevComponent, nextElement, nextContext, container, callback) {\n    ReactMount.scrollMonitor(container, function () {\n      ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement, nextContext);\n      if (callback) {\n        ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);\n      }\n    });\n\n    return prevComponent;\n  },\n\n  /**\n   * Render a new component into the DOM. Hooked by devtools!\n   *\n   * @param {ReactElement} nextElement element to render\n   * @param {DOMElement} container container to render into\n   * @param {boolean} shouldReuseMarkup if we should skip the markup insertion\n   * @return {ReactComponent} nextComponent\n   */\n  _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case.\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '_renderNewRootComponent(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from ' + 'render is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : _prodInvariant('37') : void 0;\n\n    ReactBrowserEventEmitter.ensureScrollValueMonitoring();\n    var componentInstance = instantiateReactComponent(nextElement, false);\n\n    // The initial render is synchronous but any updates that happen during\n    // rendering, in componentWillMount or componentDidMount, will be batched\n    // according to the current batching strategy.\n\n    ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);\n\n    var wrapperID = componentInstance._instance.rootID;\n    instancesByReactRootID[wrapperID] = componentInstance;\n\n    if (\"development\" !== 'production') {\n      // The instance here is TopLevelWrapper so we report mount for its child.\n      ReactInstrumentation.debugTool.onMountRootComponent(componentInstance._renderedComponent._debugID);\n    }\n\n    return componentInstance;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactComponent} parentComponent The conceptual parent of this render tree.\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    !(parentComponent != null && ReactInstanceMap.has(parentComponent)) ? \"development\" !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : _prodInvariant('38') : void 0;\n    return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback);\n  },\n\n  _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');\n    !ReactElement.isValidElement(nextElement) ? \"development\" !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' :\n    // Check if it quacks like an element\n    nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : _prodInvariant('39', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : void 0;\n\n    \"development\" !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0;\n\n    var nextWrappedElement = ReactElement(TopLevelWrapper, null, null, null, null, null, nextElement);\n\n    var nextContext;\n    if (parentComponent) {\n      var parentInst = ReactInstanceMap.get(parentComponent);\n      nextContext = parentInst._processChildContext(parentInst._context);\n    } else {\n      nextContext = emptyObject;\n    }\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n\n    if (prevComponent) {\n      var prevWrappedElement = prevComponent._currentElement;\n      var prevElement = prevWrappedElement.props;\n      if (shouldUpdateReactComponent(prevElement, nextElement)) {\n        var publicInst = prevComponent._renderedComponent.getPublicInstance();\n        var updatedCallback = callback && function () {\n          callback.call(publicInst);\n        };\n        ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);\n        return publicInst;\n      } else {\n        ReactMount.unmountComponentAtNode(container);\n      }\n    }\n\n    var reactRootElement = getReactRootElementInContainer(container);\n    var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);\n    var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0;\n\n      if (!containerHasReactMarkup || reactRootElement.nextSibling) {\n        var rootElementSibling = reactRootElement;\n        while (rootElementSibling) {\n          if (internalGetID(rootElementSibling)) {\n            \"development\" !== 'production' ? warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.') : void 0;\n            break;\n          }\n          rootElementSibling = rootElementSibling.nextSibling;\n        }\n      }\n    }\n\n    var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;\n    var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();\n    if (callback) {\n      callback.call(component);\n    }\n    return component;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  render: function (nextElement, container, callback) {\n    return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);\n  },\n\n  /**\n   * Unmounts and destroys the React component rendered in the `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode\n   *\n   * @param {DOMElement} container DOM element containing a React component.\n   * @return {boolean} True if a component was found in and unmounted from\n   *                   `container`\n   */\n  unmountComponentAtNode: function (container) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case. (Strictly speaking, unmounting won't cause a\n    // render but we still don't expect to be in a render call here.)\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : _prodInvariant('40') : void 0;\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n    if (!prevComponent) {\n      // Check if the node being unmounted was rendered by React, but isn't a\n      // root node.\n      var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n      // Check if the container itself is a React root node.\n      var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME);\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'unmountComponentAtNode(): The node you\\'re attempting to unmount ' + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0;\n      }\n\n      return false;\n    }\n    delete instancesByReactRootID[prevComponent._instance.rootID];\n    ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false);\n    return true;\n  },\n\n  _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) {\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : _prodInvariant('41') : void 0;\n\n    if (shouldReuseMarkup) {\n      var rootElement = getReactRootElementInContainer(container);\n      if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {\n        ReactDOMComponentTree.precacheNode(instance, rootElement);\n        return;\n      } else {\n        var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n        rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n\n        var rootMarkup = rootElement.outerHTML;\n        rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum);\n\n        var normalizedMarkup = markup;\n        if (\"development\" !== 'production') {\n          // because rootMarkup is retrieved from the DOM, various normalizations\n          // will have occurred which will not be present in `markup`. Here,\n          // insert markup into a <div> or <iframe> depending on the container\n          // type to perform the same normalizations before comparing.\n          var normalizer;\n          if (container.nodeType === ELEMENT_NODE_TYPE) {\n            normalizer = document.createElement('div');\n            normalizer.innerHTML = markup;\n            normalizedMarkup = normalizer.innerHTML;\n          } else {\n            normalizer = document.createElement('iframe');\n            document.body.appendChild(normalizer);\n            normalizer.contentDocument.write(markup);\n            normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;\n            document.body.removeChild(normalizer);\n          }\n        }\n\n        var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);\n        var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);\n\n        !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure. React cannot handle this case due to cross-browser quirks by rendering at the document root. You should look for environment dependent code in your components and ensure the props are the same client and server side:\\n%s', difference) : _prodInvariant('42', difference) : void 0;\n\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'React attempted to reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are ' + 'using server rendering and the markup generated on the ' + 'server was not what the client was expecting. React injected ' + 'new markup to compensate which works but you have lost many ' + 'of the benefits of server rendering. Instead, figure out ' + 'why the markup being generated is different on the client ' + 'or server:\\n%s', difference) : void 0;\n        }\n      }\n    }\n\n    !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document but you didn\\'t use server rendering. We can\\'t do this without using server rendering due to cross-browser quirks. See ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('43') : void 0;\n\n    if (transaction.useCreateElement) {\n      while (container.lastChild) {\n        container.removeChild(container.lastChild);\n      }\n      DOMLazyTree.insertTreeBefore(container, markup, null);\n    } else {\n      setInnerHTML(container, markup);\n      ReactDOMComponentTree.precacheNode(instance, container.firstChild);\n    }\n\n    if (\"development\" !== 'production') {\n      var hostNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);\n      if (hostNode._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(hostNode._debugID, 'mount', markup.toString());\n      }\n    }\n  }\n};\n\nmodule.exports = ReactMount;\n},{\"10\":10,\"134\":134,\"139\":139,\"141\":141,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"27\":27,\"36\":36,\"41\":41,\"42\":42,\"46\":46,\"62\":62,\"68\":68,\"73\":73,\"74\":74,\"76\":76,\"8\":8,\"87\":87,\"94\":94,\"95\":95}],78:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChild\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactReconciler = _dereq_(87);\nvar ReactChildReconciler = _dereq_(28);\n\nvar emptyFunction = _dereq_(153);\nvar flattenChildren = _dereq_(123);\nvar invariant = _dereq_(161);\n\n/**\n * Make an update for markup to be rendered and inserted at a supplied index.\n *\n * @param {string} markup Markup that renders into an element.\n * @param {number} toIndex Destination index.\n * @private\n */\nfunction makeInsertMarkup(markup, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.INSERT_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for moving an existing element to another index.\n *\n * @param {number} fromIndex Source index of the existing element.\n * @param {number} toIndex Destination index of the element.\n * @private\n */\nfunction makeMove(child, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.MOVE_EXISTING,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: ReactReconciler.getHostNode(child),\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for removing an element at an index.\n *\n * @param {number} fromIndex Index of the element to remove.\n * @private\n */\nfunction makeRemove(child, node) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.REMOVE_NODE,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: node,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the markup of a node.\n *\n * @param {string} markup Markup that renders into an element.\n * @private\n */\nfunction makeSetMarkup(markup) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.SET_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the text content.\n *\n * @param {string} textContent Text content to set.\n * @private\n */\nfunction makeTextContent(textContent) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.TEXT_CONTENT,\n    content: textContent,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Push an update, if any, onto the queue. Creates a new queue if none is\n * passed and always returns the queue. Mutative.\n */\nfunction enqueue(queue, update) {\n  if (update) {\n    queue = queue || [];\n    queue.push(update);\n  }\n  return queue;\n}\n\n/**\n * Processes any enqueued updates.\n *\n * @private\n */\nfunction processQueue(inst, updateQueue) {\n  ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue);\n}\n\nvar setParentForInstrumentation = emptyFunction;\nvar setChildrenForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  var getDebugID = function (inst) {\n    if (!inst._debugID) {\n      // Check for ART-like instances. TODO: This is silly/gross.\n      var internal;\n      if (internal = ReactInstanceMap.get(inst)) {\n        inst = internal;\n      }\n    }\n    return inst._debugID;\n  };\n  setParentForInstrumentation = function (child) {\n    if (child._debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetParent(child._debugID, getDebugID(this));\n    }\n  };\n  setChildrenForInstrumentation = function (children) {\n    var debugID = getDebugID(this);\n    // TODO: React Native empty components are also multichild.\n    // This means they still get into this method but don't have _debugID.\n    if (debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetChildren(debugID, children ? Object.keys(children).map(function (key) {\n        return children[key]._debugID;\n      }) : []);\n    }\n  };\n}\n\n/**\n * ReactMultiChild are capable of reconciling multiple children.\n *\n * @class ReactMultiChild\n * @internal\n */\nvar ReactMultiChild = {\n\n  /**\n   * Provides common functionality for components that must reconcile multiple\n   * children. This is used by `ReactDOMComponent` to mount, update, and\n   * unmount child components.\n   *\n   * @lends {ReactMultiChild.prototype}\n   */\n  Mixin: {\n\n    _reconcilerInstantiateChildren: function (nestedChildren, transaction, context) {\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n        }\n      }\n      return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context);\n    },\n\n    _reconcilerUpdateChildren: function (prevChildren, nextNestedChildrenElements, removedNodes, transaction, context) {\n      var nextChildren;\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            nextChildren = flattenChildren(nextNestedChildrenElements, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n          ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n          return nextChildren;\n        }\n      }\n      nextChildren = flattenChildren(nextNestedChildrenElements);\n      ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n      return nextChildren;\n    },\n\n    /**\n     * Generates a \"mount image\" for each of the supplied children. In the case\n     * of `ReactDOMComponent`, a mount image is a string of markup.\n     *\n     * @param {?object} nestedChildren Nested child maps.\n     * @return {array} An array of mounted representations.\n     * @internal\n     */\n    mountChildren: function (nestedChildren, transaction, context) {\n      var children = this._reconcilerInstantiateChildren(nestedChildren, transaction, context);\n      this._renderedChildren = children;\n\n      var mountImages = [];\n      var index = 0;\n      for (var name in children) {\n        if (children.hasOwnProperty(name)) {\n          var child = children[name];\n          if (\"development\" !== 'production') {\n            setParentForInstrumentation.call(this, child);\n          }\n          var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n          child._mountIndex = index++;\n          mountImages.push(mountImage);\n        }\n      }\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, children);\n      }\n\n      return mountImages;\n    },\n\n    /**\n     * Replaces any rendered children with a text content string.\n     *\n     * @param {string} nextContent String of content.\n     * @internal\n     */\n    updateTextContent: function (nextContent) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      // Set new text content.\n      var updates = [makeTextContent(nextContent)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Replaces any rendered children with a markup string.\n     *\n     * @param {string} nextMarkup String of markup.\n     * @internal\n     */\n    updateMarkup: function (nextMarkup) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      var updates = [makeSetMarkup(nextMarkup)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Updates the rendered children with new children.\n     *\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @internal\n     */\n    updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      // Hook used by React ART\n      this._updateChildren(nextNestedChildrenElements, transaction, context);\n    },\n\n    /**\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @final\n     * @protected\n     */\n    _updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      var prevChildren = this._renderedChildren;\n      var removedNodes = {};\n      var nextChildren = this._reconcilerUpdateChildren(prevChildren, nextNestedChildrenElements, removedNodes, transaction, context);\n      if (!nextChildren && !prevChildren) {\n        return;\n      }\n      var updates = null;\n      var name;\n      // `nextIndex` will increment for each child in `nextChildren`, but\n      // `lastIndex` will be the last index visited in `prevChildren`.\n      var lastIndex = 0;\n      var nextIndex = 0;\n      var lastPlacedNode = null;\n      for (name in nextChildren) {\n        if (!nextChildren.hasOwnProperty(name)) {\n          continue;\n        }\n        var prevChild = prevChildren && prevChildren[name];\n        var nextChild = nextChildren[name];\n        if (prevChild === nextChild) {\n          updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));\n          lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n          prevChild._mountIndex = nextIndex;\n        } else {\n          if (prevChild) {\n            // Update `lastIndex` before `_mountIndex` gets unset by unmounting.\n            lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n            // The `removedNodes` loop below will actually remove the child.\n          }\n          // The child must be instantiated before it's mounted.\n          updates = enqueue(updates, this._mountChildAtIndex(nextChild, lastPlacedNode, nextIndex, transaction, context));\n        }\n        nextIndex++;\n        lastPlacedNode = ReactReconciler.getHostNode(nextChild);\n      }\n      // Remove children that are no longer present.\n      for (name in removedNodes) {\n        if (removedNodes.hasOwnProperty(name)) {\n          updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name]));\n        }\n      }\n      if (updates) {\n        processQueue(this, updates);\n      }\n      this._renderedChildren = nextChildren;\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, nextChildren);\n      }\n    },\n\n    /**\n     * Unmounts all rendered children. This should be used to clean up children\n     * when this component is unmounted. It does not actually perform any\n     * backend operations.\n     *\n     * @internal\n     */\n    unmountChildren: function (safely) {\n      var renderedChildren = this._renderedChildren;\n      ReactChildReconciler.unmountChildren(renderedChildren, safely);\n      this._renderedChildren = null;\n    },\n\n    /**\n     * Moves a child component to the supplied index.\n     *\n     * @param {ReactComponent} child Component to move.\n     * @param {number} toIndex Destination index of the element.\n     * @param {number} lastIndex Last index visited of the siblings of `child`.\n     * @protected\n     */\n    moveChild: function (child, afterNode, toIndex, lastIndex) {\n      // If the index of `child` is less than `lastIndex`, then it needs to\n      // be moved. Otherwise, we do not need to move it because a child will be\n      // inserted or moved before `child`.\n      if (child._mountIndex < lastIndex) {\n        return makeMove(child, afterNode, toIndex);\n      }\n    },\n\n    /**\n     * Creates a child component.\n     *\n     * @param {ReactComponent} child Component to create.\n     * @param {string} mountImage Markup to insert.\n     * @protected\n     */\n    createChild: function (child, afterNode, mountImage) {\n      return makeInsertMarkup(mountImage, afterNode, child._mountIndex);\n    },\n\n    /**\n     * Removes a child component.\n     *\n     * @param {ReactComponent} child Child to remove.\n     * @protected\n     */\n    removeChild: function (child, node) {\n      return makeRemove(child, node);\n    },\n\n    /**\n     * Mounts a child with the supplied name.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to mount.\n     * @param {string} name Name of the child.\n     * @param {number} index Index at which to insert the child.\n     * @param {ReactReconcileTransaction} transaction\n     * @private\n     */\n    _mountChildAtIndex: function (child, afterNode, index, transaction, context) {\n      var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n      child._mountIndex = index;\n      return this.createChild(child, afterNode, mountImage);\n    },\n\n    /**\n     * Unmounts a rendered child.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to unmount.\n     * @private\n     */\n    _unmountChild: function (child, node) {\n      var update = this.removeChild(child, node);\n      child._mountIndex = null;\n      return update;\n    }\n\n  }\n\n};\n\nmodule.exports = ReactMultiChild;\n},{\"123\":123,\"139\":139,\"153\":153,\"161\":161,\"28\":28,\"33\":33,\"36\":36,\"73\":73,\"74\":74,\"79\":79,\"87\":87}],79:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChildUpdateTypes\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\n/**\n * When a component's children are updated, a series of update configuration\n * objects are created in order to batch and serialize the required changes.\n *\n * Enumerates all the possible types of update configurations.\n *\n * @internal\n */\nvar ReactMultiChildUpdateTypes = keyMirror({\n  INSERT_MARKUP: null,\n  MOVE_EXISTING: null,\n  REMOVE_NODE: null,\n  SET_MARKUP: null,\n  TEXT_CONTENT: null\n});\n\nmodule.exports = ReactMultiChildUpdateTypes;\n},{\"164\":164}],80:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNodeTypes\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\nvar ReactNodeTypes = {\n  HOST: 0,\n  COMPOSITE: 1,\n  EMPTY: 2,\n\n  getType: function (node) {\n    if (node === null || node === false) {\n      return ReactNodeTypes.EMPTY;\n    } else if (ReactElement.isValidElement(node)) {\n      if (typeof node.type === 'function') {\n        return ReactNodeTypes.COMPOSITE;\n      } else {\n        return ReactNodeTypes.HOST;\n      }\n    }\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unexpected node: %s', node) : _prodInvariant('26', node) : void 0;\n  }\n};\n\nmodule.exports = ReactNodeTypes;\n},{\"139\":139,\"161\":161,\"62\":62}],81:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNoopUpdateQueue\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the abstract API for an update queue.\n */\nvar ReactNoopUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    return false;\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback) {},\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    warnNoop(publicInstance, 'forceUpdate');\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    warnNoop(publicInstance, 'replaceState');\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    warnNoop(publicInstance, 'setState');\n  }\n};\n\nmodule.exports = ReactNoopUpdateQueue;\n},{\"171\":171}],82:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactOwner\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * ReactOwners are capable of storing references to owned components.\n *\n * All components are capable of //being// referenced by owner components, but\n * only ReactOwner components are capable of //referencing// owned components.\n * The named reference is known as a \"ref\".\n *\n * Refs are available when mounted and updated during reconciliation.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return (\n *         <div onClick={this.handleClick}>\n *           <CustomComponent ref=\"custom\" />\n *         </div>\n *       );\n *     },\n *     handleClick: function() {\n *       this.refs.custom.handleClick();\n *     },\n *     componentDidMount: function() {\n *       this.refs.custom.initialize();\n *     }\n *   });\n *\n * Refs should rarely be used. When refs are used, they should only be done to\n * control data that is not handled by React's data flow.\n *\n * @class ReactOwner\n */\nvar ReactOwner = {\n\n  /**\n   * @param {?object} object\n   * @return {boolean} True if `object` is a valid owner.\n   * @final\n   */\n  isValidOwner: function (object) {\n    return !!(object && typeof object.attachRef === 'function' && typeof object.detachRef === 'function');\n  },\n\n  /**\n   * Adds a component by ref to an owner component.\n   *\n   * @param {ReactComponent} component Component to reference.\n   * @param {string} ref Name by which to refer to the component.\n   * @param {ReactOwner} owner Component on which to record the ref.\n   * @final\n   * @internal\n   */\n  addComponentAsRefTo: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('119') : void 0;\n    owner.attachRef(ref, component);\n  },\n\n  /**\n   * Removes a component by ref from an owner component.\n   *\n   * @param {ReactComponent} component Component to dereference.\n   * @param {string} ref Name of the ref to remove.\n   * @param {ReactOwner} owner Component on which the ref is recorded.\n   * @final\n   * @internal\n   */\n  removeComponentAsRefFrom: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('120') : void 0;\n    var ownerPublicInstance = owner.getPublicInstance();\n    // Check that `component`'s owner is still alive and that `component` is still the current ref\n    // because we do not want to detach the ref if another component stole it.\n    if (ownerPublicInstance && ownerPublicInstance.refs[ref] === component.getPublicInstance()) {\n      owner.detachRef(ref);\n    }\n  }\n\n};\n\nmodule.exports = ReactOwner;\n},{\"139\":139,\"161\":161}],83:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocationNames\n */\n\n'use strict';\n\nvar ReactPropTypeLocationNames = {};\n\nif (\"development\" !== 'production') {\n  ReactPropTypeLocationNames = {\n    prop: 'prop',\n    context: 'context',\n    childContext: 'child context'\n  };\n}\n\nmodule.exports = ReactPropTypeLocationNames;\n},{}],84:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocations\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar ReactPropTypeLocations = keyMirror({\n  prop: null,\n  context: null,\n  childContext: null\n});\n\nmodule.exports = ReactPropTypeLocations;\n},{\"164\":164}],85:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypes\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar emptyFunction = _dereq_(153);\nvar getIteratorFn = _dereq_(130);\n\n/**\n * Collection of methods that allow declaration and validation of props that are\n * supplied to React components. Example usage:\n *\n *   var Props = require('ReactPropTypes');\n *   var MyArticle = React.createClass({\n *     propTypes: {\n *       // An optional string prop named \"description\".\n *       description: Props.string,\n *\n *       // A required enum prop named \"category\".\n *       category: Props.oneOf(['News','Photos']).isRequired,\n *\n *       // A prop named \"dialog\" that requires an instance of Dialog.\n *       dialog: Props.instanceOf(Dialog).isRequired\n *     },\n *     render: function() { ... }\n *   });\n *\n * A more formal specification of how these methods are used:\n *\n *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)\n *   decl := ReactPropTypes.{type}(.isRequired)?\n *\n * Each and every declaration produces a function with the same signature. This\n * allows the creation of custom validation functions. For example:\n *\n *  var MyLink = React.createClass({\n *    propTypes: {\n *      // An optional string or URI prop named \"href\".\n *      href: function(props, propName, componentName) {\n *        var propValue = props[propName];\n *        if (propValue != null && typeof propValue !== 'string' &&\n *            !(propValue instanceof URI)) {\n *          return new Error(\n *            'Expected a string or an URI for ' + propName + ' in ' +\n *            componentName\n *          );\n *        }\n *      }\n *    },\n *    render: function() {...}\n *  });\n *\n * @internal\n */\n\nvar ANONYMOUS = '<<anonymous>>';\n\nvar ReactPropTypes = {\n  array: createPrimitiveTypeChecker('array'),\n  bool: createPrimitiveTypeChecker('boolean'),\n  func: createPrimitiveTypeChecker('function'),\n  number: createPrimitiveTypeChecker('number'),\n  object: createPrimitiveTypeChecker('object'),\n  string: createPrimitiveTypeChecker('string'),\n  symbol: createPrimitiveTypeChecker('symbol'),\n\n  any: createAnyTypeChecker(),\n  arrayOf: createArrayOfTypeChecker,\n  element: createElementTypeChecker(),\n  instanceOf: createInstanceTypeChecker,\n  node: createNodeChecker(),\n  objectOf: createObjectOfTypeChecker,\n  oneOf: createEnumTypeChecker,\n  oneOfType: createUnionTypeChecker,\n  shape: createShapeTypeChecker\n};\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n/*eslint-disable no-self-compare*/\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n/*eslint-enable no-self-compare*/\n\nfunction createChainableTypeChecker(validate) {\n  function checkType(isRequired, props, propName, componentName, location, propFullName) {\n    componentName = componentName || ANONYMOUS;\n    propFullName = propFullName || propName;\n    if (props[propName] == null) {\n      var locationName = ReactPropTypeLocationNames[location];\n      if (isRequired) {\n        return new Error('Required ' + locationName + ' `' + propFullName + '` was not specified in ' + ('`' + componentName + '`.'));\n      }\n      return null;\n    } else {\n      return validate(props, propName, componentName, location, propFullName);\n    }\n  }\n\n  var chainedCheckType = checkType.bind(null, false);\n  chainedCheckType.isRequired = checkType.bind(null, true);\n\n  return chainedCheckType;\n}\n\nfunction createPrimitiveTypeChecker(expectedType) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== expectedType) {\n      var locationName = ReactPropTypeLocationNames[location];\n      // `propValue` being instance of, say, date/regexp, pass the 'object'\n      // check, but we can offer a more precise error message here rather than\n      // 'of type `object`'.\n      var preciseType = getPreciseType(propValue);\n\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createAnyTypeChecker() {\n  return createChainableTypeChecker(emptyFunction.thatReturns(null));\n}\n\nfunction createArrayOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');\n    }\n    var propValue = props[propName];\n    if (!Array.isArray(propValue)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var propType = getPropType(propValue);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));\n    }\n    for (var i = 0; i < propValue.length; i++) {\n      var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']');\n      if (error instanceof Error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createElementTypeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!ReactElement.isValidElement(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a single ReactElement.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createInstanceTypeChecker(expectedClass) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!(props[propName] instanceof expectedClass)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var expectedClassName = expectedClass.name || ANONYMOUS;\n      var actualClassName = getClassName(props[propName]);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createEnumTypeChecker(expectedValues) {\n  if (!Array.isArray(expectedValues)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOf, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    for (var i = 0; i < expectedValues.length; i++) {\n      if (is(propValue, expectedValues[i])) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    var valuesString = JSON.stringify(expectedValues);\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createObjectOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');\n    }\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));\n    }\n    for (var key in propValue) {\n      if (propValue.hasOwnProperty(key)) {\n        var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key);\n        if (error instanceof Error) {\n          return error;\n        }\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createUnionTypeChecker(arrayOfTypeCheckers) {\n  if (!Array.isArray(arrayOfTypeCheckers)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOfType, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n      var checker = arrayOfTypeCheckers[i];\n      if (checker(props, propName, componentName, location, propFullName) == null) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createNodeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!isNode(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createShapeTypeChecker(shapeTypes) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n    }\n    for (var key in shapeTypes) {\n      var checker = shapeTypes[key];\n      if (!checker) {\n        continue;\n      }\n      var error = checker(propValue, key, componentName, location, propFullName + '.' + key);\n      if (error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction isNode(propValue) {\n  switch (typeof propValue) {\n    case 'number':\n    case 'string':\n    case 'undefined':\n      return true;\n    case 'boolean':\n      return !propValue;\n    case 'object':\n      if (Array.isArray(propValue)) {\n        return propValue.every(isNode);\n      }\n      if (propValue === null || ReactElement.isValidElement(propValue)) {\n        return true;\n      }\n\n      var iteratorFn = getIteratorFn(propValue);\n      if (iteratorFn) {\n        var iterator = iteratorFn.call(propValue);\n        var step;\n        if (iteratorFn !== propValue.entries) {\n          while (!(step = iterator.next()).done) {\n            if (!isNode(step.value)) {\n              return false;\n            }\n          }\n        } else {\n          // Iterator will provide entry [k,v] tuples rather than values.\n          while (!(step = iterator.next()).done) {\n            var entry = step.value;\n            if (entry) {\n              if (!isNode(entry[1])) {\n                return false;\n              }\n            }\n          }\n        }\n      } else {\n        return false;\n      }\n\n      return true;\n    default:\n      return false;\n  }\n}\n\nfunction isSymbol(propType, propValue) {\n  // Native Symbol.\n  if (propType === 'symbol') {\n    return true;\n  }\n\n  // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'\n  if (propValue['@@toStringTag'] === 'Symbol') {\n    return true;\n  }\n\n  // Fallback for non-spec compliant Symbols which are polyfilled.\n  if (typeof Symbol === 'function' && propValue instanceof Symbol) {\n    return true;\n  }\n\n  return false;\n}\n\n// Equivalent of `typeof` but with special handling for array and regexp.\nfunction getPropType(propValue) {\n  var propType = typeof propValue;\n  if (Array.isArray(propValue)) {\n    return 'array';\n  }\n  if (propValue instanceof RegExp) {\n    // Old webkits (at least until Android 4.0) return 'function' rather than\n    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/\n    // passes PropTypes.object.\n    return 'object';\n  }\n  if (isSymbol(propType, propValue)) {\n    return 'symbol';\n  }\n  return propType;\n}\n\n// This handles more types than `getPropType`. Only used for error messages.\n// See `createPrimitiveTypeChecker`.\nfunction getPreciseType(propValue) {\n  var propType = getPropType(propValue);\n  if (propType === 'object') {\n    if (propValue instanceof Date) {\n      return 'date';\n    } else if (propValue instanceof RegExp) {\n      return 'regexp';\n    }\n  }\n  return propType;\n}\n\n// Returns class name of the object, if any.\nfunction getClassName(propValue) {\n  if (!propValue.constructor || !propValue.constructor.name) {\n    return ANONYMOUS;\n  }\n  return propValue.constructor.name;\n}\n\nmodule.exports = ReactPropTypes;\n},{\"130\":130,\"153\":153,\"62\":62,\"83\":83}],86:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconcileTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactInputSelection = _dereq_(72);\nvar ReactInstrumentation = _dereq_(74);\nvar Transaction = _dereq_(113);\nvar ReactUpdateQueue = _dereq_(94);\n\n/**\n * Ensures that, when possible, the selection range (currently selected text\n * input) is not disturbed by performing the transaction.\n */\nvar SELECTION_RESTORATION = {\n  /**\n   * @return {Selection} Selection information.\n   */\n  initialize: ReactInputSelection.getSelectionInformation,\n  /**\n   * @param {Selection} sel Selection information returned from `initialize`.\n   */\n  close: ReactInputSelection.restoreSelection\n};\n\n/**\n * Suppresses events (blur/focus) that could be inadvertently dispatched due to\n * high level DOM manipulations (like temporarily removing a text input from the\n * DOM).\n */\nvar EVENT_SUPPRESSION = {\n  /**\n   * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before\n   * the reconciliation.\n   */\n  initialize: function () {\n    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();\n    ReactBrowserEventEmitter.setEnabled(false);\n    return currentlyEnabled;\n  },\n\n  /**\n   * @param {boolean} previouslyEnabled Enabled status of\n   *   `ReactBrowserEventEmitter` before the reconciliation occurred. `close`\n   *   restores the previous value.\n   */\n  close: function (previouslyEnabled) {\n    ReactBrowserEventEmitter.setEnabled(previouslyEnabled);\n  }\n};\n\n/**\n * Provides a queue for collecting `componentDidMount` and\n * `componentDidUpdate` callbacks during the transaction.\n */\nvar ON_DOM_READY_QUEUEING = {\n  /**\n   * Initializes the internal `onDOMReady` queue.\n   */\n  initialize: function () {\n    this.reactMountReady.reset();\n  },\n\n  /**\n   * After DOM is flushed, invoke all registered `onDOMReady` callbacks.\n   */\n  close: function () {\n    this.reactMountReady.notifyAll();\n  }\n};\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\n/**\n * Currently:\n * - The order that these are listed in the transaction is critical:\n * - Suppresses events.\n * - Restores selection range.\n *\n * Future:\n * - Restore document/overflow scroll positions that were unintentionally\n *   modified via DOM insertions above the top viewport boundary.\n * - Implement/integrate with customized constraint based layout system and keep\n *   track of which dimensions must be remeasured.\n *\n * @class ReactReconcileTransaction\n */\nfunction ReactReconcileTransaction(useCreateElement) {\n  this.reinitializeTransaction();\n  // Only server-side rendering really needs this option (see\n  // `ReactServerRendering`), but server-side uses\n  // `ReactServerRenderingTransaction` instead. This option is here so that it's\n  // accessible and defaults to false when `ReactDOMComponent` and\n  // `ReactDOMTextComponent` checks it in `mountComponent`.`\n  this.renderToStaticMarkup = false;\n  this.reactMountReady = CallbackQueue.getPooled(null);\n  this.useCreateElement = useCreateElement;\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array<object>} List of operation wrap procedures.\n   *   TODO: convert to array<TransactionWrapper>\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return this.reactMountReady;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return ReactUpdateQueue;\n  },\n\n  /**\n   * Save current transaction state -- if the return value from this method is\n   * passed to `rollback`, the transaction will be reset to that state.\n   */\n  checkpoint: function () {\n    // reactMountReady is the our only stateful wrapper\n    return this.reactMountReady.checkpoint();\n  },\n\n  rollback: function (checkpoint) {\n    this.reactMountReady.rollback(checkpoint);\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {\n    CallbackQueue.release(this.reactMountReady);\n    this.reactMountReady = null;\n  }\n};\n\n_assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactReconcileTransaction);\n\nmodule.exports = ReactReconcileTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"27\":27,\"5\":5,\"72\":72,\"74\":74,\"94\":94}],87:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconciler\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactRef = _dereq_(88);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\n\n/**\n * Helper to call ReactRef.attachRefs with this composite component, split out\n * to avoid allocations in the transaction mount-ready queue.\n */\nfunction attachRefs() {\n  ReactRef.attachRefs(this, this._currentElement);\n}\n\nvar ReactReconciler = {\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} the containing host component instance\n   * @param {?object} info about the host container\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (internalInstance, transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeMountComponent(internalInstance._debugID, internalInstance._currentElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'mountComponent');\n      }\n    }\n    var markup = internalInstance.mountComponent(transaction, hostParent, hostContainerInfo, context);\n    if (internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'mountComponent');\n        ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID);\n      }\n    }\n    return markup;\n  },\n\n  /**\n   * Returns a value that can be passed to\n   * ReactComponentEnvironment.replaceNodeWithMarkup.\n   */\n  getHostNode: function (internalInstance) {\n    return internalInstance.getHostNode();\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (internalInstance, safely) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n      }\n    }\n    ReactRef.detachRefs(internalInstance, internalInstance._currentElement);\n    internalInstance.unmountComponent(safely);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n        ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Update a component using a new element.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @internal\n   */\n  receiveComponent: function (internalInstance, nextElement, transaction, context) {\n    var prevElement = internalInstance._currentElement;\n\n    if (nextElement === prevElement && context === internalInstance._context) {\n      // Since elements are immutable after the owner is rendered,\n      // we can do a cheap identity compare here to determine if this is a\n      // superfluous reconcile. It's possible for state to be mutable but such\n      // change should trigger an update of the owner which would recreate\n      // the element. We explicitly check for the existence of an owner since\n      // it's possible for an element created outside a composite to be\n      // deeply mutated and reused.\n\n      // TODO: Bailing out early is just a perf optimization right?\n      // TODO: Removing the return statement should affect correctness?\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, nextElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n      }\n    }\n\n    var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);\n\n    if (refsChanged) {\n      ReactRef.detachRefs(internalInstance, prevElement);\n    }\n\n    internalInstance.receiveComponent(nextElement, transaction, context);\n\n    if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Flush any dirty changes in a component.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (internalInstance, transaction, updateBatchNumber) {\n    if (internalInstance._updateBatchNumber !== updateBatchNumber) {\n      // The component's enqueued batch number should always be the current\n      // batch or the following one.\n      !(internalInstance._updateBatchNumber == null || internalInstance._updateBatchNumber === updateBatchNumber + 1) ? \"development\" !== 'production' ? invariant(false, 'performUpdateIfNecessary: Unexpected batch number (current %s, pending %s)', updateBatchNumber, internalInstance._updateBatchNumber) : _prodInvariant('121', updateBatchNumber, internalInstance._updateBatchNumber) : void 0;\n      return;\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, internalInstance._currentElement);\n      }\n    }\n    internalInstance.performUpdateIfNecessary(transaction);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactReconciler;\n},{\"139\":139,\"161\":161,\"74\":74,\"88\":88}],88:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactRef\n */\n\n'use strict';\n\nvar ReactOwner = _dereq_(82);\n\nvar ReactRef = {};\n\nfunction attachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(component.getPublicInstance());\n  } else {\n    // Legacy ref\n    ReactOwner.addComponentAsRefTo(component, ref, owner);\n  }\n}\n\nfunction detachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(null);\n  } else {\n    // Legacy ref\n    ReactOwner.removeComponentAsRefFrom(component, ref, owner);\n  }\n}\n\nReactRef.attachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    attachRef(ref, instance, element._owner);\n  }\n};\n\nReactRef.shouldUpdateRefs = function (prevElement, nextElement) {\n  // If either the owner or a `ref` has changed, make sure the newest owner\n  // has stored a reference to `this`, and the previous owner (if different)\n  // has forgotten the reference to `this`. We use the element instead\n  // of the public this.props because the post processing cannot determine\n  // a ref. The ref conceptually lives on the element.\n\n  // TODO: Should this even be possible? The owner cannot change because\n  // it's forbidden by shouldUpdateReactComponent. The ref can change\n  // if you swap the keys of but not the refs. Reconsider where this check\n  // is made. It probably belongs where the key checking and\n  // instantiateReactComponent is done.\n\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n\n  return(\n    // This has a few false positives w/r/t empty components.\n    prevEmpty || nextEmpty || nextElement._owner !== prevElement._owner || nextElement.ref !== prevElement.ref\n  );\n};\n\nReactRef.detachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    detachRef(ref, instance, element._owner);\n  }\n};\n\nmodule.exports = ReactRef;\n},{\"82\":82}],89:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerBatchingStrategy\n */\n\n'use strict';\n\nvar ReactServerBatchingStrategy = {\n  isBatchingUpdates: false,\n  batchedUpdates: function (callback) {\n    // Don't do anything here. During the server rendering we don't want to\n    // schedule any updates. We will simply ignore them.\n  }\n};\n\nmodule.exports = ReactServerBatchingStrategy;\n},{}],90:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRendering\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactElement = _dereq_(62);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactServerBatchingStrategy = _dereq_(89);\nvar ReactServerRenderingTransaction = _dereq_(91);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\n\n/**\n * @param {ReactElement} element\n * @return {string} the HTML markup\n */\nfunction renderToStringImpl(element, makeStaticMarkup) {\n  var transaction;\n  try {\n    ReactUpdates.injection.injectBatchingStrategy(ReactServerBatchingStrategy);\n\n    transaction = ReactServerRenderingTransaction.getPooled(makeStaticMarkup);\n\n    return transaction.perform(function () {\n      var componentInstance = instantiateReactComponent(element, true);\n      var markup = ReactReconciler.mountComponent(componentInstance, transaction, null, ReactDOMContainerInfo(), emptyObject);\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onUnmountComponent(componentInstance._debugID);\n      }\n      if (!makeStaticMarkup) {\n        markup = ReactMarkupChecksum.addChecksumToMarkup(markup);\n      }\n      return markup;\n    }, null);\n  } finally {\n    ReactServerRenderingTransaction.release(transaction);\n    // Revert to the DOM batching strategy since these two renderers\n    // currently share these stateful modules.\n    ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n  }\n}\n\n/**\n * Render a ReactElement to its initial HTML. This should only be used on the\n * server.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostring\n */\nfunction renderToString(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToString(): You must pass a valid ReactElement.') : _prodInvariant('46') : void 0;\n  return renderToStringImpl(element, false);\n}\n\n/**\n * Similar to renderToString, except this doesn't create extra DOM attributes\n * such as data-react-id that React uses internally.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostaticmarkup\n */\nfunction renderToStaticMarkup(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToStaticMarkup(): You must pass a valid ReactElement.') : _prodInvariant('47') : void 0;\n  return renderToStringImpl(element, true);\n}\n\nmodule.exports = {\n  renderToString: renderToString,\n  renderToStaticMarkup: renderToStaticMarkup\n};\n},{\"134\":134,\"139\":139,\"154\":154,\"161\":161,\"42\":42,\"60\":60,\"62\":62,\"74\":74,\"76\":76,\"87\":87,\"89\":89,\"91\":91,\"95\":95}],91:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRenderingTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\nvar Transaction = _dereq_(113);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactServerUpdateQueue = _dereq_(92);\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\nvar noopCallbackQueue = {\n  enqueue: function () {}\n};\n\n/**\n * @class ReactServerRenderingTransaction\n * @param {boolean} renderToStaticMarkup\n */\nfunction ReactServerRenderingTransaction(renderToStaticMarkup) {\n  this.reinitializeTransaction();\n  this.renderToStaticMarkup = renderToStaticMarkup;\n  this.useCreateElement = false;\n  this.updateQueue = new ReactServerUpdateQueue(this);\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array} Empty list of operation wrap procedures.\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return noopCallbackQueue;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return this.updateQueue;\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {},\n\n  checkpoint: function () {},\n\n  rollback: function () {}\n};\n\n_assign(ReactServerRenderingTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactServerRenderingTransaction);\n\nmodule.exports = ReactServerRenderingTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"74\":74,\"92\":92}],92:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerUpdateQueue\n * \n */\n\n'use strict';\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar ReactUpdateQueue = _dereq_(94);\nvar Transaction = _dereq_(113);\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounting component. ' + 'This usually means you called %s() outside componentWillMount() on the server. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the update queue used for server rendering.\n * It delegates to ReactUpdateQueue while server rendering is in progress and\n * switches to ReactNoopUpdateQueue after the transaction has completed.\n * @class ReactServerUpdateQueue\n * @param {Transaction} transaction\n */\n\nvar ReactServerUpdateQueue = function () {\n  /* :: transaction: Transaction; */\n\n  function ReactServerUpdateQueue(transaction) {\n    _classCallCheck(this, ReactServerUpdateQueue);\n\n    this.transaction = transaction;\n  }\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n\n\n  ReactServerUpdateQueue.prototype.isMounted = function isMounted(publicInstance) {\n    return false;\n  };\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueCallback = function enqueueCallback(publicInstance, callback, callerName) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueCallback(publicInstance, callback, callerName);\n    }\n  };\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueForceUpdate = function enqueueForceUpdate(publicInstance) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueForceUpdate(publicInstance);\n    } else {\n      warnNoop(publicInstance, 'forceUpdate');\n    }\n  };\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} completeState Next state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueReplaceState = function enqueueReplaceState(publicInstance, completeState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueReplaceState(publicInstance, completeState);\n    } else {\n      warnNoop(publicInstance, 'replaceState');\n    }\n  };\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} partialState Next partial state to be merged with state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueSetState = function enqueueSetState(publicInstance, partialState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueSetState(publicInstance, partialState);\n    } else {\n      warnNoop(publicInstance, 'setState');\n    }\n  };\n\n  return ReactServerUpdateQueue;\n}();\n\nmodule.exports = ReactServerUpdateQueue;\n},{\"113\":113,\"171\":171,\"94\":94}],93:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUMDEntry\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactDOM = _dereq_(37);\nvar ReactDOMServer = _dereq_(54);\nvar React = _dereq_(26);\n\n// `version` will be added here by ReactIsomorphic.\nvar ReactUMDEntry = _assign({\n  __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOM,\n  __SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOMServer\n}, React);\n\nmodule.exports = ReactUMDEntry;\n},{\"172\":172,\"26\":26,\"37\":37,\"54\":54}],94:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdateQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nfunction enqueueUpdate(internalInstance) {\n  ReactUpdates.enqueueUpdate(internalInstance);\n}\n\nfunction formatUnexpectedArgument(arg) {\n  var type = typeof arg;\n  if (type !== 'object') {\n    return type;\n  }\n  var displayName = arg.constructor && arg.constructor.name || type;\n  var keys = Object.keys(arg);\n  if (keys.length > 0 && keys.length < 20) {\n    return displayName + ' (keys: ' + keys.join(', ') + ')';\n  }\n  return displayName;\n}\n\nfunction getInternalInstanceReadyForUpdate(publicInstance, callerName) {\n  var internalInstance = ReactInstanceMap.get(publicInstance);\n  if (!internalInstance) {\n    if (\"development\" !== 'production') {\n      // Only warn when we have a callerName. Otherwise we should be silent.\n      // We're probably calling from enqueueCallback. We don't want to warn\n      // there because we already warned for the corresponding lifecycle method.\n      \"development\" !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor.displayName) : void 0;\n    }\n    return null;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition (such as ' + 'within `render` or another component\\'s constructor). Render methods ' + 'should be a pure function of props and state; constructor ' + 'side-effects are an anti-pattern, but can be moved to ' + '`componentWillMount`.', callerName) : void 0;\n  }\n\n  return internalInstance;\n}\n\n/**\n * ReactUpdateQueue allows for state updates to be scheduled into a later\n * reconciliation step.\n */\nvar ReactUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    if (\"development\" !== 'production') {\n      var owner = ReactCurrentOwner.current;\n      if (owner !== null) {\n        \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n        owner._warnedAboutRefsInRender = true;\n      }\n    }\n    var internalInstance = ReactInstanceMap.get(publicInstance);\n    if (internalInstance) {\n      // During componentWillMount and render this will still be null but after\n      // that will always render to something. At least for now. So we can use\n      // this hack.\n      return !!internalInstance._renderedComponent;\n    } else {\n      return false;\n    }\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @param {string} callerName Name of the calling function in the public API.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback, callerName) {\n    ReactUpdateQueue.validateCallback(callback, callerName);\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);\n\n    // Previously we would throw an error if we didn't have an internal\n    // instance. Since we want to make it a no-op instead, we mirror the same\n    // behavior we have in other enqueue* methods.\n    // We also need to ignore callbacks in componentWillMount. See\n    // enqueueUpdates.\n    if (!internalInstance) {\n      return null;\n    }\n\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    // TODO: The callback here is ignored when setState is called from\n    // componentWillMount. Either fix it or disallow doing so completely in\n    // favor of getInitialState. Alternatively, we can disallow\n    // componentWillMount during server-side rendering.\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueCallbackInternal: function (internalInstance, callback) {\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'forceUpdate');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingForceUpdate = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingStateQueue = [completeState];\n    internalInstance._pendingReplaceState = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetState();\n      \"development\" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;\n    }\n\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);\n    queue.push(partialState);\n\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueElementInternal: function (internalInstance, nextElement, nextContext) {\n    internalInstance._pendingElement = nextElement;\n    // TODO: introduce _pendingContext instead of setting it directly.\n    internalInstance._context = nextContext;\n    enqueueUpdate(internalInstance);\n  },\n\n  validateCallback: function (callback, callerName) {\n    !(!callback || typeof callback === 'function') ? \"development\" !== 'production' ? invariant(false, '%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.', callerName, formatUnexpectedArgument(callback)) : _prodInvariant('122', callerName, formatUnexpectedArgument(callback)) : void 0;\n  }\n\n};\n\nmodule.exports = ReactUpdateQueue;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"73\":73,\"74\":74,\"95\":95}],95:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdates\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactReconciler = _dereq_(87);\nvar Transaction = _dereq_(113);\n\nvar invariant = _dereq_(161);\n\nvar dirtyComponents = [];\nvar updateBatchNumber = 0;\nvar asapCallbackQueue = CallbackQueue.getPooled();\nvar asapEnqueued = false;\n\nvar batchingStrategy = null;\n\nfunction ensureInjected() {\n  !(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching strategy') : _prodInvariant('123') : void 0;\n}\n\nvar NESTED_UPDATES = {\n  initialize: function () {\n    this.dirtyComponentsLength = dirtyComponents.length;\n  },\n  close: function () {\n    if (this.dirtyComponentsLength !== dirtyComponents.length) {\n      // Additional updates were enqueued by componentDidUpdate handlers or\n      // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run\n      // these new updates so that if A's componentDidUpdate calls setState on\n      // B, B will update before the callback A's updater provided when calling\n      // setState.\n      dirtyComponents.splice(0, this.dirtyComponentsLength);\n      flushBatchedUpdates();\n    } else {\n      dirtyComponents.length = 0;\n    }\n  }\n};\n\nvar UPDATE_QUEUEING = {\n  initialize: function () {\n    this.callbackQueue.reset();\n  },\n  close: function () {\n    this.callbackQueue.notifyAll();\n  }\n};\n\nvar TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];\n\nfunction ReactUpdatesFlushTransaction() {\n  this.reinitializeTransaction();\n  this.dirtyComponentsLength = null;\n  this.callbackQueue = CallbackQueue.getPooled();\n  this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */true);\n}\n\n_assign(ReactUpdatesFlushTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  destructor: function () {\n    this.dirtyComponentsLength = null;\n    CallbackQueue.release(this.callbackQueue);\n    this.callbackQueue = null;\n    ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);\n    this.reconcileTransaction = null;\n  },\n\n  perform: function (method, scope, a) {\n    // Essentially calls `this.reconcileTransaction.perform(method, scope, a)`\n    // with this transaction's wrappers around it.\n    return Transaction.Mixin.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a);\n  }\n});\n\nPooledClass.addPoolingTo(ReactUpdatesFlushTransaction);\n\nfunction batchedUpdates(callback, a, b, c, d, e) {\n  ensureInjected();\n  batchingStrategy.batchedUpdates(callback, a, b, c, d, e);\n}\n\n/**\n * Array comparator for ReactComponents by mount ordering.\n *\n * @param {ReactComponent} c1 first component you're comparing\n * @param {ReactComponent} c2 second component you're comparing\n * @return {number} Return value usable by Array.prototype.sort().\n */\nfunction mountOrderComparator(c1, c2) {\n  return c1._mountOrder - c2._mountOrder;\n}\n\nfunction runBatchedUpdates(transaction) {\n  var len = transaction.dirtyComponentsLength;\n  !(len === dirtyComponents.length) ? \"development\" !== 'production' ? invariant(false, 'Expected flush transaction\\'s stored dirty-components length (%s) to match dirty-components array length (%s).', len, dirtyComponents.length) : _prodInvariant('124', len, dirtyComponents.length) : void 0;\n\n  // Since reconciling a component higher in the owner hierarchy usually (not\n  // always -- see shouldComponentUpdate()) will reconcile children, reconcile\n  // them before their children by sorting the array.\n  dirtyComponents.sort(mountOrderComparator);\n\n  // Any updates enqueued while reconciling must be performed after this entire\n  // batch. Otherwise, if dirtyComponents is [A, B] where A has children B and\n  // C, B could update twice in a single batch if C's render enqueues an update\n  // to B (since B would have already updated, we should skip it, and the only\n  // way we can know to do so is by checking the batch counter).\n  updateBatchNumber++;\n\n  for (var i = 0; i < len; i++) {\n    // If a component is unmounted before pending changes apply, it will still\n    // be here, but we assume that it has cleared its _pendingCallbacks and\n    // that performUpdateIfNecessary is a noop.\n    var component = dirtyComponents[i];\n\n    // If performUpdateIfNecessary happens to enqueue any new updates, we\n    // shouldn't execute the callbacks until the next render happens, so\n    // stash the callbacks first\n    var callbacks = component._pendingCallbacks;\n    component._pendingCallbacks = null;\n\n    var markerName;\n    if (ReactFeatureFlags.logTopLevelRenders) {\n      var namedComponent = component;\n      // Duck type TopLevelWrapper. This is probably always true.\n      if (component._currentElement.props === component._renderedComponent._currentElement) {\n        namedComponent = component._renderedComponent;\n      }\n      markerName = 'React update: ' + namedComponent.getName();\n      console.time(markerName);\n    }\n\n    ReactReconciler.performUpdateIfNecessary(component, transaction.reconcileTransaction, updateBatchNumber);\n\n    if (markerName) {\n      console.timeEnd(markerName);\n    }\n\n    if (callbacks) {\n      for (var j = 0; j < callbacks.length; j++) {\n        transaction.callbackQueue.enqueue(callbacks[j], component.getPublicInstance());\n      }\n    }\n  }\n}\n\nvar flushBatchedUpdates = function () {\n  // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents\n  // array and perform any updates enqueued by mount-ready handlers (i.e.,\n  // componentDidUpdate) but we need to check here too in order to catch\n  // updates enqueued by setState callbacks and asap calls.\n  while (dirtyComponents.length || asapEnqueued) {\n    if (dirtyComponents.length) {\n      var transaction = ReactUpdatesFlushTransaction.getPooled();\n      transaction.perform(runBatchedUpdates, null, transaction);\n      ReactUpdatesFlushTransaction.release(transaction);\n    }\n\n    if (asapEnqueued) {\n      asapEnqueued = false;\n      var queue = asapCallbackQueue;\n      asapCallbackQueue = CallbackQueue.getPooled();\n      queue.notifyAll();\n      CallbackQueue.release(queue);\n    }\n  }\n};\n\n/**\n * Mark a component as needing a rerender, adding an optional callback to a\n * list of functions which will be executed once the rerender occurs.\n */\nfunction enqueueUpdate(component) {\n  ensureInjected();\n\n  // Various parts of our code (such as ReactCompositeComponent's\n  // _renderValidatedComponent) assume that calls to render aren't nested;\n  // verify that that's the case. (This is called by each top-level update\n  // function, like setState, forceUpdate, etc.; creation and\n  // destruction of top-level components is guarded in ReactMount.)\n\n  if (!batchingStrategy.isBatchingUpdates) {\n    batchingStrategy.batchedUpdates(enqueueUpdate, component);\n    return;\n  }\n\n  dirtyComponents.push(component);\n  if (component._updateBatchNumber == null) {\n    component._updateBatchNumber = updateBatchNumber + 1;\n  }\n}\n\n/**\n * Enqueue a callback to be run at the end of the current batching cycle. Throws\n * if no updates are currently being performed.\n */\nfunction asap(callback, context) {\n  !batchingStrategy.isBatchingUpdates ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates.asap: Can\\'t enqueue an asap callback in a context whereupdates are not being batched.') : _prodInvariant('125') : void 0;\n  asapCallbackQueue.enqueue(callback, context);\n  asapEnqueued = true;\n}\n\nvar ReactUpdatesInjection = {\n  injectReconcileTransaction: function (ReconcileTransaction) {\n    !ReconcileTransaction ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : _prodInvariant('126') : void 0;\n    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;\n  },\n\n  injectBatchingStrategy: function (_batchingStrategy) {\n    !_batchingStrategy ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : _prodInvariant('127') : void 0;\n    !(typeof _batchingStrategy.batchedUpdates === 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : _prodInvariant('128') : void 0;\n    !(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : _prodInvariant('129') : void 0;\n    batchingStrategy = _batchingStrategy;\n  }\n};\n\nvar ReactUpdates = {\n  /**\n   * React references `ReactReconcileTransaction` using this property in order\n   * to allow dependency injection.\n   *\n   * @internal\n   */\n  ReactReconcileTransaction: null,\n\n  batchedUpdates: batchedUpdates,\n  enqueueUpdate: enqueueUpdate,\n  flushBatchedUpdates: flushBatchedUpdates,\n  injection: ReactUpdatesInjection,\n  asap: asap\n};\n\nmodule.exports = ReactUpdates;\n},{\"113\":113,\"139\":139,\"161\":161,\"172\":172,\"25\":25,\"5\":5,\"68\":68,\"87\":87}],96:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactVersion\n */\n\n'use strict';\n\nmodule.exports = '15.2.1';\n},{}],97:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SVGDOMPropertyConfig\n */\n\n'use strict';\n\nvar NS = {\n  xlink: 'http://www.w3.org/1999/xlink',\n  xml: 'http://www.w3.org/XML/1998/namespace'\n};\n\n// We use attributes for everything SVG so let's avoid some duplication and run\n// code instead.\n// The following are all specified in the HTML config already so we exclude here.\n// - class (as className)\n// - color\n// - height\n// - id\n// - lang\n// - max\n// - media\n// - method\n// - min\n// - name\n// - style\n// - target\n// - type\n// - width\nvar ATTRS = {\n  accentHeight: 'accent-height',\n  accumulate: 0,\n  additive: 0,\n  alignmentBaseline: 'alignment-baseline',\n  allowReorder: 'allowReorder',\n  alphabetic: 0,\n  amplitude: 0,\n  arabicForm: 'arabic-form',\n  ascent: 0,\n  attributeName: 'attributeName',\n  attributeType: 'attributeType',\n  autoReverse: 'autoReverse',\n  azimuth: 0,\n  baseFrequency: 'baseFrequency',\n  baseProfile: 'baseProfile',\n  baselineShift: 'baseline-shift',\n  bbox: 0,\n  begin: 0,\n  bias: 0,\n  by: 0,\n  calcMode: 'calcMode',\n  capHeight: 'cap-height',\n  clip: 0,\n  clipPath: 'clip-path',\n  clipRule: 'clip-rule',\n  clipPathUnits: 'clipPathUnits',\n  colorInterpolation: 'color-interpolation',\n  colorInterpolationFilters: 'color-interpolation-filters',\n  colorProfile: 'color-profile',\n  colorRendering: 'color-rendering',\n  contentScriptType: 'contentScriptType',\n  contentStyleType: 'contentStyleType',\n  cursor: 0,\n  cx: 0,\n  cy: 0,\n  d: 0,\n  decelerate: 0,\n  descent: 0,\n  diffuseConstant: 'diffuseConstant',\n  direction: 0,\n  display: 0,\n  divisor: 0,\n  dominantBaseline: 'dominant-baseline',\n  dur: 0,\n  dx: 0,\n  dy: 0,\n  edgeMode: 'edgeMode',\n  elevation: 0,\n  enableBackground: 'enable-background',\n  end: 0,\n  exponent: 0,\n  externalResourcesRequired: 'externalResourcesRequired',\n  fill: 0,\n  fillOpacity: 'fill-opacity',\n  fillRule: 'fill-rule',\n  filter: 0,\n  filterRes: 'filterRes',\n  filterUnits: 'filterUnits',\n  floodColor: 'flood-color',\n  floodOpacity: 'flood-opacity',\n  focusable: 0,\n  fontFamily: 'font-family',\n  fontSize: 'font-size',\n  fontSizeAdjust: 'font-size-adjust',\n  fontStretch: 'font-stretch',\n  fontStyle: 'font-style',\n  fontVariant: 'font-variant',\n  fontWeight: 'font-weight',\n  format: 0,\n  from: 0,\n  fx: 0,\n  fy: 0,\n  g1: 0,\n  g2: 0,\n  glyphName: 'glyph-name',\n  glyphOrientationHorizontal: 'glyph-orientation-horizontal',\n  glyphOrientationVertical: 'glyph-orientation-vertical',\n  glyphRef: 'glyphRef',\n  gradientTransform: 'gradientTransform',\n  gradientUnits: 'gradientUnits',\n  hanging: 0,\n  horizAdvX: 'horiz-adv-x',\n  horizOriginX: 'horiz-origin-x',\n  ideographic: 0,\n  imageRendering: 'image-rendering',\n  'in': 0,\n  in2: 0,\n  intercept: 0,\n  k: 0,\n  k1: 0,\n  k2: 0,\n  k3: 0,\n  k4: 0,\n  kernelMatrix: 'kernelMatrix',\n  kernelUnitLength: 'kernelUnitLength',\n  kerning: 0,\n  keyPoints: 'keyPoints',\n  keySplines: 'keySplines',\n  keyTimes: 'keyTimes',\n  lengthAdjust: 'lengthAdjust',\n  letterSpacing: 'letter-spacing',\n  lightingColor: 'lighting-color',\n  limitingConeAngle: 'limitingConeAngle',\n  local: 0,\n  markerEnd: 'marker-end',\n  markerMid: 'marker-mid',\n  markerStart: 'marker-start',\n  markerHeight: 'markerHeight',\n  markerUnits: 'markerUnits',\n  markerWidth: 'markerWidth',\n  mask: 0,\n  maskContentUnits: 'maskContentUnits',\n  maskUnits: 'maskUnits',\n  mathematical: 0,\n  mode: 0,\n  numOctaves: 'numOctaves',\n  offset: 0,\n  opacity: 0,\n  operator: 0,\n  order: 0,\n  orient: 0,\n  orientation: 0,\n  origin: 0,\n  overflow: 0,\n  overlinePosition: 'overline-position',\n  overlineThickness: 'overline-thickness',\n  paintOrder: 'paint-order',\n  panose1: 'panose-1',\n  pathLength: 'pathLength',\n  patternContentUnits: 'patternContentUnits',\n  patternTransform: 'patternTransform',\n  patternUnits: 'patternUnits',\n  pointerEvents: 'pointer-events',\n  points: 0,\n  pointsAtX: 'pointsAtX',\n  pointsAtY: 'pointsAtY',\n  pointsAtZ: 'pointsAtZ',\n  preserveAlpha: 'preserveAlpha',\n  preserveAspectRatio: 'preserveAspectRatio',\n  primitiveUnits: 'primitiveUnits',\n  r: 0,\n  radius: 0,\n  refX: 'refX',\n  refY: 'refY',\n  renderingIntent: 'rendering-intent',\n  repeatCount: 'repeatCount',\n  repeatDur: 'repeatDur',\n  requiredExtensions: 'requiredExtensions',\n  requiredFeatures: 'requiredFeatures',\n  restart: 0,\n  result: 0,\n  rotate: 0,\n  rx: 0,\n  ry: 0,\n  scale: 0,\n  seed: 0,\n  shapeRendering: 'shape-rendering',\n  slope: 0,\n  spacing: 0,\n  specularConstant: 'specularConstant',\n  specularExponent: 'specularExponent',\n  speed: 0,\n  spreadMethod: 'spreadMethod',\n  startOffset: 'startOffset',\n  stdDeviation: 'stdDeviation',\n  stemh: 0,\n  stemv: 0,\n  stitchTiles: 'stitchTiles',\n  stopColor: 'stop-color',\n  stopOpacity: 'stop-opacity',\n  strikethroughPosition: 'strikethrough-position',\n  strikethroughThickness: 'strikethrough-thickness',\n  string: 0,\n  stroke: 0,\n  strokeDasharray: 'stroke-dasharray',\n  strokeDashoffset: 'stroke-dashoffset',\n  strokeLinecap: 'stroke-linecap',\n  strokeLinejoin: 'stroke-linejoin',\n  strokeMiterlimit: 'stroke-miterlimit',\n  strokeOpacity: 'stroke-opacity',\n  strokeWidth: 'stroke-width',\n  surfaceScale: 'surfaceScale',\n  systemLanguage: 'systemLanguage',\n  tableValues: 'tableValues',\n  targetX: 'targetX',\n  targetY: 'targetY',\n  textAnchor: 'text-anchor',\n  textDecoration: 'text-decoration',\n  textRendering: 'text-rendering',\n  textLength: 'textLength',\n  to: 0,\n  transform: 0,\n  u1: 0,\n  u2: 0,\n  underlinePosition: 'underline-position',\n  underlineThickness: 'underline-thickness',\n  unicode: 0,\n  unicodeBidi: 'unicode-bidi',\n  unicodeRange: 'unicode-range',\n  unitsPerEm: 'units-per-em',\n  vAlphabetic: 'v-alphabetic',\n  vHanging: 'v-hanging',\n  vIdeographic: 'v-ideographic',\n  vMathematical: 'v-mathematical',\n  values: 0,\n  vectorEffect: 'vector-effect',\n  version: 0,\n  vertAdvY: 'vert-adv-y',\n  vertOriginX: 'vert-origin-x',\n  vertOriginY: 'vert-origin-y',\n  viewBox: 'viewBox',\n  viewTarget: 'viewTarget',\n  visibility: 0,\n  widths: 0,\n  wordSpacing: 'word-spacing',\n  writingMode: 'writing-mode',\n  x: 0,\n  xHeight: 'x-height',\n  x1: 0,\n  x2: 0,\n  xChannelSelector: 'xChannelSelector',\n  xlinkActuate: 'xlink:actuate',\n  xlinkArcrole: 'xlink:arcrole',\n  xlinkHref: 'xlink:href',\n  xlinkRole: 'xlink:role',\n  xlinkShow: 'xlink:show',\n  xlinkTitle: 'xlink:title',\n  xlinkType: 'xlink:type',\n  xmlBase: 'xml:base',\n  xmlLang: 'xml:lang',\n  xmlSpace: 'xml:space',\n  y: 0,\n  y1: 0,\n  y2: 0,\n  yChannelSelector: 'yChannelSelector',\n  z: 0,\n  zoomAndPan: 'zoomAndPan'\n};\n\nvar SVGDOMPropertyConfig = {\n  Properties: {},\n  DOMAttributeNamespaces: {\n    xlinkActuate: NS.xlink,\n    xlinkArcrole: NS.xlink,\n    xlinkHref: NS.xlink,\n    xlinkRole: NS.xlink,\n    xlinkShow: NS.xlink,\n    xlinkTitle: NS.xlink,\n    xlinkType: NS.xlink,\n    xmlBase: NS.xml,\n    xmlLang: NS.xml,\n    xmlSpace: NS.xml\n  },\n  DOMAttributeNames: {}\n};\n\nObject.keys(ATTRS).forEach(function (key) {\n  SVGDOMPropertyConfig.Properties[key] = 0;\n  if (ATTRS[key]) {\n    SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key];\n  }\n});\n\nmodule.exports = SVGDOMPropertyConfig;\n},{}],98:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SelectEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInputSelection = _dereq_(72);\nvar SyntheticEvent = _dereq_(104);\n\nvar getActiveElement = _dereq_(156);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11;\n\nvar eventTypes = {\n  select: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSelect: null }),\n      captured: keyOf({ onSelectCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange]\n  }\n};\n\nvar activeElement = null;\nvar activeElementInst = null;\nvar lastSelection = null;\nvar mouseDown = false;\n\n// Track whether a listener exists for this plugin. If none exist, we do\n// not extract events. See #3639.\nvar hasListener = false;\nvar ON_SELECT_KEY = keyOf({ onSelect: null });\n\n/**\n * Get an object which is a unique representation of the current selection.\n *\n * The return value will not be consistent across nodes or browsers, but\n * two identical selections on the same node will return identical objects.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getSelection(node) {\n  if ('selectionStart' in node && ReactInputSelection.hasSelectionCapabilities(node)) {\n    return {\n      start: node.selectionStart,\n      end: node.selectionEnd\n    };\n  } else if (window.getSelection) {\n    var selection = window.getSelection();\n    return {\n      anchorNode: selection.anchorNode,\n      anchorOffset: selection.anchorOffset,\n      focusNode: selection.focusNode,\n      focusOffset: selection.focusOffset\n    };\n  } else if (document.selection) {\n    var range = document.selection.createRange();\n    return {\n      parentElement: range.parentElement(),\n      text: range.text,\n      top: range.boundingTop,\n      left: range.boundingLeft\n    };\n  }\n}\n\n/**\n * Poll selection to see whether it's changed.\n *\n * @param {object} nativeEvent\n * @return {?SyntheticEvent}\n */\nfunction constructSelectEvent(nativeEvent, nativeEventTarget) {\n  // Ensure we have the right element, and that the user is not dragging a\n  // selection (this matches native `select` event behavior). In HTML5, select\n  // fires only on input and textarea thus if there's no focused element we\n  // won't dispatch.\n  if (mouseDown || activeElement == null || activeElement !== getActiveElement()) {\n    return null;\n  }\n\n  // Only fire when selection has actually changed.\n  var currentSelection = getSelection(activeElement);\n  if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {\n    lastSelection = currentSelection;\n\n    var syntheticEvent = SyntheticEvent.getPooled(eventTypes.select, activeElementInst, nativeEvent, nativeEventTarget);\n\n    syntheticEvent.type = 'select';\n    syntheticEvent.target = activeElement;\n\n    EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent);\n\n    return syntheticEvent;\n  }\n\n  return null;\n}\n\n/**\n * This plugin creates an `onSelect` event that normalizes select events\n * across form elements.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - contentEditable\n *\n * This differs from native browser implementations in the following ways:\n * - Fires on contentEditable fields as well as inputs.\n * - Fires for collapsed selection.\n * - Fires after user input.\n */\nvar SelectEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (!hasListener) {\n      return null;\n    }\n\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    switch (topLevelType) {\n      // Track the input node that has focus.\n      case topLevelTypes.topFocus:\n        if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {\n          activeElement = targetNode;\n          activeElementInst = targetInst;\n          lastSelection = null;\n        }\n        break;\n      case topLevelTypes.topBlur:\n        activeElement = null;\n        activeElementInst = null;\n        lastSelection = null;\n        break;\n\n      // Don't fire the event while the user is dragging. This matches the\n      // semantics of the native select event.\n      case topLevelTypes.topMouseDown:\n        mouseDown = true;\n        break;\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topMouseUp:\n        mouseDown = false;\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n\n      // Chrome and IE fire non-standard event when selection is changed (and\n      // sometimes when it hasn't). IE's event fires out of order with respect\n      // to key and input events on deletion, so we discard it.\n      //\n      // Firefox doesn't support selectionchange, so check selection status\n      // after each key entry. The selection changes after keydown and before\n      // keyup, but we check on keydown as well in the case of holding down a\n      // key, when multiple keydown events are fired but only one keyup is.\n      // This is also our approach for IE handling, for the reason above.\n      case topLevelTypes.topSelectionChange:\n        if (skipSelectionChangeEvent) {\n          break;\n        }\n      // falls through\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n    }\n\n    return null;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    if (registrationName === ON_SELECT_KEY) {\n      hasListener = true;\n    }\n  }\n};\n\nmodule.exports = SelectEventPlugin;\n},{\"104\":104,\"136\":136,\"147\":147,\"156\":156,\"16\":16,\"165\":165,\"170\":170,\"20\":20,\"41\":41,\"72\":72}],99:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SimpleEventPlugin\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar EventListener = _dereq_(146);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticAnimationEvent = _dereq_(100);\nvar SyntheticClipboardEvent = _dereq_(101);\nvar SyntheticEvent = _dereq_(104);\nvar SyntheticFocusEvent = _dereq_(105);\nvar SyntheticKeyboardEvent = _dereq_(107);\nvar SyntheticMouseEvent = _dereq_(108);\nvar SyntheticDragEvent = _dereq_(103);\nvar SyntheticTouchEvent = _dereq_(109);\nvar SyntheticTransitionEvent = _dereq_(110);\nvar SyntheticUIEvent = _dereq_(111);\nvar SyntheticWheelEvent = _dereq_(112);\n\nvar emptyFunction = _dereq_(153);\nvar getEventCharCode = _dereq_(125);\nvar invariant = _dereq_(161);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  abort: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAbort: true }),\n      captured: keyOf({ onAbortCapture: true })\n    }\n  },\n  animationEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationEnd: true }),\n      captured: keyOf({ onAnimationEndCapture: true })\n    }\n  },\n  animationIteration: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationIteration: true }),\n      captured: keyOf({ onAnimationIterationCapture: true })\n    }\n  },\n  animationStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationStart: true }),\n      captured: keyOf({ onAnimationStartCapture: true })\n    }\n  },\n  blur: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBlur: true }),\n      captured: keyOf({ onBlurCapture: true })\n    }\n  },\n  canPlay: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlay: true }),\n      captured: keyOf({ onCanPlayCapture: true })\n    }\n  },\n  canPlayThrough: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlayThrough: true }),\n      captured: keyOf({ onCanPlayThroughCapture: true })\n    }\n  },\n  click: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onClick: true }),\n      captured: keyOf({ onClickCapture: true })\n    }\n  },\n  contextMenu: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onContextMenu: true }),\n      captured: keyOf({ onContextMenuCapture: true })\n    }\n  },\n  copy: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCopy: true }),\n      captured: keyOf({ onCopyCapture: true })\n    }\n  },\n  cut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCut: true }),\n      captured: keyOf({ onCutCapture: true })\n    }\n  },\n  doubleClick: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDoubleClick: true }),\n      captured: keyOf({ onDoubleClickCapture: true })\n    }\n  },\n  drag: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrag: true }),\n      captured: keyOf({ onDragCapture: true })\n    }\n  },\n  dragEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnd: true }),\n      captured: keyOf({ onDragEndCapture: true })\n    }\n  },\n  dragEnter: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnter: true }),\n      captured: keyOf({ onDragEnterCapture: true })\n    }\n  },\n  dragExit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragExit: true }),\n      captured: keyOf({ onDragExitCapture: true })\n    }\n  },\n  dragLeave: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragLeave: true }),\n      captured: keyOf({ onDragLeaveCapture: true })\n    }\n  },\n  dragOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragOver: true }),\n      captured: keyOf({ onDragOverCapture: true })\n    }\n  },\n  dragStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragStart: true }),\n      captured: keyOf({ onDragStartCapture: true })\n    }\n  },\n  drop: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrop: true }),\n      captured: keyOf({ onDropCapture: true })\n    }\n  },\n  durationChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDurationChange: true }),\n      captured: keyOf({ onDurationChangeCapture: true })\n    }\n  },\n  emptied: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEmptied: true }),\n      captured: keyOf({ onEmptiedCapture: true })\n    }\n  },\n  encrypted: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEncrypted: true }),\n      captured: keyOf({ onEncryptedCapture: true })\n    }\n  },\n  ended: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEnded: true }),\n      captured: keyOf({ onEndedCapture: true })\n    }\n  },\n  error: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onError: true }),\n      captured: keyOf({ onErrorCapture: true })\n    }\n  },\n  focus: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onFocus: true }),\n      captured: keyOf({ onFocusCapture: true })\n    }\n  },\n  input: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInput: true }),\n      captured: keyOf({ onInputCapture: true })\n    }\n  },\n  invalid: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInvalid: true }),\n      captured: keyOf({ onInvalidCapture: true })\n    }\n  },\n  keyDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyDown: true }),\n      captured: keyOf({ onKeyDownCapture: true })\n    }\n  },\n  keyPress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyPress: true }),\n      captured: keyOf({ onKeyPressCapture: true })\n    }\n  },\n  keyUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyUp: true }),\n      captured: keyOf({ onKeyUpCapture: true })\n    }\n  },\n  load: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoad: true }),\n      captured: keyOf({ onLoadCapture: true })\n    }\n  },\n  loadedData: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedData: true }),\n      captured: keyOf({ onLoadedDataCapture: true })\n    }\n  },\n  loadedMetadata: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedMetadata: true }),\n      captured: keyOf({ onLoadedMetadataCapture: true })\n    }\n  },\n  loadStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadStart: true }),\n      captured: keyOf({ onLoadStartCapture: true })\n    }\n  },\n  // Note: We do not allow listening to mouseOver events. Instead, use the\n  // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`.\n  mouseDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseDown: true }),\n      captured: keyOf({ onMouseDownCapture: true })\n    }\n  },\n  mouseMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseMove: true }),\n      captured: keyOf({ onMouseMoveCapture: true })\n    }\n  },\n  mouseOut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOut: true }),\n      captured: keyOf({ onMouseOutCapture: true })\n    }\n  },\n  mouseOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOver: true }),\n      captured: keyOf({ onMouseOverCapture: true })\n    }\n  },\n  mouseUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseUp: true }),\n      captured: keyOf({ onMouseUpCapture: true })\n    }\n  },\n  paste: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPaste: true }),\n      captured: keyOf({ onPasteCapture: true })\n    }\n  },\n  pause: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPause: true }),\n      captured: keyOf({ onPauseCapture: true })\n    }\n  },\n  play: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlay: true }),\n      captured: keyOf({ onPlayCapture: true })\n    }\n  },\n  playing: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlaying: true }),\n      captured: keyOf({ onPlayingCapture: true })\n    }\n  },\n  progress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onProgress: true }),\n      captured: keyOf({ onProgressCapture: true })\n    }\n  },\n  rateChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onRateChange: true }),\n      captured: keyOf({ onRateChangeCapture: true })\n    }\n  },\n  reset: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onReset: true }),\n      captured: keyOf({ onResetCapture: true })\n    }\n  },\n  scroll: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onScroll: true }),\n      captured: keyOf({ onScrollCapture: true })\n    }\n  },\n  seeked: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeked: true }),\n      captured: keyOf({ onSeekedCapture: true })\n    }\n  },\n  seeking: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeking: true }),\n      captured: keyOf({ onSeekingCapture: true })\n    }\n  },\n  stalled: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onStalled: true }),\n      captured: keyOf({ onStalledCapture: true })\n    }\n  },\n  submit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSubmit: true }),\n      captured: keyOf({ onSubmitCapture: true })\n    }\n  },\n  suspend: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSuspend: true }),\n      captured: keyOf({ onSuspendCapture: true })\n    }\n  },\n  timeUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTimeUpdate: true }),\n      captured: keyOf({ onTimeUpdateCapture: true })\n    }\n  },\n  touchCancel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchCancel: true }),\n      captured: keyOf({ onTouchCancelCapture: true })\n    }\n  },\n  touchEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchEnd: true }),\n      captured: keyOf({ onTouchEndCapture: true })\n    }\n  },\n  touchMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchMove: true }),\n      captured: keyOf({ onTouchMoveCapture: true })\n    }\n  },\n  touchStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchStart: true }),\n      captured: keyOf({ onTouchStartCapture: true })\n    }\n  },\n  transitionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTransitionEnd: true }),\n      captured: keyOf({ onTransitionEndCapture: true })\n    }\n  },\n  volumeChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onVolumeChange: true }),\n      captured: keyOf({ onVolumeChangeCapture: true })\n    }\n  },\n  waiting: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWaiting: true }),\n      captured: keyOf({ onWaitingCapture: true })\n    }\n  },\n  wheel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWheel: true }),\n      captured: keyOf({ onWheelCapture: true })\n    }\n  }\n};\n\nvar topLevelEventsToDispatchConfig = {\n  topAbort: eventTypes.abort,\n  topAnimationEnd: eventTypes.animationEnd,\n  topAnimationIteration: eventTypes.animationIteration,\n  topAnimationStart: eventTypes.animationStart,\n  topBlur: eventTypes.blur,\n  topCanPlay: eventTypes.canPlay,\n  topCanPlayThrough: eventTypes.canPlayThrough,\n  topClick: eventTypes.click,\n  topContextMenu: eventTypes.contextMenu,\n  topCopy: eventTypes.copy,\n  topCut: eventTypes.cut,\n  topDoubleClick: eventTypes.doubleClick,\n  topDrag: eventTypes.drag,\n  topDragEnd: eventTypes.dragEnd,\n  topDragEnter: eventTypes.dragEnter,\n  topDragExit: eventTypes.dragExit,\n  topDragLeave: eventTypes.dragLeave,\n  topDragOver: eventTypes.dragOver,\n  topDragStart: eventTypes.dragStart,\n  topDrop: eventTypes.drop,\n  topDurationChange: eventTypes.durationChange,\n  topEmptied: eventTypes.emptied,\n  topEncrypted: eventTypes.encrypted,\n  topEnded: eventTypes.ended,\n  topError: eventTypes.error,\n  topFocus: eventTypes.focus,\n  topInput: eventTypes.input,\n  topInvalid: eventTypes.invalid,\n  topKeyDown: eventTypes.keyDown,\n  topKeyPress: eventTypes.keyPress,\n  topKeyUp: eventTypes.keyUp,\n  topLoad: eventTypes.load,\n  topLoadedData: eventTypes.loadedData,\n  topLoadedMetadata: eventTypes.loadedMetadata,\n  topLoadStart: eventTypes.loadStart,\n  topMouseDown: eventTypes.mouseDown,\n  topMouseMove: eventTypes.mouseMove,\n  topMouseOut: eventTypes.mouseOut,\n  topMouseOver: eventTypes.mouseOver,\n  topMouseUp: eventTypes.mouseUp,\n  topPaste: eventTypes.paste,\n  topPause: eventTypes.pause,\n  topPlay: eventTypes.play,\n  topPlaying: eventTypes.playing,\n  topProgress: eventTypes.progress,\n  topRateChange: eventTypes.rateChange,\n  topReset: eventTypes.reset,\n  topScroll: eventTypes.scroll,\n  topSeeked: eventTypes.seeked,\n  topSeeking: eventTypes.seeking,\n  topStalled: eventTypes.stalled,\n  topSubmit: eventTypes.submit,\n  topSuspend: eventTypes.suspend,\n  topTimeUpdate: eventTypes.timeUpdate,\n  topTouchCancel: eventTypes.touchCancel,\n  topTouchEnd: eventTypes.touchEnd,\n  topTouchMove: eventTypes.touchMove,\n  topTouchStart: eventTypes.touchStart,\n  topTransitionEnd: eventTypes.transitionEnd,\n  topVolumeChange: eventTypes.volumeChange,\n  topWaiting: eventTypes.waiting,\n  topWheel: eventTypes.wheel\n};\n\nfor (var type in topLevelEventsToDispatchConfig) {\n  topLevelEventsToDispatchConfig[type].dependencies = [type];\n}\n\nvar ON_CLICK_KEY = keyOf({ onClick: null });\nvar onClickListeners = {};\n\nvar SimpleEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];\n    if (!dispatchConfig) {\n      return null;\n    }\n    var EventConstructor;\n    switch (topLevelType) {\n      case topLevelTypes.topAbort:\n      case topLevelTypes.topCanPlay:\n      case topLevelTypes.topCanPlayThrough:\n      case topLevelTypes.topDurationChange:\n      case topLevelTypes.topEmptied:\n      case topLevelTypes.topEncrypted:\n      case topLevelTypes.topEnded:\n      case topLevelTypes.topError:\n      case topLevelTypes.topInput:\n      case topLevelTypes.topInvalid:\n      case topLevelTypes.topLoad:\n      case topLevelTypes.topLoadedData:\n      case topLevelTypes.topLoadedMetadata:\n      case topLevelTypes.topLoadStart:\n      case topLevelTypes.topPause:\n      case topLevelTypes.topPlay:\n      case topLevelTypes.topPlaying:\n      case topLevelTypes.topProgress:\n      case topLevelTypes.topRateChange:\n      case topLevelTypes.topReset:\n      case topLevelTypes.topSeeked:\n      case topLevelTypes.topSeeking:\n      case topLevelTypes.topStalled:\n      case topLevelTypes.topSubmit:\n      case topLevelTypes.topSuspend:\n      case topLevelTypes.topTimeUpdate:\n      case topLevelTypes.topVolumeChange:\n      case topLevelTypes.topWaiting:\n        // HTML Events\n        // @see http://www.w3.org/TR/html5/index.html#events-0\n        EventConstructor = SyntheticEvent;\n        break;\n      case topLevelTypes.topKeyPress:\n        // Firefox creates a keypress event for function keys too. This removes\n        // the unwanted keypress events. Enter is however both printable and\n        // non-printable. One would expect Tab to be as well (but it isn't).\n        if (getEventCharCode(nativeEvent) === 0) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        EventConstructor = SyntheticKeyboardEvent;\n        break;\n      case topLevelTypes.topBlur:\n      case topLevelTypes.topFocus:\n        EventConstructor = SyntheticFocusEvent;\n        break;\n      case topLevelTypes.topClick:\n        // Firefox creates a click event on right mouse clicks. This removes the\n        // unwanted click events.\n        if (nativeEvent.button === 2) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topDoubleClick:\n      case topLevelTypes.topMouseDown:\n      case topLevelTypes.topMouseMove:\n      case topLevelTypes.topMouseOut:\n      case topLevelTypes.topMouseOver:\n      case topLevelTypes.topMouseUp:\n        EventConstructor = SyntheticMouseEvent;\n        break;\n      case topLevelTypes.topDrag:\n      case topLevelTypes.topDragEnd:\n      case topLevelTypes.topDragEnter:\n      case topLevelTypes.topDragExit:\n      case topLevelTypes.topDragLeave:\n      case topLevelTypes.topDragOver:\n      case topLevelTypes.topDragStart:\n      case topLevelTypes.topDrop:\n        EventConstructor = SyntheticDragEvent;\n        break;\n      case topLevelTypes.topTouchCancel:\n      case topLevelTypes.topTouchEnd:\n      case topLevelTypes.topTouchMove:\n      case topLevelTypes.topTouchStart:\n        EventConstructor = SyntheticTouchEvent;\n        break;\n      case topLevelTypes.topAnimationEnd:\n      case topLevelTypes.topAnimationIteration:\n      case topLevelTypes.topAnimationStart:\n        EventConstructor = SyntheticAnimationEvent;\n        break;\n      case topLevelTypes.topTransitionEnd:\n        EventConstructor = SyntheticTransitionEvent;\n        break;\n      case topLevelTypes.topScroll:\n        EventConstructor = SyntheticUIEvent;\n        break;\n      case topLevelTypes.topWheel:\n        EventConstructor = SyntheticWheelEvent;\n        break;\n      case topLevelTypes.topCopy:\n      case topLevelTypes.topCut:\n      case topLevelTypes.topPaste:\n        EventConstructor = SyntheticClipboardEvent;\n        break;\n    }\n    !EventConstructor ? \"development\" !== 'production' ? invariant(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : _prodInvariant('86', topLevelType) : void 0;\n    var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);\n    EventPropagators.accumulateTwoPhaseDispatches(event);\n    return event;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    // Mobile Safari does not fire properly bubble click events on\n    // non-interactive elements, which means delegated click listeners do not\n    // fire. The workaround for this bug involves attaching an empty click\n    // listener on the target node.\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      if (!onClickListeners[id]) {\n        onClickListeners[id] = EventListener.listen(node, 'click', emptyFunction);\n      }\n    }\n  },\n\n  willDeleteListener: function (inst, registrationName) {\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      onClickListeners[id].remove();\n      delete onClickListeners[id];\n    }\n  }\n\n};\n\nmodule.exports = SimpleEventPlugin;\n},{\"100\":100,\"101\":101,\"103\":103,\"104\":104,\"105\":105,\"107\":107,\"108\":108,\"109\":109,\"110\":110,\"111\":111,\"112\":112,\"125\":125,\"139\":139,\"146\":146,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"20\":20,\"41\":41}],100:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticAnimationEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface\n * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent\n */\nvar AnimationEventInterface = {\n  animationName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);\n\nmodule.exports = SyntheticAnimationEvent;\n},{\"104\":104}],101:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticClipboardEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/clipboard-apis/\n */\nvar ClipboardEventInterface = {\n  clipboardData: function (event) {\n    return 'clipboardData' in event ? event.clipboardData : window.clipboardData;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);\n\nmodule.exports = SyntheticClipboardEvent;\n},{\"104\":104}],102:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticCompositionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents\n */\nvar CompositionEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);\n\nmodule.exports = SyntheticCompositionEvent;\n},{\"104\":104}],103:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticDragEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface DragEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar DragEventInterface = {\n  dataTransfer: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);\n\nmodule.exports = SyntheticDragEvent;\n},{\"108\":108}],104:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticEvent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar didWarnForAddedNewProperty = false;\nvar isProxySupported = typeof Proxy === 'function';\n\nvar shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar EventInterface = {\n  type: null,\n  target: null,\n  // currentTarget is set when dispatching; no use in copying it here\n  currentTarget: emptyFunction.thatReturnsNull,\n  eventPhase: null,\n  bubbles: null,\n  cancelable: null,\n  timeStamp: function (event) {\n    return event.timeStamp || Date.now();\n  },\n  defaultPrevented: null,\n  isTrusted: null\n};\n\n/**\n * Synthetic events are dispatched by event plugins, typically in response to a\n * top-level event delegation handler.\n *\n * These systems should generally use pooling to reduce the frequency of garbage\n * collection. The system should check `isPersistent` to determine whether the\n * event should be released into the pool after being dispatched. Users that\n * need a persisted event should invoke `persist`.\n *\n * Synthetic events (and subclasses) implement the DOM Level 3 Events API by\n * normalizing browser quirks. Subclasses do not necessarily have to implement a\n * DOM interface; custom application-specific events can also subclass this.\n *\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {*} targetInst Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @param {DOMEventTarget} nativeEventTarget Target node.\n */\nfunction SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {\n  if (\"development\" !== 'production') {\n    // these have a getter/setter for warnings\n    delete this.nativeEvent;\n    delete this.preventDefault;\n    delete this.stopPropagation;\n  }\n\n  this.dispatchConfig = dispatchConfig;\n  this._targetInst = targetInst;\n  this.nativeEvent = nativeEvent;\n\n  var Interface = this.constructor.Interface;\n  for (var propName in Interface) {\n    if (!Interface.hasOwnProperty(propName)) {\n      continue;\n    }\n    if (\"development\" !== 'production') {\n      delete this[propName]; // this has a getter/setter for warnings\n    }\n    var normalize = Interface[propName];\n    if (normalize) {\n      this[propName] = normalize(nativeEvent);\n    } else {\n      if (propName === 'target') {\n        this.target = nativeEventTarget;\n      } else {\n        this[propName] = nativeEvent[propName];\n      }\n    }\n  }\n\n  var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;\n  if (defaultPrevented) {\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  } else {\n    this.isDefaultPrevented = emptyFunction.thatReturnsFalse;\n  }\n  this.isPropagationStopped = emptyFunction.thatReturnsFalse;\n  return this;\n}\n\n_assign(SyntheticEvent.prototype, {\n\n  preventDefault: function () {\n    this.defaultPrevented = true;\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.preventDefault) {\n      event.preventDefault();\n    } else {\n      event.returnValue = false;\n    }\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  },\n\n  stopPropagation: function () {\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.stopPropagation) {\n      event.stopPropagation();\n    } else {\n      event.cancelBubble = true;\n    }\n    this.isPropagationStopped = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * We release all dispatched `SyntheticEvent`s after each event loop, adding\n   * them back into the pool. This allows a way to hold onto a reference that\n   * won't be added back into the pool.\n   */\n  persist: function () {\n    this.isPersistent = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * Checks if this event should be released back into the pool.\n   *\n   * @return {boolean} True if this should not be released, false otherwise.\n   */\n  isPersistent: emptyFunction.thatReturnsFalse,\n\n  /**\n   * `PooledClass` looks for `destructor` on each instance it releases.\n   */\n  destructor: function () {\n    var Interface = this.constructor.Interface;\n    for (var propName in Interface) {\n      if (\"development\" !== 'production') {\n        Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));\n      } else {\n        this[propName] = null;\n      }\n    }\n    for (var i = 0; i < shouldBeReleasedProperties.length; i++) {\n      this[shouldBeReleasedProperties[i]] = null;\n    }\n    if (\"development\" !== 'production') {\n      Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));\n      Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction));\n      Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction));\n    }\n  }\n\n});\n\nSyntheticEvent.Interface = EventInterface;\n\nif (\"development\" !== 'production') {\n  if (isProxySupported) {\n    /*eslint-disable no-func-assign */\n    SyntheticEvent = new Proxy(SyntheticEvent, {\n      construct: function (target, args) {\n        return this.apply(target, Object.create(target.prototype), args);\n      },\n      apply: function (constructor, that, args) {\n        return new Proxy(constructor.apply(that, args), {\n          set: function (target, prop, value) {\n            if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {\n              \"development\" !== 'production' ? warning(didWarnForAddedNewProperty || target.isPersistent(), 'This synthetic event is reused for performance reasons. If you\\'re ' + 'seeing this, you\\'re adding a new property in the synthetic event object. ' + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;\n              didWarnForAddedNewProperty = true;\n            }\n            target[prop] = value;\n            return true;\n          }\n        });\n      }\n    });\n    /*eslint-enable no-func-assign */\n  }\n}\n/**\n * Helper to reduce boilerplate when creating subclasses.\n *\n * @param {function} Class\n * @param {?object} Interface\n */\nSyntheticEvent.augmentClass = function (Class, Interface) {\n  var Super = this;\n\n  var E = function () {};\n  E.prototype = Super.prototype;\n  var prototype = new E();\n\n  _assign(prototype, Class.prototype);\n  Class.prototype = prototype;\n  Class.prototype.constructor = Class;\n\n  Class.Interface = _assign({}, Super.Interface, Interface);\n  Class.augmentClass = Super.augmentClass;\n\n  PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);\n};\n\nPooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);\n\nmodule.exports = SyntheticEvent;\n\n/**\n  * Helper to nullify syntheticEvent instance properties when destructing\n  *\n  * @param {object} SyntheticEvent\n  * @param {String} propName\n  * @return {object} defineProperty object\n  */\nfunction getPooledWarningPropertyDefinition(propName, getVal) {\n  var isFunction = typeof getVal === 'function';\n  return {\n    configurable: true,\n    set: set,\n    get: get\n  };\n\n  function set(val) {\n    var action = isFunction ? 'setting the method' : 'setting the property';\n    warn(action, 'This is effectively a no-op');\n    return val;\n  }\n\n  function get() {\n    var action = isFunction ? 'accessing the method' : 'accessing the property';\n    var result = isFunction ? 'This is a no-op function' : 'This is set to null';\n    warn(action, result);\n    return getVal;\n  }\n\n  function warn(action, result) {\n    var warningCondition = false;\n    \"development\" !== 'production' ? warning(warningCondition, 'This synthetic event is reused for performance reasons. If you\\'re seeing this, ' + 'you\\'re %s `%s` on a released/nullified synthetic event. %s. ' + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;\n  }\n}\n},{\"153\":153,\"171\":171,\"172\":172,\"25\":25}],105:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticFocusEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\n/**\n * @interface FocusEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar FocusEventInterface = {\n  relatedTarget: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);\n\nmodule.exports = SyntheticFocusEvent;\n},{\"111\":111}],106:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticInputEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105\n *      /#events-inputevents\n */\nvar InputEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface);\n\nmodule.exports = SyntheticInputEvent;\n},{\"104\":104}],107:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticKeyboardEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventCharCode = _dereq_(125);\nvar getEventKey = _dereq_(126);\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface KeyboardEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar KeyboardEventInterface = {\n  key: getEventKey,\n  location: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  repeat: null,\n  locale: null,\n  getModifierState: getEventModifierState,\n  // Legacy Interface\n  charCode: function (event) {\n    // `charCode` is the result of a KeyPress event and represents the value of\n    // the actual printable character.\n\n    // KeyPress is deprecated, but its replacement is not yet final and not\n    // implemented in any major browser. Only KeyPress has charCode.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    return 0;\n  },\n  keyCode: function (event) {\n    // `keyCode` is the result of a KeyDown/Up event and represents the value of\n    // physical keyboard key.\n\n    // The actual meaning of the value depends on the users' keyboard layout\n    // which cannot be detected. Assuming that it is a US keyboard layout\n    // provides a surprisingly accurate mapping for US and European users.\n    // Due to this, it is left to the user to implement at this time.\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  },\n  which: function (event) {\n    // `which` is an alias for either `keyCode` or `charCode` depending on the\n    // type of the event.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);\n\nmodule.exports = SyntheticKeyboardEvent;\n},{\"111\":111,\"125\":125,\"126\":126,\"127\":127}],108:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticMouseEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\nvar ViewportMetrics = _dereq_(114);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface MouseEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar MouseEventInterface = {\n  screenX: null,\n  screenY: null,\n  clientX: null,\n  clientY: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  getModifierState: getEventModifierState,\n  button: function (event) {\n    // Webkit, Firefox, IE9+\n    // which:  1 2 3\n    // button: 0 1 2 (standard)\n    var button = event.button;\n    if ('which' in event) {\n      return button;\n    }\n    // IE<9\n    // which:  undefined\n    // button: 0 0 0\n    // button: 1 4 2 (onmouseup)\n    return button === 2 ? 2 : button === 4 ? 1 : 0;\n  },\n  buttons: null,\n  relatedTarget: function (event) {\n    return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);\n  },\n  // \"Proprietary\" Interface.\n  pageX: function (event) {\n    return 'pageX' in event ? event.pageX : event.clientX + ViewportMetrics.currentScrollLeft;\n  },\n  pageY: function (event) {\n    return 'pageY' in event ? event.pageY : event.clientY + ViewportMetrics.currentScrollTop;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);\n\nmodule.exports = SyntheticMouseEvent;\n},{\"111\":111,\"114\":114,\"127\":127}],109:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTouchEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface TouchEvent\n * @see http://www.w3.org/TR/touch-events/\n */\nvar TouchEventInterface = {\n  touches: null,\n  targetTouches: null,\n  changedTouches: null,\n  altKey: null,\n  metaKey: null,\n  ctrlKey: null,\n  shiftKey: null,\n  getModifierState: getEventModifierState\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);\n\nmodule.exports = SyntheticTouchEvent;\n},{\"111\":111,\"127\":127}],110:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTransitionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent\n */\nvar TransitionEventInterface = {\n  propertyName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);\n\nmodule.exports = SyntheticTransitionEvent;\n},{\"104\":104}],111:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticUIEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\n\n/**\n * @interface UIEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar UIEventInterface = {\n  view: function (event) {\n    if (event.view) {\n      return event.view;\n    }\n\n    var target = getEventTarget(event);\n    if (target.window === target) {\n      // target is a window object\n      return target;\n    }\n\n    var doc = target.ownerDocument;\n    // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n    if (doc) {\n      return doc.defaultView || doc.parentWindow;\n    } else {\n      return window;\n    }\n  },\n  detail: function (event) {\n    return event.detail || 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);\n\nmodule.exports = SyntheticUIEvent;\n},{\"104\":104,\"128\":128}],112:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticWheelEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface WheelEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar WheelEventInterface = {\n  deltaX: function (event) {\n    return 'deltaX' in event ? event.deltaX :\n    // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).\n    'wheelDeltaX' in event ? -event.wheelDeltaX : 0;\n  },\n  deltaY: function (event) {\n    return 'deltaY' in event ? event.deltaY :\n    // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).\n    'wheelDeltaY' in event ? -event.wheelDeltaY :\n    // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).\n    'wheelDelta' in event ? -event.wheelDelta : 0;\n  },\n  deltaZ: null,\n\n  // Browsers without \"deltaMode\" is reporting in raw wheel delta where one\n  // notch on the scroll is always +/- 120, roughly equivalent to pixels.\n  // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or\n  // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.\n  deltaMode: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticMouseEvent}\n */\nfunction SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);\n\nmodule.exports = SyntheticWheelEvent;\n},{\"108\":108}],113:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Transaction\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * `Transaction` creates a black box that is able to wrap any method such that\n * certain invariants are maintained before and after the method is invoked\n * (Even if an exception is thrown while invoking the wrapped method). Whoever\n * instantiates a transaction can provide enforcers of the invariants at\n * creation time. The `Transaction` class itself will supply one additional\n * automatic invariant for you - the invariant that any transaction instance\n * should not be run while it is already being run. You would typically create a\n * single instance of a `Transaction` for reuse multiple times, that potentially\n * is used to wrap several different methods. Wrappers are extremely simple -\n * they only require implementing two methods.\n *\n * <pre>\n *                       wrappers (injected at creation time)\n *                                      +        +\n *                                      |        |\n *                    +-----------------|--------|--------------+\n *                    |                 v        |              |\n *                    |      +---------------+   |              |\n *                    |   +--|    wrapper1   |---|----+         |\n *                    |   |  +---------------+   v    |         |\n *                    |   |          +-------------+  |         |\n *                    |   |     +----|   wrapper2  |--------+   |\n *                    |   |     |    +-------------+  |     |   |\n *                    |   |     |                     |     |   |\n *                    |   v     v                     v     v   | wrapper\n *                    | +---+ +---+   +---------+   +---+ +---+ | invariants\n * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained\n * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | +---+ +---+   +---------+   +---+ +---+ |\n *                    |  initialize                    close    |\n *                    +-----------------------------------------+\n * </pre>\n *\n * Use cases:\n * - Preserving the input selection ranges before/after reconciliation.\n *   Restoring selection even in the event of an unexpected error.\n * - Deactivating events while rearranging the DOM, preventing blurs/focuses,\n *   while guaranteeing that afterwards, the event system is reactivated.\n * - Flushing a queue of collected DOM mutations to the main UI thread after a\n *   reconciliation takes place in a worker thread.\n * - Invoking any collected `componentDidUpdate` callbacks after rendering new\n *   content.\n * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue\n *   to preserve the `scrollTop` (an automatic scroll aware DOM).\n * - (Future use case): Layout calculations before and after DOM updates.\n *\n * Transactional plugin API:\n * - A module that has an `initialize` method that returns any precomputation.\n * - and a `close` method that accepts the precomputation. `close` is invoked\n *   when the wrapped process is completed, or has failed.\n *\n * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules\n * that implement `initialize` and `close`.\n * @return {Transaction} Single transaction for reuse in thread.\n *\n * @class Transaction\n */\nvar Mixin = {\n  /**\n   * Sets up this instance so that it is prepared for collecting metrics. Does\n   * so such that this setup method may be used on an instance that is already\n   * initialized, in a way that does not consume additional memory upon reuse.\n   * That can be useful if you decide to make your subclass of this mixin a\n   * \"PooledClass\".\n   */\n  reinitializeTransaction: function () {\n    this.transactionWrappers = this.getTransactionWrappers();\n    if (this.wrapperInitData) {\n      this.wrapperInitData.length = 0;\n    } else {\n      this.wrapperInitData = [];\n    }\n    this._isInTransaction = false;\n  },\n\n  _isInTransaction: false,\n\n  /**\n   * @abstract\n   * @return {Array<TransactionWrapper>} Array of transaction wrappers.\n   */\n  getTransactionWrappers: null,\n\n  isInTransaction: function () {\n    return !!this._isInTransaction;\n  },\n\n  /**\n   * Executes the function within a safety window. Use this for the top level\n   * methods that result in large amounts of computation/mutations that would\n   * need to be safety checked. The optional arguments helps prevent the need\n   * to bind in many cases.\n   *\n   * @param {function} method Member of scope to call.\n   * @param {Object} scope Scope to invoke from.\n   * @param {Object?=} a Argument to pass to the method.\n   * @param {Object?=} b Argument to pass to the method.\n   * @param {Object?=} c Argument to pass to the method.\n   * @param {Object?=} d Argument to pass to the method.\n   * @param {Object?=} e Argument to pass to the method.\n   * @param {Object?=} f Argument to pass to the method.\n   *\n   * @return {*} Return value from `method`.\n   */\n  perform: function (method, scope, a, b, c, d, e, f) {\n    !!this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.perform(...): Cannot initialize a transaction when there is already an outstanding transaction.') : _prodInvariant('27') : void 0;\n    var errorThrown;\n    var ret;\n    try {\n      this._isInTransaction = true;\n      // Catching errors makes debugging more difficult, so we start with\n      // errorThrown set to true before setting it to false after calling\n      // close -- if it's still set to true in the finally block, it means\n      // one of these calls threw.\n      errorThrown = true;\n      this.initializeAll(0);\n      ret = method.call(scope, a, b, c, d, e, f);\n      errorThrown = false;\n    } finally {\n      try {\n        if (errorThrown) {\n          // If `method` throws, prefer to show that stack trace over any thrown\n          // by invoking `closeAll`.\n          try {\n            this.closeAll(0);\n          } catch (err) {}\n        } else {\n          // Since `method` didn't throw, we don't want to silence the exception\n          // here.\n          this.closeAll(0);\n        }\n      } finally {\n        this._isInTransaction = false;\n      }\n    }\n    return ret;\n  },\n\n  initializeAll: function (startIndex) {\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      try {\n        // Catching errors makes debugging more difficult, so we start with the\n        // OBSERVED_ERROR state before overwriting it with the real return value\n        // of initialize -- if it's still set to OBSERVED_ERROR in the finally\n        // block, it means wrapper.initialize threw.\n        this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;\n        this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null;\n      } finally {\n        if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {\n          // The initializer for wrapper i threw an error; initialize the\n          // remaining wrappers but silence any exceptions from them to ensure\n          // that the first error is the one to bubble up.\n          try {\n            this.initializeAll(i + 1);\n          } catch (err) {}\n        }\n      }\n    }\n  },\n\n  /**\n   * Invokes each of `this.transactionWrappers.close[i]` functions, passing into\n   * them the respective return values of `this.transactionWrappers.init[i]`\n   * (`close`rs that correspond to initializers that failed will not be\n   * invoked).\n   */\n  closeAll: function (startIndex) {\n    !this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') : _prodInvariant('28') : void 0;\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      var initData = this.wrapperInitData[i];\n      var errorThrown;\n      try {\n        // Catching errors makes debugging more difficult, so we start with\n        // errorThrown set to true before setting it to false after calling\n        // close -- if it's still set to true in the finally block, it means\n        // wrapper.close threw.\n        errorThrown = true;\n        if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) {\n          wrapper.close.call(this, initData);\n        }\n        errorThrown = false;\n      } finally {\n        if (errorThrown) {\n          // The closer for wrapper i threw an error; close the remaining\n          // wrappers but silence any exceptions from them to ensure that the\n          // first error is the one to bubble up.\n          try {\n            this.closeAll(i + 1);\n          } catch (e) {}\n        }\n      }\n    }\n    this.wrapperInitData.length = 0;\n  }\n};\n\nvar Transaction = {\n\n  Mixin: Mixin,\n\n  /**\n   * Token to look for to determine if an error occurred.\n   */\n  OBSERVED_ERROR: {}\n\n};\n\nmodule.exports = Transaction;\n},{\"139\":139,\"161\":161}],114:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ViewportMetrics\n */\n\n'use strict';\n\nvar ViewportMetrics = {\n\n  currentScrollLeft: 0,\n\n  currentScrollTop: 0,\n\n  refreshScrollValues: function (scrollPosition) {\n    ViewportMetrics.currentScrollLeft = scrollPosition.x;\n    ViewportMetrics.currentScrollTop = scrollPosition.y;\n  }\n\n};\n\nmodule.exports = ViewportMetrics;\n},{}],115:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule accumulateInto\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Accumulates items that must not be null or undefined into the first one. This\n * is used to conserve memory by avoiding array allocations, and thus sacrifices\n * API cleanness. Since `current` can be null before being passed in and not\n * null after this function, make sure to assign it back to `current`:\n *\n * `a = accumulateInto(a, b);`\n *\n * This API should be sparingly used. Try `accumulate` for something cleaner.\n *\n * @return {*|array<*>} An accumulation of items.\n */\n\nfunction accumulateInto(current, next) {\n  !(next != null) ? \"development\" !== 'production' ? invariant(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : _prodInvariant('30') : void 0;\n\n  if (current == null) {\n    return next;\n  }\n\n  // Both are not empty. Warning: Never call x.concat(y) when you are not\n  // certain that x is an Array (x could be a string with concat method).\n  if (Array.isArray(current)) {\n    if (Array.isArray(next)) {\n      current.push.apply(current, next);\n      return current;\n    }\n    current.push(next);\n    return current;\n  }\n\n  if (Array.isArray(next)) {\n    // A bit too dangerous to mutate `next`.\n    return [current].concat(next);\n  }\n\n  return [current, next];\n}\n\nmodule.exports = accumulateInto;\n},{\"139\":139,\"161\":161}],116:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule adler32\n * \n */\n\n'use strict';\n\nvar MOD = 65521;\n\n// adler32 is not cryptographically strong, and is only used to sanity check that\n// markup generated on the server matches the markup generated on the client.\n// This implementation (a modified version of the SheetJS version) has been optimized\n// for our use case, at the expense of conforming to the adler32 specification\n// for non-ascii inputs.\nfunction adler32(data) {\n  var a = 1;\n  var b = 0;\n  var i = 0;\n  var l = data.length;\n  var m = l & ~0x3;\n  while (i < m) {\n    var n = Math.min(i + 4096, m);\n    for (; i < n; i += 4) {\n      b += (a += data.charCodeAt(i)) + (a += data.charCodeAt(i + 1)) + (a += data.charCodeAt(i + 2)) + (a += data.charCodeAt(i + 3));\n    }\n    a %= MOD;\n    b %= MOD;\n  }\n  for (; i < l; i++) {\n    b += a += data.charCodeAt(i);\n  }\n  a %= MOD;\n  b %= MOD;\n  return a | b << 16;\n}\n\nmodule.exports = adler32;\n},{}],117:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule canDefineProperty\n */\n\n'use strict';\n\nvar canDefineProperty = false;\nif (\"development\" !== 'production') {\n  try {\n    Object.defineProperty({}, 'x', { get: function () {} });\n    canDefineProperty = true;\n  } catch (x) {\n    // IE will fail on defineProperty\n  }\n}\n\nmodule.exports = canDefineProperty;\n},{}],118:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule checkReactTypeSpec\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar loggedTypeFailures = {};\n\n/**\n * Assert that the values match with the type specs.\n * Error messages are memorized and will only be shown once.\n *\n * @param {object} typeSpecs Map of name to a ReactPropType\n * @param {object} values Runtime values that need to be type-checked\n * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n * @param {string} componentName Name of the component for error messages.\n * @param {?object} element The React element that is being type-checked\n * @param {?number} debugID The React component instance that is being type-checked\n * @private\n */\nfunction checkReactTypeSpec(typeSpecs, values, location, componentName, element, debugID) {\n  for (var typeSpecName in typeSpecs) {\n    if (typeSpecs.hasOwnProperty(typeSpecName)) {\n      var error;\n      // Prop type validation may throw. In case they do, we don't want to\n      // fail the render phase where it didn't fail before. So we log it.\n      // After these have been cleaned up, we'll let them throw.\n      try {\n        // This is intentionally an invariant that gets caught. It's the same\n        // behavior as without this statement except with a better message.\n        !(typeof typeSpecs[typeSpecName] === 'function') ? \"development\" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : _prodInvariant('84', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : void 0;\n        error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location);\n      } catch (ex) {\n        error = ex;\n      }\n      \"development\" !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName, typeof error) : void 0;\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var componentStackInfo = '';\n\n        if (\"development\" !== 'production') {\n          var ReactComponentTreeDevtool = _dereq_(34);\n          if (debugID !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getStackAddendumByID(debugID);\n          } else if (element !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getCurrentStackAddendum(element);\n          }\n        }\n\n        \"development\" !== 'production' ? warning(false, 'Failed %s type: %s%s', location, error.message, componentStackInfo) : void 0;\n      }\n    }\n  }\n}\n\nmodule.exports = checkReactTypeSpec;\n},{\"139\":139,\"161\":161,\"171\":171,\"34\":34,\"83\":83}],119:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule createMicrosoftUnsafeLocalFunction\n */\n\n/* globals MSApp */\n\n'use strict';\n\n/**\n * Create a function which has 'unsafe' privileges (required by windows8 apps)\n */\n\nvar createMicrosoftUnsafeLocalFunction = function (func) {\n  if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {\n    return function (arg0, arg1, arg2, arg3) {\n      MSApp.execUnsafeLocalFunction(function () {\n        return func(arg0, arg1, arg2, arg3);\n      });\n    };\n  } else {\n    return func;\n  }\n};\n\nmodule.exports = createMicrosoftUnsafeLocalFunction;\n},{}],120:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule dangerousStyleValue\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar warning = _dereq_(171);\n\nvar isUnitlessNumber = CSSProperty.isUnitlessNumber;\nvar styleWarnings = {};\n\n/**\n * Convert a value into the proper css writable value. The style name `name`\n * should be logical (no hyphens), as specified\n * in `CSSProperty.isUnitlessNumber`.\n *\n * @param {string} name CSS property name such as `topMargin`.\n * @param {*} value CSS property value such as `10px`.\n * @param {ReactDOMComponent} component\n * @return {string} Normalized style value with dimensions applied.\n */\nfunction dangerousStyleValue(name, value, component) {\n  // Note that we've removed escapeTextForBrowser() calls here since the\n  // whole string will be escaped when the attribute is injected into\n  // the markup. If you provide unsafe user data here they can inject\n  // arbitrary CSS which may be problematic (I couldn't repro this):\n  // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet\n  // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/\n  // This is not an XSS hole but instead a potential CSS injection issue\n  // which has lead to a greater discussion about how we're going to\n  // trust URLs moving forward. See #2115901\n\n  var isEmpty = value == null || typeof value === 'boolean' || value === '';\n  if (isEmpty) {\n    return '';\n  }\n\n  var isNonNumeric = isNaN(value);\n  if (isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {\n    return '' + value; // cast to string\n  }\n\n  if (typeof value === 'string') {\n    if (\"development\" !== 'production') {\n      // Allow '0' to pass through without warning. 0 is already special and\n      // doesn't require units, so we don't need to warn about it.\n      if (component && value !== '0') {\n        var owner = component._currentElement._owner;\n        var ownerName = owner ? owner.getName() : null;\n        if (ownerName && !styleWarnings[ownerName]) {\n          styleWarnings[ownerName] = {};\n        }\n        var warned = false;\n        if (ownerName) {\n          var warnings = styleWarnings[ownerName];\n          warned = warnings[name];\n          if (!warned) {\n            warnings[name] = true;\n          }\n        }\n        if (!warned) {\n          \"development\" !== 'production' ? warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' + 'for CSS property `%s` (value: `%s`) which will be treated ' + 'as a unitless number in a future version of React.', component._currentElement.type, ownerName || 'unknown', name, value) : void 0;\n        }\n      }\n    }\n    value = value.trim();\n  }\n  return value + 'px';\n}\n\nmodule.exports = dangerousStyleValue;\n},{\"171\":171,\"3\":3}],121:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * Based on the escape-html library, which is used under the MIT License below:\n *\n * Copyright (c) 2012-2013 TJ Holowaychuk\n * Copyright (c) 2015 Andreas Lubbe\n * Copyright (c) 2015 Tiancheng \"Timothy\" Gu\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * @providesModule escapeTextContentForBrowser\n */\n\n'use strict';\n\n// code copied and modified from escape-html\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param  {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n  var str = '' + string;\n  var match = matchHtmlRegExp.exec(str);\n\n  if (!match) {\n    return str;\n  }\n\n  var escape;\n  var html = '';\n  var index = 0;\n  var lastIndex = 0;\n\n  for (index = match.index; index < str.length; index++) {\n    switch (str.charCodeAt(index)) {\n      case 34:\n        // \"\n        escape = '&quot;';\n        break;\n      case 38:\n        // &\n        escape = '&amp;';\n        break;\n      case 39:\n        // '\n        escape = '&#x27;'; // modified from escape-html; used to be '&#39'\n        break;\n      case 60:\n        // <\n        escape = '&lt;';\n        break;\n      case 62:\n        // >\n        escape = '&gt;';\n        break;\n      default:\n        continue;\n    }\n\n    if (lastIndex !== index) {\n      html += str.substring(lastIndex, index);\n    }\n\n    lastIndex = index + 1;\n    html += escape;\n  }\n\n  return lastIndex !== index ? html + str.substring(lastIndex, index) : html;\n}\n// end code copied and modified from escape-html\n\n/**\n * Escapes text to prevent scripting attacks.\n *\n * @param {*} text Text value to escape.\n * @return {string} An escaped string.\n */\nfunction escapeTextContentForBrowser(text) {\n  if (typeof text === 'boolean' || typeof text === 'number') {\n    // this shortcircuit helps perf for types that we know will never have\n    // special characters, especially given that this function is used often\n    // for numeric dom ids.\n    return '' + text;\n  }\n  return escapeHtml(text);\n}\n\nmodule.exports = escapeTextContentForBrowser;\n},{}],122:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule findDOMNode\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstanceMap = _dereq_(73);\n\nvar getHostComponentFromComposite = _dereq_(129);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Returns the DOM node rendered by this element.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode\n *\n * @param {ReactComponent|DOMElement} componentOrElement\n * @return {?DOMElement} The root node of this element.\n */\nfunction findDOMNode(componentOrElement) {\n  if (\"development\" !== 'production') {\n    var owner = ReactCurrentOwner.current;\n    if (owner !== null) {\n      \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n      owner._warnedAboutRefsInRender = true;\n    }\n  }\n  if (componentOrElement == null) {\n    return null;\n  }\n  if (componentOrElement.nodeType === 1) {\n    return componentOrElement;\n  }\n\n  var inst = ReactInstanceMap.get(componentOrElement);\n  if (inst) {\n    inst = getHostComponentFromComposite(inst);\n    return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null;\n  }\n\n  if (typeof componentOrElement.render === 'function') {\n    !false ? \"development\" !== 'production' ? invariant(false, 'findDOMNode was called on an unmounted component.') : _prodInvariant('44') : void 0;\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', Object.keys(componentOrElement)) : _prodInvariant('45', Object.keys(componentOrElement)) : void 0;\n  }\n}\n\nmodule.exports = findDOMNode;\n},{\"129\":129,\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"41\":41,\"73\":73}],123:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule flattenChildren\n * \n */\n\n'use strict';\n\nvar KeyEscapeUtils = _dereq_(23);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\n/**\n * @param {function} traverseContext Context passed through traversal.\n * @param {?ReactComponent} child React child component.\n * @param {!string} name String name of key path to child.\n * @param {number=} selfDebugID Optional debugID of the current internal instance.\n */\nfunction flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID) {\n  // We found a component instance.\n  if (traverseContext && typeof traverseContext === 'object') {\n    var result = traverseContext;\n    var keyUnique = result[name] === undefined;\n    if (\"development\" !== 'production') {\n      var ReactComponentTreeDevtool = _dereq_(34);\n      \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n    }\n    if (keyUnique && child != null) {\n      result[name] = child;\n    }\n  }\n}\n\n/**\n * Flattens children that are typically specified as `props.children`. Any null\n * children will not be included in the resulting object.\n * @return {!object} flattened children keyed by name.\n */\nfunction flattenChildren(children, selfDebugID) {\n  if (children == null) {\n    return children;\n  }\n  var result = {};\n\n  if (\"development\" !== 'production') {\n    traverseAllChildren(children, function (traverseContext, child, name) {\n      return flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID);\n    }, result);\n  } else {\n    traverseAllChildren(children, flattenSingleChildIntoContext, result);\n  }\n  return result;\n}\n\nmodule.exports = flattenChildren;\n},{\"144\":144,\"171\":171,\"23\":23,\"34\":34}],124:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule forEachAccumulated\n * \n */\n\n'use strict';\n\n/**\n * @param {array} arr an \"accumulation\" of items which is either an Array or\n * a single item. Useful when paired with the `accumulate` module. This is a\n * simple utility that allows us to reason about a collection of items, but\n * handling the case when there is exactly one item (and we do not need to\n * allocate an array).\n */\n\nfunction forEachAccumulated(arr, cb, scope) {\n  if (Array.isArray(arr)) {\n    arr.forEach(cb, scope);\n  } else if (arr) {\n    cb.call(scope, arr);\n  }\n}\n\nmodule.exports = forEachAccumulated;\n},{}],125:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventCharCode\n */\n\n'use strict';\n\n/**\n * `charCode` represents the actual \"character code\" and is safe to use with\n * `String.fromCharCode`. As such, only keys that correspond to printable\n * characters produce a valid `charCode`, the only exception to this is Enter.\n * The Tab-key is considered non-printable and does not have a `charCode`,\n * presumably because it does not produce a tab-character in browsers.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {number} Normalized `charCode` property.\n */\n\nfunction getEventCharCode(nativeEvent) {\n  var charCode;\n  var keyCode = nativeEvent.keyCode;\n\n  if ('charCode' in nativeEvent) {\n    charCode = nativeEvent.charCode;\n\n    // FF does not set `charCode` for the Enter-key, check against `keyCode`.\n    if (charCode === 0 && keyCode === 13) {\n      charCode = 13;\n    }\n  } else {\n    // IE8 does not implement `charCode`, but `keyCode` has the correct value.\n    charCode = keyCode;\n  }\n\n  // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.\n  // Must not discard the (non-)printable Enter-key.\n  if (charCode >= 32 || charCode === 13) {\n    return charCode;\n  }\n\n  return 0;\n}\n\nmodule.exports = getEventCharCode;\n},{}],126:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventKey\n */\n\n'use strict';\n\nvar getEventCharCode = _dereq_(125);\n\n/**\n * Normalization of deprecated HTML5 `key` values\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar normalizeKey = {\n  'Esc': 'Escape',\n  'Spacebar': ' ',\n  'Left': 'ArrowLeft',\n  'Up': 'ArrowUp',\n  'Right': 'ArrowRight',\n  'Down': 'ArrowDown',\n  'Del': 'Delete',\n  'Win': 'OS',\n  'Menu': 'ContextMenu',\n  'Apps': 'ContextMenu',\n  'Scroll': 'ScrollLock',\n  'MozPrintableKey': 'Unidentified'\n};\n\n/**\n * Translation from legacy `keyCode` to HTML5 `key`\n * Only special keys supported, all others depend on keyboard layout or browser\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar translateToKey = {\n  8: 'Backspace',\n  9: 'Tab',\n  12: 'Clear',\n  13: 'Enter',\n  16: 'Shift',\n  17: 'Control',\n  18: 'Alt',\n  19: 'Pause',\n  20: 'CapsLock',\n  27: 'Escape',\n  32: ' ',\n  33: 'PageUp',\n  34: 'PageDown',\n  35: 'End',\n  36: 'Home',\n  37: 'ArrowLeft',\n  38: 'ArrowUp',\n  39: 'ArrowRight',\n  40: 'ArrowDown',\n  45: 'Insert',\n  46: 'Delete',\n  112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',\n  118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12',\n  144: 'NumLock',\n  145: 'ScrollLock',\n  224: 'Meta'\n};\n\n/**\n * @param {object} nativeEvent Native browser event.\n * @return {string} Normalized `key` property.\n */\nfunction getEventKey(nativeEvent) {\n  if (nativeEvent.key) {\n    // Normalize inconsistent values reported by browsers due to\n    // implementations of a working draft specification.\n\n    // FireFox implements `key` but returns `MozPrintableKey` for all\n    // printable characters (normalized to `Unidentified`), ignore it.\n    var key = normalizeKey[nativeEvent.key] || nativeEvent.key;\n    if (key !== 'Unidentified') {\n      return key;\n    }\n  }\n\n  // Browser does not implement `key`, polyfill as much of it as we can.\n  if (nativeEvent.type === 'keypress') {\n    var charCode = getEventCharCode(nativeEvent);\n\n    // The enter-key is technically both printable and non-printable and can\n    // thus be captured by `keypress`, no other non-printable key should.\n    return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);\n  }\n  if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {\n    // While user keyboard layout determines the actual meaning of each\n    // `keyCode` value, almost all function keys have a universal value.\n    return translateToKey[nativeEvent.keyCode] || 'Unidentified';\n  }\n  return '';\n}\n\nmodule.exports = getEventKey;\n},{\"125\":125}],127:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventModifierState\n */\n\n'use strict';\n\n/**\n * Translation from modifier key to the associated property in the event.\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers\n */\n\nvar modifierKeyToProp = {\n  'Alt': 'altKey',\n  'Control': 'ctrlKey',\n  'Meta': 'metaKey',\n  'Shift': 'shiftKey'\n};\n\n// IE8 does not implement getModifierState so we simply map it to the only\n// modifier keys exposed by the event itself, does not support Lock-keys.\n// Currently, all major browsers except Chrome seems to support Lock-keys.\nfunction modifierStateGetter(keyArg) {\n  var syntheticEvent = this;\n  var nativeEvent = syntheticEvent.nativeEvent;\n  if (nativeEvent.getModifierState) {\n    return nativeEvent.getModifierState(keyArg);\n  }\n  var keyProp = modifierKeyToProp[keyArg];\n  return keyProp ? !!nativeEvent[keyProp] : false;\n}\n\nfunction getEventModifierState(nativeEvent) {\n  return modifierStateGetter;\n}\n\nmodule.exports = getEventModifierState;\n},{}],128:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventTarget\n */\n\n'use strict';\n\n/**\n * Gets the target node from a native browser event by accounting for\n * inconsistencies in browser DOM APIs.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {DOMEventTarget} Target node.\n */\n\nfunction getEventTarget(nativeEvent) {\n  var target = nativeEvent.target || nativeEvent.srcElement || window;\n\n  // Normalize SVG <use> element events #4963\n  if (target.correspondingUseElement) {\n    target = target.correspondingUseElement;\n  }\n\n  // Safari may fire events on text nodes (Node.TEXT_NODE is 3).\n  // @see http://www.quirksmode.org/js/events_properties.html\n  return target.nodeType === 3 ? target.parentNode : target;\n}\n\nmodule.exports = getEventTarget;\n},{}],129:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getHostComponentFromComposite\n */\n\n'use strict';\n\nvar ReactNodeTypes = _dereq_(80);\n\nfunction getHostComponentFromComposite(inst) {\n  var type;\n\n  while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {\n    inst = inst._renderedComponent;\n  }\n\n  if (type === ReactNodeTypes.HOST) {\n    return inst._renderedComponent;\n  } else if (type === ReactNodeTypes.EMPTY) {\n    return null;\n  }\n}\n\nmodule.exports = getHostComponentFromComposite;\n},{\"80\":80}],130:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getIteratorFn\n * \n */\n\n'use strict';\n\n/* global Symbol */\n\nvar ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.\n\n/**\n * Returns the iterator method function contained on the iterable object.\n *\n * Be sure to invoke the function with the iterable as context:\n *\n *     var iteratorFn = getIteratorFn(myIterable);\n *     if (iteratorFn) {\n *       var iterator = iteratorFn.call(myIterable);\n *       ...\n *     }\n *\n * @param {?object} maybeIterable\n * @return {?function}\n */\nfunction getIteratorFn(maybeIterable) {\n  var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);\n  if (typeof iteratorFn === 'function') {\n    return iteratorFn;\n  }\n}\n\nmodule.exports = getIteratorFn;\n},{}],131:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getNodeForCharacterOffset\n */\n\n'use strict';\n\n/**\n * Given any node return the first leaf node without children.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {DOMElement|DOMTextNode}\n */\n\nfunction getLeafNode(node) {\n  while (node && node.firstChild) {\n    node = node.firstChild;\n  }\n  return node;\n}\n\n/**\n * Get the next sibling within a container. This will walk up the\n * DOM if a node's siblings have been exhausted.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {?DOMElement|DOMTextNode}\n */\nfunction getSiblingNode(node) {\n  while (node) {\n    if (node.nextSibling) {\n      return node.nextSibling;\n    }\n    node = node.parentNode;\n  }\n}\n\n/**\n * Get object describing the nodes which contain characters at offset.\n *\n * @param {DOMElement|DOMTextNode} root\n * @param {number} offset\n * @return {?object}\n */\nfunction getNodeForCharacterOffset(root, offset) {\n  var node = getLeafNode(root);\n  var nodeStart = 0;\n  var nodeEnd = 0;\n\n  while (node) {\n    if (node.nodeType === 3) {\n      nodeEnd = nodeStart + node.textContent.length;\n\n      if (nodeStart <= offset && nodeEnd >= offset) {\n        return {\n          node: node,\n          offset: offset - nodeStart\n        };\n      }\n\n      nodeStart = nodeEnd;\n    }\n\n    node = getLeafNode(getSiblingNode(node));\n  }\n}\n\nmodule.exports = getNodeForCharacterOffset;\n},{}],132:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getTextContentAccessor\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar contentKey = null;\n\n/**\n * Gets the key used to access text content on a DOM node.\n *\n * @return {?string} Key used to access text content.\n * @internal\n */\nfunction getTextContentAccessor() {\n  if (!contentKey && ExecutionEnvironment.canUseDOM) {\n    // Prefer textContent to innerText because many browsers support both but\n    // SVG <text> elements don't support innerText even when <div> does.\n    contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';\n  }\n  return contentKey;\n}\n\nmodule.exports = getTextContentAccessor;\n},{\"147\":147}],133:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getVendorPrefixedEventName\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\n/**\n * Generate a mapping of standard vendor prefixes using the defined style property and event name.\n *\n * @param {string} styleProp\n * @param {string} eventName\n * @returns {object}\n */\nfunction makePrefixMap(styleProp, eventName) {\n  var prefixes = {};\n\n  prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();\n  prefixes['Webkit' + styleProp] = 'webkit' + eventName;\n  prefixes['Moz' + styleProp] = 'moz' + eventName;\n  prefixes['ms' + styleProp] = 'MS' + eventName;\n  prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();\n\n  return prefixes;\n}\n\n/**\n * A list of event names to a configurable list of vendor prefixes.\n */\nvar vendorPrefixes = {\n  animationend: makePrefixMap('Animation', 'AnimationEnd'),\n  animationiteration: makePrefixMap('Animation', 'AnimationIteration'),\n  animationstart: makePrefixMap('Animation', 'AnimationStart'),\n  transitionend: makePrefixMap('Transition', 'TransitionEnd')\n};\n\n/**\n * Event names that have already been detected and prefixed (if applicable).\n */\nvar prefixedEventNames = {};\n\n/**\n * Element to check for prefixes on.\n */\nvar style = {};\n\n/**\n * Bootstrap if a DOM exists.\n */\nif (ExecutionEnvironment.canUseDOM) {\n  style = document.createElement('div').style;\n\n  // On some platforms, in particular some releases of Android 4.x,\n  // the un-prefixed \"animation\" and \"transition\" properties are defined on the\n  // style object but the events that fire will still be prefixed, so we need\n  // to check if the un-prefixed events are usable, and if not remove them from the map.\n  if (!('AnimationEvent' in window)) {\n    delete vendorPrefixes.animationend.animation;\n    delete vendorPrefixes.animationiteration.animation;\n    delete vendorPrefixes.animationstart.animation;\n  }\n\n  // Same as above\n  if (!('TransitionEvent' in window)) {\n    delete vendorPrefixes.transitionend.transition;\n  }\n}\n\n/**\n * Attempts to determine the correct vendor prefixed event name.\n *\n * @param {string} eventName\n * @returns {string}\n */\nfunction getVendorPrefixedEventName(eventName) {\n  if (prefixedEventNames[eventName]) {\n    return prefixedEventNames[eventName];\n  } else if (!vendorPrefixes[eventName]) {\n    return eventName;\n  }\n\n  var prefixMap = vendorPrefixes[eventName];\n\n  for (var styleProp in prefixMap) {\n    if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {\n      return prefixedEventNames[eventName] = prefixMap[styleProp];\n    }\n  }\n\n  return '';\n}\n\nmodule.exports = getVendorPrefixedEventName;\n},{\"147\":147}],134:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule instantiateReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactCompositeComponent = _dereq_(35);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactHostComponent = _dereq_(69);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n// To avoid a cyclic dependency, we create the final class in this module\nvar ReactCompositeComponentWrapper = function (element) {\n  this.construct(element);\n};\n_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent.Mixin, {\n  _instantiateReactComponent: instantiateReactComponent\n});\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nfunction getDisplayName(instance) {\n  var element = instance._currentElement;\n  if (element == null) {\n    return '#empty';\n  } else if (typeof element === 'string' || typeof element === 'number') {\n    return '#text';\n  } else if (typeof element.type === 'string') {\n    return element.type;\n  } else if (instance.getName) {\n    return instance.getName() || 'Unknown';\n  } else {\n    return element.type.displayName || element.type.name || 'Unknown';\n  }\n}\n\n/**\n * Check if the type reference is a known internal type. I.e. not a user\n * provided composite type.\n *\n * @param {function} type\n * @return {boolean} Returns true if this is a valid internal type.\n */\nfunction isInternalComponentType(type) {\n  return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';\n}\n\nvar nextDebugID = 1;\n\n/**\n * Given a ReactNode, create an instance that will actually be mounted.\n *\n * @param {ReactNode} node\n * @param {boolean} shouldHaveDebugID\n * @return {object} A new instance of the element's constructor.\n * @protected\n */\nfunction instantiateReactComponent(node, shouldHaveDebugID) {\n  var instance;\n\n  if (node === null || node === false) {\n    instance = ReactEmptyComponent.create(instantiateReactComponent);\n  } else if (typeof node === 'object') {\n    var element = node;\n    !(element && (typeof element.type === 'function' || typeof element.type === 'string')) ? \"development\" !== 'production' ? invariant(false, 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : _prodInvariant('130', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : void 0;\n\n    // Special case string values\n    if (typeof element.type === 'string') {\n      instance = ReactHostComponent.createInternalComponent(element);\n    } else if (isInternalComponentType(element.type)) {\n      // This is temporarily available for custom components that are not string\n      // representations. I.e. ART. Once those are updated to use the string\n      // representation, we can drop this code path.\n      instance = new element.type(element);\n\n      // We renamed this. Allow the old name for compat. :(\n      if (!instance.getHostNode) {\n        instance.getHostNode = instance.getNativeNode;\n      }\n    } else {\n      instance = new ReactCompositeComponentWrapper(element);\n    }\n  } else if (typeof node === 'string' || typeof node === 'number') {\n    instance = ReactHostComponent.createInstanceForText(node);\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : _prodInvariant('131', typeof node) : void 0;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getHostNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;\n  }\n\n  // These two fields are used by the DOM and ART diffing algorithms\n  // respectively. Instead of using expandos on components, we should be\n  // storing the state needed by the diffing algorithms elsewhere.\n  instance._mountIndex = 0;\n  instance._mountImage = null;\n\n  if (\"development\" !== 'production') {\n    if (shouldHaveDebugID) {\n      var debugID = nextDebugID++;\n      instance._debugID = debugID;\n      var displayName = getDisplayName(instance);\n      ReactInstrumentation.debugTool.onSetDisplayName(debugID, displayName);\n      var owner = node && node._owner;\n      if (owner) {\n        ReactInstrumentation.debugTool.onSetOwner(debugID, owner._debugID);\n      }\n    } else {\n      instance._debugID = 0;\n    }\n  }\n\n  // Internal instances should fully constructed at this point, so they should\n  // not get any new fields added to them at this point.\n  if (\"development\" !== 'production') {\n    if (Object.preventExtensions) {\n      Object.preventExtensions(instance);\n    }\n  }\n\n  return instance;\n}\n\nmodule.exports = instantiateReactComponent;\n},{\"139\":139,\"161\":161,\"171\":171,\"172\":172,\"35\":35,\"64\":64,\"69\":69,\"74\":74}],135:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isEventSupported\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar useHasFeature;\nif (ExecutionEnvironment.canUseDOM) {\n  useHasFeature = document.implementation && document.implementation.hasFeature &&\n  // always returns true in newer browsers as per the standard.\n  // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature\n  document.implementation.hasFeature('', '') !== true;\n}\n\n/**\n * Checks if an event is supported in the current execution environment.\n *\n * NOTE: This will not work correctly for non-generic events such as `change`,\n * `reset`, `load`, `error`, and `select`.\n *\n * Borrows from Modernizr.\n *\n * @param {string} eventNameSuffix Event name, e.g. \"click\".\n * @param {?boolean} capture Check if the capture phase is supported.\n * @return {boolean} True if the event is supported.\n * @internal\n * @license Modernizr 3.0.0pre (Custom Build) | MIT\n */\nfunction isEventSupported(eventNameSuffix, capture) {\n  if (!ExecutionEnvironment.canUseDOM || capture && !('addEventListener' in document)) {\n    return false;\n  }\n\n  var eventName = 'on' + eventNameSuffix;\n  var isSupported = eventName in document;\n\n  if (!isSupported) {\n    var element = document.createElement('div');\n    element.setAttribute(eventName, 'return;');\n    isSupported = typeof element[eventName] === 'function';\n  }\n\n  if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {\n    // This is the only way to test support for the `wheel` event in IE9+.\n    isSupported = document.implementation.hasFeature('Events.wheel', '3.0');\n  }\n\n  return isSupported;\n}\n\nmodule.exports = isEventSupported;\n},{\"147\":147}],136:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isTextInputElement\n * \n */\n\n'use strict';\n\n/**\n * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary\n */\n\nvar supportedInputTypes = {\n  'color': true,\n  'date': true,\n  'datetime': true,\n  'datetime-local': true,\n  'email': true,\n  'month': true,\n  'number': true,\n  'password': true,\n  'range': true,\n  'search': true,\n  'tel': true,\n  'text': true,\n  'time': true,\n  'url': true,\n  'week': true\n};\n\nfunction isTextInputElement(elem) {\n  var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n\n  if (nodeName === 'input') {\n    return !!supportedInputTypes[elem.type];\n  }\n\n  if (nodeName === 'textarea') {\n    return true;\n  }\n\n  return false;\n}\n\nmodule.exports = isTextInputElement;\n},{}],137:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule onlyChild\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\n/**\n * Returns the first child in a collection of children and verifies that there\n * is only one child in the collection.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.only\n *\n * The current implementation of this function assumes that a single child gets\n * passed without a wrapper, but the purpose of this helper function is to\n * abstract away the particular structure of children.\n *\n * @param {?object} children Child collection structure.\n * @return {ReactElement} The first and only `ReactElement` contained in the\n * structure.\n */\nfunction onlyChild(children) {\n  !ReactElement.isValidElement(children) ? \"development\" !== 'production' ? invariant(false, 'onlyChild must be passed a children with exactly one child.') : _prodInvariant('23') : void 0;\n  return children;\n}\n\nmodule.exports = onlyChild;\n},{\"139\":139,\"161\":161,\"62\":62}],138:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule quoteAttributeValueForBrowser\n */\n\n'use strict';\n\nvar escapeTextContentForBrowser = _dereq_(121);\n\n/**\n * Escapes attribute value to prevent scripting attacks.\n *\n * @param {*} value Value to escape.\n * @return {string} An escaped string.\n */\nfunction quoteAttributeValueForBrowser(value) {\n  return '\"' + escapeTextContentForBrowser(value) + '\"';\n}\n\nmodule.exports = quoteAttributeValueForBrowser;\n},{\"121\":121}],139:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule reactProdInvariant\n * \n */\n'use strict';\n\n/**\n * WARNING: DO NOT manually require this module.\n * This is a replacement for `invariant(...)` used by the error code system\n * and will _only_ be required by the corresponding babel pass.\n * It always throws.\n */\n\nfunction reactProdInvariant(code) {\n  var argCount = arguments.length - 1;\n\n  var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;\n\n  for (var argIdx = 0; argIdx < argCount; argIdx++) {\n    message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);\n  }\n\n  message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';\n\n  var error = new Error(message);\n  error.name = 'Invariant Violation';\n  error.framesToPop = 1; // we don't care about reactProdInvariant's own frame\n\n  throw error;\n}\n\nmodule.exports = reactProdInvariant;\n},{}],140:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n* @providesModule renderSubtreeIntoContainer\n*/\n\n'use strict';\n\nvar ReactMount = _dereq_(77);\n\nmodule.exports = ReactMount.renderSubtreeIntoContainer;\n},{\"77\":77}],141:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setInnerHTML\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar DOMNamespaces = _dereq_(9);\n\nvar WHITESPACE_TEST = /^[ \\r\\n\\t\\f]/;\nvar NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \\r\\n\\t\\f\\/>]/;\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\n\n// SVG temp container for IE lacking innerHTML\nvar reusableSVGContainer;\n\n/**\n * Set the innerHTML property of a node, ensuring that whitespace is preserved\n * even in IE8.\n *\n * @param {DOMElement} node\n * @param {string} html\n * @internal\n */\nvar setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {\n  // IE does not have innerHTML for SVG nodes, so instead we inject the\n  // new markup in a temp node and then move the child nodes across into\n  // the target node\n  if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {\n    reusableSVGContainer = reusableSVGContainer || document.createElement('div');\n    reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';\n    var newNodes = reusableSVGContainer.firstChild.childNodes;\n    for (var i = 0; i < newNodes.length; i++) {\n      node.appendChild(newNodes[i]);\n    }\n  } else {\n    node.innerHTML = html;\n  }\n});\n\nif (ExecutionEnvironment.canUseDOM) {\n  // IE8: When updating a just created node with innerHTML only leading\n  // whitespace is removed. When updating an existing node with innerHTML\n  // whitespace in root TextNodes is also collapsed.\n  // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html\n\n  // Feature detection; only IE8 is known to behave improperly like this.\n  var testElement = document.createElement('div');\n  testElement.innerHTML = ' ';\n  if (testElement.innerHTML === '') {\n    setInnerHTML = function (node, html) {\n      // Magic theory: IE8 supposedly differentiates between added and updated\n      // nodes when processing innerHTML, innerHTML on updated nodes suffers\n      // from worse whitespace behavior. Re-adding a node like this triggers\n      // the initial and more favorable whitespace behavior.\n      // TODO: What to do on a detached node?\n      if (node.parentNode) {\n        node.parentNode.replaceChild(node, node);\n      }\n\n      // We also implement a workaround for non-visible tags disappearing into\n      // thin air on IE8, this only happens if there is no visible text\n      // in-front of the non-visible tags. Piggyback on the whitespace fix\n      // and simply check if any non-visible tags appear in the source.\n      if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {\n        // Recover leading whitespace by temporarily prepending any character.\n        // \\uFEFF has the potential advantage of being zero-width/invisible.\n        // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode\n        // in hopes that this is preserved even if \"\\uFEFF\" is transformed to\n        // the actual Unicode character (by Babel, for example).\n        // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216\n        node.innerHTML = String.fromCharCode(0xFEFF) + html;\n\n        // deleteData leaves an empty `TextNode` which offsets the index of all\n        // children. Definitely want to avoid this.\n        var textNode = node.firstChild;\n        if (textNode.data.length === 1) {\n          node.removeChild(textNode);\n        } else {\n          textNode.deleteData(0, 1);\n        }\n      } else {\n        node.innerHTML = html;\n      }\n    };\n  }\n  testElement = null;\n}\n\nmodule.exports = setInnerHTML;\n},{\"119\":119,\"147\":147,\"9\":9}],142:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setTextContent\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar setInnerHTML = _dereq_(141);\n\n/**\n * Set the textContent property of a node, ensuring that whitespace is preserved\n * even in IE8. innerText is a poor substitute for textContent and, among many\n * issues, inserts <br> instead of the literal newline chars. innerHTML behaves\n * as it should.\n *\n * @param {DOMElement} node\n * @param {string} text\n * @internal\n */\nvar setTextContent = function (node, text) {\n  if (text) {\n    var firstChild = node.firstChild;\n\n    if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {\n      firstChild.nodeValue = text;\n      return;\n    }\n  }\n  node.textContent = text;\n};\n\nif (ExecutionEnvironment.canUseDOM) {\n  if (!('textContent' in document.documentElement)) {\n    setTextContent = function (node, text) {\n      setInnerHTML(node, escapeTextContentForBrowser(text));\n    };\n  }\n}\n\nmodule.exports = setTextContent;\n},{\"121\":121,\"141\":141,\"147\":147}],143:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule shouldUpdateReactComponent\n */\n\n'use strict';\n\n/**\n * Given a `prevElement` and `nextElement`, determines if the existing\n * instance should be updated as opposed to being destroyed or replaced by a new\n * instance. Both arguments are elements. This ensures that this logic can\n * operate on stateless trees without any backing instance.\n *\n * @param {?object} prevElement\n * @param {?object} nextElement\n * @return {boolean} True if the existing instance should be updated.\n * @protected\n */\n\nfunction shouldUpdateReactComponent(prevElement, nextElement) {\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n  if (prevEmpty || nextEmpty) {\n    return prevEmpty === nextEmpty;\n  }\n\n  var prevType = typeof prevElement;\n  var nextType = typeof nextElement;\n  if (prevType === 'string' || prevType === 'number') {\n    return nextType === 'string' || nextType === 'number';\n  } else {\n    return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key;\n  }\n}\n\nmodule.exports = shouldUpdateReactComponent;\n},{}],144:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule traverseAllChildren\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\n\nvar getIteratorFn = _dereq_(130);\nvar invariant = _dereq_(161);\nvar KeyEscapeUtils = _dereq_(23);\nvar warning = _dereq_(171);\n\nvar SEPARATOR = '.';\nvar SUBSEPARATOR = ':';\n\n/**\n * TODO: Test that a single child and an array with one item have the same key\n * pattern.\n */\n\nvar didWarnAboutMaps = false;\n\n/**\n * Generate a key string that identifies a component within a set.\n *\n * @param {*} component A component that could contain a manual key.\n * @param {number} index Index that is used if a manual key is not provided.\n * @return {string}\n */\nfunction getComponentKey(component, index) {\n  // Do some typechecking here since we call this blindly. We want to ensure\n  // that we don't block potential future ES APIs.\n  if (component && typeof component === 'object' && component.key != null) {\n    // Explicit key\n    return KeyEscapeUtils.escape(component.key);\n  }\n  // Implicit key determined by the index in the set\n  return index.toString(36);\n}\n\n/**\n * @param {?*} children Children tree container.\n * @param {!string} nameSoFar Name of the key path so far.\n * @param {!function} callback Callback to invoke with each child found.\n * @param {?*} traverseContext Used to pass information throughout the traversal\n * process.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {\n  var type = typeof children;\n\n  if (type === 'undefined' || type === 'boolean') {\n    // All of the above are perceived as null.\n    children = null;\n  }\n\n  if (children === null || type === 'string' || type === 'number' || ReactElement.isValidElement(children)) {\n    callback(traverseContext, children,\n    // If it's the only child, treat the name as if it was wrapped in an array\n    // so that it's consistent if the number of children grows.\n    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);\n    return 1;\n  }\n\n  var child;\n  var nextName;\n  var subtreeCount = 0; // Count of children found in the current subtree.\n  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;\n\n  if (Array.isArray(children)) {\n    for (var i = 0; i < children.length; i++) {\n      child = children[i];\n      nextName = nextNamePrefix + getComponentKey(child, i);\n      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n    }\n  } else {\n    var iteratorFn = getIteratorFn(children);\n    if (iteratorFn) {\n      var iterator = iteratorFn.call(children);\n      var step;\n      if (iteratorFn !== children.entries) {\n        var ii = 0;\n        while (!(step = iterator.next()).done) {\n          child = step.value;\n          nextName = nextNamePrefix + getComponentKey(child, ii++);\n          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n        }\n      } else {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : void 0;\n          didWarnAboutMaps = true;\n        }\n        // Iterator will provide entry [k,v] tuples rather than values.\n        while (!(step = iterator.next()).done) {\n          var entry = step.value;\n          if (entry) {\n            child = entry[1];\n            nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);\n            subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n          }\n        }\n      }\n    } else if (type === 'object') {\n      var addendum = '';\n      if (\"development\" !== 'production') {\n        addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';\n        if (children._isReactElement) {\n          addendum = ' It looks like you\\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.';\n        }\n        if (ReactCurrentOwner.current) {\n          var name = ReactCurrentOwner.current.getName();\n          if (name) {\n            addendum += ' Check the render method of `' + name + '`.';\n          }\n        }\n      }\n      var childrenString = String(children);\n      !false ? \"development\" !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0;\n    }\n  }\n\n  return subtreeCount;\n}\n\n/**\n * Traverses children that are typically specified as `props.children`, but\n * might also be specified through attributes:\n *\n * - `traverseAllChildren(this.props.children, ...)`\n * - `traverseAllChildren(this.props.leftPanelChildren, ...)`\n *\n * The `traverseContext` is an optional argument that is passed through the\n * entire traversal. It can be used to store accumulations or anything else that\n * the callback might find relevant.\n *\n * @param {?*} children Children tree object.\n * @param {!function} callback To invoke upon traversing each child.\n * @param {?*} traverseContext Context for traversal.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildren(children, callback, traverseContext) {\n  if (children == null) {\n    return 0;\n  }\n\n  return traverseAllChildrenImpl(children, '', callback, traverseContext);\n}\n\nmodule.exports = traverseAllChildren;\n},{\"130\":130,\"139\":139,\"161\":161,\"171\":171,\"23\":23,\"36\":36,\"62\":62}],145:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule validateDOMNesting\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar validateDOMNesting = emptyFunction;\n\nif (\"development\" !== 'production') {\n  // This validation code was written based on the HTML5 parsing spec:\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  //\n  // Note: this does not catch all invalid nesting, nor does it try to (as it's\n  // not clear what practical benefit doing so provides); instead, we warn only\n  // for cases where the parser will give a parse tree differing from what React\n  // intended. For example, <b><div></div></b> is invalid but we don't warn\n  // because it still parses correctly; we do warn for other cases like nested\n  // <p> tags where the beginning of the second element implicitly closes the\n  // first, causing a confusing mess.\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#special\n  var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point\n  // TODO: Distinguish by namespace here -- for <title>, including it here\n  // errs on the side of fewer warnings\n  'foreignObject', 'desc', 'title'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope\n  var buttonScopeTags = inScopeTags.concat(['button']);\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags\n  var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];\n\n  var emptyAncestorInfo = {\n    current: null,\n\n    formTag: null,\n    aTagInScope: null,\n    buttonTagInScope: null,\n    nobrTagInScope: null,\n    pTagInButtonScope: null,\n\n    listItemTagAutoclosing: null,\n    dlItemTagAutoclosing: null\n  };\n\n  var updatedAncestorInfo = function (oldInfo, tag, instance) {\n    var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);\n    var info = { tag: tag, instance: instance };\n\n    if (inScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.aTagInScope = null;\n      ancestorInfo.buttonTagInScope = null;\n      ancestorInfo.nobrTagInScope = null;\n    }\n    if (buttonScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.pTagInButtonScope = null;\n    }\n\n    // See rules for 'li', 'dd', 'dt' start tags in\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {\n      ancestorInfo.listItemTagAutoclosing = null;\n      ancestorInfo.dlItemTagAutoclosing = null;\n    }\n\n    ancestorInfo.current = info;\n\n    if (tag === 'form') {\n      ancestorInfo.formTag = info;\n    }\n    if (tag === 'a') {\n      ancestorInfo.aTagInScope = info;\n    }\n    if (tag === 'button') {\n      ancestorInfo.buttonTagInScope = info;\n    }\n    if (tag === 'nobr') {\n      ancestorInfo.nobrTagInScope = info;\n    }\n    if (tag === 'p') {\n      ancestorInfo.pTagInButtonScope = info;\n    }\n    if (tag === 'li') {\n      ancestorInfo.listItemTagAutoclosing = info;\n    }\n    if (tag === 'dd' || tag === 'dt') {\n      ancestorInfo.dlItemTagAutoclosing = info;\n    }\n\n    return ancestorInfo;\n  };\n\n  /**\n   * Returns whether\n   */\n  var isTagValidWithParent = function (tag, parentTag) {\n    // First, let's check if we're in an unusual parsing mode...\n    switch (parentTag) {\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect\n      case 'select':\n        return tag === 'option' || tag === 'optgroup' || tag === '#text';\n      case 'optgroup':\n        return tag === 'option' || tag === '#text';\n      // Strictly speaking, seeing an <option> doesn't mean we're in a <select>\n      // but\n      case 'option':\n        return tag === '#text';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption\n      // No special behavior since these rules fall back to \"in body\" mode for\n      // all except special table nodes which cause bad parsing behavior anyway.\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr\n      case 'tr':\n        return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody\n      case 'tbody':\n      case 'thead':\n      case 'tfoot':\n        return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup\n      case 'colgroup':\n        return tag === 'col' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable\n      case 'table':\n        return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead\n      case 'head':\n        return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element\n      case 'html':\n        return tag === 'head' || tag === 'body';\n      case '#document':\n        return tag === 'html';\n    }\n\n    // Probably in the \"in body\" parsing mode, so we outlaw only tag combos\n    // where the parsing rules cause implicit opens or closes to be added.\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    switch (tag) {\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';\n\n      case 'rp':\n      case 'rt':\n        return impliedEndTags.indexOf(parentTag) === -1;\n\n      case 'body':\n      case 'caption':\n      case 'col':\n      case 'colgroup':\n      case 'frame':\n      case 'head':\n      case 'html':\n      case 'tbody':\n      case 'td':\n      case 'tfoot':\n      case 'th':\n      case 'thead':\n      case 'tr':\n        // These tags are only valid with a few parents that have special child\n        // parsing rules -- if we're down here, then none of those matched and\n        // so we allow it only if we don't know what the parent is, as all other\n        // cases are invalid.\n        return parentTag == null;\n    }\n\n    return true;\n  };\n\n  /**\n   * Returns whether\n   */\n  var findInvalidAncestorForTag = function (tag, ancestorInfo) {\n    switch (tag) {\n      case 'address':\n      case 'article':\n      case 'aside':\n      case 'blockquote':\n      case 'center':\n      case 'details':\n      case 'dialog':\n      case 'dir':\n      case 'div':\n      case 'dl':\n      case 'fieldset':\n      case 'figcaption':\n      case 'figure':\n      case 'footer':\n      case 'header':\n      case 'hgroup':\n      case 'main':\n      case 'menu':\n      case 'nav':\n      case 'ol':\n      case 'p':\n      case 'section':\n      case 'summary':\n      case 'ul':\n\n      case 'pre':\n      case 'listing':\n\n      case 'table':\n\n      case 'hr':\n\n      case 'xmp':\n\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return ancestorInfo.pTagInButtonScope;\n\n      case 'form':\n        return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;\n\n      case 'li':\n        return ancestorInfo.listItemTagAutoclosing;\n\n      case 'dd':\n      case 'dt':\n        return ancestorInfo.dlItemTagAutoclosing;\n\n      case 'button':\n        return ancestorInfo.buttonTagInScope;\n\n      case 'a':\n        // Spec says something about storing a list of markers, but it sounds\n        // equivalent to this check.\n        return ancestorInfo.aTagInScope;\n\n      case 'nobr':\n        return ancestorInfo.nobrTagInScope;\n    }\n\n    return null;\n  };\n\n  /**\n   * Given a ReactCompositeComponent instance, return a list of its recursive\n   * owners, starting at the root and ending with the instance itself.\n   */\n  var findOwnerStack = function (instance) {\n    if (!instance) {\n      return [];\n    }\n\n    var stack = [];\n    do {\n      stack.push(instance);\n    } while (instance = instance._currentElement._owner);\n    stack.reverse();\n    return stack;\n  };\n\n  var didWarn = {};\n\n  validateDOMNesting = function (childTag, childInstance, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n\n    var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;\n    var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);\n    var problematic = invalidParent || invalidAncestor;\n\n    if (problematic) {\n      var ancestorTag = problematic.tag;\n      var ancestorInstance = problematic.instance;\n\n      var childOwner = childInstance && childInstance._currentElement._owner;\n      var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;\n\n      var childOwners = findOwnerStack(childOwner);\n      var ancestorOwners = findOwnerStack(ancestorOwner);\n\n      var minStackLen = Math.min(childOwners.length, ancestorOwners.length);\n      var i;\n\n      var deepestCommon = -1;\n      for (i = 0; i < minStackLen; i++) {\n        if (childOwners[i] === ancestorOwners[i]) {\n          deepestCommon = i;\n        } else {\n          break;\n        }\n      }\n\n      var UNKNOWN = '(unknown)';\n      var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ownerInfo = [].concat(\n      // If the parent and child instances have a common owner ancestor, start\n      // with that -- otherwise we just start with the parent's owners.\n      deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,\n      // If we're warning about an invalid (non-parent) ancestry, add '...'\n      invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');\n\n      var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;\n      if (didWarn[warnKey]) {\n        return;\n      }\n      didWarn[warnKey] = true;\n\n      var tagDisplayName = childTag;\n      if (childTag !== '#text') {\n        tagDisplayName = '<' + childTag + '>';\n      }\n\n      if (invalidParent) {\n        var info = '';\n        if (ancestorTag === 'table' && childTag === 'tr') {\n          info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';\n        }\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>. ' + 'See %s.%s', tagDisplayName, ancestorTag, ownerInfo, info) : void 0;\n      } else {\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;\n      }\n    }\n  };\n\n  validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;\n\n  // For testing\n  validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n    return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);\n  };\n}\n\nmodule.exports = validateDOMNesting;\n},{\"153\":153,\"171\":171,\"172\":172}],146:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * @typechecks\n */\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Upstream version of event listener. Does not take into account specific\n * nature of platform.\n */\nvar EventListener = {\n  /**\n   * Listen to DOM events during the bubble phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  listen: function listen(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, false);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, false);\n        }\n      };\n    } else if (target.attachEvent) {\n      target.attachEvent('on' + eventType, callback);\n      return {\n        remove: function remove() {\n          target.detachEvent('on' + eventType, callback);\n        }\n      };\n    }\n  },\n\n  /**\n   * Listen to DOM events during the capture phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  capture: function capture(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, true);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, true);\n        }\n      };\n    } else {\n      if (\"development\" !== 'production') {\n        console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');\n      }\n      return {\n        remove: emptyFunction\n      };\n    }\n  },\n\n  registerDefault: function registerDefault() {}\n};\n\nmodule.exports = EventListener;\n},{\"153\":153}],147:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);\n\n/**\n * Simple, lightweight module assisting with the detection and context of\n * Worker. Helps avoid circular dependencies and allows code to reason about\n * whether or not they are in a Worker, even if they never include the main\n * `ReactWorker` dependency.\n */\nvar ExecutionEnvironment = {\n\n  canUseDOM: canUseDOM,\n\n  canUseWorkers: typeof Worker !== 'undefined',\n\n  canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),\n\n  canUseViewport: canUseDOM && !!window.screen,\n\n  isInWorker: !canUseDOM // For now, this is true - might change in the future.\n\n};\n\nmodule.exports = ExecutionEnvironment;\n},{}],148:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _hyphenPattern = /-(.)/g;\n\n/**\n * Camelcases a hyphenated string, for example:\n *\n *   > camelize('background-color')\n *   < \"backgroundColor\"\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelize(string) {\n  return string.replace(_hyphenPattern, function (_, character) {\n    return character.toUpperCase();\n  });\n}\n\nmodule.exports = camelize;\n},{}],149:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar camelize = _dereq_(148);\n\nvar msPattern = /^-ms-/;\n\n/**\n * Camelcases a hyphenated CSS property name, for example:\n *\n *   > camelizeStyleName('background-color')\n *   < \"backgroundColor\"\n *   > camelizeStyleName('-moz-transition')\n *   < \"MozTransition\"\n *   > camelizeStyleName('-ms-transition')\n *   < \"msTransition\"\n *\n * As Andi Smith suggests\n * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix\n * is converted to lowercase `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelizeStyleName(string) {\n  return camelize(string.replace(msPattern, 'ms-'));\n}\n\nmodule.exports = camelizeStyleName;\n},{\"148\":148}],150:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nvar isTextNode = _dereq_(163);\n\n/*eslint-disable no-bitwise */\n\n/**\n * Checks if a given DOM node contains or is another DOM node.\n */\nfunction containsNode(outerNode, innerNode) {\n  if (!outerNode || !innerNode) {\n    return false;\n  } else if (outerNode === innerNode) {\n    return true;\n  } else if (isTextNode(outerNode)) {\n    return false;\n  } else if (isTextNode(innerNode)) {\n    return containsNode(outerNode, innerNode.parentNode);\n  } else if ('contains' in outerNode) {\n    return outerNode.contains(innerNode);\n  } else if (outerNode.compareDocumentPosition) {\n    return !!(outerNode.compareDocumentPosition(innerNode) & 16);\n  } else {\n    return false;\n  }\n}\n\nmodule.exports = containsNode;\n},{\"163\":163}],151:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar invariant = _dereq_(161);\n\n/**\n * Convert array-like objects to arrays.\n *\n * This API assumes the caller knows the contents of the data type. For less\n * well defined inputs use createArrayFromMixed.\n *\n * @param {object|function|filelist} obj\n * @return {array}\n */\nfunction toArray(obj) {\n  var length = obj.length;\n\n  // Some browsers builtin objects can report typeof 'function' (e.g. NodeList\n  // in old versions of Safari).\n  !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? \"development\" !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0;\n\n  !(typeof length === 'number') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0;\n\n  !(length === 0 || length - 1 in obj) ? \"development\" !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0;\n\n  !(typeof obj.callee !== 'function') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object can\\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0;\n\n  // Old IE doesn't give collections access to hasOwnProperty. Assume inputs\n  // without method will throw during the slice call and skip straight to the\n  // fallback.\n  if (obj.hasOwnProperty) {\n    try {\n      return Array.prototype.slice.call(obj);\n    } catch (e) {\n      // IE < 9 does not support Array#slice on collections objects\n    }\n  }\n\n  // Fall back to copying key by key. This assumes all keys have a value,\n  // so will not preserve sparsely populated inputs.\n  var ret = Array(length);\n  for (var ii = 0; ii < length; ii++) {\n    ret[ii] = obj[ii];\n  }\n  return ret;\n}\n\n/**\n * Perform a heuristic test to determine if an object is \"array-like\".\n *\n *   A monk asked Joshu, a Zen master, \"Has a dog Buddha nature?\"\n *   Joshu replied: \"Mu.\"\n *\n * This function determines if its argument has \"array nature\": it returns\n * true if the argument is an actual array, an `arguments' object, or an\n * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).\n *\n * It will return false for other array-like objects like Filelist.\n *\n * @param {*} obj\n * @return {boolean}\n */\nfunction hasArrayNature(obj) {\n  return(\n    // not null/false\n    !!obj && (\n    // arrays are objects, NodeLists are functions in Safari\n    typeof obj == 'object' || typeof obj == 'function') &&\n    // quacks like an array\n    'length' in obj &&\n    // not window\n    !('setInterval' in obj) &&\n    // no DOM node should be considered an array-like\n    // a 'select' element has 'length' and 'item' properties on IE8\n    typeof obj.nodeType != 'number' && (\n    // a real array\n    Array.isArray(obj) ||\n    // arguments\n    'callee' in obj ||\n    // HTMLCollection/NodeList\n    'item' in obj)\n  );\n}\n\n/**\n * Ensure that the argument is an array by wrapping it in an array if it is not.\n * Creates a copy of the argument if it is already an array.\n *\n * This is mostly useful idiomatically:\n *\n *   var createArrayFromMixed = require('createArrayFromMixed');\n *\n *   function takesOneOrMoreThings(things) {\n *     things = createArrayFromMixed(things);\n *     ...\n *   }\n *\n * This allows you to treat `things' as an array, but accept scalars in the API.\n *\n * If you need to convert an array-like object, like `arguments`, into an array\n * use toArray instead.\n *\n * @param {*} obj\n * @return {array}\n */\nfunction createArrayFromMixed(obj) {\n  if (!hasArrayNature(obj)) {\n    return [obj];\n  } else if (Array.isArray(obj)) {\n    return obj.slice();\n  } else {\n    return toArray(obj);\n  }\n}\n\nmodule.exports = createArrayFromMixed;\n},{\"161\":161}],152:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/*eslint-disable fb-www/unsafe-html*/\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createArrayFromMixed = _dereq_(151);\nvar getMarkupWrap = _dereq_(157);\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to render all markup.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Pattern used by `getNodeName`.\n */\nvar nodeNamePattern = /^\\s*<(\\w+)/;\n\n/**\n * Extracts the `nodeName` of the first element in a string of markup.\n *\n * @param {string} markup String of markup.\n * @return {?string} Node name of the supplied markup.\n */\nfunction getNodeName(markup) {\n  var nodeNameMatch = markup.match(nodeNamePattern);\n  return nodeNameMatch && nodeNameMatch[1].toLowerCase();\n}\n\n/**\n * Creates an array containing the nodes rendered from the supplied markup. The\n * optionally supplied `handleScript` function will be invoked once for each\n * <script> element that is rendered. If no `handleScript` function is supplied,\n * an exception is thrown if any <script> elements are rendered.\n *\n * @param {string} markup A string of valid HTML markup.\n * @param {?function} handleScript Invoked once for each rendered <script>.\n * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.\n */\nfunction createNodesFromMarkup(markup, handleScript) {\n  var node = dummyNode;\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;\n  var nodeName = getNodeName(markup);\n\n  var wrap = nodeName && getMarkupWrap(nodeName);\n  if (wrap) {\n    node.innerHTML = wrap[1] + markup + wrap[2];\n\n    var wrapDepth = wrap[0];\n    while (wrapDepth--) {\n      node = node.lastChild;\n    }\n  } else {\n    node.innerHTML = markup;\n  }\n\n  var scripts = node.getElementsByTagName('script');\n  if (scripts.length) {\n    !handleScript ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;\n    createArrayFromMixed(scripts).forEach(handleScript);\n  }\n\n  var nodes = Array.from(node.childNodes);\n  while (node.lastChild) {\n    node.removeChild(node.lastChild);\n  }\n  return nodes;\n}\n\nmodule.exports = createNodesFromMarkup;\n},{\"147\":147,\"151\":151,\"157\":157,\"161\":161}],153:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nfunction makeEmptyFunction(arg) {\n  return function () {\n    return arg;\n  };\n}\n\n/**\n * This function accepts and discards inputs; it has no side effects. This is\n * primarily useful idiomatically for overridable function endpoints which\n * always need to be callable, since JS lacks a null-call idiom ala Cocoa.\n */\nvar emptyFunction = function emptyFunction() {};\n\nemptyFunction.thatReturns = makeEmptyFunction;\nemptyFunction.thatReturnsFalse = makeEmptyFunction(false);\nemptyFunction.thatReturnsTrue = makeEmptyFunction(true);\nemptyFunction.thatReturnsNull = makeEmptyFunction(null);\nemptyFunction.thatReturnsThis = function () {\n  return this;\n};\nemptyFunction.thatReturnsArgument = function (arg) {\n  return arg;\n};\n\nmodule.exports = emptyFunction;\n},{}],154:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyObject = {};\n\nif (\"development\" !== 'production') {\n  Object.freeze(emptyObject);\n}\n\nmodule.exports = emptyObject;\n},{}],155:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * @param {DOMElement} node input/textarea to focus\n */\n\nfunction focusNode(node) {\n  // IE8 can throw \"Can't move focus to the control because it is invisible,\n  // not enabled, or of a type that does not accept the focus.\" for all kinds of\n  // reasons that are too expensive and fragile to test.\n  try {\n    node.focus();\n  } catch (e) {}\n}\n\nmodule.exports = focusNode;\n},{}],156:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/* eslint-disable fb-www/typeof-undefined */\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n */\nfunction getActiveElement() /*?DOMElement*/{\n  if (typeof document === 'undefined') {\n    return null;\n  }\n  try {\n    return document.activeElement || document.body;\n  } catch (e) {\n    return document.body;\n  }\n}\n\nmodule.exports = getActiveElement;\n},{}],157:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/*eslint-disable fb-www/unsafe-html */\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to detect which wraps are necessary.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Some browsers cannot use `innerHTML` to render certain elements standalone,\n * so we wrap them, render the wrapped nodes, then extract the desired node.\n *\n * In IE8, certain elements cannot render alone, so wrap all elements ('*').\n */\n\nvar shouldWrap = {};\n\nvar selectWrap = [1, '<select multiple=\"true\">', '</select>'];\nvar tableWrap = [1, '<table>', '</table>'];\nvar trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];\n\nvar svgWrap = [1, '<svg xmlns=\"http://www.w3.org/2000/svg\">', '</svg>'];\n\nvar markupWrap = {\n  '*': [1, '?<div>', '</div>'],\n\n  'area': [1, '<map>', '</map>'],\n  'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],\n  'legend': [1, '<fieldset>', '</fieldset>'],\n  'param': [1, '<object>', '</object>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n\n  'optgroup': selectWrap,\n  'option': selectWrap,\n\n  'caption': tableWrap,\n  'colgroup': tableWrap,\n  'tbody': tableWrap,\n  'tfoot': tableWrap,\n  'thead': tableWrap,\n\n  'td': trWrap,\n  'th': trWrap\n};\n\n// Initialize the SVG elements since we know they'll always need to be wrapped\n// consistently. If they are created inside a <div> they will be initialized in\n// the wrong namespace (and will not display).\nvar svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];\nsvgElements.forEach(function (nodeName) {\n  markupWrap[nodeName] = svgWrap;\n  shouldWrap[nodeName] = true;\n});\n\n/**\n * Gets the markup wrap configuration for the supplied `nodeName`.\n *\n * NOTE: This lazily detects which wraps are necessary for the current browser.\n *\n * @param {string} nodeName Lowercase `nodeName`.\n * @return {?array} Markup wrap configuration, if applicable.\n */\nfunction getMarkupWrap(nodeName) {\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;\n  if (!markupWrap.hasOwnProperty(nodeName)) {\n    nodeName = '*';\n  }\n  if (!shouldWrap.hasOwnProperty(nodeName)) {\n    if (nodeName === '*') {\n      dummyNode.innerHTML = '<link />';\n    } else {\n      dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';\n    }\n    shouldWrap[nodeName] = !dummyNode.firstChild;\n  }\n  return shouldWrap[nodeName] ? markupWrap[nodeName] : null;\n}\n\nmodule.exports = getMarkupWrap;\n},{\"147\":147,\"161\":161}],158:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\n/**\n * Gets the scroll position of the supplied element or window.\n *\n * The return values are unbounded, unlike `getScrollPosition`. This means they\n * may be negative or exceed the element boundaries (which is possible using\n * inertial scrolling).\n *\n * @param {DOMWindow|DOMElement} scrollable\n * @return {object} Map with `x` and `y` keys.\n */\n\nfunction getUnboundedScrollPosition(scrollable) {\n  if (scrollable === window) {\n    return {\n      x: window.pageXOffset || document.documentElement.scrollLeft,\n      y: window.pageYOffset || document.documentElement.scrollTop\n    };\n  }\n  return {\n    x: scrollable.scrollLeft,\n    y: scrollable.scrollTop\n  };\n}\n\nmodule.exports = getUnboundedScrollPosition;\n},{}],159:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _uppercasePattern = /([A-Z])/g;\n\n/**\n * Hyphenates a camelcased string, for example:\n *\n *   > hyphenate('backgroundColor')\n *   < \"background-color\"\n *\n * For CSS style names, use `hyphenateStyleName` instead which works properly\n * with all vendor prefixes, including `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenate(string) {\n  return string.replace(_uppercasePattern, '-$1').toLowerCase();\n}\n\nmodule.exports = hyphenate;\n},{}],160:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar hyphenate = _dereq_(159);\n\nvar msPattern = /^ms-/;\n\n/**\n * Hyphenates a camelcased CSS property name, for example:\n *\n *   > hyphenateStyleName('backgroundColor')\n *   < \"background-color\"\n *   > hyphenateStyleName('MozTransition')\n *   < \"-moz-transition\"\n *   > hyphenateStyleName('msTransition')\n *   < \"-ms-transition\"\n *\n * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix\n * is converted to `-ms-`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenateStyleName(string) {\n  return hyphenate(string).replace(msPattern, '-ms-');\n}\n\nmodule.exports = hyphenateStyleName;\n},{\"159\":159}],161:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * Use invariant() to assert state which your program assumes to be true.\n *\n * Provide sprintf-style format (only %s is supported) and arguments\n * to provide information about what broke and what you were\n * expecting.\n *\n * The invariant message will be stripped in production, but the invariant\n * will remain to ensure logic does not differ in production.\n */\n\nfunction invariant(condition, format, a, b, c, d, e, f) {\n  if (\"development\" !== 'production') {\n    if (format === undefined) {\n      throw new Error('invariant requires an error message argument');\n    }\n  }\n\n  if (!condition) {\n    var error;\n    if (format === undefined) {\n      error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');\n    } else {\n      var args = [a, b, c, d, e, f];\n      var argIndex = 0;\n      error = new Error(format.replace(/%s/g, function () {\n        return args[argIndex++];\n      }));\n      error.name = 'Invariant Violation';\n    }\n\n    error.framesToPop = 1; // we don't care about invariant's own frame\n    throw error;\n  }\n}\n\nmodule.exports = invariant;\n},{}],162:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM node.\n */\nfunction isNode(object) {\n  return !!(object && (typeof Node === 'function' ? object instanceof Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));\n}\n\nmodule.exports = isNode;\n},{}],163:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar isNode = _dereq_(162);\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM text node.\n */\nfunction isTextNode(object) {\n  return isNode(object) && object.nodeType == 3;\n}\n\nmodule.exports = isTextNode;\n},{\"162\":162}],164:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks static-only\n */\n\n'use strict';\n\nvar invariant = _dereq_(161);\n\n/**\n * Constructs an enumeration with keys equal to their value.\n *\n * For example:\n *\n *   var COLORS = keyMirror({blue: null, red: null});\n *   var myColor = COLORS.blue;\n *   var isColorValid = !!COLORS[myColor];\n *\n * The last line could not be performed if the values of the generated enum were\n * not equal to their keys.\n *\n *   Input:  {key1: val1, key2: val2}\n *   Output: {key1: key1, key2: key2}\n *\n * @param {object} obj\n * @return {object}\n */\nvar keyMirror = function keyMirror(obj) {\n  var ret = {};\n  var key;\n  !(obj instanceof Object && !Array.isArray(obj)) ? \"development\" !== 'production' ? invariant(false, 'keyMirror(...): Argument must be an object.') : invariant(false) : void 0;\n  for (key in obj) {\n    if (!obj.hasOwnProperty(key)) {\n      continue;\n    }\n    ret[key] = key;\n  }\n  return ret;\n};\n\nmodule.exports = keyMirror;\n},{\"161\":161}],165:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/**\n * Allows extraction of a minified key. Let's the build system minify keys\n * without losing the ability to dynamically use key strings as values\n * themselves. Pass in an object with a single key/val pair and it will return\n * you the string key of that single record. Suppose you want to grab the\n * value for a key 'className' inside of an object. Key/val minification may\n * have aliased that key to be 'xa12'. keyOf({className: null}) will return\n * 'xa12' in that case. Resolve keys you want to use once at startup time, then\n * reuse those resolutions.\n */\nvar keyOf = function keyOf(oneKeyObj) {\n  var key;\n  for (key in oneKeyObj) {\n    if (!oneKeyObj.hasOwnProperty(key)) {\n      continue;\n    }\n    return key;\n  }\n  return null;\n};\n\nmodule.exports = keyOf;\n},{}],166:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Executes the provided `callback` once for each enumerable own property in the\n * object and constructs a new object from the results. The `callback` is\n * invoked with three arguments:\n *\n *  - the property value\n *  - the property name\n *  - the object being traversed\n *\n * Properties that are added after the call to `mapObject` will not be visited\n * by `callback`. If the values of existing properties are changed, the value\n * passed to `callback` will be the value at the time `mapObject` visits them.\n * Properties that are deleted before being visited are not visited.\n *\n * @grep function objectMap()\n * @grep function objMap()\n *\n * @param {?object} object\n * @param {function} callback\n * @param {*} context\n * @return {?object}\n */\nfunction mapObject(object, callback, context) {\n  if (!object) {\n    return null;\n  }\n  var result = {};\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result[name] = callback.call(context, object[name], name, object);\n    }\n  }\n  return result;\n}\n\nmodule.exports = mapObject;\n},{}],167:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n * @typechecks static-only\n */\n\n'use strict';\n\n/**\n * Memoizes the return value of a function that accepts one string argument.\n */\n\nfunction memoizeStringOnly(callback) {\n  var cache = {};\n  return function (string) {\n    if (!cache.hasOwnProperty(string)) {\n      cache[string] = callback.call(this, string);\n    }\n    return cache[string];\n  };\n}\n\nmodule.exports = memoizeStringOnly;\n},{}],168:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performance;\n\nif (ExecutionEnvironment.canUseDOM) {\n  performance = window.performance || window.msPerformance || window.webkitPerformance;\n}\n\nmodule.exports = performance || {};\n},{\"147\":147}],169:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar performance = _dereq_(168);\n\nvar performanceNow;\n\n/**\n * Detect if we can use `window.performance.now()` and gracefully fallback to\n * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now\n * because of Facebook's testing infrastructure.\n */\nif (performance.now) {\n  performanceNow = function performanceNow() {\n    return performance.now();\n  };\n} else {\n  performanceNow = function performanceNow() {\n    return Date.now();\n  };\n}\n\nmodule.exports = performanceNow;\n},{\"168\":168}],170:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n * \n */\n\n/*eslint-disable no-self-compare */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n\n/**\n * Performs equality by iterating through keys on an object and returning false\n * when any key has values which are not strictly equal between the arguments.\n * Returns true when the values of all keys are strictly equal.\n */\nfunction shallowEqual(objA, objB) {\n  if (is(objA, objB)) {\n    return true;\n  }\n\n  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n    return false;\n  }\n\n  var keysA = Object.keys(objA);\n  var keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (var i = 0; i < keysA.length; i++) {\n    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nmodule.exports = shallowEqual;\n},{}],171:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-2015, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Similar to invariant but only logs a warning if the condition is not met.\n * This can be used to log issues in development environments in critical\n * paths. Removing the logging code for production environments will keep the\n * same logic and follow the same code paths.\n */\n\nvar warning = emptyFunction;\n\nif (\"development\" !== 'production') {\n  warning = function warning(condition, format) {\n    for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n      args[_key - 2] = arguments[_key];\n    }\n\n    if (format === undefined) {\n      throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');\n    }\n\n    if (format.indexOf('Failed Composite propType: ') === 0) {\n      return; // Ignore CompositeComponent proptype check.\n    }\n\n    if (!condition) {\n      var argIndex = 0;\n      var message = 'Warning: ' + format.replace(/%s/g, function () {\n        return args[argIndex++];\n      });\n      if (typeof console !== 'undefined') {\n        console.error(message);\n      }\n      try {\n        // --- Welcome to debugging React ---\n        // This error was thrown as a convenience so that you can use this stack\n        // to find the callsite that caused this warning to fire.\n        throw new Error(message);\n      } catch (x) {}\n    }\n  };\n}\n\nmodule.exports = warning;\n},{\"153\":153}],172:[function(_dereq_,module,exports){\n'use strict';\n/* eslint-disable no-unused-vars */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc');  // eslint-disable-line\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (e) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (Object.getOwnPropertySymbols) {\n\t\t\tsymbols = Object.getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n\n},{}]},{},[93])(93)\n});"
  },
  {
    "path": "30-jstraining/demos/nightmare-demo/server.js",
    "content": "var httpServer = require('http-server');\nvar server = httpServer.createServer();\nserver.listen(8080);\nprocess.send('listening');\n"
  },
  {
    "path": "30-jstraining/demos/nightmare-demo/taobao.test.js",
    "content": "var Nightmare = require('nightmare');\nvar nightmare = Nightmare({ show: true });\n\nnightmare\n  .goto('https://www.taobao.com/')\n  .type('#q', '电视机')\n  .click('form[action*=\"/search\"] [type=submit]')\n  .wait('#spulist-grid')\n  .evaluate(function () {\n    return document.querySelector('#spulist-grid .grid-item .info-cont')\n      .textContent.trim();\n  })\n  .end()\n  .then(function (result) {\n    console.log(result);\n  })\n  .catch(function (error) {\n    console.error('Search failed:', error);\n  });\n"
  },
  {
    "path": "30-jstraining/demos/nightmare-demo/test.js",
    "content": "var Nightmare = require('nightmare');\nvar expect = require('chai').expect;\nvar fork = require('child_process').fork;\n\ndescribe('test index.html', function() {\n  var child;\n\n  before(function (done) {\n    child = fork('./server.js');\n    child.on('message', function (msg) {\n      if (msg === 'listening') {\n        done();\n      }\n    });\n  });\n\n  after(function () {\n    child.kill();\n  });\n\n  it('点击后标题改变', function (done) {\n    var nightmare = Nightmare({ show: true });\n    nightmare\n      .goto('http://127.0.0.1:8080/index.html')\n      .click('h1')\n      .wait(1000)\n      .evaluate(function () {\n        return document.querySelector('h1').textContent;\n      })\n      .end()\n      .then(function(text) {\n        expect(text).to.equal('Hello Clicked');\n        done();\n      })\n  });\n\n});\n\n"
  },
  {
    "path": "30-jstraining/demos/react-component-demo/index1.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\"></div>\n    <script type=\"text/babel\">\n  class MyTitle extends React.Component {\n    render() {\n      return <h1>Hello World</h1>;\n    }\n  };\n\n  ReactDOM.render(\n    <MyTitle/>,\n    document.getElementById('example')\n  );\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/react-component-demo/index2.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\"></div>\n    <script type=\"text/babel\">\n  class MyTitle extends React.Component {\n    render() {\n      return <h1 style={{color: this.props.color}}>Hello World</h1>;\n    }\n  };\n\n  ReactDOM.render(\n    <MyTitle color=\"red\" />,\n    document.getElementById('example')\n  );\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/react-component-demo/index3.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\"></div>\n    <script type=\"text/babel\">\n  class MyTitle extends React.Component {\n    constructor(...args) {\n      super(...args);\n      this.state = {\n        name: '访问者'\n      };\n    }\n\n    handleChange(e) {\n      let name = e.target.value;\n      this.setState({\n        name: name\n      });\n    }\n\n    render() {\n      return <div>\n        <input type=\"text\" onChange={this.handleChange.bind(this)} />\n        <p>你好，{this.state.name}</p>\n      </div>;\n    }\n  };\n\n  ReactDOM.render(\n    <MyTitle/>,\n    document.getElementById('example')\n  );\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/react-component-demo/index4.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\"></div>\n    <script type=\"text/babel\">\n  class MyTitle extends React.Component {\n    constructor(...args) {\n      super(...args);\n      this.state = {\n        text: 'World'\n      };\n    }\n\n    handleClick() {\n      this.setState({\n        text: 'Clicked'\n      });\n    }\n\n    render() {\n      return <h1 onClick={this.handleClick.bind(this)}>\n        {'Hello ' + this.state.text}\n      </h1>;\n    }\n  };\n\n  ReactDOM.render(\n    <MyTitle/>,\n    document.getElementById('example')\n  );\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/react-component-demo/react-dom.js",
    "content": "/**\n * ReactDOM v15.2.1\n *\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js\n;(function(f) {\n  // CommonJS\n  if (typeof exports === \"object\" && typeof module !== \"undefined\") {\n    module.exports = f(require('react'));\n\n  // RequireJS\n  } else if (typeof define === \"function\" && define.amd) {\n    define(['react'], f);\n\n  // <script>\n  } else {\n    var g;\n    if (typeof window !== \"undefined\") {\n      g = window;\n    } else if (typeof global !== \"undefined\") {\n      g = global;\n    } else if (typeof self !== \"undefined\") {\n      g = self;\n    } else {\n      // works providing we're not in \"use strict\";\n      // needed for Java 8 Nashorn\n      // see https://github.com/facebook/react/issues/3037\n      g = this;\n    }\n    g.ReactDOM = f(g.React);\n  }\n\n})(function(React) {\n  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n});\n"
  },
  {
    "path": "30-jstraining/demos/react-component-demo/react.js",
    "content": " /**\n  * React v15.2.1\n  */\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule AutoFocusUtils\n */\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar focusNode = _dereq_(155);\n\nvar AutoFocusUtils = {\n  focusDOMComponent: function () {\n    focusNode(ReactDOMComponentTree.getNodeFromInstance(this));\n  }\n};\n\nmodule.exports = AutoFocusUtils;\n},{\"155\":155,\"41\":41}],2:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule BeforeInputEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar FallbackCompositionState = _dereq_(21);\nvar SyntheticCompositionEvent = _dereq_(102);\nvar SyntheticInputEvent = _dereq_(106);\n\nvar keyOf = _dereq_(165);\n\nvar END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space\nvar START_KEYCODE = 229;\n\nvar canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;\n\nvar documentMode = null;\nif (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {\n  documentMode = document.documentMode;\n}\n\n// Webkit offers a very useful `textInput` event that can be used to\n// directly represent `beforeInput`. The IE `textinput` event is not as\n// useful, so we don't use it.\nvar canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();\n\n// In IE9+, we have access to composition events, but the data supplied\n// by the native compositionend event may be incorrect. Japanese ideographic\n// spaces, for instance (\\u3000) are not recorded correctly.\nvar useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);\n\n/**\n * Opera <= 12 includes TextEvent in window, but does not fire\n * text input events. Rely on keypress instead.\n */\nfunction isPresto() {\n  var opera = window.opera;\n  return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;\n}\n\nvar SPACEBAR_CODE = 32;\nvar SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\n// Events and their corresponding property names.\nvar eventTypes = {\n  beforeInput: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBeforeInput: null }),\n      captured: keyOf({ onBeforeInputCapture: null })\n    },\n    dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste]\n  },\n  compositionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionEnd: null }),\n      captured: keyOf({ onCompositionEndCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionStart: null }),\n      captured: keyOf({ onCompositionStartCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionUpdate: null }),\n      captured: keyOf({ onCompositionUpdateCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  }\n};\n\n// Track whether we've ever handled a keypress on the space key.\nvar hasSpaceKeypress = false;\n\n/**\n * Return whether a native keypress event is assumed to be a command.\n * This is required because Firefox fires `keypress` events for key commands\n * (cut, copy, select-all, etc.) even though no character is inserted.\n */\nfunction isKeypressCommand(nativeEvent) {\n  return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&\n  // ctrlKey && altKey is equivalent to AltGr, and is not a command.\n  !(nativeEvent.ctrlKey && nativeEvent.altKey);\n}\n\n/**\n * Translate native top level events into event types.\n *\n * @param {string} topLevelType\n * @return {object}\n */\nfunction getCompositionEventType(topLevelType) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionStart:\n      return eventTypes.compositionStart;\n    case topLevelTypes.topCompositionEnd:\n      return eventTypes.compositionEnd;\n    case topLevelTypes.topCompositionUpdate:\n      return eventTypes.compositionUpdate;\n  }\n}\n\n/**\n * Does our fallback best-guess model think this event signifies that\n * composition has begun?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionStart(topLevelType, nativeEvent) {\n  return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE;\n}\n\n/**\n * Does our fallback mode think that this event is the end of composition?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionEnd(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topKeyUp:\n      // Command keys insert or clear IME input.\n      return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;\n    case topLevelTypes.topKeyDown:\n      // Expect IME keyCode on each keydown. If we get any other\n      // code we must have exited earlier.\n      return nativeEvent.keyCode !== START_KEYCODE;\n    case topLevelTypes.topKeyPress:\n    case topLevelTypes.topMouseDown:\n    case topLevelTypes.topBlur:\n      // Events are not possible without cancelling IME.\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Google Input Tools provides composition data via a CustomEvent,\n * with the `data` property populated in the `detail` object. If this\n * is available on the event object, use it. If not, this is a plain\n * composition event and we have nothing special to extract.\n *\n * @param {object} nativeEvent\n * @return {?string}\n */\nfunction getDataFromCustomEvent(nativeEvent) {\n  var detail = nativeEvent.detail;\n  if (typeof detail === 'object' && 'data' in detail) {\n    return detail.data;\n  }\n  return null;\n}\n\n// Track the current IME composition fallback object, if any.\nvar currentComposition = null;\n\n/**\n * @return {?object} A SyntheticCompositionEvent.\n */\nfunction extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var eventType;\n  var fallbackData;\n\n  if (canUseCompositionEvent) {\n    eventType = getCompositionEventType(topLevelType);\n  } else if (!currentComposition) {\n    if (isFallbackCompositionStart(topLevelType, nativeEvent)) {\n      eventType = eventTypes.compositionStart;\n    }\n  } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n    eventType = eventTypes.compositionEnd;\n  }\n\n  if (!eventType) {\n    return null;\n  }\n\n  if (useFallbackCompositionData) {\n    // The current composition is stored statically and must not be\n    // overwritten while composition continues.\n    if (!currentComposition && eventType === eventTypes.compositionStart) {\n      currentComposition = FallbackCompositionState.getPooled(nativeEventTarget);\n    } else if (eventType === eventTypes.compositionEnd) {\n      if (currentComposition) {\n        fallbackData = currentComposition.getData();\n      }\n    }\n  }\n\n  var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);\n\n  if (fallbackData) {\n    // Inject data generated from fallback path into the synthetic event.\n    // This matches the property of native CompositionEventInterface.\n    event.data = fallbackData;\n  } else {\n    var customData = getDataFromCustomEvent(nativeEvent);\n    if (customData !== null) {\n      event.data = customData;\n    }\n  }\n\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The string corresponding to this `beforeInput` event.\n */\nfunction getNativeBeforeInputChars(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionEnd:\n      return getDataFromCustomEvent(nativeEvent);\n    case topLevelTypes.topKeyPress:\n      /**\n       * If native `textInput` events are available, our goal is to make\n       * use of them. However, there is a special case: the spacebar key.\n       * In Webkit, preventing default on a spacebar `textInput` event\n       * cancels character insertion, but it *also* causes the browser\n       * to fall back to its default spacebar behavior of scrolling the\n       * page.\n       *\n       * Tracking at:\n       * https://code.google.com/p/chromium/issues/detail?id=355103\n       *\n       * To avoid this issue, use the keypress event as if no `textInput`\n       * event is available.\n       */\n      var which = nativeEvent.which;\n      if (which !== SPACEBAR_CODE) {\n        return null;\n      }\n\n      hasSpaceKeypress = true;\n      return SPACEBAR_CHAR;\n\n    case topLevelTypes.topTextInput:\n      // Record the characters to be added to the DOM.\n      var chars = nativeEvent.data;\n\n      // If it's a spacebar character, assume that we have already handled\n      // it at the keypress level and bail immediately. Android Chrome\n      // doesn't give us keycodes, so we need to blacklist it.\n      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {\n        return null;\n      }\n\n      return chars;\n\n    default:\n      // For other native event types, do nothing.\n      return null;\n  }\n}\n\n/**\n * For browsers that do not provide the `textInput` event, extract the\n * appropriate string to use for SyntheticInputEvent.\n *\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The fallback string for this `beforeInput` event.\n */\nfunction getFallbackBeforeInputChars(topLevelType, nativeEvent) {\n  // If we are currently composing (IME) and using a fallback to do so,\n  // try to extract the composed characters from the fallback object.\n  if (currentComposition) {\n    if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n      var chars = currentComposition.getData();\n      FallbackCompositionState.release(currentComposition);\n      currentComposition = null;\n      return chars;\n    }\n    return null;\n  }\n\n  switch (topLevelType) {\n    case topLevelTypes.topPaste:\n      // If a paste event occurs after a keypress, throw out the input\n      // chars. Paste events should not lead to BeforeInput events.\n      return null;\n    case topLevelTypes.topKeyPress:\n      /**\n       * As of v27, Firefox may fire keypress events even when no character\n       * will be inserted. A few possibilities:\n       *\n       * - `which` is `0`. Arrow keys, Esc key, etc.\n       *\n       * - `which` is the pressed key code, but no char is available.\n       *   Ex: 'AltGr + d` in Polish. There is no modified character for\n       *   this key combination and no character is inserted into the\n       *   document, but FF fires the keypress for char code `100` anyway.\n       *   No `input` event will occur.\n       *\n       * - `which` is the pressed key code, but a command combination is\n       *   being used. Ex: `Cmd+C`. No character is inserted, and no\n       *   `input` event will occur.\n       */\n      if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {\n        return String.fromCharCode(nativeEvent.which);\n      }\n      return null;\n    case topLevelTypes.topCompositionEnd:\n      return useFallbackCompositionData ? null : nativeEvent.data;\n    default:\n      return null;\n  }\n}\n\n/**\n * Extract a SyntheticInputEvent for `beforeInput`, based on either native\n * `textInput` or fallback behavior.\n *\n * @return {?object} A SyntheticInputEvent.\n */\nfunction extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var chars;\n\n  if (canUseTextInputEvent) {\n    chars = getNativeBeforeInputChars(topLevelType, nativeEvent);\n  } else {\n    chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);\n  }\n\n  // If no characters are being inserted, no BeforeInput event should\n  // be fired.\n  if (!chars) {\n    return null;\n  }\n\n  var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);\n\n  event.data = chars;\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * Create an `onBeforeInput` event to match\n * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.\n *\n * This event plugin is based on the native `textInput` event\n * available in Chrome, Safari, Opera, and IE. This event fires after\n * `onKeyPress` and `onCompositionEnd`, but before `onInput`.\n *\n * `beforeInput` is spec'd but not implemented in any browsers, and\n * the `input` event does not provide any useful information about what has\n * actually been added, contrary to the spec. Thus, `textInput` is the best\n * available event to identify the characters that have actually been inserted\n * into the target node.\n *\n * This plugin is also responsible for emitting `composition` events, thus\n * allowing us to share composition fallback code for both `beforeInput` and\n * `composition` event types.\n */\nvar BeforeInputEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];\n  }\n};\n\nmodule.exports = BeforeInputEventPlugin;\n},{\"102\":102,\"106\":106,\"147\":147,\"16\":16,\"165\":165,\"20\":20,\"21\":21}],3:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSProperty\n */\n\n'use strict';\n\n/**\n * CSS properties which accept numbers but are not in units of \"px\".\n */\n\nvar isUnitlessNumber = {\n  animationIterationCount: true,\n  borderImageOutset: true,\n  borderImageSlice: true,\n  borderImageWidth: true,\n  boxFlex: true,\n  boxFlexGroup: true,\n  boxOrdinalGroup: true,\n  columnCount: true,\n  flex: true,\n  flexGrow: true,\n  flexPositive: true,\n  flexShrink: true,\n  flexNegative: true,\n  flexOrder: true,\n  gridRow: true,\n  gridColumn: true,\n  fontWeight: true,\n  lineClamp: true,\n  lineHeight: true,\n  opacity: true,\n  order: true,\n  orphans: true,\n  tabSize: true,\n  widows: true,\n  zIndex: true,\n  zoom: true,\n\n  // SVG-related properties\n  fillOpacity: true,\n  floodOpacity: true,\n  stopOpacity: true,\n  strokeDasharray: true,\n  strokeDashoffset: true,\n  strokeMiterlimit: true,\n  strokeOpacity: true,\n  strokeWidth: true\n};\n\n/**\n * @param {string} prefix vendor-specific prefix, eg: Webkit\n * @param {string} key style name, eg: transitionDuration\n * @return {string} style name prefixed with `prefix`, properly camelCased, eg:\n * WebkitTransitionDuration\n */\nfunction prefixKey(prefix, key) {\n  return prefix + key.charAt(0).toUpperCase() + key.substring(1);\n}\n\n/**\n * Support style names that may come passed in prefixed by adding permutations\n * of vendor prefixes.\n */\nvar prefixes = ['Webkit', 'ms', 'Moz', 'O'];\n\n// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an\n// infinite loop, because it iterates over the newly added props too.\nObject.keys(isUnitlessNumber).forEach(function (prop) {\n  prefixes.forEach(function (prefix) {\n    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];\n  });\n});\n\n/**\n * Most style properties can be unset by doing .style[prop] = '' but IE8\n * doesn't like doing that with shorthand properties so for the properties that\n * IE8 breaks on, which are listed here, we instead unset each of the\n * individual properties. See http://bugs.jquery.com/ticket/12385.\n * The 4-value 'clock' properties like margin, padding, border-width seem to\n * behave without any problems. Curiously, list-style works too without any\n * special prodding.\n */\nvar shorthandPropertyExpansions = {\n  background: {\n    backgroundAttachment: true,\n    backgroundColor: true,\n    backgroundImage: true,\n    backgroundPositionX: true,\n    backgroundPositionY: true,\n    backgroundRepeat: true\n  },\n  backgroundPosition: {\n    backgroundPositionX: true,\n    backgroundPositionY: true\n  },\n  border: {\n    borderWidth: true,\n    borderStyle: true,\n    borderColor: true\n  },\n  borderBottom: {\n    borderBottomWidth: true,\n    borderBottomStyle: true,\n    borderBottomColor: true\n  },\n  borderLeft: {\n    borderLeftWidth: true,\n    borderLeftStyle: true,\n    borderLeftColor: true\n  },\n  borderRight: {\n    borderRightWidth: true,\n    borderRightStyle: true,\n    borderRightColor: true\n  },\n  borderTop: {\n    borderTopWidth: true,\n    borderTopStyle: true,\n    borderTopColor: true\n  },\n  font: {\n    fontStyle: true,\n    fontVariant: true,\n    fontWeight: true,\n    fontSize: true,\n    lineHeight: true,\n    fontFamily: true\n  },\n  outline: {\n    outlineWidth: true,\n    outlineStyle: true,\n    outlineColor: true\n  }\n};\n\nvar CSSProperty = {\n  isUnitlessNumber: isUnitlessNumber,\n  shorthandPropertyExpansions: shorthandPropertyExpansions\n};\n\nmodule.exports = CSSProperty;\n},{}],4:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSPropertyOperations\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactInstrumentation = _dereq_(74);\n\nvar camelizeStyleName = _dereq_(149);\nvar dangerousStyleValue = _dereq_(120);\nvar hyphenateStyleName = _dereq_(160);\nvar memoizeStringOnly = _dereq_(167);\nvar warning = _dereq_(171);\n\nvar processStyleName = memoizeStringOnly(function (styleName) {\n  return hyphenateStyleName(styleName);\n});\n\nvar hasShorthandPropertyBug = false;\nvar styleFloatAccessor = 'cssFloat';\nif (ExecutionEnvironment.canUseDOM) {\n  var tempStyle = document.createElement('div').style;\n  try {\n    // IE8 throws \"Invalid argument.\" if resetting shorthand style properties.\n    tempStyle.font = '';\n  } catch (e) {\n    hasShorthandPropertyBug = true;\n  }\n  // IE8 only supports accessing cssFloat (standard) as styleFloat\n  if (document.documentElement.style.cssFloat === undefined) {\n    styleFloatAccessor = 'styleFloat';\n  }\n}\n\nif (\"development\" !== 'production') {\n  // 'msTransform' is correct, but the other prefixes should be capitalized\n  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;\n\n  // style values shouldn't contain a semicolon\n  var badStyleValueWithSemicolonPattern = /;\\s*$/;\n\n  var warnedStyleNames = {};\n  var warnedStyleValues = {};\n  var warnedForNaNValue = false;\n\n  var warnHyphenatedStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnBadVendoredStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnStyleValueWithSemicolon = function (name, value, owner) {\n    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {\n      return;\n    }\n\n    warnedStyleValues[value] = true;\n    \"development\" !== 'production' ? warning(false, 'Style property values shouldn\\'t contain a semicolon.%s ' + 'Try \"%s: %s\" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;\n  };\n\n  var warnStyleValueIsNaN = function (name, value, owner) {\n    if (warnedForNaNValue) {\n      return;\n    }\n\n    warnedForNaNValue = true;\n    \"development\" !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0;\n  };\n\n  var checkRenderMessage = function (owner) {\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' Check the render method of `' + name + '`.';\n      }\n    }\n    return '';\n  };\n\n  /**\n   * @param {string} name\n   * @param {*} value\n   * @param {ReactDOMComponent} component\n   */\n  var warnValidStyle = function (name, value, component) {\n    var owner;\n    if (component) {\n      owner = component._currentElement._owner;\n    }\n    if (name.indexOf('-') > -1) {\n      warnHyphenatedStyleName(name, owner);\n    } else if (badVendoredStyleNamePattern.test(name)) {\n      warnBadVendoredStyleName(name, owner);\n    } else if (badStyleValueWithSemicolonPattern.test(value)) {\n      warnStyleValueWithSemicolon(name, value, owner);\n    }\n\n    if (typeof value === 'number' && isNaN(value)) {\n      warnStyleValueIsNaN(name, value, owner);\n    }\n  };\n}\n\n/**\n * Operations for dealing with CSS properties.\n */\nvar CSSPropertyOperations = {\n\n  /**\n   * Serializes a mapping of style properties for use as inline styles:\n   *\n   *   > createMarkupForStyles({width: '200px', height: 0})\n   *   \"width:200px;height:0;\"\n   *\n   * Undefined values are ignored so that declarative programming is easier.\n   * The result should be HTML-escaped before insertion into the DOM.\n   *\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   * @return {?string}\n   */\n  createMarkupForStyles: function (styles, component) {\n    var serialized = '';\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      var styleValue = styles[styleName];\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styleValue, component);\n      }\n      if (styleValue != null) {\n        serialized += processStyleName(styleName) + ':';\n        serialized += dangerousStyleValue(styleName, styleValue, component) + ';';\n      }\n    }\n    return serialized || null;\n  },\n\n  /**\n   * Sets the value for multiple styles on a node.  If a value is specified as\n   * '' (empty string), the corresponding style property will be unset.\n   *\n   * @param {DOMElement} node\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   */\n  setValueForStyles: function (node, styles, component) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onHostOperation(component._debugID, 'update styles', styles);\n    }\n\n    var style = node.style;\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styles[styleName], component);\n      }\n      var styleValue = dangerousStyleValue(styleName, styles[styleName], component);\n      if (styleName === 'float' || styleName === 'cssFloat') {\n        styleName = styleFloatAccessor;\n      }\n      if (styleValue) {\n        style[styleName] = styleValue;\n      } else {\n        var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];\n        if (expansion) {\n          // Shorthand property that IE8 won't like unsetting, so unset each\n          // component to placate it\n          for (var individualStyleName in expansion) {\n            style[individualStyleName] = '';\n          }\n        } else {\n          style[styleName] = '';\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = CSSPropertyOperations;\n},{\"120\":120,\"147\":147,\"149\":149,\"160\":160,\"167\":167,\"171\":171,\"3\":3,\"74\":74}],5:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CallbackQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar invariant = _dereq_(161);\n\n/**\n * A specialized pseudo-event module to help keep track of components waiting to\n * be notified when their DOM representations are available for use.\n *\n * This implements `PooledClass`, so you should never need to instantiate this.\n * Instead, use `CallbackQueue.getPooled()`.\n *\n * @class ReactMountReady\n * @implements PooledClass\n * @internal\n */\nfunction CallbackQueue() {\n  this._callbacks = null;\n  this._contexts = null;\n}\n\n_assign(CallbackQueue.prototype, {\n\n  /**\n   * Enqueues a callback to be invoked when `notifyAll` is invoked.\n   *\n   * @param {function} callback Invoked when `notifyAll` is invoked.\n   * @param {?object} context Context to call `callback` with.\n   * @internal\n   */\n  enqueue: function (callback, context) {\n    this._callbacks = this._callbacks || [];\n    this._contexts = this._contexts || [];\n    this._callbacks.push(callback);\n    this._contexts.push(context);\n  },\n\n  /**\n   * Invokes all enqueued callbacks and clears the queue. This is invoked after\n   * the DOM representation of a component has been created or updated.\n   *\n   * @internal\n   */\n  notifyAll: function () {\n    var callbacks = this._callbacks;\n    var contexts = this._contexts;\n    if (callbacks) {\n      !(callbacks.length === contexts.length) ? \"development\" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : _prodInvariant('24') : void 0;\n      this._callbacks = null;\n      this._contexts = null;\n      for (var i = 0; i < callbacks.length; i++) {\n        callbacks[i].call(contexts[i]);\n      }\n      callbacks.length = 0;\n      contexts.length = 0;\n    }\n  },\n\n  checkpoint: function () {\n    return this._callbacks ? this._callbacks.length : 0;\n  },\n\n  rollback: function (len) {\n    if (this._callbacks) {\n      this._callbacks.length = len;\n      this._contexts.length = len;\n    }\n  },\n\n  /**\n   * Resets the internal queue.\n   *\n   * @internal\n   */\n  reset: function () {\n    this._callbacks = null;\n    this._contexts = null;\n  },\n\n  /**\n   * `PooledClass` looks for this.\n   */\n  destructor: function () {\n    this.reset();\n  }\n\n});\n\nPooledClass.addPoolingTo(CallbackQueue);\n\nmodule.exports = CallbackQueue;\n},{\"139\":139,\"161\":161,\"172\":172,\"25\":25}],6:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ChangeEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\nvar isEventSupported = _dereq_(135);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  change: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onChange: null }),\n      captured: keyOf({ onChangeCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topSelectionChange]\n  }\n};\n\n/**\n * For IE shims\n */\nvar activeElement = null;\nvar activeElementInst = null;\nvar activeElementValue = null;\nvar activeElementValueProp = null;\n\n/**\n * SECTION: handle `change` event\n */\nfunction shouldUseChangeEvent(elem) {\n  var nodeName = elem.nodeName && elem.nodeName.toLowerCase();\n  return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';\n}\n\nvar doesChangeEventBubble = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // See `handleChange` comment below\n  doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8);\n}\n\nfunction manualDispatchChangeEvent(nativeEvent) {\n  var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent));\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n\n  // If change and propertychange bubbled, we'd just bind to it like all the\n  // other events and have it go through ReactBrowserEventEmitter. Since it\n  // doesn't, we manually listen for the events and so we have to enqueue and\n  // process the abstract event manually.\n  //\n  // Batching is necessary here in order to ensure that all event handlers run\n  // before the next rerender (including event handlers attached to ancestor\n  // elements instead of directly on the input). Without this, controlled\n  // components don't work properly in conjunction with event bubbling because\n  // the component is rerendered and the value reverted before all the event\n  // handlers can run. See https://github.com/facebook/react/issues/708.\n  ReactUpdates.batchedUpdates(runEventInBatch, event);\n}\n\nfunction runEventInBatch(event) {\n  EventPluginHub.enqueueEvents(event);\n  EventPluginHub.processEventQueue(false);\n}\n\nfunction startWatchingForChangeEventIE8(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElement.attachEvent('onchange', manualDispatchChangeEvent);\n}\n\nfunction stopWatchingForChangeEventIE8() {\n  if (!activeElement) {\n    return;\n  }\n  activeElement.detachEvent('onchange', manualDispatchChangeEvent);\n  activeElement = null;\n  activeElementInst = null;\n}\n\nfunction getTargetInstForChangeEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topChange) {\n    return targetInst;\n  }\n}\nfunction handleEventsForChangeEventIE8(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForChangeEventIE8();\n    startWatchingForChangeEventIE8(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForChangeEventIE8();\n  }\n}\n\n/**\n * SECTION: handle `input` event\n */\nvar isInputEventSupported = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // IE9 claims to support the input event but fails to trigger it when\n  // deleting text, so we ignore its input events.\n  // IE10+ fire input events to often, such when a placeholder\n  // changes or when an input with a placeholder is focused.\n  isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11);\n}\n\n/**\n * (For IE <=11) Replacement getter/setter for the `value` property that gets\n * set on the active element.\n */\nvar newValueProp = {\n  get: function () {\n    return activeElementValueProp.get.call(this);\n  },\n  set: function (val) {\n    // Cast to a string so we can do equality checks.\n    activeElementValue = '' + val;\n    activeElementValueProp.set.call(this, val);\n  }\n};\n\n/**\n * (For IE <=11) Starts tracking propertychange events on the passed-in element\n * and override the value property so that we can distinguish user events from\n * value changes in JS.\n */\nfunction startWatchingForValueChange(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElementValue = target.value;\n  activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value');\n\n  // Not guarded in a canDefineProperty check: IE8 supports defineProperty only\n  // on DOM elements\n  Object.defineProperty(activeElement, 'value', newValueProp);\n  if (activeElement.attachEvent) {\n    activeElement.attachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.addEventListener('propertychange', handlePropertyChange, false);\n  }\n}\n\n/**\n * (For IE <=11) Removes the event listeners from the currently-tracked element,\n * if any exists.\n */\nfunction stopWatchingForValueChange() {\n  if (!activeElement) {\n    return;\n  }\n\n  // delete restores the original property definition\n  delete activeElement.value;\n\n  if (activeElement.detachEvent) {\n    activeElement.detachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.removeEventListener('propertychange', handlePropertyChange, false);\n  }\n\n  activeElement = null;\n  activeElementInst = null;\n  activeElementValue = null;\n  activeElementValueProp = null;\n}\n\n/**\n * (For IE <=11) Handles a propertychange event, sending a `change` event if\n * the value of the active element has changed.\n */\nfunction handlePropertyChange(nativeEvent) {\n  if (nativeEvent.propertyName !== 'value') {\n    return;\n  }\n  var value = nativeEvent.srcElement.value;\n  if (value === activeElementValue) {\n    return;\n  }\n  activeElementValue = value;\n\n  manualDispatchChangeEvent(nativeEvent);\n}\n\n/**\n * If a `change` event should be fired, returns the target's ID.\n */\nfunction getTargetInstForInputEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topInput) {\n    // In modern browsers (i.e., not IE8 or IE9), the input event is exactly\n    // what we want so fall through here and trigger an abstract event\n    return targetInst;\n  }\n}\n\nfunction handleEventsForInputEventIE(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // In IE8, we can capture almost all .value changes by adding a\n    // propertychange handler and looking for events with propertyName\n    // equal to 'value'\n    // In IE9-11, propertychange fires for most input events but is buggy and\n    // doesn't fire when text is deleted, but conveniently, selectionchange\n    // appears to fire in all of the remaining cases so we catch those and\n    // forward the event if the value has changed\n    // In either case, we don't want to call the event handler if the value\n    // is changed from JS so we redefine a setter for `.value` that updates\n    // our activeElementValue variable, allowing us to ignore those changes\n    //\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForValueChange();\n    startWatchingForValueChange(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForValueChange();\n  }\n}\n\n// For IE8 and IE9.\nfunction getTargetInstForInputEventIE(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) {\n    // On the selectionchange event, the target is just document which isn't\n    // helpful for us so just check activeElement instead.\n    //\n    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire\n    // propertychange on the first input event after setting `value` from a\n    // script and fires only keydown, keypress, keyup. Catching keyup usually\n    // gets it and catching keydown lets us fire an event for the first\n    // keystroke if user does a key repeat (it'll be a little delayed: right\n    // before the second keystroke). Other input methods (e.g., paste) seem to\n    // fire selectionchange normally.\n    if (activeElement && activeElement.value !== activeElementValue) {\n      activeElementValue = activeElement.value;\n      return activeElementInst;\n    }\n  }\n}\n\n/**\n * SECTION: handle `click` event\n */\nfunction shouldUseClickEvent(elem) {\n  // Use the `click` event to detect changes to checkbox and radio inputs.\n  // This approach works across all browsers, whereas `change` does not fire\n  // until `blur` in IE8.\n  return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');\n}\n\nfunction getTargetInstForClickEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topClick) {\n    return targetInst;\n  }\n}\n\n/**\n * This plugin creates an `onChange` event that normalizes change events\n * across form elements. This event fires at a time when it's possible to\n * change the element's value without seeing a flicker.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - select\n */\nvar ChangeEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    var getTargetInstFunc, handleEventFunc;\n    if (shouldUseChangeEvent(targetNode)) {\n      if (doesChangeEventBubble) {\n        getTargetInstFunc = getTargetInstForChangeEvent;\n      } else {\n        handleEventFunc = handleEventsForChangeEventIE8;\n      }\n    } else if (isTextInputElement(targetNode)) {\n      if (isInputEventSupported) {\n        getTargetInstFunc = getTargetInstForInputEvent;\n      } else {\n        getTargetInstFunc = getTargetInstForInputEventIE;\n        handleEventFunc = handleEventsForInputEventIE;\n      }\n    } else if (shouldUseClickEvent(targetNode)) {\n      getTargetInstFunc = getTargetInstForClickEvent;\n    }\n\n    if (getTargetInstFunc) {\n      var inst = getTargetInstFunc(topLevelType, targetInst);\n      if (inst) {\n        var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget);\n        event.type = 'change';\n        EventPropagators.accumulateTwoPhaseDispatches(event);\n        return event;\n      }\n    }\n\n    if (handleEventFunc) {\n      handleEventFunc(topLevelType, targetNode, targetInst);\n    }\n  }\n\n};\n\nmodule.exports = ChangeEventPlugin;\n},{\"104\":104,\"128\":128,\"135\":135,\"136\":136,\"147\":147,\"16\":16,\"165\":165,\"17\":17,\"20\":20,\"41\":41,\"95\":95}],7:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMChildrenOperations\n */\n\n'use strict';\n\nvar DOMLazyTree = _dereq_(8);\nvar Danger = _dereq_(12);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setInnerHTML = _dereq_(141);\nvar setTextContent = _dereq_(142);\n\nfunction getNodeAfter(parentNode, node) {\n  // Special case for text components, which return [open, close] comments\n  // from getHostNode.\n  if (Array.isArray(node)) {\n    node = node[1];\n  }\n  return node ? node.nextSibling : parentNode.firstChild;\n}\n\n/**\n * Inserts `childNode` as a child of `parentNode` at the `index`.\n *\n * @param {DOMElement} parentNode Parent node in which to insert.\n * @param {DOMElement} childNode Child node to insert.\n * @param {number} index Index at which to insert the child.\n * @internal\n */\nvar insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) {\n  // We rely exclusively on `insertBefore(node, null)` instead of also using\n  // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so\n  // we are careful to use `null`.)\n  parentNode.insertBefore(childNode, referenceNode);\n});\n\nfunction insertLazyTreeChildAt(parentNode, childTree, referenceNode) {\n  DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);\n}\n\nfunction moveChild(parentNode, childNode, referenceNode) {\n  if (Array.isArray(childNode)) {\n    moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);\n  } else {\n    insertChildAt(parentNode, childNode, referenceNode);\n  }\n}\n\nfunction removeChild(parentNode, childNode) {\n  if (Array.isArray(childNode)) {\n    var closingComment = childNode[1];\n    childNode = childNode[0];\n    removeDelimitedText(parentNode, childNode, closingComment);\n    parentNode.removeChild(closingComment);\n  }\n  parentNode.removeChild(childNode);\n}\n\nfunction moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) {\n  var node = openingComment;\n  while (true) {\n    var nextNode = node.nextSibling;\n    insertChildAt(parentNode, node, referenceNode);\n    if (node === closingComment) {\n      break;\n    }\n    node = nextNode;\n  }\n}\n\nfunction removeDelimitedText(parentNode, startNode, closingComment) {\n  while (true) {\n    var node = startNode.nextSibling;\n    if (node === closingComment) {\n      // The closing comment is removed by ReactMultiChild.\n      break;\n    } else {\n      parentNode.removeChild(node);\n    }\n  }\n}\n\nfunction replaceDelimitedText(openingComment, closingComment, stringText) {\n  var parentNode = openingComment.parentNode;\n  var nodeAfterComment = openingComment.nextSibling;\n  if (nodeAfterComment === closingComment) {\n    // There are no text nodes between the opening and closing comments; insert\n    // a new one if stringText isn't empty.\n    if (stringText) {\n      insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment);\n    }\n  } else {\n    if (stringText) {\n      // Set the text content of the first node after the opening comment, and\n      // remove all following nodes up until the closing comment.\n      setTextContent(nodeAfterComment, stringText);\n      removeDelimitedText(parentNode, nodeAfterComment, closingComment);\n    } else {\n      removeDelimitedText(parentNode, openingComment, closingComment);\n    }\n  }\n\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID, 'replace text', stringText);\n  }\n}\n\nvar dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup;\nif (\"development\" !== 'production') {\n  dangerouslyReplaceNodeWithMarkup = function (oldChild, markup, prevInstance) {\n    Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup);\n    if (prevInstance._debugID !== 0) {\n      ReactInstrumentation.debugTool.onHostOperation(prevInstance._debugID, 'replace with', markup.toString());\n    } else {\n      var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node);\n      if (nextInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(nextInstance._debugID, 'mount', markup.toString());\n      }\n    }\n  };\n}\n\n/**\n * Operations for updating with DOM children.\n */\nvar DOMChildrenOperations = {\n\n  dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,\n\n  replaceDelimitedText: replaceDelimitedText,\n\n  /**\n   * Updates a component's children by processing a series of updates. The\n   * update configurations are each expected to have a `parentNode` property.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  processUpdates: function (parentNode, updates) {\n    if (\"development\" !== 'production') {\n      var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID;\n    }\n\n    for (var k = 0; k < updates.length; k++) {\n      var update = updates[k];\n      switch (update.type) {\n        case ReactMultiChildUpdateTypes.INSERT_MARKUP:\n          insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'insert child', { toIndex: update.toIndex, content: update.content.toString() });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.MOVE_EXISTING:\n          moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'move child', { fromIndex: update.fromIndex, toIndex: update.toIndex });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.SET_MARKUP:\n          setInnerHTML(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace children', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.TEXT_CONTENT:\n          setTextContent(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace text', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.REMOVE_NODE:\n          removeChild(parentNode, update.fromNode);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'remove child', { fromIndex: update.fromIndex });\n          }\n          break;\n      }\n    }\n  }\n\n};\n\nmodule.exports = DOMChildrenOperations;\n},{\"119\":119,\"12\":12,\"141\":141,\"142\":142,\"41\":41,\"74\":74,\"79\":79,\"8\":8}],8:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMLazyTree\n */\n\n'use strict';\n\nvar DOMNamespaces = _dereq_(9);\nvar setInnerHTML = _dereq_(141);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setTextContent = _dereq_(142);\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\n/**\n * In IE (8-11) and Edge, appending nodes with no children is dramatically\n * faster than appending a full subtree, so we essentially queue up the\n * .appendChild calls here and apply them so each node is added to its parent\n * before any children are added.\n *\n * In other browsers, doing so is slower or neutral compared to the other order\n * (in Firefox, twice as slow) so we only do this inversion in IE.\n *\n * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.\n */\nvar enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\\bEdge\\/\\d/.test(navigator.userAgent);\n\nfunction insertTreeChildren(tree) {\n  if (!enableLazy) {\n    return;\n  }\n  var node = tree.node;\n  var children = tree.children;\n  if (children.length) {\n    for (var i = 0; i < children.length; i++) {\n      insertTreeBefore(node, children[i], null);\n    }\n  } else if (tree.html != null) {\n    setInnerHTML(node, tree.html);\n  } else if (tree.text != null) {\n    setTextContent(node, tree.text);\n  }\n}\n\nvar insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {\n  // DocumentFragments aren't actually part of the DOM after insertion so\n  // appending children won't update the DOM. We need to ensure the fragment\n  // is properly populated first, breaking out of our lazy approach for just\n  // this level. Also, some <object> plugins (like Flash Player) will read\n  // <param> nodes immediately upon insertion into the DOM, so <object>\n  // must also be populated prior to insertion into the DOM.\n  if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) {\n    insertTreeChildren(tree);\n    parentNode.insertBefore(tree.node, referenceNode);\n  } else {\n    parentNode.insertBefore(tree.node, referenceNode);\n    insertTreeChildren(tree);\n  }\n});\n\nfunction replaceChildWithTree(oldNode, newTree) {\n  oldNode.parentNode.replaceChild(newTree.node, oldNode);\n  insertTreeChildren(newTree);\n}\n\nfunction queueChild(parentTree, childTree) {\n  if (enableLazy) {\n    parentTree.children.push(childTree);\n  } else {\n    parentTree.node.appendChild(childTree.node);\n  }\n}\n\nfunction queueHTML(tree, html) {\n  if (enableLazy) {\n    tree.html = html;\n  } else {\n    setInnerHTML(tree.node, html);\n  }\n}\n\nfunction queueText(tree, text) {\n  if (enableLazy) {\n    tree.text = text;\n  } else {\n    setTextContent(tree.node, text);\n  }\n}\n\nfunction toString() {\n  return this.node.nodeName;\n}\n\nfunction DOMLazyTree(node) {\n  return {\n    node: node,\n    children: [],\n    html: null,\n    text: null,\n    toString: toString\n  };\n}\n\nDOMLazyTree.insertTreeBefore = insertTreeBefore;\nDOMLazyTree.replaceChildWithTree = replaceChildWithTree;\nDOMLazyTree.queueChild = queueChild;\nDOMLazyTree.queueHTML = queueHTML;\nDOMLazyTree.queueText = queueText;\n\nmodule.exports = DOMLazyTree;\n},{\"119\":119,\"141\":141,\"142\":142,\"9\":9}],9:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMNamespaces\n */\n\n'use strict';\n\nvar DOMNamespaces = {\n  html: 'http://www.w3.org/1999/xhtml',\n  mathml: 'http://www.w3.org/1998/Math/MathML',\n  svg: 'http://www.w3.org/2000/svg'\n};\n\nmodule.exports = DOMNamespaces;\n},{}],10:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMProperty\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nfunction checkMask(value, bitmask) {\n  return (value & bitmask) === bitmask;\n}\n\nvar DOMPropertyInjection = {\n  /**\n   * Mapping from normalized, camelcased property names to a configuration that\n   * specifies how the associated DOM property should be accessed or rendered.\n   */\n  MUST_USE_PROPERTY: 0x1,\n  HAS_BOOLEAN_VALUE: 0x4,\n  HAS_NUMERIC_VALUE: 0x8,\n  HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,\n  HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,\n\n  /**\n   * Inject some specialized knowledge about the DOM. This takes a config object\n   * with the following properties:\n   *\n   * isCustomAttribute: function that given an attribute name will return true\n   * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*\n   * attributes where it's impossible to enumerate all of the possible\n   * attribute names,\n   *\n   * Properties: object mapping DOM property name to one of the\n   * DOMPropertyInjection constants or null. If your attribute isn't in here,\n   * it won't get written to the DOM.\n   *\n   * DOMAttributeNames: object mapping React attribute name to the DOM\n   * attribute name. Attribute names not specified use the **lowercase**\n   * normalized name.\n   *\n   * DOMAttributeNamespaces: object mapping React attribute name to the DOM\n   * attribute namespace URL. (Attribute names not specified use no namespace.)\n   *\n   * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.\n   * Property names not specified use the normalized name.\n   *\n   * DOMMutationMethods: Properties that require special mutation methods. If\n   * `value` is undefined, the mutation method should unset the property.\n   *\n   * @param {object} domPropertyConfig the config as described above.\n   */\n  injectDOMPropertyConfig: function (domPropertyConfig) {\n    var Injection = DOMPropertyInjection;\n    var Properties = domPropertyConfig.Properties || {};\n    var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};\n    var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};\n    var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};\n    var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};\n\n    if (domPropertyConfig.isCustomAttribute) {\n      DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute);\n    }\n\n    for (var propName in Properties) {\n      !!DOMProperty.properties.hasOwnProperty(propName) ? \"development\" !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\\'re trying to inject DOM property \\'%s\\' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.', propName) : _prodInvariant('48', propName) : void 0;\n\n      var lowerCased = propName.toLowerCase();\n      var propConfig = Properties[propName];\n\n      var propertyInfo = {\n        attributeName: lowerCased,\n        attributeNamespace: null,\n        propertyName: propName,\n        mutationMethod: null,\n\n        mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),\n        hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),\n        hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),\n        hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),\n        hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE)\n      };\n      !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? \"development\" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : _prodInvariant('50', propName) : void 0;\n\n      if (\"development\" !== 'production') {\n        DOMProperty.getPossibleStandardName[lowerCased] = propName;\n      }\n\n      if (DOMAttributeNames.hasOwnProperty(propName)) {\n        var attributeName = DOMAttributeNames[propName];\n        propertyInfo.attributeName = attributeName;\n        if (\"development\" !== 'production') {\n          DOMProperty.getPossibleStandardName[attributeName] = propName;\n        }\n      }\n\n      if (DOMAttributeNamespaces.hasOwnProperty(propName)) {\n        propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];\n      }\n\n      if (DOMPropertyNames.hasOwnProperty(propName)) {\n        propertyInfo.propertyName = DOMPropertyNames[propName];\n      }\n\n      if (DOMMutationMethods.hasOwnProperty(propName)) {\n        propertyInfo.mutationMethod = DOMMutationMethods[propName];\n      }\n\n      DOMProperty.properties[propName] = propertyInfo;\n    }\n  }\n};\n\n/* eslint-disable max-len */\nvar ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\n/* eslint-enable max-len */\n\n/**\n * DOMProperty exports lookup objects that can be used like functions:\n *\n *   > DOMProperty.isValid['id']\n *   true\n *   > DOMProperty.isValid['foobar']\n *   undefined\n *\n * Although this may be confusing, it performs better in general.\n *\n * @see http://jsperf.com/key-exists\n * @see http://jsperf.com/key-missing\n */\nvar DOMProperty = {\n\n  ID_ATTRIBUTE_NAME: 'data-reactid',\n  ROOT_ATTRIBUTE_NAME: 'data-reactroot',\n\n  ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,\n  ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\\\-.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040',\n\n  /**\n   * Map from property \"standard name\" to an object with info about how to set\n   * the property in the DOM. Each object contains:\n   *\n   * attributeName:\n   *   Used when rendering markup or with `*Attribute()`.\n   * attributeNamespace\n   * propertyName:\n   *   Used on DOM node instances. (This includes properties that mutate due to\n   *   external factors.)\n   * mutationMethod:\n   *   If non-null, used instead of the property or `setAttribute()` after\n   *   initial render.\n   * mustUseProperty:\n   *   Whether the property must be accessed and mutated as an object property.\n   * hasBooleanValue:\n   *   Whether the property should be removed when set to a falsey value.\n   * hasNumericValue:\n   *   Whether the property must be numeric or parse as a numeric and should be\n   *   removed when set to a falsey value.\n   * hasPositiveNumericValue:\n   *   Whether the property must be positive numeric or parse as a positive\n   *   numeric and should be removed when set to a falsey value.\n   * hasOverloadedBooleanValue:\n   *   Whether the property can be used as a flag as well as with a value.\n   *   Removed when strictly equal to false; present without a value when\n   *   strictly equal to true; present with a value otherwise.\n   */\n  properties: {},\n\n  /**\n   * Mapping from lowercase property names to the properly cased version, used\n   * to warn in the case of missing properties. Available only in __DEV__.\n   * @type {Object}\n   */\n  getPossibleStandardName: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * All of the isCustomAttribute() functions that have been injected.\n   */\n  _isCustomAttributeFunctions: [],\n\n  /**\n   * Checks whether a property name is a custom attribute.\n   * @method\n   */\n  isCustomAttribute: function (attributeName) {\n    for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {\n      var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];\n      if (isCustomAttributeFn(attributeName)) {\n        return true;\n      }\n    }\n    return false;\n  },\n\n  injection: DOMPropertyInjection\n};\n\nmodule.exports = DOMProperty;\n},{\"139\":139,\"161\":161}],11:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMPropertyOperations\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInstrumentation = _dereq_(49);\nvar ReactInstrumentation = _dereq_(74);\n\nvar quoteAttributeValueForBrowser = _dereq_(138);\nvar warning = _dereq_(171);\n\nvar VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');\nvar illegalAttributeNameCache = {};\nvar validatedAttributeNameCache = {};\n\nfunction isAttributeNameSafe(attributeName) {\n  if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {\n    return true;\n  }\n  if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {\n    return false;\n  }\n  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {\n    validatedAttributeNameCache[attributeName] = true;\n    return true;\n  }\n  illegalAttributeNameCache[attributeName] = true;\n  \"development\" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;\n  return false;\n}\n\nfunction shouldIgnoreValue(propertyInfo, value) {\n  return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;\n}\n\n/**\n * Operations for dealing with DOM properties.\n */\nvar DOMPropertyOperations = {\n\n  /**\n   * Creates markup for the ID property.\n   *\n   * @param {string} id Unescaped ID.\n   * @return {string} Markup string.\n   */\n  createMarkupForID: function (id) {\n    return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);\n  },\n\n  setAttributeForID: function (node, id) {\n    node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);\n  },\n\n  createMarkupForRoot: function () {\n    return DOMProperty.ROOT_ATTRIBUTE_NAME + '=\"\"';\n  },\n\n  setAttributeForRoot: function (node) {\n    node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');\n  },\n\n  /**\n   * Creates markup for a property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {?string} Markup string, or null if the property was invalid.\n   */\n  createMarkupForProperty: function (name, value) {\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onCreateMarkupForProperty(name, value);\n    }\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      if (shouldIgnoreValue(propertyInfo, value)) {\n        return '';\n      }\n      var attributeName = propertyInfo.attributeName;\n      if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n        return attributeName + '=\"\"';\n      }\n      return attributeName + '=' + quoteAttributeValueForBrowser(value);\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      if (value == null) {\n        return '';\n      }\n      return name + '=' + quoteAttributeValueForBrowser(value);\n    }\n    return null;\n  },\n\n  /**\n   * Creates markup for a custom property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {string} Markup string, or empty string if the property was invalid.\n   */\n  createMarkupForCustomAttribute: function (name, value) {\n    if (!isAttributeNameSafe(name) || value == null) {\n      return '';\n    }\n    return name + '=' + quoteAttributeValueForBrowser(value);\n  },\n\n  /**\n   * Sets the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   * @param {*} value\n   */\n  setValueForProperty: function (node, name, value) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, value);\n      } else if (shouldIgnoreValue(propertyInfo, value)) {\n        this.deleteValueForProperty(node, name);\n        return;\n      } else if (propertyInfo.mustUseProperty) {\n        // Contrary to `setAttribute`, object properties are properly\n        // `toString`ed by IE8/9.\n        node[propertyInfo.propertyName] = value;\n      } else {\n        var attributeName = propertyInfo.attributeName;\n        var namespace = propertyInfo.attributeNamespace;\n        // `setAttribute` with objects becomes only `[object]` in IE8/9,\n        // ('' + value) makes it output the correct toString()-value.\n        if (namespace) {\n          node.setAttributeNS(namespace, attributeName, '' + value);\n        } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n          node.setAttribute(attributeName, '');\n        } else {\n          node.setAttribute(attributeName, '' + value);\n        }\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      DOMPropertyOperations.setValueForAttribute(node, name, value);\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onSetValueForProperty(node, name, value);\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  setValueForAttribute: function (node, name, value) {\n    if (!isAttributeNameSafe(name)) {\n      return;\n    }\n    if (value == null) {\n      node.removeAttribute(name);\n    } else {\n      node.setAttribute(name, '' + value);\n    }\n\n    if (\"development\" !== 'production') {\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  /**\n   * Deletes an attributes from a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForAttribute: function (node, name) {\n    node.removeAttribute(name);\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  },\n\n  /**\n   * Deletes the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForProperty: function (node, name) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, undefined);\n      } else if (propertyInfo.mustUseProperty) {\n        var propName = propertyInfo.propertyName;\n        if (propertyInfo.hasBooleanValue) {\n          node[propName] = false;\n        } else {\n          node[propName] = '';\n        }\n      } else {\n        node.removeAttribute(propertyInfo.attributeName);\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      node.removeAttribute(name);\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  }\n\n};\n\nmodule.exports = DOMPropertyOperations;\n},{\"10\":10,\"138\":138,\"171\":171,\"41\":41,\"49\":49,\"74\":74}],12:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Danger\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createNodesFromMarkup = _dereq_(152);\nvar emptyFunction = _dereq_(153);\nvar invariant = _dereq_(161);\n\nvar Danger = {\n\n  /**\n   * Replaces a node with a string of markup at its current position within its\n   * parent. The markup must render into a single root node.\n   *\n   * @param {DOMElement} oldChild Child node to replace.\n   * @param {string} markup Markup to render in place of the child node.\n   * @internal\n   */\n  dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) {\n    !ExecutionEnvironment.canUseDOM ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('56') : void 0;\n    !markup ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : _prodInvariant('57') : void 0;\n    !(oldChild.nodeName !== 'HTML') ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().') : _prodInvariant('58') : void 0;\n\n    if (typeof markup === 'string') {\n      var newChild = createNodesFromMarkup(markup, emptyFunction)[0];\n      oldChild.parentNode.replaceChild(newChild, oldChild);\n    } else {\n      DOMLazyTree.replaceChildWithTree(oldChild, markup);\n    }\n  }\n\n};\n\nmodule.exports = Danger;\n},{\"139\":139,\"147\":147,\"152\":152,\"153\":153,\"161\":161,\"8\":8}],13:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DefaultEventPluginOrder\n */\n\n'use strict';\n\nvar keyOf = _dereq_(165);\n\n/**\n * Module that is injectable into `EventPluginHub`, that specifies a\n * deterministic ordering of `EventPlugin`s. A convenient way to reason about\n * plugins, without having to package every one of them. This is better than\n * having plugins be ordered in the same order that they are injected because\n * that ordering would be influenced by the packaging order.\n * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that\n * preventing default on events is convenient in `SimpleEventPlugin` handlers.\n */\nvar DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })];\n\nmodule.exports = DefaultEventPluginOrder;\n},{\"165\":165}],14:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DisabledInputUtils\n */\n\n'use strict';\n\nvar disableableMouseListenerNames = {\n  onClick: true,\n  onDoubleClick: true,\n  onMouseDown: true,\n  onMouseMove: true,\n  onMouseUp: true,\n\n  onClickCapture: true,\n  onDoubleClickCapture: true,\n  onMouseDownCapture: true,\n  onMouseMoveCapture: true,\n  onMouseUpCapture: true\n};\n\n/**\n * Implements a host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar DisabledInputUtils = {\n  getHostProps: function (inst, props) {\n    if (!props.disabled) {\n      return props;\n    }\n\n    // Copy the props, except the mouse listeners\n    var hostProps = {};\n    for (var key in props) {\n      if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) {\n        hostProps[key] = props[key];\n      }\n    }\n\n    return hostProps;\n  }\n};\n\nmodule.exports = DisabledInputUtils;\n},{}],15:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EnterLeaveEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticMouseEvent = _dereq_(108);\n\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  mouseEnter: {\n    registrationName: keyOf({ onMouseEnter: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  },\n  mouseLeave: {\n    registrationName: keyOf({ onMouseLeave: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  }\n};\n\nvar EnterLeaveEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  /**\n   * For almost every interaction we care about, there will be both a top-level\n   * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that\n   * we do not extract duplicate events. However, moving the mouse into the\n   * browser from outside will not fire a `mouseout` event. In this case, we use\n   * the `mouseover` top-level event.\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {\n      return null;\n    }\n    if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) {\n      // Must not be a mouse in or mouse out - ignoring.\n      return null;\n    }\n\n    var win;\n    if (nativeEventTarget.window === nativeEventTarget) {\n      // `nativeEventTarget` is probably a window object.\n      win = nativeEventTarget;\n    } else {\n      // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n      var doc = nativeEventTarget.ownerDocument;\n      if (doc) {\n        win = doc.defaultView || doc.parentWindow;\n      } else {\n        win = window;\n      }\n    }\n\n    var from;\n    var to;\n    if (topLevelType === topLevelTypes.topMouseOut) {\n      from = targetInst;\n      var related = nativeEvent.relatedTarget || nativeEvent.toElement;\n      to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;\n    } else {\n      // Moving to a node from outside the window.\n      from = null;\n      to = targetInst;\n    }\n\n    if (from === to) {\n      // Nothing pertains to our managed components.\n      return null;\n    }\n\n    var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);\n    var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);\n\n    var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);\n    leave.type = 'mouseleave';\n    leave.target = fromNode;\n    leave.relatedTarget = toNode;\n\n    var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);\n    enter.type = 'mouseenter';\n    enter.target = toNode;\n    enter.relatedTarget = fromNode;\n\n    EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);\n\n    return [leave, enter];\n  }\n\n};\n\nmodule.exports = EnterLeaveEventPlugin;\n},{\"108\":108,\"16\":16,\"165\":165,\"20\":20,\"41\":41}],16:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventConstants\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar PropagationPhases = keyMirror({ bubbled: null, captured: null });\n\n/**\n * Types of raw signals from the browser caught at the top level.\n */\nvar topLevelTypes = keyMirror({\n  topAbort: null,\n  topAnimationEnd: null,\n  topAnimationIteration: null,\n  topAnimationStart: null,\n  topBlur: null,\n  topCanPlay: null,\n  topCanPlayThrough: null,\n  topChange: null,\n  topClick: null,\n  topCompositionEnd: null,\n  topCompositionStart: null,\n  topCompositionUpdate: null,\n  topContextMenu: null,\n  topCopy: null,\n  topCut: null,\n  topDoubleClick: null,\n  topDrag: null,\n  topDragEnd: null,\n  topDragEnter: null,\n  topDragExit: null,\n  topDragLeave: null,\n  topDragOver: null,\n  topDragStart: null,\n  topDrop: null,\n  topDurationChange: null,\n  topEmptied: null,\n  topEncrypted: null,\n  topEnded: null,\n  topError: null,\n  topFocus: null,\n  topInput: null,\n  topInvalid: null,\n  topKeyDown: null,\n  topKeyPress: null,\n  topKeyUp: null,\n  topLoad: null,\n  topLoadedData: null,\n  topLoadedMetadata: null,\n  topLoadStart: null,\n  topMouseDown: null,\n  topMouseMove: null,\n  topMouseOut: null,\n  topMouseOver: null,\n  topMouseUp: null,\n  topPaste: null,\n  topPause: null,\n  topPlay: null,\n  topPlaying: null,\n  topProgress: null,\n  topRateChange: null,\n  topReset: null,\n  topScroll: null,\n  topSeeked: null,\n  topSeeking: null,\n  topSelectionChange: null,\n  topStalled: null,\n  topSubmit: null,\n  topSuspend: null,\n  topTextInput: null,\n  topTimeUpdate: null,\n  topTouchCancel: null,\n  topTouchEnd: null,\n  topTouchMove: null,\n  topTouchStart: null,\n  topTransitionEnd: null,\n  topVolumeChange: null,\n  topWaiting: null,\n  topWheel: null\n});\n\nvar EventConstants = {\n  topLevelTypes: topLevelTypes,\n  PropagationPhases: PropagationPhases\n};\n\nmodule.exports = EventConstants;\n},{\"164\":164}],17:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginHub\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventPluginRegistry = _dereq_(18);\nvar EventPluginUtils = _dereq_(19);\nvar ReactErrorUtils = _dereq_(65);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar invariant = _dereq_(161);\n\n/**\n * Internal store for event listeners\n */\nvar listenerBank = {};\n\n/**\n * Internal queue of events that have accumulated their dispatches and are\n * waiting to have their dispatches executed.\n */\nvar eventQueue = null;\n\n/**\n * Dispatches an event and releases it back into the pool, unless persistent.\n *\n * @param {?object} event Synthetic event to be dispatched.\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @private\n */\nvar executeDispatchesAndRelease = function (event, simulated) {\n  if (event) {\n    EventPluginUtils.executeDispatchesInOrder(event, simulated);\n\n    if (!event.isPersistent()) {\n      event.constructor.release(event);\n    }\n  }\n};\nvar executeDispatchesAndReleaseSimulated = function (e) {\n  return executeDispatchesAndRelease(e, true);\n};\nvar executeDispatchesAndReleaseTopLevel = function (e) {\n  return executeDispatchesAndRelease(e, false);\n};\n\n/**\n * This is a unified interface for event plugins to be installed and configured.\n *\n * Event plugins can implement the following properties:\n *\n *   `extractEvents` {function(string, DOMEventTarget, string, object): *}\n *     Required. When a top-level event is fired, this method is expected to\n *     extract synthetic events that will in turn be queued and dispatched.\n *\n *   `eventTypes` {object}\n *     Optional, plugins that fire events must publish a mapping of registration\n *     names that are used to register listeners. Values of this mapping must\n *     be objects that contain `registrationName` or `phasedRegistrationNames`.\n *\n *   `executeDispatch` {function(object, function, string)}\n *     Optional, allows plugins to override how an event gets dispatched. By\n *     default, the listener is simply invoked.\n *\n * Each plugin that is injected into `EventsPluginHub` is immediately operable.\n *\n * @public\n */\nvar EventPluginHub = {\n\n  /**\n   * Methods for injecting dependencies.\n   */\n  injection: {\n\n    /**\n     * @param {array} InjectedEventPluginOrder\n     * @public\n     */\n    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,\n\n    /**\n     * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n     */\n    injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName\n\n  },\n\n  /**\n   * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {function} listener The callback to store.\n   */\n  putListener: function (inst, registrationName, listener) {\n    !(typeof listener === 'function') ? \"development\" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : _prodInvariant('94', registrationName, typeof listener) : void 0;\n\n    var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});\n    bankForRegistrationName[inst._rootNodeID] = listener;\n\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.didPutListener) {\n      PluginModule.didPutListener(inst, registrationName, listener);\n    }\n  },\n\n  /**\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @return {?function} The stored callback.\n   */\n  getListener: function (inst, registrationName) {\n    var bankForRegistrationName = listenerBank[registrationName];\n    return bankForRegistrationName && bankForRegistrationName[inst._rootNodeID];\n  },\n\n  /**\n   * Deletes a listener from the registration bank.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   */\n  deleteListener: function (inst, registrationName) {\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.willDeleteListener) {\n      PluginModule.willDeleteListener(inst, registrationName);\n    }\n\n    var bankForRegistrationName = listenerBank[registrationName];\n    // TODO: This should never be null -- when is it?\n    if (bankForRegistrationName) {\n      delete bankForRegistrationName[inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Deletes all listeners for the DOM element with the supplied ID.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   */\n  deleteAllListeners: function (inst) {\n    for (var registrationName in listenerBank) {\n      if (!listenerBank.hasOwnProperty(registrationName)) {\n        continue;\n      }\n\n      if (!listenerBank[registrationName][inst._rootNodeID]) {\n        continue;\n      }\n\n      var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n      if (PluginModule && PluginModule.willDeleteListener) {\n        PluginModule.willDeleteListener(inst, registrationName);\n      }\n\n      delete listenerBank[registrationName][inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Allows registered plugins an opportunity to extract events from top-level\n   * native browser events.\n   *\n   * @return {*} An accumulation of synthetic events.\n   * @internal\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events;\n    var plugins = EventPluginRegistry.plugins;\n    for (var i = 0; i < plugins.length; i++) {\n      // Not every plugin in the ordering may be loaded at runtime.\n      var possiblePlugin = plugins[i];\n      if (possiblePlugin) {\n        var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n        if (extractedEvents) {\n          events = accumulateInto(events, extractedEvents);\n        }\n      }\n    }\n    return events;\n  },\n\n  /**\n   * Enqueues a synthetic event that should be dispatched when\n   * `processEventQueue` is invoked.\n   *\n   * @param {*} events An accumulation of synthetic events.\n   * @internal\n   */\n  enqueueEvents: function (events) {\n    if (events) {\n      eventQueue = accumulateInto(eventQueue, events);\n    }\n  },\n\n  /**\n   * Dispatches all synthetic events on the event queue.\n   *\n   * @internal\n   */\n  processEventQueue: function (simulated) {\n    // Set `eventQueue` to null before processing it so that we can tell if more\n    // events get enqueued while processing.\n    var processingEventQueue = eventQueue;\n    eventQueue = null;\n    if (simulated) {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);\n    } else {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);\n    }\n    !!eventQueue ? \"development\" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : _prodInvariant('95') : void 0;\n    // This would be a good time to rethrow if any of the event handlers threw.\n    ReactErrorUtils.rethrowCaughtError();\n  },\n\n  /**\n   * These are needed for tests only. Do not use!\n   */\n  __purge: function () {\n    listenerBank = {};\n  },\n\n  __getListenerBank: function () {\n    return listenerBank;\n  }\n\n};\n\nmodule.exports = EventPluginHub;\n},{\"115\":115,\"124\":124,\"139\":139,\"161\":161,\"18\":18,\"19\":19,\"65\":65}],18:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginRegistry\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Injectable ordering of event plugins.\n */\nvar EventPluginOrder = null;\n\n/**\n * Injectable mapping from names to event plugin modules.\n */\nvar namesToPlugins = {};\n\n/**\n * Recomputes the plugin list using the injected plugins and plugin ordering.\n *\n * @private\n */\nfunction recomputePluginOrdering() {\n  if (!EventPluginOrder) {\n    // Wait until an `EventPluginOrder` is injected.\n    return;\n  }\n  for (var pluginName in namesToPlugins) {\n    var PluginModule = namesToPlugins[pluginName];\n    var pluginIndex = EventPluginOrder.indexOf(pluginName);\n    !(pluginIndex > -1) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0;\n    if (EventPluginRegistry.plugins[pluginIndex]) {\n      continue;\n    }\n    !PluginModule.extractEvents ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0;\n    EventPluginRegistry.plugins[pluginIndex] = PluginModule;\n    var publishedEvents = PluginModule.eventTypes;\n    for (var eventName in publishedEvents) {\n      !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('98', eventName, pluginName) : void 0;\n    }\n  }\n}\n\n/**\n * Publishes an event so that it can be dispatched by the supplied plugin.\n *\n * @param {object} dispatchConfig Dispatch configuration for the event.\n * @param {object} PluginModule Plugin publishing the event.\n * @return {boolean} True if the event was successfully published.\n * @private\n */\nfunction publishEventForPlugin(dispatchConfig, PluginModule, eventName) {\n  !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0;\n  EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;\n\n  var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;\n  if (phasedRegistrationNames) {\n    for (var phaseName in phasedRegistrationNames) {\n      if (phasedRegistrationNames.hasOwnProperty(phaseName)) {\n        var phasedRegistrationName = phasedRegistrationNames[phaseName];\n        publishRegistrationName(phasedRegistrationName, PluginModule, eventName);\n      }\n    }\n    return true;\n  } else if (dispatchConfig.registrationName) {\n    publishRegistrationName(dispatchConfig.registrationName, PluginModule, eventName);\n    return true;\n  }\n  return false;\n}\n\n/**\n * Publishes a registration name that is used to identify dispatched events and\n * can be used with `EventPluginHub.putListener` to register listeners.\n *\n * @param {string} registrationName Registration name to add.\n * @param {object} PluginModule Plugin publishing the event.\n * @private\n */\nfunction publishRegistrationName(registrationName, PluginModule, eventName) {\n  !!EventPluginRegistry.registrationNameModules[registrationName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0;\n  EventPluginRegistry.registrationNameModules[registrationName] = PluginModule;\n  EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies;\n\n  if (\"development\" !== 'production') {\n    var lowerCasedName = registrationName.toLowerCase();\n    EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;\n\n    if (registrationName === 'onDoubleClick') {\n      EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;\n    }\n  }\n}\n\n/**\n * Registers plugins so that they can extract and dispatch events.\n *\n * @see {EventPluginHub}\n */\nvar EventPluginRegistry = {\n\n  /**\n   * Ordered list of injected plugins.\n   */\n  plugins: [],\n\n  /**\n   * Mapping from event name to dispatch config\n   */\n  eventNameDispatchConfigs: {},\n\n  /**\n   * Mapping from registration name to plugin module\n   */\n  registrationNameModules: {},\n\n  /**\n   * Mapping from registration name to event name\n   */\n  registrationNameDependencies: {},\n\n  /**\n   * Mapping from lowercase registration names to the properly cased version,\n   * used to warn in the case of missing event handlers. Available\n   * only in __DEV__.\n   * @type {Object}\n   */\n  possibleRegistrationNames: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * Injects an ordering of plugins (by plugin name). This allows the ordering\n   * to be decoupled from injection of the actual plugins so that ordering is\n   * always deterministic regardless of packaging, on-the-fly injection, etc.\n   *\n   * @param {array} InjectedEventPluginOrder\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginOrder}\n   */\n  injectEventPluginOrder: function (InjectedEventPluginOrder) {\n    !!EventPluginOrder ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : _prodInvariant('101') : void 0;\n    // Clone the ordering so it cannot be dynamically mutated.\n    EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);\n    recomputePluginOrdering();\n  },\n\n  /**\n   * Injects plugins to be used by `EventPluginHub`. The plugin names must be\n   * in the ordering injected by `injectEventPluginOrder`.\n   *\n   * Plugins can be injected as part of page initialization or on-the-fly.\n   *\n   * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginsByName}\n   */\n  injectEventPluginsByName: function (injectedNamesToPlugins) {\n    var isOrderingDirty = false;\n    for (var pluginName in injectedNamesToPlugins) {\n      if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {\n        continue;\n      }\n      var PluginModule = injectedNamesToPlugins[pluginName];\n      if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== PluginModule) {\n        !!namesToPlugins[pluginName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0;\n        namesToPlugins[pluginName] = PluginModule;\n        isOrderingDirty = true;\n      }\n    }\n    if (isOrderingDirty) {\n      recomputePluginOrdering();\n    }\n  },\n\n  /**\n   * Looks up the plugin for the supplied event.\n   *\n   * @param {object} event A synthetic event.\n   * @return {?object} The plugin that created the supplied event.\n   * @internal\n   */\n  getPluginModuleForEvent: function (event) {\n    var dispatchConfig = event.dispatchConfig;\n    if (dispatchConfig.registrationName) {\n      return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null;\n    }\n    for (var phase in dispatchConfig.phasedRegistrationNames) {\n      if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) {\n        continue;\n      }\n      var PluginModule = EventPluginRegistry.registrationNameModules[dispatchConfig.phasedRegistrationNames[phase]];\n      if (PluginModule) {\n        return PluginModule;\n      }\n    }\n    return null;\n  },\n\n  /**\n   * Exposed for unit testing.\n   * @private\n   */\n  _resetEventPlugins: function () {\n    EventPluginOrder = null;\n    for (var pluginName in namesToPlugins) {\n      if (namesToPlugins.hasOwnProperty(pluginName)) {\n        delete namesToPlugins[pluginName];\n      }\n    }\n    EventPluginRegistry.plugins.length = 0;\n\n    var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs;\n    for (var eventName in eventNameDispatchConfigs) {\n      if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {\n        delete eventNameDispatchConfigs[eventName];\n      }\n    }\n\n    var registrationNameModules = EventPluginRegistry.registrationNameModules;\n    for (var registrationName in registrationNameModules) {\n      if (registrationNameModules.hasOwnProperty(registrationName)) {\n        delete registrationNameModules[registrationName];\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames;\n      for (var lowerCasedName in possibleRegistrationNames) {\n        if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) {\n          delete possibleRegistrationNames[lowerCasedName];\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = EventPluginRegistry;\n},{\"139\":139,\"161\":161}],19:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar ReactErrorUtils = _dereq_(65);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Injected dependencies:\n */\n\n/**\n * - `ComponentTree`: [required] Module that can convert between React instances\n *   and actual node references.\n */\nvar ComponentTree;\nvar TreeTraversal;\nvar injection = {\n  injectComponentTree: function (Injected) {\n    ComponentTree = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;\n    }\n  },\n  injectTreeTraversal: function (Injected) {\n    TreeTraversal = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;\n    }\n  }\n};\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nfunction isEndish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel;\n}\n\nfunction isMoveish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove;\n}\nfunction isStartish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart;\n}\n\nvar validateEventDispatches;\nif (\"development\" !== 'production') {\n  validateEventDispatches = function (event) {\n    var dispatchListeners = event._dispatchListeners;\n    var dispatchInstances = event._dispatchInstances;\n\n    var listenersIsArr = Array.isArray(dispatchListeners);\n    var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;\n\n    var instancesIsArr = Array.isArray(dispatchInstances);\n    var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;\n\n    \"development\" !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;\n  };\n}\n\n/**\n * Dispatch the event to the listener.\n * @param {SyntheticEvent} event SyntheticEvent to handle\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @param {function} listener Application-level callback\n * @param {*} inst Internal component instance\n */\nfunction executeDispatch(event, simulated, listener, inst) {\n  var type = event.type || 'unknown-event';\n  event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);\n  if (simulated) {\n    ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);\n  } else {\n    ReactErrorUtils.invokeGuardedCallback(type, listener, event);\n  }\n  event.currentTarget = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches.\n */\nfunction executeDispatchesInOrder(event, simulated) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);\n    }\n  } else if (dispatchListeners) {\n    executeDispatch(event, simulated, dispatchListeners, dispatchInstances);\n  }\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches, but stops\n * at the first dispatch execution returning true, and returns that id.\n *\n * @return {?string} id of the first dispatch execution who's listener returns\n * true, or null if no listener returned true.\n */\nfunction executeDispatchesInOrderStopAtTrueImpl(event) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      if (dispatchListeners[i](event, dispatchInstances[i])) {\n        return dispatchInstances[i];\n      }\n    }\n  } else if (dispatchListeners) {\n    if (dispatchListeners(event, dispatchInstances)) {\n      return dispatchInstances;\n    }\n  }\n  return null;\n}\n\n/**\n * @see executeDispatchesInOrderStopAtTrueImpl\n */\nfunction executeDispatchesInOrderStopAtTrue(event) {\n  var ret = executeDispatchesInOrderStopAtTrueImpl(event);\n  event._dispatchInstances = null;\n  event._dispatchListeners = null;\n  return ret;\n}\n\n/**\n * Execution of a \"direct\" dispatch - there must be at most one dispatch\n * accumulated on the event or it is considered an error. It doesn't really make\n * sense for an event with multiple dispatches (bubbled) to keep track of the\n * return values at each dispatch execution, but it does tend to make sense when\n * dealing with \"direct\" dispatches.\n *\n * @return {*} The return value of executing the single dispatch.\n */\nfunction executeDirectDispatch(event) {\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  var dispatchListener = event._dispatchListeners;\n  var dispatchInstance = event._dispatchInstances;\n  !!Array.isArray(dispatchListener) ? \"development\" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0;\n  event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;\n  var res = dispatchListener ? dispatchListener(event) : null;\n  event.currentTarget = null;\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n  return res;\n}\n\n/**\n * @param {SyntheticEvent} event\n * @return {boolean} True iff number of dispatches accumulated is greater than 0.\n */\nfunction hasDispatches(event) {\n  return !!event._dispatchListeners;\n}\n\n/**\n * General utilities that are useful in creating custom Event Plugins.\n */\nvar EventPluginUtils = {\n  isEndish: isEndish,\n  isMoveish: isMoveish,\n  isStartish: isStartish,\n\n  executeDirectDispatch: executeDirectDispatch,\n  executeDispatchesInOrder: executeDispatchesInOrder,\n  executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,\n  hasDispatches: hasDispatches,\n\n  getInstanceFromNode: function (node) {\n    return ComponentTree.getInstanceFromNode(node);\n  },\n  getNodeFromInstance: function (node) {\n    return ComponentTree.getNodeFromInstance(node);\n  },\n  isAncestor: function (a, b) {\n    return TreeTraversal.isAncestor(a, b);\n  },\n  getLowestCommonAncestor: function (a, b) {\n    return TreeTraversal.getLowestCommonAncestor(a, b);\n  },\n  getParentInstance: function (inst) {\n    return TreeTraversal.getParentInstance(inst);\n  },\n  traverseTwoPhase: function (target, fn, arg) {\n    return TreeTraversal.traverseTwoPhase(target, fn, arg);\n  },\n  traverseEnterLeave: function (from, to, fn, argFrom, argTo) {\n    return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);\n  },\n\n  injection: injection\n};\n\nmodule.exports = EventPluginUtils;\n},{\"139\":139,\"16\":16,\"161\":161,\"171\":171,\"65\":65}],20:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPropagators\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar warning = _dereq_(171);\n\nvar PropagationPhases = EventConstants.PropagationPhases;\nvar getListener = EventPluginHub.getListener;\n\n/**\n * Some event types have a notion of different registration names for different\n * \"phases\" of propagation. This finds listeners by a given phase.\n */\nfunction listenerAtPhase(inst, event, propagationPhase) {\n  var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];\n  return getListener(inst, registrationName);\n}\n\n/**\n * Tags a `SyntheticEvent` with dispatched listeners. Creating this function\n * here, allows us to not have to bind or create functions for each event.\n * Mutating the event's members allows us to not have to create a wrapping\n * \"dispatch\" object that pairs the event with the listener.\n */\nfunction accumulateDirectionalDispatches(inst, upwards, event) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;\n  }\n  var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured;\n  var listener = listenerAtPhase(inst, event, phase);\n  if (listener) {\n    event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n  }\n}\n\n/**\n * Collect dispatches (must be entirely collected before dispatching - see unit\n * tests). Lazily allocate the array to conserve memory.  We must loop through\n * each event and perform the traversal for each one. We cannot perform a\n * single traversal for the entire collection of events because each event may\n * have a different target.\n */\nfunction accumulateTwoPhaseDispatchesSingle(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.\n */\nfunction accumulateTwoPhaseDispatchesSingleSkipTarget(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    var targetInst = event._targetInst;\n    var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;\n    EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Accumulates without regard to direction, does not look for phased\n * registration names. Same as `accumulateDirectDispatchesSingle` but without\n * requiring that the `dispatchMarker` be the same as the dispatched ID.\n */\nfunction accumulateDispatches(inst, ignoredDirection, event) {\n  if (event && event.dispatchConfig.registrationName) {\n    var registrationName = event.dispatchConfig.registrationName;\n    var listener = getListener(inst, registrationName);\n    if (listener) {\n      event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n    }\n  }\n}\n\n/**\n * Accumulates dispatches on an `SyntheticEvent`, but only for the\n * `dispatchMarker`.\n * @param {SyntheticEvent} event\n */\nfunction accumulateDirectDispatchesSingle(event) {\n  if (event && event.dispatchConfig.registrationName) {\n    accumulateDispatches(event._targetInst, null, event);\n  }\n}\n\nfunction accumulateTwoPhaseDispatches(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);\n}\n\nfunction accumulateTwoPhaseDispatchesSkipTarget(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);\n}\n\nfunction accumulateEnterLeaveDispatches(leave, enter, from, to) {\n  EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);\n}\n\nfunction accumulateDirectDispatches(events) {\n  forEachAccumulated(events, accumulateDirectDispatchesSingle);\n}\n\n/**\n * A small set of propagation patterns, each of which will accept a small amount\n * of information, and generate a set of \"dispatch ready event objects\" - which\n * are sets of events that have already been annotated with a set of dispatched\n * listener functions/ids. The API is designed this way to discourage these\n * propagation strategies from actually executing the dispatches, since we\n * always want to collect the entire set of dispatches before executing event a\n * single one.\n *\n * @constructor EventPropagators\n */\nvar EventPropagators = {\n  accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,\n  accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,\n  accumulateDirectDispatches: accumulateDirectDispatches,\n  accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches\n};\n\nmodule.exports = EventPropagators;\n},{\"115\":115,\"124\":124,\"16\":16,\"17\":17,\"171\":171,\"19\":19}],21:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule FallbackCompositionState\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * This helper class stores information about text content of a target node,\n * allowing comparison of content before and after a given event.\n *\n * Identify the node where selection currently begins, then observe\n * both its text content and its current position in the DOM. Since the\n * browser may natively replace the target node during composition, we can\n * use its position to find its replacement.\n *\n * @param {DOMEventTarget} root\n */\nfunction FallbackCompositionState(root) {\n  this._root = root;\n  this._startText = this.getText();\n  this._fallbackText = null;\n}\n\n_assign(FallbackCompositionState.prototype, {\n  destructor: function () {\n    this._root = null;\n    this._startText = null;\n    this._fallbackText = null;\n  },\n\n  /**\n   * Get current text of input.\n   *\n   * @return {string}\n   */\n  getText: function () {\n    if ('value' in this._root) {\n      return this._root.value;\n    }\n    return this._root[getTextContentAccessor()];\n  },\n\n  /**\n   * Determine the differing substring between the initially stored\n   * text content and the current content.\n   *\n   * @return {string}\n   */\n  getData: function () {\n    if (this._fallbackText) {\n      return this._fallbackText;\n    }\n\n    var start;\n    var startValue = this._startText;\n    var startLength = startValue.length;\n    var end;\n    var endValue = this.getText();\n    var endLength = endValue.length;\n\n    for (start = 0; start < startLength; start++) {\n      if (startValue[start] !== endValue[start]) {\n        break;\n      }\n    }\n\n    var minEnd = startLength - start;\n    for (end = 1; end <= minEnd; end++) {\n      if (startValue[startLength - end] !== endValue[endLength - end]) {\n        break;\n      }\n    }\n\n    var sliceTail = end > 1 ? 1 - end : undefined;\n    this._fallbackText = endValue.slice(start, sliceTail);\n    return this._fallbackText;\n  }\n});\n\nPooledClass.addPoolingTo(FallbackCompositionState);\n\nmodule.exports = FallbackCompositionState;\n},{\"132\":132,\"172\":172,\"25\":25}],22:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule HTMLDOMPropertyConfig\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\n\nvar MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;\nvar HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;\nvar HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;\nvar HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;\nvar HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;\n\nvar HTMLDOMPropertyConfig = {\n  isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')),\n  Properties: {\n    /**\n     * Standard Properties\n     */\n    accept: 0,\n    acceptCharset: 0,\n    accessKey: 0,\n    action: 0,\n    allowFullScreen: HAS_BOOLEAN_VALUE,\n    allowTransparency: 0,\n    alt: 0,\n    async: HAS_BOOLEAN_VALUE,\n    autoComplete: 0,\n    // autoFocus is polyfilled/normalized by AutoFocusUtils\n    // autoFocus: HAS_BOOLEAN_VALUE,\n    autoPlay: HAS_BOOLEAN_VALUE,\n    capture: HAS_BOOLEAN_VALUE,\n    cellPadding: 0,\n    cellSpacing: 0,\n    charSet: 0,\n    challenge: 0,\n    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    cite: 0,\n    classID: 0,\n    className: 0,\n    cols: HAS_POSITIVE_NUMERIC_VALUE,\n    colSpan: 0,\n    content: 0,\n    contentEditable: 0,\n    contextMenu: 0,\n    controls: HAS_BOOLEAN_VALUE,\n    coords: 0,\n    crossOrigin: 0,\n    data: 0, // For `<object />` acts as `src`.\n    dateTime: 0,\n    'default': HAS_BOOLEAN_VALUE,\n    defer: HAS_BOOLEAN_VALUE,\n    dir: 0,\n    disabled: HAS_BOOLEAN_VALUE,\n    download: HAS_OVERLOADED_BOOLEAN_VALUE,\n    draggable: 0,\n    encType: 0,\n    form: 0,\n    formAction: 0,\n    formEncType: 0,\n    formMethod: 0,\n    formNoValidate: HAS_BOOLEAN_VALUE,\n    formTarget: 0,\n    frameBorder: 0,\n    headers: 0,\n    height: 0,\n    hidden: HAS_BOOLEAN_VALUE,\n    high: 0,\n    href: 0,\n    hrefLang: 0,\n    htmlFor: 0,\n    httpEquiv: 0,\n    icon: 0,\n    id: 0,\n    inputMode: 0,\n    integrity: 0,\n    is: 0,\n    keyParams: 0,\n    keyType: 0,\n    kind: 0,\n    label: 0,\n    lang: 0,\n    list: 0,\n    loop: HAS_BOOLEAN_VALUE,\n    low: 0,\n    manifest: 0,\n    marginHeight: 0,\n    marginWidth: 0,\n    max: 0,\n    maxLength: 0,\n    media: 0,\n    mediaGroup: 0,\n    method: 0,\n    min: 0,\n    minLength: 0,\n    // Caution; `option.selected` is not updated if `select.multiple` is\n    // disabled with `removeAttribute`.\n    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    name: 0,\n    nonce: 0,\n    noValidate: HAS_BOOLEAN_VALUE,\n    open: HAS_BOOLEAN_VALUE,\n    optimum: 0,\n    pattern: 0,\n    placeholder: 0,\n    poster: 0,\n    preload: 0,\n    profile: 0,\n    radioGroup: 0,\n    readOnly: HAS_BOOLEAN_VALUE,\n    rel: 0,\n    required: HAS_BOOLEAN_VALUE,\n    reversed: HAS_BOOLEAN_VALUE,\n    role: 0,\n    rows: HAS_POSITIVE_NUMERIC_VALUE,\n    rowSpan: HAS_NUMERIC_VALUE,\n    sandbox: 0,\n    scope: 0,\n    scoped: HAS_BOOLEAN_VALUE,\n    scrolling: 0,\n    seamless: HAS_BOOLEAN_VALUE,\n    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    shape: 0,\n    size: HAS_POSITIVE_NUMERIC_VALUE,\n    sizes: 0,\n    span: HAS_POSITIVE_NUMERIC_VALUE,\n    spellCheck: 0,\n    src: 0,\n    srcDoc: 0,\n    srcLang: 0,\n    srcSet: 0,\n    start: HAS_NUMERIC_VALUE,\n    step: 0,\n    style: 0,\n    summary: 0,\n    tabIndex: 0,\n    target: 0,\n    title: 0,\n    // Setting .type throws on non-<input> tags\n    type: 0,\n    useMap: 0,\n    value: 0,\n    width: 0,\n    wmode: 0,\n    wrap: 0,\n\n    /**\n     * RDFa Properties\n     */\n    about: 0,\n    datatype: 0,\n    inlist: 0,\n    prefix: 0,\n    // property is also supported for OpenGraph in meta tags.\n    property: 0,\n    resource: 0,\n    'typeof': 0,\n    vocab: 0,\n\n    /**\n     * Non-standard Properties\n     */\n    // autoCapitalize and autoCorrect are supported in Mobile Safari for\n    // keyboard hints.\n    autoCapitalize: 0,\n    autoCorrect: 0,\n    // autoSave allows WebKit/Blink to persist values of input fields on page reloads\n    autoSave: 0,\n    // color is for Safari mask-icon link\n    color: 0,\n    // itemProp, itemScope, itemType are for\n    // Microdata support. See http://schema.org/docs/gs.html\n    itemProp: 0,\n    itemScope: HAS_BOOLEAN_VALUE,\n    itemType: 0,\n    // itemID and itemRef are for Microdata support as well but\n    // only specified in the WHATWG spec document. See\n    // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api\n    itemID: 0,\n    itemRef: 0,\n    // results show looking glass icon and recent searches on input\n    // search fields in WebKit/Blink\n    results: 0,\n    // IE-only attribute that specifies security restrictions on an iframe\n    // as an alternative to the sandbox attribute on IE<10\n    security: 0,\n    // IE-only attribute that controls focus behavior\n    unselectable: 0\n  },\n  DOMAttributeNames: {\n    acceptCharset: 'accept-charset',\n    className: 'class',\n    htmlFor: 'for',\n    httpEquiv: 'http-equiv'\n  },\n  DOMPropertyNames: {}\n};\n\nmodule.exports = HTMLDOMPropertyConfig;\n},{\"10\":10}],23:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule KeyEscapeUtils\n * \n */\n\n'use strict';\n\n/**\n * Escape and wrap key so it is safe to use as a reactid\n *\n * @param {string} key to be escaped.\n * @return {string} the escaped key.\n */\n\nfunction escape(key) {\n  var escapeRegex = /[=:]/g;\n  var escaperLookup = {\n    '=': '=0',\n    ':': '=2'\n  };\n  var escapedString = ('' + key).replace(escapeRegex, function (match) {\n    return escaperLookup[match];\n  });\n\n  return '$' + escapedString;\n}\n\n/**\n * Unescape and unwrap key for human-readable display\n *\n * @param {string} key to unescape.\n * @return {string} the unescaped key.\n */\nfunction unescape(key) {\n  var unescapeRegex = /(=0|=2)/g;\n  var unescaperLookup = {\n    '=0': '=',\n    '=2': ':'\n  };\n  var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);\n\n  return ('' + keySubstring).replace(unescapeRegex, function (match) {\n    return unescaperLookup[match];\n  });\n}\n\nvar KeyEscapeUtils = {\n  escape: escape,\n  unescape: unescape\n};\n\nmodule.exports = KeyEscapeUtils;\n},{}],24:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule LinkedValueUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypes = _dereq_(85);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar hasReadOnlyValue = {\n  'button': true,\n  'checkbox': true,\n  'image': true,\n  'hidden': true,\n  'radio': true,\n  'reset': true,\n  'submit': true\n};\n\nfunction _assertSingleLink(inputProps) {\n  !(inputProps.checkedLink == null || inputProps.valueLink == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don\\'t want to use valueLink and vice versa.') : _prodInvariant('87') : void 0;\n}\nfunction _assertValueLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.value == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don\\'t want to use valueLink.') : _prodInvariant('88') : void 0;\n}\n\nfunction _assertCheckedLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.checked == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don\\'t want to use checkedLink') : _prodInvariant('89') : void 0;\n}\n\nvar propTypes = {\n  value: function (props, propName, componentName) {\n    if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  checked: function (props, propName, componentName) {\n    if (!props[propName] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  onChange: ReactPropTypes.func\n};\n\nvar loggedTypeFailures = {};\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Provide a linked `value` attribute for controlled forms. You should not use\n * this outside of the ReactDOM controlled form components.\n */\nvar LinkedValueUtils = {\n  checkPropTypes: function (tagName, props, owner) {\n    for (var propName in propTypes) {\n      if (propTypes.hasOwnProperty(propName)) {\n        var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop);\n      }\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var addendum = getDeclarationErrorAddendum(owner);\n        \"development\" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0;\n      }\n    }\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current value of the input either from value prop or link.\n   */\n  getValue: function (inputProps) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.value;\n    }\n    return inputProps.value;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current checked status of the input either from checked prop\n   *             or link.\n   */\n  getChecked: function (inputProps) {\n    if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.value;\n    }\n    return inputProps.checked;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @param {SyntheticEvent} event change event to handle\n   */\n  executeOnChange: function (inputProps, event) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.requestChange(event.target.value);\n    } else if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.requestChange(event.target.checked);\n    } else if (inputProps.onChange) {\n      return inputProps.onChange.call(undefined, event);\n    }\n  }\n};\n\nmodule.exports = LinkedValueUtils;\n},{\"139\":139,\"161\":161,\"171\":171,\"84\":84,\"85\":85}],25:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule PooledClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Static poolers. Several custom versions for each potential number of\n * arguments. A completely generic pooler is easy to implement, but would\n * require accessing the `arguments` object. In each of these, `this` refers to\n * the Class itself, not an instance. If any others are needed, simply add them\n * here, or in their own files.\n */\nvar oneArgumentPooler = function (copyFieldsFrom) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, copyFieldsFrom);\n    return instance;\n  } else {\n    return new Klass(copyFieldsFrom);\n  }\n};\n\nvar twoArgumentPooler = function (a1, a2) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2);\n    return instance;\n  } else {\n    return new Klass(a1, a2);\n  }\n};\n\nvar threeArgumentPooler = function (a1, a2, a3) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3);\n  }\n};\n\nvar fourArgumentPooler = function (a1, a2, a3, a4) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4);\n  }\n};\n\nvar fiveArgumentPooler = function (a1, a2, a3, a4, a5) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4, a5);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4, a5);\n  }\n};\n\nvar standardReleaser = function (instance) {\n  var Klass = this;\n  !(instance instanceof Klass) ? \"development\" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0;\n  instance.destructor();\n  if (Klass.instancePool.length < Klass.poolSize) {\n    Klass.instancePool.push(instance);\n  }\n};\n\nvar DEFAULT_POOL_SIZE = 10;\nvar DEFAULT_POOLER = oneArgumentPooler;\n\n/**\n * Augments `CopyConstructor` to be a poolable class, augmenting only the class\n * itself (statically) not adding any prototypical fields. Any CopyConstructor\n * you give this may have a `poolSize` property, and will look for a\n * prototypical `destructor` on instances.\n *\n * @param {Function} CopyConstructor Constructor that can be used to reset.\n * @param {Function} pooler Customizable pooler.\n */\nvar addPoolingTo = function (CopyConstructor, pooler) {\n  var NewKlass = CopyConstructor;\n  NewKlass.instancePool = [];\n  NewKlass.getPooled = pooler || DEFAULT_POOLER;\n  if (!NewKlass.poolSize) {\n    NewKlass.poolSize = DEFAULT_POOL_SIZE;\n  }\n  NewKlass.release = standardReleaser;\n  return NewKlass;\n};\n\nvar PooledClass = {\n  addPoolingTo: addPoolingTo,\n  oneArgumentPooler: oneArgumentPooler,\n  twoArgumentPooler: twoArgumentPooler,\n  threeArgumentPooler: threeArgumentPooler,\n  fourArgumentPooler: fourArgumentPooler,\n  fiveArgumentPooler: fiveArgumentPooler\n};\n\nmodule.exports = PooledClass;\n},{\"139\":139,\"161\":161}],26:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule React\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactComponent = _dereq_(31);\nvar ReactClass = _dereq_(30);\nvar ReactDOMFactories = _dereq_(45);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypes = _dereq_(85);\nvar ReactVersion = _dereq_(96);\n\nvar onlyChild = _dereq_(137);\nvar warning = _dereq_(171);\n\nvar createElement = ReactElement.createElement;\nvar createFactory = ReactElement.createFactory;\nvar cloneElement = ReactElement.cloneElement;\n\nif (\"development\" !== 'production') {\n  var ReactElementValidator = _dereq_(63);\n  createElement = ReactElementValidator.createElement;\n  createFactory = ReactElementValidator.createFactory;\n  cloneElement = ReactElementValidator.cloneElement;\n}\n\nvar __spread = _assign;\n\nif (\"development\" !== 'production') {\n  var warned = false;\n  __spread = function () {\n    \"development\" !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;\n    warned = true;\n    return _assign.apply(null, arguments);\n  };\n}\n\nvar React = {\n\n  // Modern\n\n  Children: {\n    map: ReactChildren.map,\n    forEach: ReactChildren.forEach,\n    count: ReactChildren.count,\n    toArray: ReactChildren.toArray,\n    only: onlyChild\n  },\n\n  Component: ReactComponent,\n\n  createElement: createElement,\n  cloneElement: cloneElement,\n  isValidElement: ReactElement.isValidElement,\n\n  // Classic\n\n  PropTypes: ReactPropTypes,\n  createClass: ReactClass.createClass,\n  createFactory: createFactory,\n  createMixin: function (mixin) {\n    // Currently a noop. Will be used to validate and trace mixins.\n    return mixin;\n  },\n\n  // This looks DOM specific but these are actually isomorphic helpers\n  // since they are just generating DOM strings.\n  DOM: ReactDOMFactories,\n\n  version: ReactVersion,\n\n  // Deprecated hook for JSX spread, don't use this for anything.\n  __spread: __spread\n};\n\nmodule.exports = React;\n},{\"137\":137,\"171\":171,\"172\":172,\"29\":29,\"30\":30,\"31\":31,\"45\":45,\"62\":62,\"63\":63,\"85\":85,\"96\":96}],27:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactBrowserEventEmitter\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventConstants = _dereq_(16);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactEventEmitterMixin = _dereq_(66);\nvar ViewportMetrics = _dereq_(114);\n\nvar getVendorPrefixedEventName = _dereq_(133);\nvar isEventSupported = _dereq_(135);\n\n/**\n * Summary of `ReactBrowserEventEmitter` event handling:\n *\n *  - Top-level delegation is used to trap most native browser events. This\n *    may only occur in the main thread and is the responsibility of\n *    ReactEventListener, which is injected and can therefore support pluggable\n *    event sources. This is the only work that occurs in the main thread.\n *\n *  - We normalize and de-duplicate events to account for browser quirks. This\n *    may be done in the worker thread.\n *\n *  - Forward these native events (with the associated top-level type used to\n *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want\n *    to extract any synthetic events.\n *\n *  - The `EventPluginHub` will then process each event by annotating them with\n *    \"dispatches\", a sequence of listeners and IDs that care about that event.\n *\n *  - The `EventPluginHub` then dispatches the events.\n *\n * Overview of React and the event system:\n *\n * +------------+    .\n * |    DOM     |    .\n * +------------+    .\n *       |           .\n *       v           .\n * +------------+    .\n * | ReactEvent |    .\n * |  Listener  |    .\n * +------------+    .                         +-----------+\n *       |           .               +--------+|SimpleEvent|\n *       |           .               |         |Plugin     |\n * +-----|------+    .               v         +-----------+\n * |     |      |    .    +--------------+                    +------------+\n * |     +-----------.--->|EventPluginHub|                    |    Event   |\n * |            |    .    |              |     +-----------+  | Propagators|\n * | ReactEvent |    .    |              |     |TapEvent   |  |------------|\n * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|\n * |            |    .    |              |     +-----------+  |  utilities |\n * |     +-----------.--->|              |                    +------------+\n * |     |      |    .    +--------------+\n * +-----|------+    .                ^        +-----------+\n *       |           .                |        |Enter/Leave|\n *       +           .                +-------+|Plugin     |\n * +-------------+   .                         +-----------+\n * | application |   .\n * |-------------|   .\n * |             |   .\n * |             |   .\n * +-------------+   .\n *                   .\n *    React Core     .  General Purpose Event Plugin System\n */\n\nvar hasEventPageXY;\nvar alreadyListeningTo = {};\nvar isMonitoringScrollValue = false;\nvar reactTopListenersCounter = 0;\n\n// For events like 'submit' which don't consistently bubble (which we trap at a\n// lower node than `document`), binding at `document` would cause duplicate\n// events so we don't include them here\nvar topEventMapping = {\n  topAbort: 'abort',\n  topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',\n  topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',\n  topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',\n  topBlur: 'blur',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topChange: 'change',\n  topClick: 'click',\n  topCompositionEnd: 'compositionend',\n  topCompositionStart: 'compositionstart',\n  topCompositionUpdate: 'compositionupdate',\n  topContextMenu: 'contextmenu',\n  topCopy: 'copy',\n  topCut: 'cut',\n  topDoubleClick: 'dblclick',\n  topDrag: 'drag',\n  topDragEnd: 'dragend',\n  topDragEnter: 'dragenter',\n  topDragExit: 'dragexit',\n  topDragLeave: 'dragleave',\n  topDragOver: 'dragover',\n  topDragStart: 'dragstart',\n  topDrop: 'drop',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topFocus: 'focus',\n  topInput: 'input',\n  topKeyDown: 'keydown',\n  topKeyPress: 'keypress',\n  topKeyUp: 'keyup',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topMouseDown: 'mousedown',\n  topMouseMove: 'mousemove',\n  topMouseOut: 'mouseout',\n  topMouseOver: 'mouseover',\n  topMouseUp: 'mouseup',\n  topPaste: 'paste',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topScroll: 'scroll',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topSelectionChange: 'selectionchange',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTextInput: 'textInput',\n  topTimeUpdate: 'timeupdate',\n  topTouchCancel: 'touchcancel',\n  topTouchEnd: 'touchend',\n  topTouchMove: 'touchmove',\n  topTouchStart: 'touchstart',\n  topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting',\n  topWheel: 'wheel'\n};\n\n/**\n * To ensure no conflicts with other potential React instances on the page\n */\nvar topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2);\n\nfunction getListeningForDocument(mountAt) {\n  // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`\n  // directly.\n  if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {\n    mountAt[topListenersIDKey] = reactTopListenersCounter++;\n    alreadyListeningTo[mountAt[topListenersIDKey]] = {};\n  }\n  return alreadyListeningTo[mountAt[topListenersIDKey]];\n}\n\n/**\n * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For\n * example:\n *\n *   EventPluginHub.putListener('myID', 'onClick', myFunction);\n *\n * This would allocate a \"registration\" of `('onClick', myFunction)` on 'myID'.\n *\n * @internal\n */\nvar ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {\n\n  /**\n   * Injectable event backend\n   */\n  ReactEventListener: null,\n\n  injection: {\n    /**\n     * @param {object} ReactEventListener\n     */\n    injectReactEventListener: function (ReactEventListener) {\n      ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel);\n      ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;\n    }\n  },\n\n  /**\n   * Sets whether or not any created callbacks should be enabled.\n   *\n   * @param {boolean} enabled True if callbacks should be enabled.\n   */\n  setEnabled: function (enabled) {\n    if (ReactBrowserEventEmitter.ReactEventListener) {\n      ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled);\n    }\n  },\n\n  /**\n   * @return {boolean} True if callbacks are enabled.\n   */\n  isEnabled: function () {\n    return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled());\n  },\n\n  /**\n   * We listen for bubbled touch events on the document object.\n   *\n   * Firefox v8.01 (and possibly others) exhibited strange behavior when\n   * mounting `onmousemove` events at some node that was not the document\n   * element. The symptoms were that if your mouse is not moving over something\n   * contained within that mount point (for example on the background) the\n   * top-level listeners for `onmousemove` won't be called. However, if you\n   * register the `mousemove` on the document object, then it will of course\n   * catch all `mousemove`s. This along with iOS quirks, justifies restricting\n   * top-level listeners to the document object only, at least for these\n   * movement types of events and possibly all events.\n   *\n   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html\n   *\n   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but\n   * they bubble to document.\n   *\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {object} contentDocumentHandle Document which owns the container\n   */\n  listenTo: function (registrationName, contentDocumentHandle) {\n    var mountAt = contentDocumentHandle;\n    var isListening = getListeningForDocument(mountAt);\n    var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName];\n\n    var topLevelTypes = EventConstants.topLevelTypes;\n    for (var i = 0; i < dependencies.length; i++) {\n      var dependency = dependencies[i];\n      if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {\n        if (dependency === topLevelTypes.topWheel) {\n          if (isEventSupported('wheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);\n          } else if (isEventSupported('mousewheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);\n          } else {\n            // Firefox needs to capture a different mouse scroll event.\n            // @see http://www.quirksmode.org/dom/events/tests/scroll.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt);\n          }\n        } else if (dependency === topLevelTypes.topScroll) {\n\n          if (isEventSupported('scroll', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);\n          } else {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE);\n          }\n        } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) {\n\n          if (isEventSupported('focus', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);\n          } else if (isEventSupported('focusin')) {\n            // IE has `focusin` and `focusout` events which bubble.\n            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);\n          }\n\n          // to make sure blur and focus event listeners are only attached once\n          isListening[topLevelTypes.topBlur] = true;\n          isListening[topLevelTypes.topFocus] = true;\n        } else if (topEventMapping.hasOwnProperty(dependency)) {\n          ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt);\n        }\n\n        isListening[dependency] = true;\n      }\n    }\n  },\n\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  /**\n   * Listens to window scroll and resize events. We cache scroll values so that\n   * application code can access them without triggering reflows.\n   *\n   * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when\n   * pageX/pageY isn't supported (legacy browsers).\n   *\n   * NOTE: Scroll events do not bubble.\n   *\n   * @see http://www.quirksmode.org/dom/events/scroll.html\n   */\n  ensureScrollValueMonitoring: function () {\n    if (hasEventPageXY === undefined) {\n      hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent');\n    }\n    if (!hasEventPageXY && !isMonitoringScrollValue) {\n      var refresh = ViewportMetrics.refreshScrollValues;\n      ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);\n      isMonitoringScrollValue = true;\n    }\n  }\n\n});\n\nmodule.exports = ReactBrowserEventEmitter;\n},{\"114\":114,\"133\":133,\"135\":135,\"16\":16,\"172\":172,\"18\":18,\"66\":66}],28:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildReconciler\n */\n\n'use strict';\n\nvar ReactReconciler = _dereq_(87);\n\nvar instantiateReactComponent = _dereq_(134);\nvar KeyEscapeUtils = _dereq_(23);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\nfunction instantiateChild(childInstances, child, name, selfDebugID) {\n  // We found a component instance.\n  var keyUnique = childInstances[name] === undefined;\n  if (\"development\" !== 'production') {\n    var ReactComponentTreeDevtool = _dereq_(34);\n    \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n  }\n  if (child != null && keyUnique) {\n    childInstances[name] = instantiateReactComponent(child, true);\n  }\n}\n\n/**\n * ReactChildReconciler provides helpers for initializing or updating a set of\n * children. Its output is suitable for passing it onto ReactMultiChild which\n * does diffed reordering and insertion.\n */\nvar ReactChildReconciler = {\n  /**\n   * Generates a \"mount image\" for each of the supplied children. In the case\n   * of `ReactDOMComponent`, a mount image is a string of markup.\n   *\n   * @param {?object} nestedChildNodes Nested child maps.\n   * @return {?object} A set of child instances.\n   * @internal\n   */\n  instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID // __DEV__ only\n  ) {\n    if (nestedChildNodes == null) {\n      return null;\n    }\n    var childInstances = {};\n\n    if (\"development\" !== 'production') {\n      traverseAllChildren(nestedChildNodes, function (childInsts, child, name) {\n        return instantiateChild(childInsts, child, name, selfDebugID);\n      }, childInstances);\n    } else {\n      traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);\n    }\n    return childInstances;\n  },\n\n  /**\n   * Updates the rendered children and returns a new set of children.\n   *\n   * @param {?object} prevChildren Previously initialized set of children.\n   * @param {?object} nextChildren Flat child element maps.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @return {?object} A new set of child instances.\n   * @internal\n   */\n  updateChildren: function (prevChildren, nextChildren, removedNodes, transaction, context) {\n    // We currently don't have a way to track moves here but if we use iterators\n    // instead of for..in we can zip the iterators and check if an item has\n    // moved.\n    // TODO: If nothing has changed, return the prevChildren object so that we\n    // can quickly bailout if nothing has changed.\n    if (!nextChildren && !prevChildren) {\n      return;\n    }\n    var name;\n    var prevChild;\n    for (name in nextChildren) {\n      if (!nextChildren.hasOwnProperty(name)) {\n        continue;\n      }\n      prevChild = prevChildren && prevChildren[name];\n      var prevElement = prevChild && prevChild._currentElement;\n      var nextElement = nextChildren[name];\n      if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {\n        ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);\n        nextChildren[name] = prevChild;\n      } else {\n        if (prevChild) {\n          removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n          ReactReconciler.unmountComponent(prevChild, false);\n        }\n        // The child must be instantiated before it's mounted.\n        var nextChildInstance = instantiateReactComponent(nextElement, true);\n        nextChildren[name] = nextChildInstance;\n      }\n    }\n    // Unmount children that are no longer present.\n    for (name in prevChildren) {\n      if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {\n        prevChild = prevChildren[name];\n        removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n        ReactReconciler.unmountComponent(prevChild, false);\n      }\n    }\n  },\n\n  /**\n   * Unmounts all rendered children. This should be used to clean up children\n   * when this component is unmounted.\n   *\n   * @param {?object} renderedChildren Previously initialized set of children.\n   * @internal\n   */\n  unmountChildren: function (renderedChildren, safely) {\n    for (var name in renderedChildren) {\n      if (renderedChildren.hasOwnProperty(name)) {\n        var renderedChild = renderedChildren[name];\n        ReactReconciler.unmountComponent(renderedChild, safely);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactChildReconciler;\n},{\"134\":134,\"143\":143,\"144\":144,\"171\":171,\"23\":23,\"34\":34,\"87\":87}],29:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildren\n */\n\n'use strict';\n\nvar PooledClass = _dereq_(25);\nvar ReactElement = _dereq_(62);\n\nvar emptyFunction = _dereq_(153);\nvar traverseAllChildren = _dereq_(144);\n\nvar twoArgumentPooler = PooledClass.twoArgumentPooler;\nvar fourArgumentPooler = PooledClass.fourArgumentPooler;\n\nvar userProvidedKeyEscapeRegex = /\\/+/g;\nfunction escapeUserProvidedKey(text) {\n  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * traversal. Allows avoiding binding callbacks.\n *\n * @constructor ForEachBookKeeping\n * @param {!function} forEachFunction Function to perform traversal with.\n * @param {?*} forEachContext Context to perform context with.\n */\nfunction ForEachBookKeeping(forEachFunction, forEachContext) {\n  this.func = forEachFunction;\n  this.context = forEachContext;\n  this.count = 0;\n}\nForEachBookKeeping.prototype.destructor = function () {\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);\n\nfunction forEachSingleChild(bookKeeping, child, name) {\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n  func.call(context, child, bookKeeping.count++);\n}\n\n/**\n * Iterates through children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach\n *\n * The provided forEachFunc(child, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} forEachFunc\n * @param {*} forEachContext Context for forEachContext.\n */\nfunction forEachChildren(children, forEachFunc, forEachContext) {\n  if (children == null) {\n    return children;\n  }\n  var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);\n  traverseAllChildren(children, forEachSingleChild, traverseContext);\n  ForEachBookKeeping.release(traverseContext);\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * mapping. Allows avoiding binding callbacks.\n *\n * @constructor MapBookKeeping\n * @param {!*} mapResult Object containing the ordered map of results.\n * @param {!function} mapFunction Function to perform mapping with.\n * @param {?*} mapContext Context to perform mapping with.\n */\nfunction MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {\n  this.result = mapResult;\n  this.keyPrefix = keyPrefix;\n  this.func = mapFunction;\n  this.context = mapContext;\n  this.count = 0;\n}\nMapBookKeeping.prototype.destructor = function () {\n  this.result = null;\n  this.keyPrefix = null;\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);\n\nfunction mapSingleChildIntoContext(bookKeeping, child, childKey) {\n  var result = bookKeeping.result;\n  var keyPrefix = bookKeeping.keyPrefix;\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n\n  var mappedChild = func.call(context, child, bookKeeping.count++);\n  if (Array.isArray(mappedChild)) {\n    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);\n  } else if (mappedChild != null) {\n    if (ReactElement.isValidElement(mappedChild)) {\n      mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,\n      // Keep both the (mapped) and old keys if they differ, just as\n      // traverseAllChildren used to do for objects as children\n      keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);\n    }\n    result.push(mappedChild);\n  }\n}\n\nfunction mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {\n  var escapedPrefix = '';\n  if (prefix != null) {\n    escapedPrefix = escapeUserProvidedKey(prefix) + '/';\n  }\n  var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);\n  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);\n  MapBookKeeping.release(traverseContext);\n}\n\n/**\n * Maps children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.map\n *\n * The provided mapFunction(child, key, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} func The map function.\n * @param {*} context Context for mapFunction.\n * @return {object} Object containing the ordered map of results.\n */\nfunction mapChildren(children, func, context) {\n  if (children == null) {\n    return children;\n  }\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, func, context);\n  return result;\n}\n\nfunction forEachSingleChildDummy(traverseContext, child, name) {\n  return null;\n}\n\n/**\n * Count the number of children that are typically specified as\n * `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.count\n *\n * @param {?*} children Children tree container.\n * @return {number} The number of children.\n */\nfunction countChildren(children, context) {\n  return traverseAllChildren(children, forEachSingleChildDummy, null);\n}\n\n/**\n * Flatten a children object (typically specified as `props.children`) and\n * return an array with appropriately re-keyed children.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray\n */\nfunction toArray(children) {\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);\n  return result;\n}\n\nvar ReactChildren = {\n  forEach: forEachChildren,\n  map: mapChildren,\n  mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,\n  count: countChildren,\n  toArray: toArray\n};\n\nmodule.exports = ReactChildren;\n},{\"144\":144,\"153\":153,\"25\":25,\"62\":62}],30:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponent = _dereq_(31);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactPropTypeLocationNames = _dereq_(83);\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar keyMirror = _dereq_(164);\nvar keyOf = _dereq_(165);\nvar warning = _dereq_(171);\n\nvar MIXINS_KEY = keyOf({ mixins: null });\n\n/**\n * Policies that describe methods in `ReactClassInterface`.\n */\nvar SpecPolicy = keyMirror({\n  /**\n   * These methods may be defined only once by the class specification or mixin.\n   */\n  DEFINE_ONCE: null,\n  /**\n   * These methods may be defined by both the class specification and mixins.\n   * Subsequent definitions will be chained. These methods must return void.\n   */\n  DEFINE_MANY: null,\n  /**\n   * These methods are overriding the base class.\n   */\n  OVERRIDE_BASE: null,\n  /**\n   * These methods are similar to DEFINE_MANY, except we assume they return\n   * objects. We try to merge the keys of the return values of all the mixed in\n   * functions. If there is a key conflict we throw.\n   */\n  DEFINE_MANY_MERGED: null\n});\n\nvar injectedMixins = [];\n\n/**\n * Composite components are higher-level components that compose other composite\n * or host components.\n *\n * To create a new type of `ReactClass`, pass a specification of\n * your new class to `React.createClass`. The only requirement of your class\n * specification is that you implement a `render` method.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return <div>Hello World</div>;\n *     }\n *   });\n *\n * The class specification supports a specific protocol of methods that have\n * special meaning (e.g. `render`). See `ReactClassInterface` for\n * more the comprehensive protocol. Any other properties and methods in the\n * class specification will be available on the prototype.\n *\n * @interface ReactClassInterface\n * @internal\n */\nvar ReactClassInterface = {\n\n  /**\n   * An array of Mixin objects to include when defining your component.\n   *\n   * @type {array}\n   * @optional\n   */\n  mixins: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * An object containing properties and methods that should be defined on\n   * the component's constructor instead of its prototype (static methods).\n   *\n   * @type {object}\n   * @optional\n   */\n  statics: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of prop types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  propTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  contextTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types this component sets for its children.\n   *\n   * @type {object}\n   * @optional\n   */\n  childContextTypes: SpecPolicy.DEFINE_MANY,\n\n  // ==== Definition methods ====\n\n  /**\n   * Invoked when the component is mounted. Values in the mapping will be set on\n   * `this.props` if that prop is not specified (i.e. using an `in` check).\n   *\n   * This method is invoked before `getInitialState` and therefore cannot rely\n   * on `this.state` or use `this.setState`.\n   *\n   * @return {object}\n   * @optional\n   */\n  getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Invoked once before the component is mounted. The return value will be used\n   * as the initial value of `this.state`.\n   *\n   *   getInitialState: function() {\n   *     return {\n   *       isOn: false,\n   *       fooBaz: new BazFoo()\n   *     }\n   *   }\n   *\n   * @return {object}\n   * @optional\n   */\n  getInitialState: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * @return {object}\n   * @optional\n   */\n  getChildContext: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Uses props from `this.props` and state from `this.state` to render the\n   * structure of the component.\n   *\n   * No guarantees are made about when or how often this method is invoked, so\n   * it must not have side effects.\n   *\n   *   render: function() {\n   *     var name = this.props.name;\n   *     return <div>Hello, {name}!</div>;\n   *   }\n   *\n   * @return {ReactComponent}\n   * @nosideeffects\n   * @required\n   */\n  render: SpecPolicy.DEFINE_ONCE,\n\n  // ==== Delegate methods ====\n\n  /**\n   * Invoked when the component is initially created and about to be mounted.\n   * This may have side effects, but any external subscriptions or data created\n   * by this method must be cleaned up in `componentWillUnmount`.\n   *\n   * @optional\n   */\n  componentWillMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component has been mounted and has a DOM representation.\n   * However, there is no guarantee that the DOM node is in the document.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been mounted (initialized and rendered) for the first time.\n   *\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked before the component receives new props.\n   *\n   * Use this as an opportunity to react to a prop transition by updating the\n   * state using `this.setState`. Current props are accessed via `this.props`.\n   *\n   *   componentWillReceiveProps: function(nextProps, nextContext) {\n   *     this.setState({\n   *       likesIncreasing: nextProps.likeCount > this.props.likeCount\n   *     });\n   *   }\n   *\n   * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop\n   * transition may cause a state change, but the opposite is not true. If you\n   * need it, you are probably looking for `componentWillUpdate`.\n   *\n   * @param {object} nextProps\n   * @optional\n   */\n  componentWillReceiveProps: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked while deciding if the component should be updated as a result of\n   * receiving new props, state and/or context.\n   *\n   * Use this as an opportunity to `return false` when you're certain that the\n   * transition to the new props/state/context will not require a component\n   * update.\n   *\n   *   shouldComponentUpdate: function(nextProps, nextState, nextContext) {\n   *     return !equal(nextProps, this.props) ||\n   *       !equal(nextState, this.state) ||\n   *       !equal(nextContext, this.context);\n   *   }\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @return {boolean} True if the component should update.\n   * @optional\n   */\n  shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,\n\n  /**\n   * Invoked when the component is about to update due to a transition from\n   * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`\n   * and `nextContext`.\n   *\n   * Use this as an opportunity to perform preparation before an update occurs.\n   *\n   * NOTE: You **cannot** use `this.setState()` in this method.\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @param {ReactReconcileTransaction} transaction\n   * @optional\n   */\n  componentWillUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component's DOM representation has been updated.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been updated.\n   *\n   * @param {object} prevProps\n   * @param {?object} prevState\n   * @param {?object} prevContext\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component is about to be removed from its parent and have\n   * its DOM representation destroyed.\n   *\n   * Use this as an opportunity to deallocate any external resources.\n   *\n   * NOTE: There is no `componentDidUnmount` since your component will have been\n   * destroyed by that point.\n   *\n   * @optional\n   */\n  componentWillUnmount: SpecPolicy.DEFINE_MANY,\n\n  // ==== Advanced methods ====\n\n  /**\n   * Updates the component's currently mounted DOM representation.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   * @overridable\n   */\n  updateComponent: SpecPolicy.OVERRIDE_BASE\n\n};\n\n/**\n * Mapping from class specification keys to special processing functions.\n *\n * Although these are declared like instance properties in the specification\n * when defining classes using `React.createClass`, they are actually static\n * and are accessible on the constructor instead of the prototype. Despite\n * being static, they must be defined outside of the \"statics\" key under\n * which all other static methods are defined.\n */\nvar RESERVED_SPEC_KEYS = {\n  displayName: function (Constructor, displayName) {\n    Constructor.displayName = displayName;\n  },\n  mixins: function (Constructor, mixins) {\n    if (mixins) {\n      for (var i = 0; i < mixins.length; i++) {\n        mixSpecIntoComponent(Constructor, mixins[i]);\n      }\n    }\n  },\n  childContextTypes: function (Constructor, childContextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext);\n    }\n    Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes);\n  },\n  contextTypes: function (Constructor, contextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context);\n    }\n    Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes);\n  },\n  /**\n   * Special case getDefaultProps which should move into statics but requires\n   * automatic merging.\n   */\n  getDefaultProps: function (Constructor, getDefaultProps) {\n    if (Constructor.getDefaultProps) {\n      Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps);\n    } else {\n      Constructor.getDefaultProps = getDefaultProps;\n    }\n  },\n  propTypes: function (Constructor, propTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop);\n    }\n    Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes);\n  },\n  statics: function (Constructor, statics) {\n    mixStaticSpecIntoComponent(Constructor, statics);\n  },\n  autobind: function () {} };\n\n// noop\nfunction validateTypeDef(Constructor, typeDef, location) {\n  for (var propName in typeDef) {\n    if (typeDef.hasOwnProperty(propName)) {\n      // use a warning instead of an invariant so components\n      // don't show up in prod but only in __DEV__\n      \"development\" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0;\n    }\n  }\n}\n\nfunction validateMethodOverride(isAlreadyDefined, name) {\n  var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null;\n\n  // Disallow overriding of base class methods unless explicitly allowed.\n  if (ReactClassMixin.hasOwnProperty(name)) {\n    !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.', name) : _prodInvariant('73', name) : void 0;\n  }\n\n  // Disallow defining methods more than once unless explicitly allowed.\n  if (isAlreadyDefined) {\n    !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('74', name) : void 0;\n  }\n}\n\n/**\n * Mixin helper which handles policy validation and reserved\n * specification keys when building React classes.\n */\nfunction mixSpecIntoComponent(Constructor, spec) {\n  if (!spec) {\n    return;\n  }\n\n  !(typeof spec !== 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component class or function as a mixin. Instead, just use a regular object.') : _prodInvariant('75') : void 0;\n  !!ReactElement.isValidElement(spec) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component as a mixin. Instead, just use a regular object.') : _prodInvariant('76') : void 0;\n\n  var proto = Constructor.prototype;\n  var autoBindPairs = proto.__reactAutoBindPairs;\n\n  // By handling mixins before any other properties, we ensure the same\n  // chaining order is applied to methods with DEFINE_MANY policy, whether\n  // mixins are listed before or after these methods in the spec.\n  if (spec.hasOwnProperty(MIXINS_KEY)) {\n    RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);\n  }\n\n  for (var name in spec) {\n    if (!spec.hasOwnProperty(name)) {\n      continue;\n    }\n\n    if (name === MIXINS_KEY) {\n      // We have already handled mixins in a special case above.\n      continue;\n    }\n\n    var property = spec[name];\n    var isAlreadyDefined = proto.hasOwnProperty(name);\n    validateMethodOverride(isAlreadyDefined, name);\n\n    if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {\n      RESERVED_SPEC_KEYS[name](Constructor, property);\n    } else {\n      // Setup methods on prototype:\n      // The following member methods should not be automatically bound:\n      // 1. Expected ReactClass methods (in the \"interface\").\n      // 2. Overridden methods (that were mixed in).\n      var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);\n      var isFunction = typeof property === 'function';\n      var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;\n\n      if (shouldAutoBind) {\n        autoBindPairs.push(name, property);\n        proto[name] = property;\n      } else {\n        if (isAlreadyDefined) {\n          var specPolicy = ReactClassInterface[name];\n\n          // These cases should already be caught by validateMethodOverride.\n          !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.', specPolicy, name) : _prodInvariant('77', specPolicy, name) : void 0;\n\n          // For methods which are defined more than once, call the existing\n          // methods before calling the new property, merging if appropriate.\n          if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {\n            proto[name] = createMergedResultFunction(proto[name], property);\n          } else if (specPolicy === SpecPolicy.DEFINE_MANY) {\n            proto[name] = createChainedFunction(proto[name], property);\n          }\n        } else {\n          proto[name] = property;\n          if (\"development\" !== 'production') {\n            // Add verbose displayName to the function, which helps when looking\n            // at profiling tools.\n            if (typeof property === 'function' && spec.displayName) {\n              proto[name].displayName = spec.displayName + '_' + name;\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction mixStaticSpecIntoComponent(Constructor, statics) {\n  if (!statics) {\n    return;\n  }\n  for (var name in statics) {\n    var property = statics[name];\n    if (!statics.hasOwnProperty(name)) {\n      continue;\n    }\n\n    var isReserved = name in RESERVED_SPEC_KEYS;\n    !!isReserved ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved property, `%s`, that shouldn\\'t be on the \"statics\" key. Define it as an instance property instead; it will still be accessible on the constructor.', name) : _prodInvariant('78', name) : void 0;\n\n    var isInherited = name in Constructor;\n    !!isInherited ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('79', name) : void 0;\n    Constructor[name] = property;\n  }\n}\n\n/**\n * Merge two objects, but throw if both contain the same key.\n *\n * @param {object} one The first object, which is mutated.\n * @param {object} two The second object\n * @return {object} one after it has been mutated to contain everything in two.\n */\nfunction mergeIntoWithNoDuplicateKeys(one, two) {\n  !(one && two && typeof one === 'object' && typeof two === 'object') ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : _prodInvariant('80') : void 0;\n\n  for (var key in two) {\n    if (two.hasOwnProperty(key)) {\n      !(one[key] === undefined) ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.', key) : _prodInvariant('81', key) : void 0;\n      one[key] = two[key];\n    }\n  }\n  return one;\n}\n\n/**\n * Creates a function that invokes two functions and merges their return values.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createMergedResultFunction(one, two) {\n  return function mergedResult() {\n    var a = one.apply(this, arguments);\n    var b = two.apply(this, arguments);\n    if (a == null) {\n      return b;\n    } else if (b == null) {\n      return a;\n    }\n    var c = {};\n    mergeIntoWithNoDuplicateKeys(c, a);\n    mergeIntoWithNoDuplicateKeys(c, b);\n    return c;\n  };\n}\n\n/**\n * Creates a function that invokes two functions and ignores their return vales.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createChainedFunction(one, two) {\n  return function chainedFunction() {\n    one.apply(this, arguments);\n    two.apply(this, arguments);\n  };\n}\n\n/**\n * Binds a method to the component.\n *\n * @param {object} component Component whose method is going to be bound.\n * @param {function} method Method to be bound.\n * @return {function} The bound method.\n */\nfunction bindAutoBindMethod(component, method) {\n  var boundMethod = method.bind(component);\n  if (\"development\" !== 'production') {\n    boundMethod.__reactBoundContext = component;\n    boundMethod.__reactBoundMethod = method;\n    boundMethod.__reactBoundArguments = null;\n    var componentName = component.constructor.displayName;\n    var _bind = boundMethod.bind;\n    boundMethod.bind = function (newThis) {\n      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n        args[_key - 1] = arguments[_key];\n      }\n\n      // User is trying to bind() an autobound method; we effectively will\n      // ignore the value of \"this\" that the user is trying to use, so\n      // let's warn.\n      if (newThis !== component && newThis !== null) {\n        \"development\" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0;\n      } else if (!args.length) {\n        \"development\" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0;\n        return boundMethod;\n      }\n      var reboundMethod = _bind.apply(boundMethod, arguments);\n      reboundMethod.__reactBoundContext = component;\n      reboundMethod.__reactBoundMethod = method;\n      reboundMethod.__reactBoundArguments = args;\n      return reboundMethod;\n    };\n  }\n  return boundMethod;\n}\n\n/**\n * Binds all auto-bound methods in a component.\n *\n * @param {object} component Component whose method is going to be bound.\n */\nfunction bindAutoBindMethods(component) {\n  var pairs = component.__reactAutoBindPairs;\n  for (var i = 0; i < pairs.length; i += 2) {\n    var autoBindKey = pairs[i];\n    var method = pairs[i + 1];\n    component[autoBindKey] = bindAutoBindMethod(component, method);\n  }\n}\n\n/**\n * Add more to the ReactClass base class. These are all legacy features and\n * therefore not already part of the modern ReactComponent.\n */\nvar ReactClassMixin = {\n\n  /**\n   * TODO: This will be deprecated because state should always keep a consistent\n   * type signature and the only use case for this, is to avoid that.\n   */\n  replaceState: function (newState, callback) {\n    this.updater.enqueueReplaceState(this, newState);\n    if (callback) {\n      this.updater.enqueueCallback(this, callback, 'replaceState');\n    }\n  },\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function () {\n    return this.updater.isMounted(this);\n  }\n};\n\nvar ReactClassComponent = function () {};\n_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);\n\n/**\n * Module for creating composite components.\n *\n * @class ReactClass\n */\nvar ReactClass = {\n\n  /**\n   * Creates a composite component class given a class specification.\n   * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass\n   *\n   * @param {object} spec Class specification (which must define `render`).\n   * @return {function} Component constructor function.\n   * @public\n   */\n  createClass: function (spec) {\n    var Constructor = function (props, context, updater) {\n      // This constructor gets overridden by mocks. The argument is used\n      // by mocks to assert on what gets mounted.\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0;\n      }\n\n      // Wire up auto-binding\n      if (this.__reactAutoBindPairs.length) {\n        bindAutoBindMethods(this);\n      }\n\n      this.props = props;\n      this.context = context;\n      this.refs = emptyObject;\n      this.updater = updater || ReactNoopUpdateQueue;\n\n      this.state = null;\n\n      // ReactClasses doesn't have constructors. Instead, they use the\n      // getInitialState and componentWillMount methods for initialization.\n\n      var initialState = this.getInitialState ? this.getInitialState() : null;\n      if (\"development\" !== 'production') {\n        // We allow auto-mocks to proceed as if they're returning null.\n        if (initialState === undefined && this.getInitialState._isMockFunction) {\n          // This is probably bad practice. Consider warning here and\n          // deprecating this convenience.\n          initialState = null;\n        }\n      }\n      !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : _prodInvariant('82', Constructor.displayName || 'ReactCompositeComponent') : void 0;\n\n      this.state = initialState;\n    };\n    Constructor.prototype = new ReactClassComponent();\n    Constructor.prototype.constructor = Constructor;\n    Constructor.prototype.__reactAutoBindPairs = [];\n\n    injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));\n\n    mixSpecIntoComponent(Constructor, spec);\n\n    // Initialize the defaultProps property after all mixins have been merged.\n    if (Constructor.getDefaultProps) {\n      Constructor.defaultProps = Constructor.getDefaultProps();\n    }\n\n    if (\"development\" !== 'production') {\n      // This is a tag to indicate that the use of these method names is ok,\n      // since it's used with createClass. If it's not, then it's likely a\n      // mistake so we'll warn you to use the static property, property\n      // initializer or constructor respectively.\n      if (Constructor.getDefaultProps) {\n        Constructor.getDefaultProps.isReactClassApproved = {};\n      }\n      if (Constructor.prototype.getInitialState) {\n        Constructor.prototype.getInitialState.isReactClassApproved = {};\n      }\n    }\n\n    !Constructor.prototype.render ? \"development\" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : _prodInvariant('83') : void 0;\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0;\n    }\n\n    // Reduce time spent doing lookups by setting these on the prototype.\n    for (var methodName in ReactClassInterface) {\n      if (!Constructor.prototype[methodName]) {\n        Constructor.prototype[methodName] = null;\n      }\n    }\n\n    return Constructor;\n  },\n\n  injection: {\n    injectMixin: function (mixin) {\n      injectedMixins.push(mixin);\n    }\n  }\n\n};\n\nmodule.exports = ReactClass;\n},{\"139\":139,\"154\":154,\"161\":161,\"164\":164,\"165\":165,\"171\":171,\"172\":172,\"31\":31,\"62\":62,\"81\":81,\"83\":83,\"84\":84}],31:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar canDefineProperty = _dereq_(117);\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Base class helpers for the updating state of a component.\n */\nfunction ReactComponent(props, context, updater) {\n  this.props = props;\n  this.context = context;\n  this.refs = emptyObject;\n  // We initialize the default updater but the real one gets injected by the\n  // renderer.\n  this.updater = updater || ReactNoopUpdateQueue;\n}\n\nReactComponent.prototype.isReactComponent = {};\n\n/**\n * Sets a subset of the state. Always use this to mutate\n * state. You should treat `this.state` as immutable.\n *\n * There is no guarantee that `this.state` will be immediately updated, so\n * accessing `this.state` after calling this method may return the old value.\n *\n * There is no guarantee that calls to `setState` will run synchronously,\n * as they may eventually be batched together.  You can provide an optional\n * callback that will be executed when the call to setState is actually\n * completed.\n *\n * When a function is provided to setState, it will be called at some point in\n * the future (not synchronously). It will be called with the up to date\n * component arguments (state, props, context). These values can be different\n * from this.* because your function may be called after receiveProps but before\n * shouldComponentUpdate, and this new state, props, and context will not yet be\n * assigned to this.\n *\n * @param {object|function} partialState Next partial state or function to\n *        produce next partial state to be merged with current state.\n * @param {?function} callback Called after state is updated.\n * @final\n * @protected\n */\nReactComponent.prototype.setState = function (partialState, callback) {\n  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? \"development\" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;\n  this.updater.enqueueSetState(this, partialState);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'setState');\n  }\n};\n\n/**\n * Forces an update. This should only be invoked when it is known with\n * certainty that we are **not** in a DOM transaction.\n *\n * You may want to call this when you know that some deeper aspect of the\n * component's state has changed but `setState` was not called.\n *\n * This will not invoke `shouldComponentUpdate`, but it will invoke\n * `componentWillUpdate` and `componentDidUpdate`.\n *\n * @param {?function} callback Called after update is complete.\n * @final\n * @protected\n */\nReactComponent.prototype.forceUpdate = function (callback) {\n  this.updater.enqueueForceUpdate(this);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'forceUpdate');\n  }\n};\n\n/**\n * Deprecated APIs. These APIs used to exist on classic React classes but since\n * we would like to deprecate them, we're not going to move them over to this\n * modern base class. Instead, we define a getter that warns if it's accessed.\n */\nif (\"development\" !== 'production') {\n  var deprecatedAPIs = {\n    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],\n    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']\n  };\n  var defineDeprecationWarning = function (methodName, info) {\n    if (canDefineProperty) {\n      Object.defineProperty(ReactComponent.prototype, methodName, {\n        get: function () {\n          \"development\" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0;\n          return undefined;\n        }\n      });\n    }\n  };\n  for (var fnName in deprecatedAPIs) {\n    if (deprecatedAPIs.hasOwnProperty(fnName)) {\n      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);\n    }\n  }\n}\n\nmodule.exports = ReactComponent;\n},{\"117\":117,\"139\":139,\"154\":154,\"161\":161,\"171\":171,\"81\":81}],32:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentBrowserEnvironment\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMIDOperations = _dereq_(47);\n\n/**\n * Abstracts away all functionality of the reconciler that requires knowledge of\n * the browser context. TODO: These callers should be refactored to avoid the\n * need for this injection.\n */\nvar ReactComponentBrowserEnvironment = {\n\n  processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,\n\n  replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup,\n\n  /**\n   * If a particular environment requires that some resources be cleaned up,\n   * specify this in the injected Mixin. In the DOM, we would likely want to\n   * purge any cached node ID lookups.\n   *\n   * @private\n   */\n  unmountIDFromEnvironment: function (rootNodeID) {}\n\n};\n\nmodule.exports = ReactComponentBrowserEnvironment;\n},{\"47\":47,\"7\":7}],33:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentEnvironment\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nvar injected = false;\n\nvar ReactComponentEnvironment = {\n\n  /**\n   * Optionally injectable environment dependent cleanup hook. (server vs.\n   * browser etc). Example: A browser system caches DOM nodes based on component\n   * ID and must remove that cache entry when this instance is unmounted.\n   */\n  unmountIDFromEnvironment: null,\n\n  /**\n   * Optionally injectable hook for swapping out mount images in the middle of\n   * the tree.\n   */\n  replaceNodeWithMarkup: null,\n\n  /**\n   * Optionally injectable hook for processing a queue of child updates. Will\n   * later move into MultiChildComponents.\n   */\n  processChildrenUpdates: null,\n\n  injection: {\n    injectEnvironment: function (environment) {\n      !!injected ? \"development\" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0;\n      ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment;\n      ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;\n      ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;\n      injected = true;\n    }\n  }\n\n};\n\nmodule.exports = ReactComponentEnvironment;\n},{\"139\":139,\"161\":161}],34:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentTreeDevtool\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar tree = {};\nvar unmountedIDs = {};\nvar rootIDs = {};\n\nfunction updateTree(id, update) {\n  if (!tree[id]) {\n    tree[id] = {\n      element: null,\n      parentID: null,\n      ownerID: null,\n      text: null,\n      childIDs: [],\n      displayName: 'Unknown',\n      isMounted: false,\n      updateCount: 0\n    };\n  }\n  update(tree[id]);\n}\n\nfunction purgeDeep(id) {\n  var item = tree[id];\n  if (item) {\n    var childIDs = item.childIDs;\n\n    delete tree[id];\n    childIDs.forEach(purgeDeep);\n  }\n}\n\nfunction describeComponentFrame(name, source, ownerName) {\n  return '\\n    in ' + name + (source ? ' (at ' + source.fileName.replace(/^.*[\\\\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');\n}\n\nfunction describeID(id) {\n  var name = ReactComponentTreeDevtool.getDisplayName(id);\n  var element = ReactComponentTreeDevtool.getElement(id);\n  var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n  var ownerName;\n  if (ownerID) {\n    ownerName = ReactComponentTreeDevtool.getDisplayName(ownerID);\n  }\n  \"development\" !== 'production' ? warning(element, 'ReactComponentTreeDevtool: Missing React element for debugID %s when ' + 'building stack', id) : void 0;\n  return describeComponentFrame(name, element && element._source, ownerName);\n}\n\nvar ReactComponentTreeDevtool = {\n  onSetDisplayName: function (id, displayName) {\n    updateTree(id, function (item) {\n      return item.displayName = displayName;\n    });\n  },\n  onSetChildren: function (id, nextChildIDs) {\n    updateTree(id, function (item) {\n      item.childIDs = nextChildIDs;\n\n      nextChildIDs.forEach(function (nextChildID) {\n        var nextChild = tree[nextChildID];\n        !nextChild ? \"development\" !== 'production' ? invariant(false, 'Expected devtool events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('68') : void 0;\n        !(nextChild.displayName != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('69') : void 0;\n        !(nextChild.childIDs != null || nextChild.text != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('70') : void 0;\n        !nextChild.isMounted ? \"development\" !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;\n        if (nextChild.parentID == null) {\n          nextChild.parentID = id;\n          // TODO: This shouldn't be necessary but mounting a new root during in\n          // componentWillMount currently causes not-yet-mounted components to\n          // be purged from our tree data so their parent ID is missing.\n        }\n        !(nextChild.parentID === id) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('72', nextChildID, nextChild.parentID, id) : void 0;\n      });\n    });\n  },\n  onSetOwner: function (id, ownerID) {\n    updateTree(id, function (item) {\n      return item.ownerID = ownerID;\n    });\n  },\n  onSetParent: function (id, parentID) {\n    updateTree(id, function (item) {\n      return item.parentID = parentID;\n    });\n  },\n  onSetText: function (id, text) {\n    updateTree(id, function (item) {\n      return item.text = text;\n    });\n  },\n  onBeforeMountComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onBeforeUpdateComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onMountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = true;\n    });\n  },\n  onMountRootComponent: function (id) {\n    rootIDs[id] = true;\n  },\n  onUpdateComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.updateCount++;\n    });\n  },\n  onUnmountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = false;\n    });\n    unmountedIDs[id] = true;\n    delete rootIDs[id];\n  },\n  purgeUnmountedComponents: function () {\n    if (ReactComponentTreeDevtool._preventPurging) {\n      // Should only be used for testing.\n      return;\n    }\n\n    for (var id in unmountedIDs) {\n      purgeDeep(id);\n    }\n    unmountedIDs = {};\n  },\n  isMounted: function (id) {\n    var item = tree[id];\n    return item ? item.isMounted : false;\n  },\n  getCurrentStackAddendum: function (topElement) {\n    var info = '';\n    if (topElement) {\n      var type = topElement.type;\n      var name = typeof type === 'function' ? type.displayName || type.name : type;\n      var owner = topElement._owner;\n      info += describeComponentFrame(name || 'Unknown', topElement._source, owner && owner.getName());\n    }\n\n    var currentOwner = ReactCurrentOwner.current;\n    var id = currentOwner && currentOwner._debugID;\n\n    info += ReactComponentTreeDevtool.getStackAddendumByID(id);\n    return info;\n  },\n  getStackAddendumByID: function (id) {\n    var info = '';\n    while (id) {\n      info += describeID(id);\n      id = ReactComponentTreeDevtool.getParentID(id);\n    }\n    return info;\n  },\n  getChildIDs: function (id) {\n    var item = tree[id];\n    return item ? item.childIDs : [];\n  },\n  getDisplayName: function (id) {\n    var item = tree[id];\n    return item ? item.displayName : 'Unknown';\n  },\n  getElement: function (id) {\n    var item = tree[id];\n    return item ? item.element : null;\n  },\n  getOwnerID: function (id) {\n    var item = tree[id];\n    return item ? item.ownerID : null;\n  },\n  getParentID: function (id) {\n    var item = tree[id];\n    return item ? item.parentID : null;\n  },\n  getSource: function (id) {\n    var item = tree[id];\n    var element = item ? item.element : null;\n    var source = element != null ? element._source : null;\n    return source;\n  },\n  getText: function (id) {\n    var item = tree[id];\n    return item ? item.text : null;\n  },\n  getUpdateCount: function (id) {\n    var item = tree[id];\n    return item ? item.updateCount : 0;\n  },\n  getRootIDs: function () {\n    return Object.keys(rootIDs);\n  },\n  getRegisteredIDs: function () {\n    return Object.keys(tree);\n  }\n};\n\nmodule.exports = ReactComponentTreeDevtool;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36}],35:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCompositeComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\nvar ReactErrorUtils = _dereq_(65);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactNodeTypes = _dereq_(80);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactReconciler = _dereq_(87);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nfunction StatelessComponent(Component) {}\nStatelessComponent.prototype.render = function () {\n  var Component = ReactInstanceMap.get(this)._currentElement.type;\n  var element = Component(this.props, this.context, this.updater);\n  warnIfInvalidElement(Component, element);\n  return element;\n};\n\nfunction warnIfInvalidElement(Component, element) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;\n    \"development\" !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0;\n  }\n}\n\nfunction invokeComponentDidMountWithTimer() {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n  publicInstance.componentDidMount();\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n}\n\nfunction invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n  publicInstance.componentDidUpdate(prevProps, prevState, prevContext);\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n}\n\nfunction shouldConstruct(Component) {\n  return Component.prototype && Component.prototype.isReactComponent;\n}\n\n/**\n * ------------------ The Life-Cycle of a Composite Component ------------------\n *\n * - constructor: Initialization of state. The instance is now retained.\n *   - componentWillMount\n *   - render\n *   - [children's constructors]\n *     - [children's componentWillMount and render]\n *     - [children's componentDidMount]\n *     - componentDidMount\n *\n *       Update Phases:\n *       - componentWillReceiveProps (only called if parent updated)\n *       - shouldComponentUpdate\n *         - componentWillUpdate\n *           - render\n *           - [children's constructors or receive props phases]\n *         - componentDidUpdate\n *\n *     - componentWillUnmount\n *     - [children's componentWillUnmount]\n *   - [children destroyed]\n * - (destroyed): The instance is now blank, released by React and ready for GC.\n *\n * -----------------------------------------------------------------------------\n */\n\n/**\n * An incrementing ID assigned to each component when it is mounted. This is\n * used to enforce the order in which `ReactUpdates` updates dirty components.\n *\n * @private\n */\nvar nextMountID = 1;\n\n/**\n * @lends {ReactCompositeComponent.prototype}\n */\nvar ReactCompositeComponentMixin = {\n\n  /**\n   * Base constructor for all composite component.\n   *\n   * @param {ReactElement} element\n   * @final\n   * @internal\n   */\n  construct: function (element) {\n    this._currentElement = element;\n    this._rootNodeID = null;\n    this._instance = null;\n    this._hostParent = null;\n    this._hostContainerInfo = null;\n\n    // See ReactUpdateQueue\n    this._updateBatchNumber = null;\n    this._pendingElement = null;\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    this._renderedNodeType = null;\n    this._renderedComponent = null;\n    this._context = null;\n    this._mountOrder = 0;\n    this._topLevelWrapper = null;\n\n    // See ReactUpdates and ReactUpdateQueue.\n    this._pendingCallbacks = null;\n\n    // ComponentWillUnmount shall only be called once\n    this._calledComponentWillUnmount = false;\n\n    if (\"development\" !== 'production') {\n      this._warnedAboutRefsInRender = false;\n    }\n  },\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} hostParent\n   * @param {?object} hostContainerInfo\n   * @param {?object} context\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._context = context;\n    this._mountOrder = nextMountID++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var publicProps = this._currentElement.props;\n    var publicContext = this._processContext(context);\n\n    var Component = this._currentElement.type;\n\n    var updateQueue = transaction.getUpdateQueue();\n\n    // Initialize the public class\n    var inst = this._constructComponent(publicProps, publicContext, updateQueue);\n    var renderedElement;\n\n    // Support functional components\n    if (!shouldConstruct(Component) && (inst == null || inst.render == null)) {\n      renderedElement = inst;\n      warnIfInvalidElement(Component, renderedElement);\n      !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? \"development\" !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0;\n      inst = new StatelessComponent(Component);\n    }\n\n    if (\"development\" !== 'production') {\n      // This will throw later in _renderValidatedComponent, but add an early\n      // warning now to help debugging\n      if (inst.render == null) {\n        \"development\" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0;\n      }\n\n      var propsMutated = inst.props !== publicProps;\n      var componentName = Component.displayName || Component.name || 'Component';\n\n      \"development\" !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\\'s constructor was passed.', componentName, componentName) : void 0;\n    }\n\n    // These should be set up in the constructor, but as a convenience for\n    // simpler class abstractions, we set them up after the fact.\n    inst.props = publicProps;\n    inst.context = publicContext;\n    inst.refs = emptyObject;\n    inst.updater = updateQueue;\n\n    this._instance = inst;\n\n    // Store a reference from the instance back to the internal representation\n    ReactInstanceMap.set(inst, this);\n\n    if (\"development\" !== 'production') {\n      // Since plain JS classes are defined without any special initialization\n      // logic, we can not catch common errors early. Therefore, we have to\n      // catch them here, at initialization time, instead.\n      \"development\" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0;\n    }\n\n    var initialState = inst.state;\n    if (initialState === undefined) {\n      inst.state = initialState = null;\n    }\n    !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    var markup;\n    if (inst.unstable_handleError) {\n      markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } else {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n\n    if (inst.componentDidMount) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);\n      }\n    }\n\n    return markup;\n  },\n\n  _constructComponent: function (publicProps, publicContext, updateQueue) {\n    if (\"development\" !== 'production') {\n      ReactCurrentOwner.current = this;\n      try {\n        return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n      } finally {\n        ReactCurrentOwner.current = null;\n      }\n    } else {\n      return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n    }\n  },\n\n  _constructComponentWithoutOwner: function (publicProps, publicContext, updateQueue) {\n    var Component = this._currentElement.type;\n    var instanceOrElement;\n    if (shouldConstruct(Component)) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n      instanceOrElement = new Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n    } else {\n      // This can still be an instance in case of factory components\n      // but we'll count this as time spent rendering as the more common case.\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n      instanceOrElement = Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n    }\n    return instanceOrElement;\n  },\n\n  performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var markup;\n    var checkpoint = transaction.checkpoint();\n    try {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } catch (e) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onError();\n        }\n      }\n      // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint\n      transaction.rollback(checkpoint);\n      this._instance.unstable_handleError(e);\n      if (this._pendingStateQueue) {\n        this._instance.state = this._processPendingState(this._instance.props, this._instance.context);\n      }\n      checkpoint = transaction.checkpoint();\n\n      this._renderedComponent.unmountComponent(true);\n      transaction.rollback(checkpoint);\n\n      // Try again - we've informed the component about the error, so they can render an error message this time.\n      // If this throws again, the error will bubble up (and can be caught by a higher error boundary).\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n    return markup;\n  },\n\n  performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var inst = this._instance;\n    if (inst.componentWillMount) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      inst.componentWillMount();\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      // When mounting, calls to `setState` by `componentWillMount` will set\n      // `this._pendingStateQueue` without triggering a re-render.\n      if (this._pendingStateQueue) {\n        inst.state = this._processPendingState(inst.props, inst.context);\n      }\n    }\n\n    // If not a stateless component, we now render\n    if (renderedElement === undefined) {\n      renderedElement = this._renderValidatedComponent();\n    }\n\n    var nodeType = ReactNodeTypes.getType(renderedElement);\n    this._renderedNodeType = nodeType;\n    var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n    );\n    this._renderedComponent = child;\n    if (\"development\" !== 'production') {\n      if (child._debugID !== 0 && this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n      }\n    }\n\n    var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context));\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n      }\n    }\n\n    return markup;\n  },\n\n  getHostNode: function () {\n    return ReactReconciler.getHostNode(this._renderedComponent);\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    if (!this._renderedComponent) {\n      return;\n    }\n    var inst = this._instance;\n\n    if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {\n      inst._calledComponentWillUnmount = true;\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n      if (safely) {\n        var name = this.getName() + '.componentWillUnmount()';\n        ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));\n      } else {\n        inst.componentWillUnmount();\n      }\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n    }\n\n    if (this._renderedComponent) {\n      ReactReconciler.unmountComponent(this._renderedComponent, safely);\n      this._renderedNodeType = null;\n      this._renderedComponent = null;\n      this._instance = null;\n    }\n\n    // Reset pending fields\n    // Even if this component is scheduled for another update in ReactUpdates,\n    // it would still be ignored because these fields are reset.\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n    this._pendingCallbacks = null;\n    this._pendingElement = null;\n\n    // These fields do not really need to be reset since this object is no\n    // longer accessible.\n    this._context = null;\n    this._rootNodeID = null;\n    this._topLevelWrapper = null;\n\n    // Delete the reference from the instance to this internal representation\n    // which allow the internals to be properly cleaned up even if the user\n    // leaks a reference to the public instance.\n    ReactInstanceMap.remove(inst);\n\n    // Some existing components rely on inst.props even after they've been\n    // destroyed (in event handlers).\n    // TODO: inst.props = null;\n    // TODO: inst.state = null;\n    // TODO: inst.context = null;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _maskContext: function (context) {\n    var Component = this._currentElement.type;\n    var contextTypes = Component.contextTypes;\n    if (!contextTypes) {\n      return emptyObject;\n    }\n    var maskedContext = {};\n    for (var contextName in contextTypes) {\n      maskedContext[contextName] = context[contextName];\n    }\n    return maskedContext;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`, and asserts that they are valid.\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _processContext: function (context) {\n    var maskedContext = this._maskContext(context);\n    if (\"development\" !== 'production') {\n      var Component = this._currentElement.type;\n      if (Component.contextTypes) {\n        this._checkContextTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);\n      }\n    }\n    return maskedContext;\n  },\n\n  /**\n   * @param {object} currentContext\n   * @return {object}\n   * @private\n   */\n  _processChildContext: function (currentContext) {\n    var Component = this._currentElement.type;\n    var inst = this._instance;\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onBeginProcessingChildContext();\n    }\n    var childContext = inst.getChildContext && inst.getChildContext();\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onEndProcessingChildContext();\n    }\n    if (childContext) {\n      !(typeof Component.childContextTypes === 'object') ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;\n      if (\"development\" !== 'production') {\n        this._checkContextTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);\n      }\n      for (var name in childContext) {\n        !(name in Component.childContextTypes) ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): key \"%s\" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0;\n      }\n      return _assign({}, currentContext, childContext);\n    }\n    return currentContext;\n  },\n\n  /**\n   * Assert that the context types are valid\n   *\n   * @param {object} typeSpecs Map of context field to a ReactPropType\n   * @param {object} values Runtime values that need to be type-checked\n   * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n   * @private\n   */\n  _checkContextTypes: function (typeSpecs, values, location) {\n    checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);\n  },\n\n  receiveComponent: function (nextElement, transaction, nextContext) {\n    var prevElement = this._currentElement;\n    var prevContext = this._context;\n\n    this._pendingElement = null;\n\n    this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);\n  },\n\n  /**\n   * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`\n   * is set, update the component.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (transaction) {\n    if (this._pendingElement != null) {\n      ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);\n    } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {\n      this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);\n    } else {\n      this._updateBatchNumber = null;\n    }\n  },\n\n  /**\n   * Perform an update to a mounted component. The componentWillReceiveProps and\n   * shouldComponentUpdate methods are called, then (assuming the update isn't\n   * skipped) the remaining update lifecycle methods are called and the DOM\n   * representation is updated.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevParentElement\n   * @param {ReactElement} nextParentElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {\n    var inst = this._instance;\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    var willReceive = false;\n    var nextContext;\n    var nextProps;\n\n    // Determine if the context has changed or not\n    if (this._context === nextUnmaskedContext) {\n      nextContext = inst.context;\n    } else {\n      nextContext = this._processContext(nextUnmaskedContext);\n      willReceive = true;\n    }\n\n    nextProps = nextParentElement.props;\n\n    // Not a simple state update but a props update\n    if (prevParentElement !== nextParentElement) {\n      willReceive = true;\n    }\n\n    // An update here will schedule an update but immediately set\n    // _pendingStateQueue which will ensure that any state updates gets\n    // immediately reconciled instead of waiting for the next batch.\n    if (willReceive && inst.componentWillReceiveProps) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n      inst.componentWillReceiveProps(nextProps, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n    }\n\n    var nextState = this._processPendingState(nextProps, nextContext);\n    var shouldUpdate = true;\n\n    if (!this._pendingForceUpdate && inst.shouldComponentUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n      shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;\n    }\n\n    this._updateBatchNumber = null;\n    if (shouldUpdate) {\n      this._pendingForceUpdate = false;\n      // Will set `this.props`, `this.state` and `this.context`.\n      this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);\n    } else {\n      // If it's determined that a component should not update, we still want\n      // to set props and state but we shortcut the rest of the update.\n      this._currentElement = nextParentElement;\n      this._context = nextUnmaskedContext;\n      inst.props = nextProps;\n      inst.state = nextState;\n      inst.context = nextContext;\n    }\n  },\n\n  _processPendingState: function (props, context) {\n    var inst = this._instance;\n    var queue = this._pendingStateQueue;\n    var replace = this._pendingReplaceState;\n    this._pendingReplaceState = false;\n    this._pendingStateQueue = null;\n\n    if (!queue) {\n      return inst.state;\n    }\n\n    if (replace && queue.length === 1) {\n      return queue[0];\n    }\n\n    var nextState = _assign({}, replace ? queue[0] : inst.state);\n    for (var i = replace ? 1 : 0; i < queue.length; i++) {\n      var partial = queue[i];\n      _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);\n    }\n\n    return nextState;\n  },\n\n  /**\n   * Merges new props and state, notifies delegate methods of update and\n   * performs update.\n   *\n   * @param {ReactElement} nextElement Next element\n   * @param {object} nextProps Next public object to set as properties.\n   * @param {?object} nextState Next object to set as state.\n   * @param {?object} nextContext Next public object to set as context.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {?object} unmaskedContext\n   * @private\n   */\n  _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {\n    var inst = this._instance;\n\n    var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);\n    var prevProps;\n    var prevState;\n    var prevContext;\n    if (hasComponentDidUpdate) {\n      prevProps = inst.props;\n      prevState = inst.state;\n      prevContext = inst.context;\n    }\n\n    if (inst.componentWillUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n      inst.componentWillUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n    }\n\n    this._currentElement = nextElement;\n    this._context = unmaskedContext;\n    inst.props = nextProps;\n    inst.state = nextState;\n    inst.context = nextContext;\n\n    this._updateRenderedComponent(transaction, unmaskedContext);\n\n    if (hasComponentDidUpdate) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);\n      }\n    }\n  },\n\n  /**\n   * Call the component's `render` method and update the DOM accordingly.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  _updateRenderedComponent: function (transaction, context) {\n    var prevComponentInstance = this._renderedComponent;\n    var prevRenderedElement = prevComponentInstance._currentElement;\n    var nextRenderedElement = this._renderValidatedComponent();\n    if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {\n      ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));\n    } else {\n      var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);\n      ReactReconciler.unmountComponent(prevComponentInstance, false);\n\n      var nodeType = ReactNodeTypes.getType(nextRenderedElement);\n      this._renderedNodeType = nodeType;\n      var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n      );\n      this._renderedComponent = child;\n      if (\"development\" !== 'production') {\n        if (child._debugID !== 0 && this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n        }\n      }\n\n      var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context));\n\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n        }\n      }\n\n      this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);\n    }\n  },\n\n  /**\n   * Overridden in shallow rendering.\n   *\n   * @protected\n   */\n  _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {\n    ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);\n  },\n\n  /**\n   * @protected\n   */\n  _renderValidatedComponentWithoutOwnerOrContext: function () {\n    var inst = this._instance;\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n    var renderedComponent = inst.render();\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      // We allow auto-mocks to proceed as if they're returning null.\n      if (renderedComponent === undefined && inst.render._isMockFunction) {\n        // This is probably bad practice. Consider warning here and\n        // deprecating this convenience.\n        renderedComponent = null;\n      }\n    }\n\n    return renderedComponent;\n  },\n\n  /**\n   * @private\n   */\n  _renderValidatedComponent: function () {\n    var renderedComponent;\n    ReactCurrentOwner.current = this;\n    try {\n      renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();\n    } finally {\n      ReactCurrentOwner.current = null;\n    }\n    !(\n    // TODO: An `isValidNode` function would probably be more appropriate\n    renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? \"development\" !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    return renderedComponent;\n  },\n\n  /**\n   * Lazily allocates the refs object and stores `component` as `ref`.\n   *\n   * @param {string} ref Reference name.\n   * @param {component} component Component to store as `ref`.\n   * @final\n   * @private\n   */\n  attachRef: function (ref, component) {\n    var inst = this.getPublicInstance();\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0;\n    var publicComponentInstance = component.getPublicInstance();\n    if (\"development\" !== 'production') {\n      var componentName = component && component.getName ? component.getName() : 'a component';\n      \"development\" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref \"%s\" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;\n    }\n    var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;\n    refs[ref] = publicComponentInstance;\n  },\n\n  /**\n   * Detaches a reference name.\n   *\n   * @param {string} ref Name to dereference.\n   * @final\n   * @private\n   */\n  detachRef: function (ref) {\n    var refs = this.getPublicInstance().refs;\n    delete refs[ref];\n  },\n\n  /**\n   * Get a text description of the component that can be used to identify it\n   * in error messages.\n   * @return {string} The name or null.\n   * @internal\n   */\n  getName: function () {\n    var type = this._currentElement.type;\n    var constructor = this._instance && this._instance.constructor;\n    return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;\n  },\n\n  /**\n   * Get the publicly accessible representation of this component - i.e. what\n   * is exposed by refs and returned by render. Can be null for stateless\n   * components.\n   *\n   * @return {ReactComponent} the public component instance.\n   * @internal\n   */\n  getPublicInstance: function () {\n    var inst = this._instance;\n    if (inst instanceof StatelessComponent) {\n      return null;\n    }\n    return inst;\n  },\n\n  // Stub\n  _instantiateReactComponent: null\n\n};\n\nvar ReactCompositeComponent = {\n\n  Mixin: ReactCompositeComponentMixin\n\n};\n\nmodule.exports = ReactCompositeComponent;\n},{\"118\":118,\"139\":139,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"172\":172,\"33\":33,\"36\":36,\"62\":62,\"65\":65,\"73\":73,\"74\":74,\"80\":80,\"84\":84,\"87\":87}],36:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCurrentOwner\n */\n\n'use strict';\n\n/**\n * Keeps track of the current owner.\n *\n * The current owner is the component who should own any components that are\n * currently being constructed.\n */\n\nvar ReactCurrentOwner = {\n\n  /**\n   * @internal\n   * @type {ReactComponent}\n   */\n  current: null\n\n};\n\nmodule.exports = ReactCurrentOwner;\n},{}],37:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOM\n */\n\n/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactMount = _dereq_(77);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdates = _dereq_(95);\nvar ReactVersion = _dereq_(96);\n\nvar findDOMNode = _dereq_(122);\nvar getHostComponentFromComposite = _dereq_(129);\nvar renderSubtreeIntoContainer = _dereq_(140);\nvar warning = _dereq_(171);\n\nReactDefaultInjection.inject();\n\nvar React = {\n  findDOMNode: findDOMNode,\n  render: ReactMount.render,\n  unmountComponentAtNode: ReactMount.unmountComponentAtNode,\n  version: ReactVersion,\n\n  /* eslint-disable camelcase */\n  unstable_batchedUpdates: ReactUpdates.batchedUpdates,\n  unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer\n};\n\n// Inject the runtime into a devtools global hook regardless of browser.\n// Allows for debugging when the hook is injected on the page.\n/* eslint-enable camelcase */\nif (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {\n  __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({\n    ComponentTree: {\n      getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,\n      getNodeFromInstance: function (inst) {\n        // inst is an internal instance (but could be a composite)\n        if (inst._renderedComponent) {\n          inst = getHostComponentFromComposite(inst);\n        }\n        if (inst) {\n          return ReactDOMComponentTree.getNodeFromInstance(inst);\n        } else {\n          return null;\n        }\n      }\n    },\n    Mount: ReactMount,\n    Reconciler: ReactReconciler\n  });\n}\n\nif (\"development\" !== 'production') {\n  var ExecutionEnvironment = _dereq_(147);\n  if (ExecutionEnvironment.canUseDOM && window.top === window.self) {\n\n    // First check if devtools is not installed\n    if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {\n      // If we're in Chrome or Firefox, provide a download link if not installed.\n      if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {\n        // Firefox does not have the issue with devtools loaded over file://\n        var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;\n        console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');\n      }\n    }\n\n    var testFunc = function testFn() {};\n    \"development\" !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;\n\n    // If we're in IE8, check to see if we are in compatibility mode and provide\n    // information on preventing compatibility mode\n    var ieCompatibilityMode = document.documentMode && document.documentMode < 8;\n\n    \"development\" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />') : void 0;\n\n    var expectedFeatures = [\n    // shims\n    Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim];\n\n    for (var i = 0; i < expectedFeatures.length; i++) {\n      if (!expectedFeatures[i]) {\n        \"development\" !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;\n        break;\n      }\n    }\n  }\n}\n\nmodule.exports = React;\n},{\"122\":122,\"129\":129,\"140\":140,\"147\":147,\"171\":171,\"41\":41,\"61\":61,\"77\":77,\"87\":87,\"95\":95,\"96\":96}],38:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMButton\n */\n\n'use strict';\n\nvar DisabledInputUtils = _dereq_(14);\n\n/**\n * Implements a <button> host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar ReactDOMButton = {\n  getHostProps: DisabledInputUtils.getHostProps\n};\n\nmodule.exports = ReactDOMButton;\n},{\"14\":14}],39:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponent\n */\n\n/* global hasOwnProperty:true */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar AutoFocusUtils = _dereq_(1);\nvar CSSPropertyOperations = _dereq_(4);\nvar DOMLazyTree = _dereq_(8);\nvar DOMNamespaces = _dereq_(9);\nvar DOMProperty = _dereq_(10);\nvar DOMPropertyOperations = _dereq_(11);\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMButton = _dereq_(38);\nvar ReactDOMComponentFlags = _dereq_(40);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInput = _dereq_(48);\nvar ReactDOMOption = _dereq_(51);\nvar ReactDOMSelect = _dereq_(52);\nvar ReactDOMTextarea = _dereq_(56);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChild = _dereq_(78);\nvar ReactServerRenderingTransaction = _dereq_(91);\n\nvar emptyFunction = _dereq_(153);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar isEventSupported = _dereq_(135);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\nvar validateDOMNesting = _dereq_(145);\nvar warning = _dereq_(171);\n\nvar Flags = ReactDOMComponentFlags;\nvar deleteListener = EventPluginHub.deleteListener;\nvar getNode = ReactDOMComponentTree.getNodeFromInstance;\nvar listenTo = ReactBrowserEventEmitter.listenTo;\nvar registrationNameModules = EventPluginRegistry.registrationNameModules;\n\n// For quickly matching children type, to test if can be treated as content.\nvar CONTENT_TYPES = { 'string': true, 'number': true };\n\nvar STYLE = keyOf({ style: null });\nvar HTML = keyOf({ __html: null });\nvar RESERVED_PROPS = {\n  children: null,\n  dangerouslySetInnerHTML: null,\n  suppressContentEditableWarning: null\n};\n\n// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).\nvar DOC_FRAGMENT_TYPE = 11;\n\nfunction getDeclarationErrorAddendum(internalInstance) {\n  if (internalInstance) {\n    var owner = internalInstance._currentElement._owner || null;\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' This DOM node was rendered by `' + name + '`.';\n      }\n    }\n  }\n  return '';\n}\n\nfunction friendlyStringify(obj) {\n  if (typeof obj === 'object') {\n    if (Array.isArray(obj)) {\n      return '[' + obj.map(friendlyStringify).join(', ') + ']';\n    } else {\n      var pairs = [];\n      for (var key in obj) {\n        if (Object.prototype.hasOwnProperty.call(obj, key)) {\n          var keyEscaped = /^[a-z$_][\\w$_]*$/i.test(key) ? key : JSON.stringify(key);\n          pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));\n        }\n      }\n      return '{' + pairs.join(', ') + '}';\n    }\n  } else if (typeof obj === 'string') {\n    return JSON.stringify(obj);\n  } else if (typeof obj === 'function') {\n    return '[function object]';\n  }\n  // Differs from JSON.stringify in that undefined because undefined and that\n  // inf and nan don't become null\n  return String(obj);\n}\n\nvar styleMutationWarning = {};\n\nfunction checkAndWarnForMutatedStyle(style1, style2, component) {\n  if (style1 == null || style2 == null) {\n    return;\n  }\n  if (shallowEqual(style1, style2)) {\n    return;\n  }\n\n  var componentName = component._tag;\n  var owner = component._currentElement._owner;\n  var ownerName;\n  if (owner) {\n    ownerName = owner.getName();\n  }\n\n  var hash = ownerName + '|' + componentName;\n\n  if (styleMutationWarning.hasOwnProperty(hash)) {\n    return;\n  }\n\n  styleMutationWarning[hash] = true;\n\n  \"development\" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;\n}\n\n/**\n * @param {object} component\n * @param {?object} props\n */\nfunction assertValidProps(component, props) {\n  if (!props) {\n    return;\n  }\n  // Note the use of `==` which checks for null or undefined.\n  if (voidElementTags[component._tag]) {\n    !(props.children == null && props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : _prodInvariant('137', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : void 0;\n  }\n  if (props.dangerouslySetInnerHTML != null) {\n    !(props.children == null) ? \"development\" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : _prodInvariant('60') : void 0;\n    !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? \"development\" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : _prodInvariant('61') : void 0;\n  }\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;\n    \"development\" !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0;\n    \"development\" !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;\n  }\n  !(props.style == null || typeof props.style === 'object') ? \"development\" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \\'em\\'}} when using JSX.%s', getDeclarationErrorAddendum(component)) : _prodInvariant('62', getDeclarationErrorAddendum(component)) : void 0;\n}\n\nfunction enqueuePutListener(inst, registrationName, listener, transaction) {\n  if (transaction instanceof ReactServerRenderingTransaction) {\n    return;\n  }\n  if (\"development\" !== 'production') {\n    // IE8 has no API for event capturing and the `onScroll` event doesn't\n    // bubble.\n    \"development\" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\\'t support the `onScroll` event') : void 0;\n  }\n  var containerInfo = inst._hostContainerInfo;\n  var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;\n  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;\n  listenTo(registrationName, doc);\n  transaction.getReactMountReady().enqueue(putListener, {\n    inst: inst,\n    registrationName: registrationName,\n    listener: listener\n  });\n}\n\nfunction putListener() {\n  var listenerToPut = this;\n  EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);\n}\n\nfunction inputPostMount() {\n  var inst = this;\n  ReactDOMInput.postMountWrapper(inst);\n}\n\nfunction textareaPostMount() {\n  var inst = this;\n  ReactDOMTextarea.postMountWrapper(inst);\n}\n\nfunction optionPostMount() {\n  var inst = this;\n  ReactDOMOption.postMountWrapper(inst);\n}\n\nvar setContentChildForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  setContentChildForInstrumentation = function (content) {\n    var hasExistingContent = this._contentDebugID != null;\n    var debugID = this._debugID;\n    var contentDebugID = debugID + '#text';\n\n    if (content == null) {\n      if (hasExistingContent) {\n        ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);\n      }\n      this._contentDebugID = null;\n      return;\n    }\n\n    this._contentDebugID = contentDebugID;\n    var text = '' + content;\n\n    ReactInstrumentation.debugTool.onSetDisplayName(contentDebugID, '#text');\n    ReactInstrumentation.debugTool.onSetParent(contentDebugID, debugID);\n    ReactInstrumentation.debugTool.onSetText(contentDebugID, text);\n\n    if (hasExistingContent) {\n      ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);\n    } else {\n      ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onMountComponent(contentDebugID);\n      ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);\n    }\n  };\n}\n\n// There are so many media events, it makes sense to just\n// maintain a list rather than create a `trapBubbledEvent` for each\nvar mediaEvents = {\n  topAbort: 'abort',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTimeUpdate: 'timeupdate',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting'\n};\n\nfunction trapBubbledEventsLocal() {\n  var inst = this;\n  // If a component renders to null or if another component fatals and causes\n  // the state of the tree to be corrupted, `node` here can be null.\n  !inst._rootNodeID ? \"development\" !== 'production' ? invariant(false, 'Must be mounted to trap events') : _prodInvariant('63') : void 0;\n  var node = getNode(inst);\n  !node ? \"development\" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : _prodInvariant('64') : void 0;\n\n  switch (inst._tag) {\n    case 'iframe':\n    case 'object':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'video':\n    case 'audio':\n\n      inst._wrapperState.listeners = [];\n      // Create listener for each media event\n      for (var event in mediaEvents) {\n        if (mediaEvents.hasOwnProperty(event)) {\n          inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));\n        }\n      }\n      break;\n    case 'source':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node)];\n      break;\n    case 'img':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'form':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];\n      break;\n    case 'input':\n    case 'select':\n    case 'textarea':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topInvalid, 'invalid', node)];\n      break;\n  }\n}\n\nfunction postUpdateSelectWrapper() {\n  ReactDOMSelect.postUpdateWrapper(this);\n}\n\n// For HTML, certain tags should omit their close tag. We keep a whitelist for\n// those special-case tags.\n\nvar omittedCloseTags = {\n  'area': true,\n  'base': true,\n  'br': true,\n  'col': true,\n  'embed': true,\n  'hr': true,\n  'img': true,\n  'input': true,\n  'keygen': true,\n  'link': true,\n  'meta': true,\n  'param': true,\n  'source': true,\n  'track': true,\n  'wbr': true\n};\n\n// NOTE: menuitem's close tag should be omitted, but that causes problems.\nvar newlineEatingTags = {\n  'listing': true,\n  'pre': true,\n  'textarea': true\n};\n\n// For HTML, certain tags cannot have children. This has the same purpose as\n// `omittedCloseTags` except that `menuitem` should still have its closing tag.\n\nvar voidElementTags = _assign({\n  'menuitem': true\n}, omittedCloseTags);\n\n// We accept any tag to be rendered but since this gets injected into arbitrary\n// HTML, we want to make sure that it's a safe tag.\n// http://www.w3.org/TR/REC-xml/#NT-Name\n\nvar VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\\.\\-\\d]*$/; // Simplified subset\nvar validatedTagCache = {};\nvar hasOwnProperty = {}.hasOwnProperty;\n\nfunction validateDangerousTag(tag) {\n  if (!hasOwnProperty.call(validatedTagCache, tag)) {\n    !VALID_TAG_REGEX.test(tag) ? \"development\" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : _prodInvariant('65', tag) : void 0;\n    validatedTagCache[tag] = true;\n  }\n}\n\nfunction isCustomComponent(tagName, props) {\n  return tagName.indexOf('-') >= 0 || props.is != null;\n}\n\nvar globalIdCounter = 1;\n\n/**\n * Creates a new React class that is idempotent and capable of containing other\n * React components. It accepts event listeners and DOM properties that are\n * valid according to `DOMProperty`.\n *\n *  - Event listeners: `onClick`, `onMouseDown`, etc.\n *  - DOM properties: `className`, `name`, `title`, etc.\n *\n * The `style` property functions differently from the DOM API. It accepts an\n * object mapping of style properties to values.\n *\n * @constructor ReactDOMComponent\n * @extends ReactMultiChild\n */\nfunction ReactDOMComponent(element) {\n  var tag = element.type;\n  validateDangerousTag(tag);\n  this._currentElement = element;\n  this._tag = tag.toLowerCase();\n  this._namespaceURI = null;\n  this._renderedChildren = null;\n  this._previousStyle = null;\n  this._previousStyleCopy = null;\n  this._hostNode = null;\n  this._hostParent = null;\n  this._rootNodeID = null;\n  this._domID = null;\n  this._hostContainerInfo = null;\n  this._wrapperState = null;\n  this._topLevelWrapper = null;\n  this._flags = 0;\n  if (\"development\" !== 'production') {\n    this._ancestorInfo = null;\n    setContentChildForInstrumentation.call(this, null);\n  }\n}\n\nReactDOMComponent.displayName = 'ReactDOMComponent';\n\nReactDOMComponent.Mixin = {\n\n  /**\n   * Generates root tag markup then recurses. This method has side effects and\n   * is not idempotent.\n   *\n   * @internal\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?ReactDOMComponent} the containing DOM component instance\n   * @param {?object} info about the host container\n   * @param {object} context\n   * @return {string} The computed markup.\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._rootNodeID = globalIdCounter++;\n    this._domID = hostContainerInfo._idCounter++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var props = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        this._wrapperState = {\n          listeners: null\n        };\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'button':\n        props = ReactDOMButton.getHostProps(this, props, hostParent);\n        break;\n      case 'input':\n        ReactDOMInput.mountWrapper(this, props, hostParent);\n        props = ReactDOMInput.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'option':\n        ReactDOMOption.mountWrapper(this, props, hostParent);\n        props = ReactDOMOption.getHostProps(this, props);\n        break;\n      case 'select':\n        ReactDOMSelect.mountWrapper(this, props, hostParent);\n        props = ReactDOMSelect.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.mountWrapper(this, props, hostParent);\n        props = ReactDOMTextarea.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n    }\n\n    assertValidProps(this, props);\n\n    // We create tags in the namespace of their parent container, except HTML\n    // tags get no namespace.\n    var namespaceURI;\n    var parentTag;\n    if (hostParent != null) {\n      namespaceURI = hostParent._namespaceURI;\n      parentTag = hostParent._tag;\n    } else if (hostContainerInfo._tag) {\n      namespaceURI = hostContainerInfo._namespaceURI;\n      parentTag = hostContainerInfo._tag;\n    }\n    if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {\n      namespaceURI = DOMNamespaces.html;\n    }\n    if (namespaceURI === DOMNamespaces.html) {\n      if (this._tag === 'svg') {\n        namespaceURI = DOMNamespaces.svg;\n      } else if (this._tag === 'math') {\n        namespaceURI = DOMNamespaces.mathml;\n      }\n    }\n    this._namespaceURI = namespaceURI;\n\n    if (\"development\" !== 'production') {\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo._tag) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting(this._tag, this, parentInfo);\n      }\n      this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);\n    }\n\n    var mountImage;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var el;\n      if (namespaceURI === DOMNamespaces.html) {\n        if (this._tag === 'script') {\n          // Create the script via .innerHTML so its \"parser-inserted\" flag is\n          // set to true and it does not execute\n          var div = ownerDocument.createElement('div');\n          var type = this._currentElement.type;\n          div.innerHTML = '<' + type + '></' + type + '>';\n          el = div.removeChild(div.firstChild);\n        } else if (props.is) {\n          el = ownerDocument.createElement(this._currentElement.type, props.is);\n        } else {\n          // Separate else branch instead of using `props.is || undefined` above becuase of a Firefox bug.\n          // See discussion in https://github.com/facebook/react/pull/6896\n          // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240\n          el = ownerDocument.createElement(this._currentElement.type);\n        }\n      } else {\n        el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);\n      }\n      ReactDOMComponentTree.precacheNode(this, el);\n      this._flags |= Flags.hasCachedChildNodes;\n      if (!this._hostParent) {\n        DOMPropertyOperations.setAttributeForRoot(el);\n      }\n      this._updateDOMProperties(null, props, transaction);\n      var lazyTree = DOMLazyTree(el);\n      this._createInitialChildren(transaction, props, context, lazyTree);\n      mountImage = lazyTree;\n    } else {\n      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);\n      var tagContent = this._createContentMarkup(transaction, props, context);\n      if (!tagContent && omittedCloseTags[this._tag]) {\n        mountImage = tagOpen + '/>';\n      } else {\n        mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';\n      }\n    }\n\n    switch (this._tag) {\n      case 'input':\n        transaction.getReactMountReady().enqueue(inputPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'textarea':\n        transaction.getReactMountReady().enqueue(textareaPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'select':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'button':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'option':\n        transaction.getReactMountReady().enqueue(optionPostMount, this);\n        break;\n    }\n\n    return mountImage;\n  },\n\n  /**\n   * Creates markup for the open tag and all attributes.\n   *\n   * This method has side effects because events get registered.\n   *\n   * Iterating over object properties is faster than iterating over arrays.\n   * @see http://jsperf.com/obj-vs-arr-iteration\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @return {string} Markup of opening tag.\n   */\n  _createOpenTagMarkupAndPutListeners: function (transaction, props) {\n    var ret = '<' + this._currentElement.type;\n\n    for (var propKey in props) {\n      if (!props.hasOwnProperty(propKey)) {\n        continue;\n      }\n      var propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (propValue) {\n          enqueuePutListener(this, propKey, propValue, transaction);\n        }\n      } else {\n        if (propKey === STYLE) {\n          if (propValue) {\n            if (\"development\" !== 'production') {\n              // See `_updateDOMProperties`. style block\n              this._previousStyle = propValue;\n            }\n            propValue = this._previousStyleCopy = _assign({}, props.style);\n          }\n          propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);\n        }\n        var markup = null;\n        if (this._tag != null && isCustomComponent(this._tag, props)) {\n          if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n            markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);\n          }\n        } else {\n          markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);\n        }\n        if (markup) {\n          ret += ' ' + markup;\n        }\n      }\n    }\n\n    // For static pages, no need to put React ID and checksum. Saves lots of\n    // bytes.\n    if (transaction.renderToStaticMarkup) {\n      return ret;\n    }\n\n    if (!this._hostParent) {\n      ret += ' ' + DOMPropertyOperations.createMarkupForRoot();\n    }\n    ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);\n    return ret;\n  },\n\n  /**\n   * Creates markup for the content between the tags.\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @param {object} context\n   * @return {string} Content markup.\n   */\n  _createContentMarkup: function (transaction, props, context) {\n    var ret = '';\n\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        ret = innerHTML.__html;\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        ret = escapeTextContentForBrowser(contentToUse);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        ret = mountImages.join('');\n      }\n    }\n    if (newlineEatingTags[this._tag] && ret.charAt(0) === '\\n') {\n      // text/html ignores the first character in these tags if it's a newline\n      // Prefer to break application/xml over text/html (for now) by adding\n      // a newline specifically to get eaten by the parser. (Alternately for\n      // textareas, replacing \"^\\n\" with \"\\r\\n\" doesn't get eaten, and the first\n      // \\r is normalized out by HTMLTextAreaElement#value.)\n      // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>\n      // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>\n      // See: <http://www.w3.org/TR/html5/syntax.html#newlines>\n      // See: Parsing of \"textarea\" \"listing\" and \"pre\" elements\n      //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>\n      return '\\n' + ret;\n    } else {\n      return ret;\n    }\n  },\n\n  _createInitialChildren: function (transaction, props, context, lazyTree) {\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n        DOMLazyTree.queueText(lazyTree, contentToUse);\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        for (var i = 0; i < mountImages.length; i++) {\n          DOMLazyTree.queueChild(lazyTree, mountImages[i]);\n        }\n      }\n    }\n  },\n\n  /**\n   * Receives a next element and updates the component.\n   *\n   * @internal\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} context\n   */\n  receiveComponent: function (nextElement, transaction, context) {\n    var prevElement = this._currentElement;\n    this._currentElement = nextElement;\n    this.updateComponent(transaction, prevElement, nextElement, context);\n  },\n\n  /**\n   * Updates a DOM component after it has already been allocated and\n   * attached to the DOM. Reconciles the root DOM node, then recurses.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevElement\n   * @param {ReactElement} nextElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevElement, nextElement, context) {\n    var lastProps = prevElement.props;\n    var nextProps = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'button':\n        lastProps = ReactDOMButton.getHostProps(this, lastProps);\n        nextProps = ReactDOMButton.getHostProps(this, nextProps);\n        break;\n      case 'input':\n        ReactDOMInput.updateWrapper(this);\n        lastProps = ReactDOMInput.getHostProps(this, lastProps);\n        nextProps = ReactDOMInput.getHostProps(this, nextProps);\n        break;\n      case 'option':\n        lastProps = ReactDOMOption.getHostProps(this, lastProps);\n        nextProps = ReactDOMOption.getHostProps(this, nextProps);\n        break;\n      case 'select':\n        lastProps = ReactDOMSelect.getHostProps(this, lastProps);\n        nextProps = ReactDOMSelect.getHostProps(this, nextProps);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.updateWrapper(this);\n        lastProps = ReactDOMTextarea.getHostProps(this, lastProps);\n        nextProps = ReactDOMTextarea.getHostProps(this, nextProps);\n        break;\n    }\n\n    assertValidProps(this, nextProps);\n    this._updateDOMProperties(lastProps, nextProps, transaction);\n    this._updateDOMChildren(lastProps, nextProps, transaction, context);\n\n    if (this._tag === 'select') {\n      // <select> value update needs to occur after <option> children\n      // reconciliation\n      transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);\n    }\n  },\n\n  /**\n   * Reconciles the properties by detecting differences in property values and\n   * updating the DOM as necessary. This function is probably the single most\n   * critical path for performance optimization.\n   *\n   * TODO: Benchmark whether checking for changed values in memory actually\n   *       improves performance (especially statically positioned elements).\n   * TODO: Benchmark the effects of putting this at the top since 99% of props\n   *       do not change for a given reconciliation.\n   * TODO: Benchmark areas that can be improved with caching.\n   *\n   * @private\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {?DOMElement} node\n   */\n  _updateDOMProperties: function (lastProps, nextProps, transaction) {\n    var propKey;\n    var styleName;\n    var styleUpdates;\n    for (propKey in lastProps) {\n      if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        var lastStyle = this._previousStyleCopy;\n        for (styleName in lastStyle) {\n          if (lastStyle.hasOwnProperty(styleName)) {\n            styleUpdates = styleUpdates || {};\n            styleUpdates[styleName] = '';\n          }\n        }\n        this._previousStyleCopy = null;\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (lastProps[propKey]) {\n          // Only call deleteListener if there was a listener previously or\n          // else willDeleteListener gets called when there wasn't actually a\n          // listener (e.g., onClick={null})\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, lastProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);\n      }\n    }\n    for (propKey in nextProps) {\n      var nextProp = nextProps[propKey];\n      var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;\n      if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        if (nextProp) {\n          if (\"development\" !== 'production') {\n            checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);\n            this._previousStyle = nextProp;\n          }\n          nextProp = this._previousStyleCopy = _assign({}, nextProp);\n        } else {\n          this._previousStyleCopy = null;\n        }\n        if (lastProp) {\n          // Unset styles on `lastProp` but not on `nextProp`.\n          for (styleName in lastProp) {\n            if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = '';\n            }\n          }\n          // Update styles that changed since `lastProp`.\n          for (styleName in nextProp) {\n            if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = nextProp[styleName];\n            }\n          }\n        } else {\n          // Relies on `updateStylesByID` not mutating `styleUpdates`.\n          styleUpdates = nextProp;\n        }\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (nextProp) {\n          enqueuePutListener(this, propKey, nextProp, transaction);\n        } else if (lastProp) {\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, nextProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        var node = getNode(this);\n        // If we're updating to null or undefined, we should remove the property\n        // from the DOM node instead of inadvertently setting to a string. This\n        // brings us in line with the same behavior we have on initial render.\n        if (nextProp != null) {\n          DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);\n        } else {\n          DOMPropertyOperations.deleteValueForProperty(node, propKey);\n        }\n      }\n    }\n    if (styleUpdates) {\n      CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);\n    }\n  },\n\n  /**\n   * Reconciles the children with the various properties that affect the\n   * children content.\n   *\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   */\n  _updateDOMChildren: function (lastProps, nextProps, transaction, context) {\n    var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;\n    var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;\n\n    var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;\n    var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;\n\n    // Note the use of `!=` which checks for null or undefined.\n    var lastChildren = lastContent != null ? null : lastProps.children;\n    var nextChildren = nextContent != null ? null : nextProps.children;\n\n    // If we're switching from children to content/html or vice versa, remove\n    // the old content\n    var lastHasContentOrHtml = lastContent != null || lastHtml != null;\n    var nextHasContentOrHtml = nextContent != null || nextHtml != null;\n    if (lastChildren != null && nextChildren == null) {\n      this.updateChildren(null, transaction, context);\n    } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {\n      this.updateTextContent('');\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    }\n\n    if (nextContent != null) {\n      if (lastContent !== nextContent) {\n        this.updateTextContent('' + nextContent);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, nextContent);\n        }\n      }\n    } else if (nextHtml != null) {\n      if (lastHtml !== nextHtml) {\n        this.updateMarkup('' + nextHtml);\n      }\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    } else if (nextChildren != null) {\n      if (\"development\" !== 'production') {\n        setContentChildForInstrumentation.call(this, null);\n      }\n\n      this.updateChildren(nextChildren, transaction, context);\n    }\n  },\n\n  getHostNode: function () {\n    return getNode(this);\n  },\n\n  /**\n   * Destroys all event registrations for this instance. Does not remove from\n   * the DOM. That must be done by the parent.\n   *\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        var listeners = this._wrapperState.listeners;\n        if (listeners) {\n          for (var i = 0; i < listeners.length; i++) {\n            listeners[i].remove();\n          }\n        }\n        break;\n      case 'html':\n      case 'head':\n      case 'body':\n        /**\n         * Components like <html> <head> and <body> can't be removed or added\n         * easily in a cross-browser way, however it's valuable to be able to\n         * take advantage of React's reconciliation for styling and <title>\n         * management. So we just document it and throw in dangerous cases.\n         */\n        !false ? \"development\" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.', this._tag) : _prodInvariant('66', this._tag) : void 0;\n        break;\n    }\n\n    this.unmountChildren(safely);\n    ReactDOMComponentTree.uncacheNode(this);\n    EventPluginHub.deleteAllListeners(this);\n    ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);\n    this._rootNodeID = null;\n    this._domID = null;\n    this._wrapperState = null;\n\n    if (\"development\" !== 'production') {\n      setContentChildForInstrumentation.call(this, null);\n    }\n  },\n\n  getPublicInstance: function () {\n    return getNode(this);\n  }\n\n};\n\n_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);\n\nmodule.exports = ReactDOMComponent;\n},{\"1\":1,\"10\":10,\"11\":11,\"121\":121,\"135\":135,\"139\":139,\"145\":145,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"17\":17,\"170\":170,\"171\":171,\"172\":172,\"18\":18,\"27\":27,\"32\":32,\"38\":38,\"4\":4,\"40\":40,\"41\":41,\"48\":48,\"51\":51,\"52\":52,\"56\":56,\"74\":74,\"78\":78,\"8\":8,\"9\":9,\"91\":91}],40:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentFlags\n */\n\n'use strict';\n\nvar ReactDOMComponentFlags = {\n  hasCachedChildNodes: 1 << 0\n};\n\nmodule.exports = ReactDOMComponentFlags;\n},{}],41:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentTree\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentFlags = _dereq_(40);\n\nvar invariant = _dereq_(161);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar Flags = ReactDOMComponentFlags;\n\nvar internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);\n\n/**\n * Drill down (through composites and empty components) until we get a host or\n * host text component.\n *\n * This is pretty polymorphic but unavoidable with the current structure we have\n * for `_renderedChildren`.\n */\nfunction getRenderedHostOrTextFromComponent(component) {\n  var rendered;\n  while (rendered = component._renderedComponent) {\n    component = rendered;\n  }\n  return component;\n}\n\n/**\n * Populate `_hostNode` on the rendered host/text component with the given\n * DOM node. The passed `inst` can be a composite.\n */\nfunction precacheNode(inst, node) {\n  var hostInst = getRenderedHostOrTextFromComponent(inst);\n  hostInst._hostNode = node;\n  node[internalInstanceKey] = hostInst;\n}\n\nfunction uncacheNode(inst) {\n  var node = inst._hostNode;\n  if (node) {\n    delete node[internalInstanceKey];\n    inst._hostNode = null;\n  }\n}\n\n/**\n * Populate `_hostNode` on each child of `inst`, assuming that the children\n * match up with the DOM (element) children of `node`.\n *\n * We cache entire levels at once to avoid an n^2 problem where we access the\n * children of a node sequentially and have to walk from the start to our target\n * node every time.\n *\n * Since we update `_renderedChildren` and the actual DOM at (slightly)\n * different times, we could race here and see a newer `_renderedChildren` than\n * the DOM nodes we see. To avoid this, ReactMultiChild calls\n * `prepareToManageChildren` before we change `_renderedChildren`, at which\n * time the container's child nodes are always cached (until it unmounts).\n */\nfunction precacheChildNodes(inst, node) {\n  if (inst._flags & Flags.hasCachedChildNodes) {\n    return;\n  }\n  var children = inst._renderedChildren;\n  var childNode = node.firstChild;\n  outer: for (var name in children) {\n    if (!children.hasOwnProperty(name)) {\n      continue;\n    }\n    var childInst = children[name];\n    var childID = getRenderedHostOrTextFromComponent(childInst)._domID;\n    if (childID == null) {\n      // We're currently unmounting this child in ReactMultiChild; skip it.\n      continue;\n    }\n    // We assume the child nodes are in the same order as the child instances.\n    for (; childNode !== null; childNode = childNode.nextSibling) {\n      if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') {\n        precacheNode(childInst, childNode);\n        continue outer;\n      }\n    }\n    // We reached the end of the DOM children without finding an ID match.\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : _prodInvariant('32', childID) : void 0;\n  }\n  inst._flags |= Flags.hasCachedChildNodes;\n}\n\n/**\n * Given a DOM node, return the closest ReactDOMComponent or\n * ReactDOMTextComponent instance ancestor.\n */\nfunction getClosestInstanceFromNode(node) {\n  if (node[internalInstanceKey]) {\n    return node[internalInstanceKey];\n  }\n\n  // Walk up the tree until we find an ancestor whose instance we have cached.\n  var parents = [];\n  while (!node[internalInstanceKey]) {\n    parents.push(node);\n    if (node.parentNode) {\n      node = node.parentNode;\n    } else {\n      // Top of the tree. This node must not be part of a React tree (or is\n      // unmounted, potentially).\n      return null;\n    }\n  }\n\n  var closest;\n  var inst;\n  for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {\n    closest = inst;\n    if (parents.length) {\n      precacheChildNodes(inst, node);\n    }\n  }\n\n  return closest;\n}\n\n/**\n * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent\n * instance, or null if the node was not rendered by this React.\n */\nfunction getInstanceFromNode(node) {\n  var inst = getClosestInstanceFromNode(node);\n  if (inst != null && inst._hostNode === node) {\n    return inst;\n  } else {\n    return null;\n  }\n}\n\n/**\n * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding\n * DOM node.\n */\nfunction getNodeFromInstance(inst) {\n  // Without this first invariant, passing a non-DOM-component triggers the next\n  // invariant for a missing parent, which is super confusing.\n  !(inst._hostNode !== undefined) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  if (inst._hostNode) {\n    return inst._hostNode;\n  }\n\n  // Walk up the tree until we find an ancestor whose DOM node we have cached.\n  var parents = [];\n  while (!inst._hostNode) {\n    parents.push(inst);\n    !inst._hostParent ? \"development\" !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') : _prodInvariant('34') : void 0;\n    inst = inst._hostParent;\n  }\n\n  // Now parents contains each ancestor that does *not* have a cached native\n  // node, and `inst` is the deepest ancestor that does.\n  for (; parents.length; inst = parents.pop()) {\n    precacheChildNodes(inst, inst._hostNode);\n  }\n\n  return inst._hostNode;\n}\n\nvar ReactDOMComponentTree = {\n  getClosestInstanceFromNode: getClosestInstanceFromNode,\n  getInstanceFromNode: getInstanceFromNode,\n  getNodeFromInstance: getNodeFromInstance,\n  precacheChildNodes: precacheChildNodes,\n  precacheNode: precacheNode,\n  uncacheNode: uncacheNode\n};\n\nmodule.exports = ReactDOMComponentTree;\n},{\"10\":10,\"139\":139,\"161\":161,\"40\":40}],42:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMContainerInfo\n */\n\n'use strict';\n\nvar validateDOMNesting = _dereq_(145);\n\nvar DOC_NODE_TYPE = 9;\n\nfunction ReactDOMContainerInfo(topLevelWrapper, node) {\n  var info = {\n    _topLevelWrapper: topLevelWrapper,\n    _idCounter: 1,\n    _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null,\n    _node: node,\n    _tag: node ? node.nodeName.toLowerCase() : null,\n    _namespaceURI: node ? node.namespaceURI : null\n  };\n  if (\"development\" !== 'production') {\n    info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null;\n  }\n  return info;\n}\n\nmodule.exports = ReactDOMContainerInfo;\n},{\"145\":145}],43:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMDebugTool\n */\n\n'use strict';\n\nvar ReactDOMNullInputValuePropDevtool = _dereq_(50);\nvar ReactDOMUnknownPropertyDevtool = _dereq_(58);\nvar ReactDebugTool = _dereq_(59);\n\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar ReactDOMDebugTool = {\n  addDevtool: function (devtool) {\n    ReactDebugTool.addDevtool(devtool);\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    ReactDebugTool.removeDevtool(devtool);\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  onCreateMarkupForProperty: function (name, value) {\n    emitEvent('onCreateMarkupForProperty', name, value);\n  },\n  onSetValueForProperty: function (node, name, value) {\n    emitEvent('onSetValueForProperty', node, name, value);\n  },\n  onDeleteValueForProperty: function (node, name) {\n    emitEvent('onDeleteValueForProperty', node, name);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool);\nReactDOMDebugTool.addDevtool(ReactDOMNullInputValuePropDevtool);\n\nmodule.exports = ReactDOMDebugTool;\n},{\"171\":171,\"50\":50,\"58\":58,\"59\":59}],44:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMEmptyComponent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar ReactDOMEmptyComponent = function (instantiate) {\n  // ReactCompositeComponent uses this:\n  this._currentElement = null;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n  this._hostContainerInfo = null;\n  this._domID = null;\n};\n_assign(ReactDOMEmptyComponent.prototype, {\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    var domID = hostContainerInfo._idCounter++;\n    this._domID = domID;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var nodeValue = ' react-empty: ' + this._domID + ' ';\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var node = ownerDocument.createComment(nodeValue);\n      ReactDOMComponentTree.precacheNode(this, node);\n      return DOMLazyTree(node);\n    } else {\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd insert a comment node, but since this is a situation\n        // where React won't take over (static pages), we can simply return\n        // nothing.\n        return '';\n      }\n      return '<!--' + nodeValue + '-->';\n    }\n  },\n  receiveComponent: function () {},\n  getHostNode: function () {\n    return ReactDOMComponentTree.getNodeFromInstance(this);\n  },\n  unmountComponent: function () {\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n});\n\nmodule.exports = ReactDOMEmptyComponent;\n},{\"172\":172,\"41\":41,\"8\":8}],45:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFactories\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\n\nvar mapObject = _dereq_(166);\n\n/**\n * Create a factory that creates HTML tag elements.\n *\n * @param {string} tag Tag name (e.g. `div`).\n * @private\n */\nfunction createDOMFactory(tag) {\n  if (\"development\" !== 'production') {\n    var ReactElementValidator = _dereq_(63);\n    return ReactElementValidator.createFactory(tag);\n  }\n  return ReactElement.createFactory(tag);\n}\n\n/**\n * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.\n * This is also accessible via `React.DOM`.\n *\n * @public\n */\nvar ReactDOMFactories = mapObject({\n  a: 'a',\n  abbr: 'abbr',\n  address: 'address',\n  area: 'area',\n  article: 'article',\n  aside: 'aside',\n  audio: 'audio',\n  b: 'b',\n  base: 'base',\n  bdi: 'bdi',\n  bdo: 'bdo',\n  big: 'big',\n  blockquote: 'blockquote',\n  body: 'body',\n  br: 'br',\n  button: 'button',\n  canvas: 'canvas',\n  caption: 'caption',\n  cite: 'cite',\n  code: 'code',\n  col: 'col',\n  colgroup: 'colgroup',\n  data: 'data',\n  datalist: 'datalist',\n  dd: 'dd',\n  del: 'del',\n  details: 'details',\n  dfn: 'dfn',\n  dialog: 'dialog',\n  div: 'div',\n  dl: 'dl',\n  dt: 'dt',\n  em: 'em',\n  embed: 'embed',\n  fieldset: 'fieldset',\n  figcaption: 'figcaption',\n  figure: 'figure',\n  footer: 'footer',\n  form: 'form',\n  h1: 'h1',\n  h2: 'h2',\n  h3: 'h3',\n  h4: 'h4',\n  h5: 'h5',\n  h6: 'h6',\n  head: 'head',\n  header: 'header',\n  hgroup: 'hgroup',\n  hr: 'hr',\n  html: 'html',\n  i: 'i',\n  iframe: 'iframe',\n  img: 'img',\n  input: 'input',\n  ins: 'ins',\n  kbd: 'kbd',\n  keygen: 'keygen',\n  label: 'label',\n  legend: 'legend',\n  li: 'li',\n  link: 'link',\n  main: 'main',\n  map: 'map',\n  mark: 'mark',\n  menu: 'menu',\n  menuitem: 'menuitem',\n  meta: 'meta',\n  meter: 'meter',\n  nav: 'nav',\n  noscript: 'noscript',\n  object: 'object',\n  ol: 'ol',\n  optgroup: 'optgroup',\n  option: 'option',\n  output: 'output',\n  p: 'p',\n  param: 'param',\n  picture: 'picture',\n  pre: 'pre',\n  progress: 'progress',\n  q: 'q',\n  rp: 'rp',\n  rt: 'rt',\n  ruby: 'ruby',\n  s: 's',\n  samp: 'samp',\n  script: 'script',\n  section: 'section',\n  select: 'select',\n  small: 'small',\n  source: 'source',\n  span: 'span',\n  strong: 'strong',\n  style: 'style',\n  sub: 'sub',\n  summary: 'summary',\n  sup: 'sup',\n  table: 'table',\n  tbody: 'tbody',\n  td: 'td',\n  textarea: 'textarea',\n  tfoot: 'tfoot',\n  th: 'th',\n  thead: 'thead',\n  time: 'time',\n  title: 'title',\n  tr: 'tr',\n  track: 'track',\n  u: 'u',\n  ul: 'ul',\n  'var': 'var',\n  video: 'video',\n  wbr: 'wbr',\n\n  // SVG\n  circle: 'circle',\n  clipPath: 'clipPath',\n  defs: 'defs',\n  ellipse: 'ellipse',\n  g: 'g',\n  image: 'image',\n  line: 'line',\n  linearGradient: 'linearGradient',\n  mask: 'mask',\n  path: 'path',\n  pattern: 'pattern',\n  polygon: 'polygon',\n  polyline: 'polyline',\n  radialGradient: 'radialGradient',\n  rect: 'rect',\n  stop: 'stop',\n  svg: 'svg',\n  text: 'text',\n  tspan: 'tspan'\n\n}, createDOMFactory);\n\nmodule.exports = ReactDOMFactories;\n},{\"166\":166,\"62\":62,\"63\":63}],46:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFeatureFlags\n */\n\n'use strict';\n\nvar ReactDOMFeatureFlags = {\n  useCreateElement: true\n};\n\nmodule.exports = ReactDOMFeatureFlags;\n},{}],47:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMIDOperations\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMComponentTree = _dereq_(41);\n\n/**\n * Operations used to process updates to DOM nodes.\n */\nvar ReactDOMIDOperations = {\n\n  /**\n   * Updates a component's children by processing a series of updates.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  dangerouslyProcessChildrenUpdates: function (parentInst, updates) {\n    var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);\n    DOMChildrenOperations.processUpdates(node, updates);\n  }\n};\n\nmodule.exports = ReactDOMIDOperations;\n},{\"41\":41,\"7\":7}],48:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInput\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar DOMPropertyOperations = _dereq_(11);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnCheckedLink = false;\nvar didWarnValueDefaultValue = false;\nvar didWarnCheckedDefaultChecked = false;\nvar didWarnControlledToUncontrolled = false;\nvar didWarnUncontrolledToControlled = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMInput.updateWrapper(this);\n  }\n}\n\nfunction isControlled(props) {\n  var usesChecked = props.type === 'checkbox' || props.type === 'radio';\n  return usesChecked ? props.checked !== undefined : props.value !== undefined;\n}\n\n/**\n * Implements an <input> host component that allows setting these optional\n * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.\n *\n * If `checked` or `value` are not supplied (or null/undefined), user actions\n * that affect the checked state or value will trigger updates to the element.\n *\n * If they are supplied (and not null/undefined), the rendered element will not\n * trigger updates to the element. Instead, the props must change in order for\n * the rendered element to be updated.\n *\n * The rendered element will be initialized as unchecked (or `defaultChecked`)\n * with an empty value (or `defaultValue`).\n *\n * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html\n */\nvar ReactDOMInput = {\n  getHostProps: function (inst, props) {\n    var value = LinkedValueUtils.getValue(props);\n    var checked = LinkedValueUtils.getChecked(props);\n\n    var hostProps = _assign({\n      // Make sure we set .type before any other properties (setting .value\n      // before .type means .value is lost in IE11 and below)\n      type: undefined\n    }, DisabledInputUtils.getHostProps(inst, props), {\n      defaultChecked: undefined,\n      defaultValue: undefined,\n      value: value != null ? value : inst._wrapperState.initialValue,\n      checked: checked != null ? checked : inst._wrapperState.initialChecked,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);\n\n      var owner = inst._currentElement._owner;\n\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.checkedLink !== undefined && !didWarnCheckedLink) {\n        \"development\" !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnCheckedLink = true;\n      }\n      if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnCheckedDefaultChecked = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnValueDefaultValue = true;\n      }\n    }\n\n    var defaultValue = props.defaultValue;\n    inst._wrapperState = {\n      initialChecked: props.checked != null ? props.checked : props.defaultChecked,\n      initialValue: props.value != null ? props.value : defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n\n    if (\"development\" !== 'production') {\n      inst._wrapperState.controlled = isControlled(props);\n    }\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    if (\"development\" !== 'production') {\n      var controlled = isControlled(props);\n      var owner = inst._currentElement._owner;\n\n      if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnUncontrolledToControlled = true;\n      }\n      if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnControlledToUncontrolled = true;\n      }\n    }\n\n    // TODO: Shouldn't this be getChecked(props)?\n    var checked = props.checked;\n    if (checked != null) {\n      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);\n    }\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n    } else {\n      if (props.value == null && props.defaultValue != null) {\n        node.defaultValue = '' + props.defaultValue;\n      }\n      if (props.checked == null && props.defaultChecked != null) {\n        node.defaultChecked = !!props.defaultChecked;\n      }\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Detach value from defaultValue. We won't do anything if we're working on\n    // submit or reset inputs as those values & defaultValues are linked. They\n    // are not resetable nodes so this operation doesn't matter and actually\n    // removes browser-default values (eg \"Submit Query\") when no value is\n    // provided.\n    if (props.type !== 'submit' && props.type !== 'reset') {\n      node.value = node.value;\n    }\n\n    // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug\n    // this is needed to work around a chrome bug where setting defaultChecked\n    // will sometimes influence the value of checked (even after detachment).\n    // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416\n    // We need to temporarily unset name to avoid disrupting radio button groups.\n    var name = node.name;\n    if (name !== '') {\n      node.name = '';\n    }\n    node.defaultChecked = !node.defaultChecked;\n    node.defaultChecked = !node.defaultChecked;\n    if (name !== '') {\n      node.name = name;\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  // Here we use asap to wait until all updates have propagated, which\n  // is important when using controlled components within layers:\n  // https://github.com/facebook/react/issues/1698\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n\n  var name = props.name;\n  if (props.type === 'radio' && name != null) {\n    var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);\n    var queryRoot = rootNode;\n\n    while (queryRoot.parentNode) {\n      queryRoot = queryRoot.parentNode;\n    }\n\n    // If `rootNode.form` was non-null, then we could try `form.elements`,\n    // but that sometimes behaves strangely in IE8. We could also try using\n    // `form.getElementsByName`, but that will only return direct children\n    // and won't include inputs that use the HTML5 `form=` attribute. Since\n    // the input might not even be in a form, let's just use the global\n    // `querySelectorAll` to ensure we don't miss anything.\n    var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type=\"radio\"]');\n\n    for (var i = 0; i < group.length; i++) {\n      var otherNode = group[i];\n      if (otherNode === rootNode || otherNode.form !== rootNode.form) {\n        continue;\n      }\n      // This will throw if radio buttons rendered by different copies of React\n      // and the same name are rendered into the same form (same as #1939).\n      // That's probably okay; we don't support it just as we don't support\n      // mixing React radio buttons with non-React ones.\n      var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);\n      !otherInstance ? \"development\" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;\n      // If this is a controlled radio button group, forcing the input that\n      // was previously checked to update will cause it to be come re-checked\n      // as appropriate.\n      ReactUpdates.asap(forceUpdateIfMounted, otherInstance);\n    }\n  }\n\n  return returnValue;\n}\n\nmodule.exports = ReactDOMInput;\n},{\"11\":11,\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],49:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDOMDebugTool = _dereq_(43);\n  debugTool = ReactDOMDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"43\":43}],50:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMNullInputValuePropDevtool\n */\n\n'use strict';\n\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueNull = false;\n\nfunction handleElement(debugID, element) {\n  if (element == null) {\n    return;\n  }\n  if (element.type !== 'input' && element.type !== 'textarea' && element.type !== 'select') {\n    return;\n  }\n  if (element.props != null && element.props.value === null && !didWarnValueNull) {\n    \"development\" !== 'production' ? warning(false, '`value` prop on `%s` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n\n    didWarnValueNull = true;\n  }\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"171\":171,\"34\":34}],51:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMOption\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMSelect = _dereq_(52);\n\nvar warning = _dereq_(171);\nvar didWarnInvalidOptionChildren = false;\n\nfunction flattenChildren(children) {\n  var content = '';\n\n  // Flatten children and warn if they aren't strings or numbers;\n  // invalid types are ignored.\n  ReactChildren.forEach(children, function (child) {\n    if (child == null) {\n      return;\n    }\n    if (typeof child === 'string' || typeof child === 'number') {\n      content += child;\n    } else if (!didWarnInvalidOptionChildren) {\n      didWarnInvalidOptionChildren = true;\n      \"development\" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;\n    }\n  });\n\n  return content;\n}\n\n/**\n * Implements an <option> host component that warns when `selected` is set.\n */\nvar ReactDOMOption = {\n  mountWrapper: function (inst, props, hostParent) {\n    // TODO (yungsters): Remove support for `selected` in <option>.\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;\n    }\n\n    // Look up whether this option is 'selected'\n    var selectValue = null;\n    if (hostParent != null) {\n      var selectParent = hostParent;\n\n      if (selectParent._tag === 'optgroup') {\n        selectParent = selectParent._hostParent;\n      }\n\n      if (selectParent != null && selectParent._tag === 'select') {\n        selectValue = ReactDOMSelect.getSelectValueContext(selectParent);\n      }\n    }\n\n    // If the value is null (e.g., no specified value or after initial mount)\n    // or missing (e.g., for <datalist>), we don't change props.selected\n    var selected = null;\n    if (selectValue != null) {\n      var value;\n      if (props.value != null) {\n        value = props.value + '';\n      } else {\n        value = flattenChildren(props.children);\n      }\n      selected = false;\n      if (Array.isArray(selectValue)) {\n        // multiple\n        for (var i = 0; i < selectValue.length; i++) {\n          if ('' + selectValue[i] === value) {\n            selected = true;\n            break;\n          }\n        }\n      } else {\n        selected = '' + selectValue === value;\n      }\n    }\n\n    inst._wrapperState = { selected: selected };\n  },\n\n  postMountWrapper: function (inst) {\n    // value=\"\" should make a value attribute (#6219)\n    var props = inst._currentElement.props;\n    if (props.value != null) {\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      node.setAttribute('value', props.value);\n    }\n  },\n\n  getHostProps: function (inst, props) {\n    var hostProps = _assign({ selected: undefined, children: undefined }, props);\n\n    // Read state only from initial mount because <select> updates value\n    // manually; we need the initial state only for server rendering\n    if (inst._wrapperState.selected != null) {\n      hostProps.selected = inst._wrapperState.selected;\n    }\n\n    var content = flattenChildren(props.children);\n\n    if (content) {\n      hostProps.children = content;\n    }\n\n    return hostProps;\n  }\n\n};\n\nmodule.exports = ReactDOMOption;\n},{\"171\":171,\"172\":172,\"29\":29,\"41\":41,\"52\":52}],52:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelect\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValueDefaultValue = false;\n\nfunction updateOptionsIfPendingUpdateAndMounted() {\n  if (this._rootNodeID && this._wrapperState.pendingUpdate) {\n    this._wrapperState.pendingUpdate = false;\n\n    var props = this._currentElement.props;\n    var value = LinkedValueUtils.getValue(props);\n\n    if (value != null) {\n      updateOptions(this, Boolean(props.multiple), value);\n    }\n  }\n}\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nvar valuePropNames = ['value', 'defaultValue'];\n\n/**\n * Validation function for `value` and `defaultValue`.\n * @private\n */\nfunction checkSelectPropTypes(inst, props) {\n  var owner = inst._currentElement._owner;\n  LinkedValueUtils.checkPropTypes('select', props, owner);\n\n  if (props.valueLink !== undefined && !didWarnValueLink) {\n    \"development\" !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;\n    didWarnValueLink = true;\n  }\n\n  for (var i = 0; i < valuePropNames.length; i++) {\n    var propName = valuePropNames[i];\n    if (props[propName] == null) {\n      continue;\n    }\n    if (props.multiple) {\n      \"development\" !== 'production' ? warning(Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    } else {\n      \"development\" !== 'production' ? warning(!Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    }\n  }\n}\n\n/**\n * @param {ReactDOMComponent} inst\n * @param {boolean} multiple\n * @param {*} propValue A stringable (with `multiple`, a list of stringables).\n * @private\n */\nfunction updateOptions(inst, multiple, propValue) {\n  var selectedValue, i;\n  var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;\n\n  if (multiple) {\n    selectedValue = {};\n    for (i = 0; i < propValue.length; i++) {\n      selectedValue['' + propValue[i]] = true;\n    }\n    for (i = 0; i < options.length; i++) {\n      var selected = selectedValue.hasOwnProperty(options[i].value);\n      if (options[i].selected !== selected) {\n        options[i].selected = selected;\n      }\n    }\n  } else {\n    // Do not set `select.value` as exact behavior isn't consistent across all\n    // browsers for all cases.\n    selectedValue = '' + propValue;\n    for (i = 0; i < options.length; i++) {\n      if (options[i].value === selectedValue) {\n        options[i].selected = true;\n        return;\n      }\n    }\n    if (options.length) {\n      options[0].selected = true;\n    }\n  }\n}\n\n/**\n * Implements a <select> host component that allows optionally setting the\n * props `value` and `defaultValue`. If `multiple` is false, the prop must be a\n * stringable. If `multiple` is true, the prop must be an array of stringables.\n *\n * If `value` is not supplied (or null/undefined), user actions that change the\n * selected option will trigger updates to the rendered options.\n *\n * If it is supplied (and not null/undefined), the rendered options will not\n * update in response to user actions. Instead, the `value` prop must change in\n * order for the rendered options to update.\n *\n * If `defaultValue` is provided, any options with the supplied values will be\n * selected.\n */\nvar ReactDOMSelect = {\n  getHostProps: function (inst, props) {\n    return _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      onChange: inst._wrapperState.onChange,\n      value: undefined\n    });\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      checkSelectPropTypes(inst, props);\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    inst._wrapperState = {\n      pendingUpdate: false,\n      initialValue: value != null ? value : props.defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst),\n      wasMultiple: Boolean(props.multiple)\n    };\n\n    if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n      \"development\" !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n      didWarnValueDefaultValue = true;\n    }\n  },\n\n  getSelectValueContext: function (inst) {\n    // ReactDOMOption looks at this initial value so the initial generated\n    // markup has correct `selected` attributes\n    return inst._wrapperState.initialValue;\n  },\n\n  postUpdateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // After the initial mount, we control selected-ness manually so don't pass\n    // this value down\n    inst._wrapperState.initialValue = undefined;\n\n    var wasMultiple = inst._wrapperState.wasMultiple;\n    inst._wrapperState.wasMultiple = Boolean(props.multiple);\n\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      inst._wrapperState.pendingUpdate = false;\n      updateOptions(inst, Boolean(props.multiple), value);\n    } else if (wasMultiple !== Boolean(props.multiple)) {\n      // For simplicity, reapply `defaultValue` if `multiple` is toggled.\n      if (props.defaultValue != null) {\n        updateOptions(inst, Boolean(props.multiple), props.defaultValue);\n      } else {\n        // Revert the select back to its default unselected state.\n        updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : '');\n      }\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  if (this._rootNodeID) {\n    this._wrapperState.pendingUpdate = true;\n  }\n  ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMSelect;\n},{\"14\":14,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],53:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelection\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar getNodeForCharacterOffset = _dereq_(131);\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * While `isCollapsed` is available on the Selection object and `collapsed`\n * is available on the Range object, IE11 sometimes gets them wrong.\n * If the anchor/focus nodes and offsets are the same, the range is collapsed.\n */\nfunction isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {\n  return anchorNode === focusNode && anchorOffset === focusOffset;\n}\n\n/**\n * Get the appropriate anchor and focus node/offset pairs for IE.\n *\n * The catch here is that IE's selection API doesn't provide information\n * about whether the selection is forward or backward, so we have to\n * behave as though it's always forward.\n *\n * IE text differs from modern selection in that it behaves as though\n * block elements end with a new line. This means character offsets will\n * differ between the two APIs.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getIEOffsets(node) {\n  var selection = document.selection;\n  var selectedRange = selection.createRange();\n  var selectedLength = selectedRange.text.length;\n\n  // Duplicate selection so we can move range without breaking user selection.\n  var fromStart = selectedRange.duplicate();\n  fromStart.moveToElementText(node);\n  fromStart.setEndPoint('EndToStart', selectedRange);\n\n  var startOffset = fromStart.text.length;\n  var endOffset = startOffset + selectedLength;\n\n  return {\n    start: startOffset,\n    end: endOffset\n  };\n}\n\n/**\n * @param {DOMElement} node\n * @return {?object}\n */\nfunction getModernOffsets(node) {\n  var selection = window.getSelection && window.getSelection();\n\n  if (!selection || selection.rangeCount === 0) {\n    return null;\n  }\n\n  var anchorNode = selection.anchorNode;\n  var anchorOffset = selection.anchorOffset;\n  var focusNode = selection.focusNode;\n  var focusOffset = selection.focusOffset;\n\n  var currentRange = selection.getRangeAt(0);\n\n  // In Firefox, range.startContainer and range.endContainer can be \"anonymous\n  // divs\", e.g. the up/down buttons on an <input type=\"number\">. Anonymous\n  // divs do not seem to expose properties, triggering a \"Permission denied\n  // error\" if any of its properties are accessed. The only seemingly possible\n  // way to avoid erroring is to access a property that typically works for\n  // non-anonymous divs and catch any error that may otherwise arise. See\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=208427\n  try {\n    /* eslint-disable no-unused-expressions */\n    currentRange.startContainer.nodeType;\n    currentRange.endContainer.nodeType;\n    /* eslint-enable no-unused-expressions */\n  } catch (e) {\n    return null;\n  }\n\n  // If the node and offset values are the same, the selection is collapsed.\n  // `Selection.isCollapsed` is available natively, but IE sometimes gets\n  // this value wrong.\n  var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);\n\n  var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;\n\n  var tempRange = currentRange.cloneRange();\n  tempRange.selectNodeContents(node);\n  tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);\n\n  var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset);\n\n  var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;\n  var end = start + rangeLength;\n\n  // Detect whether the selection is backward.\n  var detectionRange = document.createRange();\n  detectionRange.setStart(anchorNode, anchorOffset);\n  detectionRange.setEnd(focusNode, focusOffset);\n  var isBackward = detectionRange.collapsed;\n\n  return {\n    start: isBackward ? end : start,\n    end: isBackward ? start : end\n  };\n}\n\n/**\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setIEOffsets(node, offsets) {\n  var range = document.selection.createRange().duplicate();\n  var start, end;\n\n  if (offsets.end === undefined) {\n    start = offsets.start;\n    end = start;\n  } else if (offsets.start > offsets.end) {\n    start = offsets.end;\n    end = offsets.start;\n  } else {\n    start = offsets.start;\n    end = offsets.end;\n  }\n\n  range.moveToElementText(node);\n  range.moveStart('character', start);\n  range.setEndPoint('EndToStart', range);\n  range.moveEnd('character', end - start);\n  range.select();\n}\n\n/**\n * In modern non-IE browsers, we can support both forward and backward\n * selections.\n *\n * Note: IE10+ supports the Selection object, but it does not support\n * the `extend` method, which means that even in modern IE, it's not possible\n * to programmatically create a backward selection. Thus, for all IE\n * versions, we use the old IE API to create our selections.\n *\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setModernOffsets(node, offsets) {\n  if (!window.getSelection) {\n    return;\n  }\n\n  var selection = window.getSelection();\n  var length = node[getTextContentAccessor()].length;\n  var start = Math.min(offsets.start, length);\n  var end = offsets.end === undefined ? start : Math.min(offsets.end, length);\n\n  // IE 11 uses modern selection, but doesn't support the extend method.\n  // Flip backward selections, so we can set with a single range.\n  if (!selection.extend && start > end) {\n    var temp = end;\n    end = start;\n    start = temp;\n  }\n\n  var startMarker = getNodeForCharacterOffset(node, start);\n  var endMarker = getNodeForCharacterOffset(node, end);\n\n  if (startMarker && endMarker) {\n    var range = document.createRange();\n    range.setStart(startMarker.node, startMarker.offset);\n    selection.removeAllRanges();\n\n    if (start > end) {\n      selection.addRange(range);\n      selection.extend(endMarker.node, endMarker.offset);\n    } else {\n      range.setEnd(endMarker.node, endMarker.offset);\n      selection.addRange(range);\n    }\n  }\n}\n\nvar useIEOffsets = ExecutionEnvironment.canUseDOM && 'selection' in document && !('getSelection' in window);\n\nvar ReactDOMSelection = {\n  /**\n   * @param {DOMElement} node\n   */\n  getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,\n\n  /**\n   * @param {DOMElement|DOMTextNode} node\n   * @param {object} offsets\n   */\n  setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets\n};\n\nmodule.exports = ReactDOMSelection;\n},{\"131\":131,\"132\":132,\"147\":147}],54:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMServer\n */\n\n'use strict';\n\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactServerRendering = _dereq_(90);\nvar ReactVersion = _dereq_(96);\n\nReactDefaultInjection.inject();\n\nvar ReactDOMServer = {\n  renderToString: ReactServerRendering.renderToString,\n  renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup,\n  version: ReactVersion\n};\n\nmodule.exports = ReactDOMServer;\n},{\"61\":61,\"90\":90,\"96\":96}],55:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DOMChildrenOperations = _dereq_(7);\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar validateDOMNesting = _dereq_(145);\n\n/**\n * Text nodes violate a couple assumptions that React makes about components:\n *\n *  - When mounting text into the DOM, adjacent text nodes are merged.\n *  - Text nodes cannot be assigned a React root ID.\n *\n * This component is used to wrap strings between comment nodes so that they\n * can undergo the same reconciliation that is applied to elements.\n *\n * TODO: Investigate representing React components in the DOM with text nodes.\n *\n * @class ReactDOMTextComponent\n * @extends ReactComponent\n * @internal\n */\nvar ReactDOMTextComponent = function (text) {\n  // TODO: This is really a ReactText (ReactNode), not a ReactElement\n  this._currentElement = text;\n  this._stringText = '' + text;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n\n  // Properties\n  this._domID = null;\n  this._mountIndex = 0;\n  this._closingComment = null;\n  this._commentNodes = null;\n};\n\n_assign(ReactDOMTextComponent.prototype, {\n\n  /**\n   * Creates the markup for this text node. This node is not intended to have\n   * any features besides containing text content.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @return {string} Markup for this text node.\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetText(this._debugID, this._stringText);\n\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo != null) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting('#text', this, parentInfo);\n      }\n    }\n\n    var domID = hostContainerInfo._idCounter++;\n    var openingValue = ' react-text: ' + domID + ' ';\n    var closingValue = ' /react-text ';\n    this._domID = domID;\n    this._hostParent = hostParent;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var openingComment = ownerDocument.createComment(openingValue);\n      var closingComment = ownerDocument.createComment(closingValue);\n      var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment());\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment));\n      if (this._stringText) {\n        DOMLazyTree.queueChild(lazyTree, DOMLazyTree(ownerDocument.createTextNode(this._stringText)));\n      }\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment));\n      ReactDOMComponentTree.precacheNode(this, openingComment);\n      this._closingComment = closingComment;\n      return lazyTree;\n    } else {\n      var escapedText = escapeTextContentForBrowser(this._stringText);\n\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd wrap this between comment nodes for the reasons stated\n        // above, but since this is a situation where React won't take over\n        // (static pages), we can simply return the text as it is.\n        return escapedText;\n      }\n\n      return '<!--' + openingValue + '-->' + escapedText + '<!--' + closingValue + '-->';\n    }\n  },\n\n  /**\n   * Updates this component by updating the text content.\n   *\n   * @param {ReactText} nextText The next text content\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  receiveComponent: function (nextText, transaction) {\n    if (nextText !== this._currentElement) {\n      this._currentElement = nextText;\n      var nextStringText = '' + nextText;\n      if (nextStringText !== this._stringText) {\n        // TODO: Save this as pending props and use performUpdateIfNecessary\n        // and/or updateComponent to do the actual update for consistency with\n        // other component types?\n        this._stringText = nextStringText;\n        var commentNodes = this.getHostNode();\n        DOMChildrenOperations.replaceDelimitedText(commentNodes[0], commentNodes[1], nextStringText);\n\n        if (\"development\" !== 'production') {\n          ReactInstrumentation.debugTool.onSetText(this._debugID, nextStringText);\n        }\n      }\n    }\n  },\n\n  getHostNode: function () {\n    var hostNode = this._commentNodes;\n    if (hostNode) {\n      return hostNode;\n    }\n    if (!this._closingComment) {\n      var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);\n      var node = openingComment.nextSibling;\n      while (true) {\n        !(node != null) ? \"development\" !== 'production' ? invariant(false, 'Missing closing comment for text component %s', this._domID) : _prodInvariant('67', this._domID) : void 0;\n        if (node.nodeType === 8 && node.nodeValue === ' /react-text ') {\n          this._closingComment = node;\n          break;\n        }\n        node = node.nextSibling;\n      }\n    }\n    hostNode = [this._hostNode, this._closingComment];\n    this._commentNodes = hostNode;\n    return hostNode;\n  },\n\n  unmountComponent: function () {\n    this._closingComment = null;\n    this._commentNodes = null;\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n\n});\n\nmodule.exports = ReactDOMTextComponent;\n},{\"121\":121,\"139\":139,\"145\":145,\"161\":161,\"172\":172,\"41\":41,\"7\":7,\"74\":74,\"8\":8}],56:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextarea\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValDefaultVal = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMTextarea.updateWrapper(this);\n  }\n}\n\n/**\n * Implements a <textarea> host component that allows setting `value`, and\n * `defaultValue`. This differs from the traditional DOM API because value is\n * usually set as PCDATA children.\n *\n * If `value` is not supplied (or null/undefined), user actions that affect the\n * value will trigger updates to the element.\n *\n * If `value` is supplied (and not null/undefined), the rendered element will\n * not trigger updates to the element. Instead, the `value` prop must change in\n * order for the rendered element to be updated.\n *\n * The rendered element will be initialized with an empty value, the prop\n * `defaultValue` if specified, or the children content (deprecated).\n */\nvar ReactDOMTextarea = {\n  getHostProps: function (inst, props) {\n    !(props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : _prodInvariant('91') : void 0;\n\n    // Always set children to the same thing. In IE9, the selection range will\n    // get reset if `textContent` is mutated.  We could add a check in setTextContent\n    // to only set the value if/when the value differs from the node value (which would\n    // completely solve this IE9 bug), but Sebastian+Ben seemed to like this solution.\n    // The value can be a boolean or object so that's why it's forced to be a string.\n    var hostProps = _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      value: undefined,\n      defaultValue: undefined,\n      children: '' + inst._wrapperState.initialValue,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `textarea` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {\n        \"development\" !== 'production' ? warning(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n        didWarnValDefaultVal = true;\n      }\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    var initialValue = value;\n\n    // Only bother fetching default value if we're going to use it\n    if (value == null) {\n      var defaultValue = props.defaultValue;\n      // TODO (yungsters): Remove support for children content in <textarea>.\n      var children = props.children;\n      if (children != null) {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.') : void 0;\n        }\n        !(defaultValue == null) ? \"development\" !== 'production' ? invariant(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : _prodInvariant('92') : void 0;\n        if (Array.isArray(children)) {\n          !(children.length <= 1) ? \"development\" !== 'production' ? invariant(false, '<textarea> can only have at most one child.') : _prodInvariant('93') : void 0;\n          children = children[0];\n        }\n\n        defaultValue = '' + children;\n      }\n      if (defaultValue == null) {\n        defaultValue = '';\n      }\n      initialValue = defaultValue;\n    }\n\n    inst._wrapperState = {\n      initialValue: '' + initialValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n      if (props.defaultValue == null) {\n        node.defaultValue = newValue;\n      }\n    }\n    if (props.defaultValue != null) {\n      node.defaultValue = props.defaultValue;\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Warning: node.value may be the empty string at this point (IE11) if placeholder is set.\n    node.value = node.textContent; // Detach value from defaultValue\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMTextarea;\n},{\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],57:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTreeTraversal\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Return the lowest common ancestor of A and B, or null if they are in\n * different trees.\n */\nfunction getLowestCommonAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  var depthA = 0;\n  for (var tempA = instA; tempA; tempA = tempA._hostParent) {\n    depthA++;\n  }\n  var depthB = 0;\n  for (var tempB = instB; tempB; tempB = tempB._hostParent) {\n    depthB++;\n  }\n\n  // If A is deeper, crawl up.\n  while (depthA - depthB > 0) {\n    instA = instA._hostParent;\n    depthA--;\n  }\n\n  // If B is deeper, crawl up.\n  while (depthB - depthA > 0) {\n    instB = instB._hostParent;\n    depthB--;\n  }\n\n  // Walk in lockstep until we find a match.\n  var depth = depthA;\n  while (depth--) {\n    if (instA === instB) {\n      return instA;\n    }\n    instA = instA._hostParent;\n    instB = instB._hostParent;\n  }\n  return null;\n}\n\n/**\n * Return if A is an ancestor of B.\n */\nfunction isAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n\n  while (instB) {\n    if (instB === instA) {\n      return true;\n    }\n    instB = instB._hostParent;\n  }\n  return false;\n}\n\n/**\n * Return the parent instance of the passed-in instance.\n */\nfunction getParentInstance(inst) {\n  !('_hostNode' in inst) ? \"development\" !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : _prodInvariant('36') : void 0;\n\n  return inst._hostParent;\n}\n\n/**\n * Simulates the traversal of a two-phase, capture/bubble event dispatch.\n */\nfunction traverseTwoPhase(inst, fn, arg) {\n  var path = [];\n  while (inst) {\n    path.push(inst);\n    inst = inst._hostParent;\n  }\n  var i;\n  for (i = path.length; i-- > 0;) {\n    fn(path[i], false, arg);\n  }\n  for (i = 0; i < path.length; i++) {\n    fn(path[i], true, arg);\n  }\n}\n\n/**\n * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that\n * should would receive a `mouseEnter` or `mouseLeave` event.\n *\n * Does not invoke the callback on the nearest common ancestor because nothing\n * \"entered\" or \"left\" that element.\n */\nfunction traverseEnterLeave(from, to, fn, argFrom, argTo) {\n  var common = from && to ? getLowestCommonAncestor(from, to) : null;\n  var pathFrom = [];\n  while (from && from !== common) {\n    pathFrom.push(from);\n    from = from._hostParent;\n  }\n  var pathTo = [];\n  while (to && to !== common) {\n    pathTo.push(to);\n    to = to._hostParent;\n  }\n  var i;\n  for (i = 0; i < pathFrom.length; i++) {\n    fn(pathFrom[i], true, argFrom);\n  }\n  for (i = pathTo.length; i-- > 0;) {\n    fn(pathTo[i], false, argTo);\n  }\n}\n\nmodule.exports = {\n  isAncestor: isAncestor,\n  getLowestCommonAncestor: getLowestCommonAncestor,\n  getParentInstance: getParentInstance,\n  traverseTwoPhase: traverseTwoPhase,\n  traverseEnterLeave: traverseEnterLeave\n};\n},{\"139\":139,\"161\":161}],58:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMUnknownPropertyDevtool\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var reactProps = {\n    children: true,\n    dangerouslySetInnerHTML: true,\n    key: true,\n    ref: true,\n\n    autoFocus: true,\n    defaultValue: true,\n    valueLink: true,\n    defaultChecked: true,\n    checkedLink: true,\n    innerHTML: true,\n    suppressContentEditableWarning: true,\n    onFocusIn: true,\n    onFocusOut: true\n  };\n  var warnedProperties = {};\n\n  var validateProperty = function (tagName, name, debugID) {\n    if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) {\n      return true;\n    }\n    if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {\n      return true;\n    }\n    if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) {\n      return true;\n    }\n    warnedProperties[name] = true;\n    var lowerCasedName = name.toLowerCase();\n\n    // data-* attributes should be lowercase; suggest the lowercase version\n    var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;\n\n    var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : null;\n\n    if (standardName != null) {\n      \"development\" !== 'production' ? warning(standardName == null, 'Unknown DOM property %s. Did you mean %s?%s', name, standardName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else if (registrationName != null) {\n      \"development\" !== 'production' ? warning(registrationName == null, 'Unknown event handler property %s. Did you mean `%s`?%s', name, registrationName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else {\n      // We were unable to guess which prop the user intended.\n      // It is likely that the user was just blindly spreading/forwarding props\n      // Components should be careful to only render valid props/attributes.\n      // Warning will be invoked in warnUnknownProperties to allow grouping.\n      return false;\n    }\n  };\n}\n\nvar warnUnknownProperties = function (debugID, element) {\n  var unknownProps = [];\n  for (var key in element.props) {\n    var isValid = validateProperty(element.type, key, debugID);\n    if (!isValid) {\n      unknownProps.push(key);\n    }\n  }\n\n  var unknownPropString = unknownProps.map(function (prop) {\n    return '`' + prop + '`';\n  }).join(', ');\n\n  if (unknownProps.length === 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown prop %s on <%s> tag. Remove this prop from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  } else if (unknownProps.length > 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown props %s on <%s> tag. Remove these props from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  }\n};\n\nfunction handleElement(debugID, element) {\n  if (element == null || typeof element.type !== 'string') {\n    return;\n  }\n  if (element.type.indexOf('-') >= 0 || element.props.is) {\n    return;\n  }\n  warnUnknownProperties(debugID, element);\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"10\":10,\"171\":171,\"18\":18,\"34\":34}],59:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDebugTool\n */\n\n'use strict';\n\nvar ReactInvalidSetStateWarningDevTool = _dereq_(75);\nvar ReactHostOperationHistoryDevtool = _dereq_(70);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performanceNow = _dereq_(169);\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar isProfiling = false;\nvar flushHistory = [];\nvar lifeCycleTimerStack = [];\nvar currentFlushNesting = 0;\nvar currentFlushMeasurements = null;\nvar currentFlushStartTime = null;\nvar currentTimerDebugID = null;\nvar currentTimerStartTime = null;\nvar currentTimerNestedFlushDuration = null;\nvar currentTimerType = null;\n\nfunction clearHistory() {\n  ReactComponentTreeDevtool.purgeUnmountedComponents();\n  ReactHostOperationHistoryDevtool.clearHistory();\n}\n\nfunction getTreeSnapshot(registeredIDs) {\n  return registeredIDs.reduce(function (tree, id) {\n    var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n    var parentID = ReactComponentTreeDevtool.getParentID(id);\n    tree[id] = {\n      displayName: ReactComponentTreeDevtool.getDisplayName(id),\n      text: ReactComponentTreeDevtool.getText(id),\n      updateCount: ReactComponentTreeDevtool.getUpdateCount(id),\n      childIDs: ReactComponentTreeDevtool.getChildIDs(id),\n      // Text nodes don't have owners but this is close enough.\n      ownerID: ownerID || ReactComponentTreeDevtool.getOwnerID(parentID),\n      parentID: parentID\n    };\n    return tree;\n  }, {});\n}\n\nfunction resetMeasurements() {\n  var previousStartTime = currentFlushStartTime;\n  var previousMeasurements = currentFlushMeasurements || [];\n  var previousOperations = ReactHostOperationHistoryDevtool.getHistory();\n\n  if (currentFlushNesting === 0) {\n    currentFlushStartTime = null;\n    currentFlushMeasurements = null;\n    clearHistory();\n    return;\n  }\n\n  if (previousMeasurements.length || previousOperations.length) {\n    var registeredIDs = ReactComponentTreeDevtool.getRegisteredIDs();\n    flushHistory.push({\n      duration: performanceNow() - previousStartTime,\n      measurements: previousMeasurements || [],\n      operations: previousOperations || [],\n      treeSnapshot: getTreeSnapshot(registeredIDs)\n    });\n  }\n\n  clearHistory();\n  currentFlushStartTime = performanceNow();\n  currentFlushMeasurements = [];\n}\n\nfunction checkDebugID(debugID) {\n  \"development\" !== 'production' ? warning(debugID, 'ReactDebugTool: debugID may not be empty.') : void 0;\n}\n\nfunction beginLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(!currentTimerType, 'There is an internal error in the React performance measurement code. ' + 'Did not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  currentTimerStartTime = performanceNow();\n  currentTimerNestedFlushDuration = 0;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nfunction endLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(currentTimerType === timerType, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  if (isProfiling) {\n    currentFlushMeasurements.push({\n      timerType: timerType,\n      instanceID: debugID,\n      duration: performanceNow() - currentTimerStartTime - currentTimerNestedFlushDuration\n    });\n  }\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction pauseCurrentLifeCycleTimer() {\n  var currentTimer = {\n    startTime: currentTimerStartTime,\n    nestedFlushStartTime: performanceNow(),\n    debugID: currentTimerDebugID,\n    timerType: currentTimerType\n  };\n  lifeCycleTimerStack.push(currentTimer);\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction resumeCurrentLifeCycleTimer() {\n  var _lifeCycleTimerStack$ = lifeCycleTimerStack.pop();\n\n  var startTime = _lifeCycleTimerStack$.startTime;\n  var nestedFlushStartTime = _lifeCycleTimerStack$.nestedFlushStartTime;\n  var debugID = _lifeCycleTimerStack$.debugID;\n  var timerType = _lifeCycleTimerStack$.timerType;\n\n  var nestedFlushDuration = performanceNow() - nestedFlushStartTime;\n  currentTimerStartTime = startTime;\n  currentTimerNestedFlushDuration += nestedFlushDuration;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nvar ReactDebugTool = {\n  addDevtool: function (devtool) {\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  isProfiling: function () {\n    return isProfiling;\n  },\n  beginProfiling: function () {\n    if (isProfiling) {\n      return;\n    }\n\n    isProfiling = true;\n    flushHistory.length = 0;\n    resetMeasurements();\n    ReactDebugTool.addDevtool(ReactHostOperationHistoryDevtool);\n  },\n  endProfiling: function () {\n    if (!isProfiling) {\n      return;\n    }\n\n    isProfiling = false;\n    resetMeasurements();\n    ReactDebugTool.removeDevtool(ReactHostOperationHistoryDevtool);\n  },\n  getFlushHistory: function () {\n    return flushHistory;\n  },\n  onBeginFlush: function () {\n    currentFlushNesting++;\n    resetMeasurements();\n    pauseCurrentLifeCycleTimer();\n    emitEvent('onBeginFlush');\n  },\n  onEndFlush: function () {\n    resetMeasurements();\n    currentFlushNesting--;\n    resumeCurrentLifeCycleTimer();\n    emitEvent('onEndFlush');\n  },\n  onBeginLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginLifeCycleTimer', debugID, timerType);\n    beginLifeCycleTimer(debugID, timerType);\n  },\n  onEndLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    endLifeCycleTimer(debugID, timerType);\n    emitEvent('onEndLifeCycleTimer', debugID, timerType);\n  },\n  onBeginReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginReconcilerTimer', debugID, timerType);\n  },\n  onEndReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onEndReconcilerTimer', debugID, timerType);\n  },\n  onError: function (debugID) {\n    if (currentTimerDebugID != null) {\n      endLifeCycleTimer(currentTimerDebugID, currentTimerType);\n    }\n    emitEvent('onError', debugID);\n  },\n  onBeginProcessingChildContext: function () {\n    emitEvent('onBeginProcessingChildContext');\n  },\n  onEndProcessingChildContext: function () {\n    emitEvent('onEndProcessingChildContext');\n  },\n  onHostOperation: function (debugID, type, payload) {\n    checkDebugID(debugID);\n    emitEvent('onHostOperation', debugID, type, payload);\n  },\n  onSetState: function () {\n    emitEvent('onSetState');\n  },\n  onSetDisplayName: function (debugID, displayName) {\n    checkDebugID(debugID);\n    emitEvent('onSetDisplayName', debugID, displayName);\n  },\n  onSetChildren: function (debugID, childDebugIDs) {\n    checkDebugID(debugID);\n    childDebugIDs.forEach(checkDebugID);\n    emitEvent('onSetChildren', debugID, childDebugIDs);\n  },\n  onSetOwner: function (debugID, ownerDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetOwner', debugID, ownerDebugID);\n  },\n  onSetParent: function (debugID, parentDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetParent', debugID, parentDebugID);\n  },\n  onSetText: function (debugID, text) {\n    checkDebugID(debugID);\n    emitEvent('onSetText', debugID, text);\n  },\n  onMountRootComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountRootComponent', debugID);\n  },\n  onBeforeMountComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeMountComponent', debugID, element);\n  },\n  onMountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountComponent', debugID);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeUpdateComponent', debugID, element);\n  },\n  onUpdateComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUpdateComponent', debugID);\n  },\n  onUnmountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUnmountComponent', debugID);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool);\nReactDebugTool.addDevtool(ReactComponentTreeDevtool);\nvar url = ExecutionEnvironment.canUseDOM && window.location.href || '';\nif (/[?&]react_perf\\b/.test(url)) {\n  ReactDebugTool.beginProfiling();\n}\n\nmodule.exports = ReactDebugTool;\n},{\"147\":147,\"169\":169,\"171\":171,\"34\":34,\"70\":70,\"75\":75}],60:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultBatchingStrategy\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactUpdates = _dereq_(95);\nvar Transaction = _dereq_(113);\n\nvar emptyFunction = _dereq_(153);\n\nvar RESET_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: function () {\n    ReactDefaultBatchingStrategy.isBatchingUpdates = false;\n  }\n};\n\nvar FLUSH_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)\n};\n\nvar TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];\n\nfunction ReactDefaultBatchingStrategyTransaction() {\n  this.reinitializeTransaction();\n}\n\n_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  }\n});\n\nvar transaction = new ReactDefaultBatchingStrategyTransaction();\n\nvar ReactDefaultBatchingStrategy = {\n  isBatchingUpdates: false,\n\n  /**\n   * Call the provided function in a context within which calls to `setState`\n   * and friends are batched such that components aren't updated unnecessarily.\n   */\n  batchedUpdates: function (callback, a, b, c, d, e) {\n    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;\n\n    ReactDefaultBatchingStrategy.isBatchingUpdates = true;\n\n    // The code is written this way to avoid extra allocations\n    if (alreadyBatchingUpdates) {\n      callback(a, b, c, d, e);\n    } else {\n      transaction.perform(callback, null, a, b, c, d, e);\n    }\n  }\n};\n\nmodule.exports = ReactDefaultBatchingStrategy;\n},{\"113\":113,\"153\":153,\"172\":172,\"95\":95}],61:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultInjection\n */\n\n'use strict';\n\nvar BeforeInputEventPlugin = _dereq_(2);\nvar ChangeEventPlugin = _dereq_(6);\nvar DefaultEventPluginOrder = _dereq_(13);\nvar EnterLeaveEventPlugin = _dereq_(15);\nvar HTMLDOMPropertyConfig = _dereq_(22);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMComponent = _dereq_(39);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMEmptyComponent = _dereq_(44);\nvar ReactDOMTreeTraversal = _dereq_(57);\nvar ReactDOMTextComponent = _dereq_(55);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactEventListener = _dereq_(67);\nvar ReactInjection = _dereq_(71);\nvar ReactReconcileTransaction = _dereq_(86);\nvar SVGDOMPropertyConfig = _dereq_(97);\nvar SelectEventPlugin = _dereq_(98);\nvar SimpleEventPlugin = _dereq_(99);\n\nvar alreadyInjected = false;\n\nfunction inject() {\n  if (alreadyInjected) {\n    // TODO: This is currently true because these injections are shared between\n    // the client and the server package. They should be built independently\n    // and not share any injection state. Then this problem will be solved.\n    return;\n  }\n  alreadyInjected = true;\n\n  ReactInjection.EventEmitter.injectReactEventListener(ReactEventListener);\n\n  /**\n   * Inject modules for resolving DOM hierarchy and plugin ordering.\n   */\n  ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);\n  ReactInjection.EventPluginUtils.injectComponentTree(ReactDOMComponentTree);\n  ReactInjection.EventPluginUtils.injectTreeTraversal(ReactDOMTreeTraversal);\n\n  /**\n   * Some important event plugins included by default (without having to require\n   * them).\n   */\n  ReactInjection.EventPluginHub.injectEventPluginsByName({\n    SimpleEventPlugin: SimpleEventPlugin,\n    EnterLeaveEventPlugin: EnterLeaveEventPlugin,\n    ChangeEventPlugin: ChangeEventPlugin,\n    SelectEventPlugin: SelectEventPlugin,\n    BeforeInputEventPlugin: BeforeInputEventPlugin\n  });\n\n  ReactInjection.HostComponent.injectGenericComponentClass(ReactDOMComponent);\n\n  ReactInjection.HostComponent.injectTextComponentClass(ReactDOMTextComponent);\n\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);\n\n  ReactInjection.EmptyComponent.injectEmptyComponentFactory(function (instantiate) {\n    return new ReactDOMEmptyComponent(instantiate);\n  });\n\n  ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction);\n  ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n\n  ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);\n}\n\nmodule.exports = {\n  inject: inject\n};\n},{\"13\":13,\"15\":15,\"2\":2,\"22\":22,\"32\":32,\"39\":39,\"41\":41,\"44\":44,\"55\":55,\"57\":57,\"6\":6,\"60\":60,\"67\":67,\"71\":71,\"86\":86,\"97\":97,\"98\":98,\"99\":99}],62:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElement\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar warning = _dereq_(171);\nvar canDefineProperty = _dereq_(117);\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// The Symbol used to tag the ReactElement type. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;\n\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\n\nvar specialPropKeyWarningShown, specialPropRefWarningShown;\n\nfunction hasValidRef(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.key !== undefined;\n}\n\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, no instanceof check\n * will work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} key\n * @param {string|object} ref\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @param {*} owner\n * @param {*} props\n * @internal\n */\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allow us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  if (\"development\" !== 'production') {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {};\n\n    // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n    if (canDefineProperty) {\n      Object.defineProperty(element._store, 'validated', {\n        configurable: false,\n        enumerable: false,\n        writable: true,\n        value: false\n      });\n      // self and source are DEV only properties.\n      Object.defineProperty(element, '_self', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: self\n      });\n      // Two elements created in two different places should be considered\n      // equal for testing purposes and therefore we hide it from enumeration.\n      Object.defineProperty(element, '_source', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: source\n      });\n    } else {\n      element._store.validated = false;\n      element._self = self;\n      element._source = source;\n    }\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n\n/**\n * Create and return a new ReactElement of the given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createelement\n */\nReactElement.createElement = function (type, config, children) {\n  var propName;\n\n  // Reserved names are extracted\n  var props = {};\n\n  var key = null;\n  var ref = null;\n  var self = null;\n  var source = null;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.createElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    self = config.__self === undefined ? null : config.__self;\n    source = config.__source === undefined ? null : config.__source;\n    // Remaining properties are added to a new props object\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  // Resolve default props\n  if (type && type.defaultProps) {\n    var defaultProps = type.defaultProps;\n    for (propName in defaultProps) {\n      if (props[propName] === undefined) {\n        props[propName] = defaultProps[propName];\n      }\n    }\n  }\n  if (\"development\" !== 'production') {\n    var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n    // Create dummy `key` and `ref` property to `props` to warn users against its use\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingKey.isReactWarning = true;\n\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingRef.isReactWarning = true;\n\n    if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) {\n      if (!props.hasOwnProperty('key')) {\n        Object.defineProperty(props, 'key', {\n          get: warnAboutAccessingKey,\n          configurable: true\n        });\n      }\n      if (!props.hasOwnProperty('ref')) {\n        Object.defineProperty(props, 'ref', {\n          get: warnAboutAccessingRef,\n          configurable: true\n        });\n      }\n    }\n  }\n  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n};\n\n/**\n * Return a function that produces ReactElements of a given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createfactory\n */\nReactElement.createFactory = function (type) {\n  var factory = ReactElement.createElement.bind(null, type);\n  // Expose the type on the factory and the prototype so that it can be\n  // easily accessed on elements. E.g. `<Foo />.type === Foo`.\n  // This should not be named `constructor` since this may not be the function\n  // that created the element, and it may not even be a constructor.\n  // Legacy hook TODO: Warn if this is accessed\n  factory.type = type;\n  return factory;\n};\n\nReactElement.cloneAndReplaceKey = function (oldElement, newKey) {\n  var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);\n\n  return newElement;\n};\n\n/**\n * Clone and return a new ReactElement using element as the starting point.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement\n */\nReactElement.cloneElement = function (element, config, children) {\n  var propName;\n\n  // Original props are copied\n  var props = _assign({}, element.props);\n\n  // Reserved names are extracted\n  var key = element.key;\n  var ref = element.ref;\n  // Self is preserved since the owner is preserved.\n  var self = element._self;\n  // Source is preserved since cloneElement is unlikely to be targeted by a\n  // transpiler, and the original source is probably a better indicator of the\n  // true owner.\n  var source = element._source;\n\n  // Owner will be preserved, unless ref is overridden\n  var owner = element._owner;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.cloneElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      // Silently steal the ref from the parent.\n      ref = config.ref;\n      owner = ReactCurrentOwner.current;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    // Remaining properties override existing props\n    var defaultProps;\n    if (element.type && element.type.defaultProps) {\n      defaultProps = element.type.defaultProps;\n    }\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        if (config[propName] === undefined && defaultProps !== undefined) {\n          // Resolve default props\n          props[propName] = defaultProps[propName];\n        } else {\n          props[propName] = config[propName];\n        }\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  return ReactElement(element.type, key, ref, self, source, owner, props);\n};\n\n/**\n * Verifies the object is a ReactElement.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a valid component.\n * @final\n */\nReactElement.isValidElement = function (object) {\n  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n};\n\nReactElement.REACT_ELEMENT_TYPE = REACT_ELEMENT_TYPE;\n\nmodule.exports = ReactElement;\n},{\"117\":117,\"171\":171,\"172\":172,\"36\":36}],63:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElementValidator\n */\n\n/**\n * ReactElementValidator provides a wrapper around a element factory\n * which validates the props passed to the element. This is intended to be\n * used only in DEV and could be replaced by a static type checker for languages\n * that support it.\n */\n\n'use strict';\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar canDefineProperty = _dereq_(117);\nvar getIteratorFn = _dereq_(130);\nvar warning = _dereq_(171);\n\nfunction getDeclarationErrorAddendum() {\n  if (ReactCurrentOwner.current) {\n    var name = ReactCurrentOwner.current.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  var info = getDeclarationErrorAddendum();\n\n  if (!info) {\n    var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n    if (parentName) {\n      info = ' Check the top-level render call using <' + parentName + '>.';\n    }\n  }\n  return info;\n}\n\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\nfunction validateExplicitKey(element, parentType) {\n  if (!element._store || element._store.validated || element.key != null) {\n    return;\n  }\n  element._store.validated = true;\n\n  var memoizer = ownerHasKeyUseWarning.uniqueKey || (ownerHasKeyUseWarning.uniqueKey = {});\n\n  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n  if (memoizer[currentComponentErrorInfo]) {\n    return;\n  }\n  memoizer[currentComponentErrorInfo] = true;\n\n  // Usually the current owner is the offender, but if it accepts children as a\n  // property, it may be the creator of the child that's responsible for\n  // assigning it a key.\n  var childOwner = '';\n  if (element && element._owner && element._owner !== ReactCurrentOwner.current) {\n    // Give the component that originally created this child.\n    childOwner = ' It was passed a child from ' + element._owner.getName() + '.';\n  }\n\n  \"development\" !== 'production' ? warning(false, 'Each child in an array or iterator should have a unique \"key\" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.%s', currentComponentErrorInfo, childOwner, ReactComponentTreeDevtool.getCurrentStackAddendum(element)) : void 0;\n}\n\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\nfunction validateChildKeys(node, parentType) {\n  if (typeof node !== 'object') {\n    return;\n  }\n  if (Array.isArray(node)) {\n    for (var i = 0; i < node.length; i++) {\n      var child = node[i];\n      if (ReactElement.isValidElement(child)) {\n        validateExplicitKey(child, parentType);\n      }\n    }\n  } else if (ReactElement.isValidElement(node)) {\n    // This element was passed in a valid location.\n    if (node._store) {\n      node._store.validated = true;\n    }\n  } else if (node) {\n    var iteratorFn = getIteratorFn(node);\n    // Entry iterators provide implicit keys.\n    if (iteratorFn) {\n      if (iteratorFn !== node.entries) {\n        var iterator = iteratorFn.call(node);\n        var step;\n        while (!(step = iterator.next()).done) {\n          if (ReactElement.isValidElement(step.value)) {\n            validateExplicitKey(step.value, parentType);\n          }\n        }\n      }\n    }\n  }\n}\n\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\nfunction validatePropTypes(element) {\n  var componentClass = element.type;\n  if (typeof componentClass !== 'function') {\n    return;\n  }\n  var name = componentClass.displayName || componentClass.name;\n  if (componentClass.propTypes) {\n    checkReactTypeSpec(componentClass.propTypes, element.props, ReactPropTypeLocations.prop, name, element, null);\n  }\n  if (typeof componentClass.getDefaultProps === 'function') {\n    \"development\" !== 'production' ? warning(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0;\n  }\n}\n\nvar ReactElementValidator = {\n\n  createElement: function (type, props, children) {\n    var validType = typeof type === 'string' || typeof type === 'function';\n    // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n    \"development\" !== 'production' ? warning(validType, 'React.createElement: type should not be null, undefined, boolean, or ' + 'number. It should be a string (for DOM elements) or a ReactClass ' + '(for composite components).%s', getDeclarationErrorAddendum()) : void 0;\n\n    var element = ReactElement.createElement.apply(this, arguments);\n\n    // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n    if (element == null) {\n      return element;\n    }\n\n    // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n    if (validType) {\n      for (var i = 2; i < arguments.length; i++) {\n        validateChildKeys(arguments[i], type);\n      }\n    }\n\n    validatePropTypes(element);\n\n    return element;\n  },\n\n  createFactory: function (type) {\n    var validatedFactory = ReactElementValidator.createElement.bind(null, type);\n    // Legacy hook TODO: Warn if this is accessed\n    validatedFactory.type = type;\n\n    if (\"development\" !== 'production') {\n      if (canDefineProperty) {\n        Object.defineProperty(validatedFactory, 'type', {\n          enumerable: false,\n          get: function () {\n            \"development\" !== 'production' ? warning(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.') : void 0;\n            Object.defineProperty(this, 'type', {\n              value: type\n            });\n            return type;\n          }\n        });\n      }\n    }\n\n    return validatedFactory;\n  },\n\n  cloneElement: function (element, props, children) {\n    var newElement = ReactElement.cloneElement.apply(this, arguments);\n    for (var i = 2; i < arguments.length; i++) {\n      validateChildKeys(arguments[i], newElement.type);\n    }\n    validatePropTypes(newElement);\n    return newElement;\n  }\n\n};\n\nmodule.exports = ReactElementValidator;\n},{\"117\":117,\"118\":118,\"130\":130,\"171\":171,\"34\":34,\"36\":36,\"62\":62,\"84\":84}],64:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEmptyComponent\n */\n\n'use strict';\n\nvar emptyComponentFactory;\n\nvar ReactEmptyComponentInjection = {\n  injectEmptyComponentFactory: function (factory) {\n    emptyComponentFactory = factory;\n  }\n};\n\nvar ReactEmptyComponent = {\n  create: function (instantiate) {\n    return emptyComponentFactory(instantiate);\n  }\n};\n\nReactEmptyComponent.injection = ReactEmptyComponentInjection;\n\nmodule.exports = ReactEmptyComponent;\n},{}],65:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactErrorUtils\n */\n\n'use strict';\n\nvar caughtError = null;\n\n/**\n * Call a function while guarding against errors that happens within it.\n *\n * @param {?String} name of the guard to use for logging or debugging\n * @param {Function} func The function to invoke\n * @param {*} a First argument\n * @param {*} b Second argument\n */\nfunction invokeGuardedCallback(name, func, a, b) {\n  try {\n    return func(a, b);\n  } catch (x) {\n    if (caughtError === null) {\n      caughtError = x;\n    }\n    return undefined;\n  }\n}\n\nvar ReactErrorUtils = {\n  invokeGuardedCallback: invokeGuardedCallback,\n\n  /**\n   * Invoked by ReactTestUtils.Simulate so that any errors thrown by the event\n   * handler are sure to be rethrown by rethrowCaughtError.\n   */\n  invokeGuardedCallbackWithCatch: invokeGuardedCallback,\n\n  /**\n   * During execution of guarded functions we will capture the first error which\n   * we will rethrow to be handled by the top level error handler.\n   */\n  rethrowCaughtError: function () {\n    if (caughtError) {\n      var error = caughtError;\n      caughtError = null;\n      throw error;\n    }\n  }\n};\n\nif (\"development\" !== 'production') {\n  /**\n   * To help development we can get better devtools integration by simulating a\n   * real browser event.\n   */\n  if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {\n    var fakeNode = document.createElement('react');\n    ReactErrorUtils.invokeGuardedCallback = function (name, func, a, b) {\n      var boundFunc = func.bind(null, a, b);\n      var evtType = 'react-' + name;\n      fakeNode.addEventListener(evtType, boundFunc, false);\n      var evt = document.createEvent('Event');\n      evt.initEvent(evtType, false, false);\n      fakeNode.dispatchEvent(evt);\n      fakeNode.removeEventListener(evtType, boundFunc, false);\n    };\n  }\n}\n\nmodule.exports = ReactErrorUtils;\n},{}],66:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventEmitterMixin\n */\n\n'use strict';\n\nvar EventPluginHub = _dereq_(17);\n\nfunction runEventQueueInBatch(events) {\n  EventPluginHub.enqueueEvents(events);\n  EventPluginHub.processEventQueue(false);\n}\n\nvar ReactEventEmitterMixin = {\n\n  /**\n   * Streams a fired top-level event to `EventPluginHub` where plugins have the\n   * opportunity to create `ReactEvent`s to be dispatched.\n   */\n  handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events = EventPluginHub.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n    runEventQueueInBatch(events);\n  }\n};\n\nmodule.exports = ReactEventEmitterMixin;\n},{\"17\":17}],67:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventListener\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventListener = _dereq_(146);\nvar ExecutionEnvironment = _dereq_(147);\nvar PooledClass = _dereq_(25);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar getEventTarget = _dereq_(128);\nvar getUnboundedScrollPosition = _dereq_(158);\n\n/**\n * Find the deepest React component completely containing the root of the\n * passed-in instance (for use when entire React trees are nested within each\n * other). If React trees are not nested, returns null.\n */\nfunction findParent(inst) {\n  // TODO: It may be a good idea to cache this to prevent unnecessary DOM\n  // traversal, but caching is difficult to do correctly without using a\n  // mutation observer to listen for all DOM changes.\n  while (inst._hostParent) {\n    inst = inst._hostParent;\n  }\n  var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);\n  var container = rootNode.parentNode;\n  return ReactDOMComponentTree.getClosestInstanceFromNode(container);\n}\n\n// Used to store ancestor hierarchy in top level callback\nfunction TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {\n  this.topLevelType = topLevelType;\n  this.nativeEvent = nativeEvent;\n  this.ancestors = [];\n}\n_assign(TopLevelCallbackBookKeeping.prototype, {\n  destructor: function () {\n    this.topLevelType = null;\n    this.nativeEvent = null;\n    this.ancestors.length = 0;\n  }\n});\nPooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler);\n\nfunction handleTopLevelImpl(bookKeeping) {\n  var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);\n  var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);\n\n  // Loop through the hierarchy, in case there's any nested components.\n  // It's important that we build the array of ancestors before calling any\n  // event handlers, because event handlers can modify the DOM, leading to\n  // inconsistencies with ReactMount's node cache. See #1105.\n  var ancestor = targetInst;\n  do {\n    bookKeeping.ancestors.push(ancestor);\n    ancestor = ancestor && findParent(ancestor);\n  } while (ancestor);\n\n  for (var i = 0; i < bookKeeping.ancestors.length; i++) {\n    targetInst = bookKeeping.ancestors[i];\n    ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));\n  }\n}\n\nfunction scrollValueMonitor(cb) {\n  var scrollPosition = getUnboundedScrollPosition(window);\n  cb(scrollPosition);\n}\n\nvar ReactEventListener = {\n  _enabled: true,\n  _handleTopLevel: null,\n\n  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,\n\n  setHandleTopLevel: function (handleTopLevel) {\n    ReactEventListener._handleTopLevel = handleTopLevel;\n  },\n\n  setEnabled: function (enabled) {\n    ReactEventListener._enabled = !!enabled;\n  },\n\n  isEnabled: function () {\n    return ReactEventListener._enabled;\n  },\n\n  /**\n   * Traps top-level events by using event bubbling.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  /**\n   * Traps a top-level event by using event capturing.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  monitorScrollValue: function (refresh) {\n    var callback = scrollValueMonitor.bind(null, refresh);\n    EventListener.listen(window, 'scroll', callback);\n  },\n\n  dispatchEvent: function (topLevelType, nativeEvent) {\n    if (!ReactEventListener._enabled) {\n      return;\n    }\n\n    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);\n    try {\n      // Event queue being processed in the same cycle allows\n      // `preventDefault`.\n      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);\n    } finally {\n      TopLevelCallbackBookKeeping.release(bookKeeping);\n    }\n  }\n};\n\nmodule.exports = ReactEventListener;\n},{\"128\":128,\"146\":146,\"147\":147,\"158\":158,\"172\":172,\"25\":25,\"41\":41,\"95\":95}],68:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactFeatureFlags\n * \n */\n\n'use strict';\n\nvar ReactFeatureFlags = {\n  // When true, call console.time() before and .timeEnd() after each top-level\n  // render (both initial renders and updates). Useful when looking at prod-mode\n  // timeline profiles in Chrome, for example.\n  logTopLevelRenders: false\n};\n\nmodule.exports = ReactFeatureFlags;\n},{}],69:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar invariant = _dereq_(161);\n\nvar genericComponentClass = null;\n// This registry keeps track of wrapper classes around host tags.\nvar tagToComponentClass = {};\nvar textComponentClass = null;\n\nvar ReactHostComponentInjection = {\n  // This accepts a class that receives the tag string. This is a catch all\n  // that can render any kind of tag.\n  injectGenericComponentClass: function (componentClass) {\n    genericComponentClass = componentClass;\n  },\n  // This accepts a text component class that takes the text string to be\n  // rendered as props.\n  injectTextComponentClass: function (componentClass) {\n    textComponentClass = componentClass;\n  },\n  // This accepts a keyed object with classes as values. Each key represents a\n  // tag. That particular tag will use this class instead of the generic one.\n  injectComponentClasses: function (componentClasses) {\n    _assign(tagToComponentClass, componentClasses);\n  }\n};\n\n/**\n * Get a host internal component class for a specific tag.\n *\n * @param {ReactElement} element The element to create.\n * @return {function} The internal class constructor function.\n */\nfunction createInternalComponent(element) {\n  !genericComponentClass ? \"development\" !== 'production' ? invariant(false, 'There is no registered component for the tag %s', element.type) : _prodInvariant('111', element.type) : void 0;\n  return new genericComponentClass(element);\n}\n\n/**\n * @param {ReactText} text\n * @return {ReactComponent}\n */\nfunction createInstanceForText(text) {\n  return new textComponentClass(text);\n}\n\n/**\n * @param {ReactComponent} component\n * @return {boolean}\n */\nfunction isTextComponent(component) {\n  return component instanceof textComponentClass;\n}\n\nvar ReactHostComponent = {\n  createInternalComponent: createInternalComponent,\n  createInstanceForText: createInstanceForText,\n  isTextComponent: isTextComponent,\n  injection: ReactHostComponentInjection\n};\n\nmodule.exports = ReactHostComponent;\n},{\"139\":139,\"161\":161,\"172\":172}],70:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostOperationHistoryDevtool\n */\n\n'use strict';\n\nvar history = [];\n\nvar ReactHostOperationHistoryDevtool = {\n  onHostOperation: function (debugID, type, payload) {\n    history.push({\n      instanceID: debugID,\n      type: type,\n      payload: payload\n    });\n  },\n  clearHistory: function () {\n    if (ReactHostOperationHistoryDevtool._preventClearing) {\n      // Should only be used for tests.\n      return;\n    }\n\n    history = [];\n  },\n  getHistory: function () {\n    return history;\n  }\n};\n\nmodule.exports = ReactHostOperationHistoryDevtool;\n},{}],71:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInjection\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactClass = _dereq_(30);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactHostComponent = _dereq_(69);\nvar ReactUpdates = _dereq_(95);\n\nvar ReactInjection = {\n  Component: ReactComponentEnvironment.injection,\n  Class: ReactClass.injection,\n  DOMProperty: DOMProperty.injection,\n  EmptyComponent: ReactEmptyComponent.injection,\n  EventPluginHub: EventPluginHub.injection,\n  EventPluginUtils: EventPluginUtils.injection,\n  EventEmitter: ReactBrowserEventEmitter.injection,\n  HostComponent: ReactHostComponent.injection,\n  Updates: ReactUpdates.injection\n};\n\nmodule.exports = ReactInjection;\n},{\"10\":10,\"17\":17,\"19\":19,\"27\":27,\"30\":30,\"33\":33,\"64\":64,\"69\":69,\"95\":95}],72:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInputSelection\n */\n\n'use strict';\n\nvar ReactDOMSelection = _dereq_(53);\n\nvar containsNode = _dereq_(150);\nvar focusNode = _dereq_(155);\nvar getActiveElement = _dereq_(156);\n\nfunction isInDocument(node) {\n  return containsNode(document.documentElement, node);\n}\n\n/**\n * @ReactInputSelection: React input selection module. Based on Selection.js,\n * but modified to be suitable for react and has a couple of bug fixes (doesn't\n * assume buttons have range selections allowed).\n * Input selection module for React.\n */\nvar ReactInputSelection = {\n\n  hasSelectionCapabilities: function (elem) {\n    var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n    return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');\n  },\n\n  getSelectionInformation: function () {\n    var focusedElem = getActiveElement();\n    return {\n      focusedElem: focusedElem,\n      selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null\n    };\n  },\n\n  /**\n   * @restoreSelection: If any selection information was potentially lost,\n   * restore it. This is useful when performing operations that could remove dom\n   * nodes and place them back in, resulting in focus being lost.\n   */\n  restoreSelection: function (priorSelectionInformation) {\n    var curFocusedElem = getActiveElement();\n    var priorFocusedElem = priorSelectionInformation.focusedElem;\n    var priorSelectionRange = priorSelectionInformation.selectionRange;\n    if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {\n      if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {\n        ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);\n      }\n      focusNode(priorFocusedElem);\n    }\n  },\n\n  /**\n   * @getSelection: Gets the selection bounds of a focused textarea, input or\n   * contentEditable node.\n   * -@input: Look up selection bounds of this input\n   * -@return {start: selectionStart, end: selectionEnd}\n   */\n  getSelection: function (input) {\n    var selection;\n\n    if ('selectionStart' in input) {\n      // Modern browser with input or textarea.\n      selection = {\n        start: input.selectionStart,\n        end: input.selectionEnd\n      };\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      // IE8 input.\n      var range = document.selection.createRange();\n      // There can only be one selection per document in IE, so it must\n      // be in our element.\n      if (range.parentElement() === input) {\n        selection = {\n          start: -range.moveStart('character', -input.value.length),\n          end: -range.moveEnd('character', -input.value.length)\n        };\n      }\n    } else {\n      // Content editable or old IE textarea.\n      selection = ReactDOMSelection.getOffsets(input);\n    }\n\n    return selection || { start: 0, end: 0 };\n  },\n\n  /**\n   * @setSelection: Sets the selection bounds of a textarea or input and focuses\n   * the input.\n   * -@input     Set selection bounds of this input or textarea\n   * -@offsets   Object of same form that is returned from get*\n   */\n  setSelection: function (input, offsets) {\n    var start = offsets.start;\n    var end = offsets.end;\n    if (end === undefined) {\n      end = start;\n    }\n\n    if ('selectionStart' in input) {\n      input.selectionStart = start;\n      input.selectionEnd = Math.min(end, input.value.length);\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      var range = input.createTextRange();\n      range.collapse(true);\n      range.moveStart('character', start);\n      range.moveEnd('character', end - start);\n      range.select();\n    } else {\n      ReactDOMSelection.setOffsets(input, offsets);\n    }\n  }\n};\n\nmodule.exports = ReactInputSelection;\n},{\"150\":150,\"155\":155,\"156\":156,\"53\":53}],73:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstanceMap\n */\n\n'use strict';\n\n/**\n * `ReactInstanceMap` maintains a mapping from a public facing stateful\n * instance (key) and the internal representation (value). This allows public\n * methods to accept the user facing instance as an argument and map them back\n * to internal methods.\n */\n\n// TODO: Replace this with ES6: var ReactInstanceMap = new Map();\n\nvar ReactInstanceMap = {\n\n  /**\n   * This API should be called `delete` but we'd have to make sure to always\n   * transform these to strings for IE support. When this transform is fully\n   * supported we can rename it.\n   */\n  remove: function (key) {\n    key._reactInternalInstance = undefined;\n  },\n\n  get: function (key) {\n    return key._reactInternalInstance;\n  },\n\n  has: function (key) {\n    return key._reactInternalInstance !== undefined;\n  },\n\n  set: function (key, value) {\n    key._reactInternalInstance = value;\n  }\n\n};\n\nmodule.exports = ReactInstanceMap;\n},{}],74:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDebugTool = _dereq_(59);\n  debugTool = ReactDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"59\":59}],75:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInvalidSetStateWarningDevTool\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var processingChildContext = false;\n\n  var warnInvalidSetState = function () {\n    \"development\" !== 'production' ? warning(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()') : void 0;\n  };\n}\n\nvar ReactInvalidSetStateWarningDevTool = {\n  onBeginProcessingChildContext: function () {\n    processingChildContext = true;\n  },\n  onEndProcessingChildContext: function () {\n    processingChildContext = false;\n  },\n  onSetState: function () {\n    warnInvalidSetState();\n  }\n};\n\nmodule.exports = ReactInvalidSetStateWarningDevTool;\n},{\"171\":171}],76:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMarkupChecksum\n */\n\n'use strict';\n\nvar adler32 = _dereq_(116);\n\nvar TAG_END = /\\/?>/;\nvar COMMENT_START = /^<\\!\\-\\-/;\n\nvar ReactMarkupChecksum = {\n  CHECKSUM_ATTR_NAME: 'data-react-checksum',\n\n  /**\n   * @param {string} markup Markup string\n   * @return {string} Markup string with checksum attribute attached\n   */\n  addChecksumToMarkup: function (markup) {\n    var checksum = adler32(markup);\n\n    // Add checksum (handle both parent tags, comments and self-closing tags)\n    if (COMMENT_START.test(markup)) {\n      return markup;\n    } else {\n      return markup.replace(TAG_END, ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '=\"' + checksum + '\"$&');\n    }\n  },\n\n  /**\n   * @param {string} markup to use\n   * @param {DOMElement} element root React element\n   * @returns {boolean} whether or not the markup is the same\n   */\n  canReuseMarkup: function (markup, element) {\n    var existingChecksum = element.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n    existingChecksum = existingChecksum && parseInt(existingChecksum, 10);\n    var markupChecksum = adler32(markup);\n    return markupChecksum === existingChecksum;\n  }\n};\n\nmodule.exports = ReactMarkupChecksum;\n},{\"116\":116}],77:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMount\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar DOMProperty = _dereq_(10);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDOMFeatureFlags = _dereq_(46);\nvar ReactElement = _dereq_(62);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdateQueue = _dereq_(94);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\nvar setInnerHTML = _dereq_(141);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOC_NODE_TYPE = 9;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\nvar instancesByReactRootID = {};\n\n/**\n * Finds the index of the first character\n * that's not common between the two given strings.\n *\n * @return {number} the index of the character where the strings diverge\n */\nfunction firstDifferenceIndex(string1, string2) {\n  var minLen = Math.min(string1.length, string2.length);\n  for (var i = 0; i < minLen; i++) {\n    if (string1.charAt(i) !== string2.charAt(i)) {\n      return i;\n    }\n  }\n  return string1.length === string2.length ? -1 : minLen;\n}\n\n/**\n * @param {DOMElement|DOMDocument} container DOM element that may contain\n * a React component\n * @return {?*} DOM element that may have the reactRoot ID, or null.\n */\nfunction getReactRootElementInContainer(container) {\n  if (!container) {\n    return null;\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    return container.documentElement;\n  } else {\n    return container.firstChild;\n  }\n}\n\nfunction internalGetID(node) {\n  // If node is something like a window, document, or text node, none of\n  // which support attributes or a .getAttribute method, gracefully return\n  // the empty string, as if the attribute were missing.\n  return node.getAttribute && node.getAttribute(ATTR_NAME) || '';\n}\n\n/**\n * Mounts this component and inserts it into the DOM.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {ReactReconcileTransaction} transaction\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) {\n  var markerName;\n  if (ReactFeatureFlags.logTopLevelRenders) {\n    var wrappedElement = wrapperInstance._currentElement.props;\n    var type = wrappedElement.type;\n    markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name);\n    console.time(markerName);\n  }\n\n  var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context);\n\n  if (markerName) {\n    console.timeEnd(markerName);\n  }\n\n  wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;\n  ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction);\n}\n\n/**\n * Batched mount.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) {\n  var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */\n  !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement);\n  transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context);\n  ReactUpdates.ReactReconcileTransaction.release(transaction);\n}\n\n/**\n * Unmounts a component and removes it from the DOM.\n *\n * @param {ReactComponent} instance React component instance.\n * @param {DOMElement} container DOM element to unmount from.\n * @final\n * @internal\n * @see {ReactMount.unmountComponentAtNode}\n */\nfunction unmountComponentFromNode(instance, container, safely) {\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onBeginFlush();\n  }\n  ReactReconciler.unmountComponent(instance, safely);\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onEndFlush();\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    container = container.documentElement;\n  }\n\n  // http://jsperf.com/emptying-a-node\n  while (container.lastChild) {\n    container.removeChild(container.lastChild);\n  }\n}\n\n/**\n * True if the supplied DOM node has a direct React-rendered child that is\n * not a React root element. Useful for warning in `render`,\n * `unmountComponentAtNode`, etc.\n *\n * @param {?DOMElement} node The candidate DOM node.\n * @return {boolean} True if the DOM element contains a direct child that was\n * rendered by React but is not a root element.\n * @internal\n */\nfunction hasNonRootReactChild(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  if (rootEl) {\n    var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);\n    return !!(inst && inst._hostParent);\n  }\n}\n\nfunction getHostRootInstanceInContainer(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  var prevHostInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);\n  return prevHostInstance && !prevHostInstance._hostParent ? prevHostInstance : null;\n}\n\nfunction getTopLevelWrapperInContainer(container) {\n  var root = getHostRootInstanceInContainer(container);\n  return root ? root._hostContainerInfo._topLevelWrapper : null;\n}\n\n/**\n * Temporary (?) hack so that we can store all top-level pending updates on\n * composites instead of having to worry about different types of components\n * here.\n */\nvar topLevelRootCounter = 1;\nvar TopLevelWrapper = function () {\n  this.rootID = topLevelRootCounter++;\n};\nTopLevelWrapper.prototype.isReactComponent = {};\nif (\"development\" !== 'production') {\n  TopLevelWrapper.displayName = 'TopLevelWrapper';\n}\nTopLevelWrapper.prototype.render = function () {\n  // this.props is actually a ReactElement\n  return this.props;\n};\n\n/**\n * Mounting is the process of initializing a React component by creating its\n * representative DOM elements and inserting them into a supplied `container`.\n * Any prior content inside `container` is destroyed in the process.\n *\n *   ReactMount.render(\n *     component,\n *     document.getElementById('container')\n *   );\n *\n *   <div id=\"container\">                   <-- Supplied `container`.\n *     <div data-reactid=\".3\">              <-- Rendered reactRoot of React\n *       // ...                                 component.\n *     </div>\n *   </div>\n *\n * Inside of `container`, the first element rendered is the \"reactRoot\".\n */\nvar ReactMount = {\n\n  TopLevelWrapper: TopLevelWrapper,\n\n  /**\n   * Used by devtools. The keys are not important.\n   */\n  _instancesByReactRootID: instancesByReactRootID,\n\n  /**\n   * This is a hook provided to support rendering React components while\n   * ensuring that the apparent scroll position of its `container` does not\n   * change.\n   *\n   * @param {DOMElement} container The `container` being rendered into.\n   * @param {function} renderCallback This must be called once to do the render.\n   */\n  scrollMonitor: function (container, renderCallback) {\n    renderCallback();\n  },\n\n  /**\n   * Take a component that's already mounted into the DOM and replace its props\n   * @param {ReactComponent} prevComponent component instance already in the DOM\n   * @param {ReactElement} nextElement component instance to render\n   * @param {DOMElement} container container to render into\n   * @param {?function} callback function triggered on completion\n   */\n  _updateRootComponent: function (prevComponent, nextElement, nextContext, container, callback) {\n    ReactMount.scrollMonitor(container, function () {\n      ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement, nextContext);\n      if (callback) {\n        ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);\n      }\n    });\n\n    return prevComponent;\n  },\n\n  /**\n   * Render a new component into the DOM. Hooked by devtools!\n   *\n   * @param {ReactElement} nextElement element to render\n   * @param {DOMElement} container container to render into\n   * @param {boolean} shouldReuseMarkup if we should skip the markup insertion\n   * @return {ReactComponent} nextComponent\n   */\n  _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case.\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '_renderNewRootComponent(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from ' + 'render is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : _prodInvariant('37') : void 0;\n\n    ReactBrowserEventEmitter.ensureScrollValueMonitoring();\n    var componentInstance = instantiateReactComponent(nextElement, false);\n\n    // The initial render is synchronous but any updates that happen during\n    // rendering, in componentWillMount or componentDidMount, will be batched\n    // according to the current batching strategy.\n\n    ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);\n\n    var wrapperID = componentInstance._instance.rootID;\n    instancesByReactRootID[wrapperID] = componentInstance;\n\n    if (\"development\" !== 'production') {\n      // The instance here is TopLevelWrapper so we report mount for its child.\n      ReactInstrumentation.debugTool.onMountRootComponent(componentInstance._renderedComponent._debugID);\n    }\n\n    return componentInstance;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactComponent} parentComponent The conceptual parent of this render tree.\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    !(parentComponent != null && ReactInstanceMap.has(parentComponent)) ? \"development\" !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : _prodInvariant('38') : void 0;\n    return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback);\n  },\n\n  _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');\n    !ReactElement.isValidElement(nextElement) ? \"development\" !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' :\n    // Check if it quacks like an element\n    nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : _prodInvariant('39', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : void 0;\n\n    \"development\" !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0;\n\n    var nextWrappedElement = ReactElement(TopLevelWrapper, null, null, null, null, null, nextElement);\n\n    var nextContext;\n    if (parentComponent) {\n      var parentInst = ReactInstanceMap.get(parentComponent);\n      nextContext = parentInst._processChildContext(parentInst._context);\n    } else {\n      nextContext = emptyObject;\n    }\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n\n    if (prevComponent) {\n      var prevWrappedElement = prevComponent._currentElement;\n      var prevElement = prevWrappedElement.props;\n      if (shouldUpdateReactComponent(prevElement, nextElement)) {\n        var publicInst = prevComponent._renderedComponent.getPublicInstance();\n        var updatedCallback = callback && function () {\n          callback.call(publicInst);\n        };\n        ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);\n        return publicInst;\n      } else {\n        ReactMount.unmountComponentAtNode(container);\n      }\n    }\n\n    var reactRootElement = getReactRootElementInContainer(container);\n    var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);\n    var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0;\n\n      if (!containerHasReactMarkup || reactRootElement.nextSibling) {\n        var rootElementSibling = reactRootElement;\n        while (rootElementSibling) {\n          if (internalGetID(rootElementSibling)) {\n            \"development\" !== 'production' ? warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.') : void 0;\n            break;\n          }\n          rootElementSibling = rootElementSibling.nextSibling;\n        }\n      }\n    }\n\n    var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;\n    var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();\n    if (callback) {\n      callback.call(component);\n    }\n    return component;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  render: function (nextElement, container, callback) {\n    return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);\n  },\n\n  /**\n   * Unmounts and destroys the React component rendered in the `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode\n   *\n   * @param {DOMElement} container DOM element containing a React component.\n   * @return {boolean} True if a component was found in and unmounted from\n   *                   `container`\n   */\n  unmountComponentAtNode: function (container) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case. (Strictly speaking, unmounting won't cause a\n    // render but we still don't expect to be in a render call here.)\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : _prodInvariant('40') : void 0;\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n    if (!prevComponent) {\n      // Check if the node being unmounted was rendered by React, but isn't a\n      // root node.\n      var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n      // Check if the container itself is a React root node.\n      var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME);\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'unmountComponentAtNode(): The node you\\'re attempting to unmount ' + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0;\n      }\n\n      return false;\n    }\n    delete instancesByReactRootID[prevComponent._instance.rootID];\n    ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false);\n    return true;\n  },\n\n  _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) {\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : _prodInvariant('41') : void 0;\n\n    if (shouldReuseMarkup) {\n      var rootElement = getReactRootElementInContainer(container);\n      if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {\n        ReactDOMComponentTree.precacheNode(instance, rootElement);\n        return;\n      } else {\n        var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n        rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n\n        var rootMarkup = rootElement.outerHTML;\n        rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum);\n\n        var normalizedMarkup = markup;\n        if (\"development\" !== 'production') {\n          // because rootMarkup is retrieved from the DOM, various normalizations\n          // will have occurred which will not be present in `markup`. Here,\n          // insert markup into a <div> or <iframe> depending on the container\n          // type to perform the same normalizations before comparing.\n          var normalizer;\n          if (container.nodeType === ELEMENT_NODE_TYPE) {\n            normalizer = document.createElement('div');\n            normalizer.innerHTML = markup;\n            normalizedMarkup = normalizer.innerHTML;\n          } else {\n            normalizer = document.createElement('iframe');\n            document.body.appendChild(normalizer);\n            normalizer.contentDocument.write(markup);\n            normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;\n            document.body.removeChild(normalizer);\n          }\n        }\n\n        var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);\n        var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);\n\n        !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure. React cannot handle this case due to cross-browser quirks by rendering at the document root. You should look for environment dependent code in your components and ensure the props are the same client and server side:\\n%s', difference) : _prodInvariant('42', difference) : void 0;\n\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'React attempted to reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are ' + 'using server rendering and the markup generated on the ' + 'server was not what the client was expecting. React injected ' + 'new markup to compensate which works but you have lost many ' + 'of the benefits of server rendering. Instead, figure out ' + 'why the markup being generated is different on the client ' + 'or server:\\n%s', difference) : void 0;\n        }\n      }\n    }\n\n    !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document but you didn\\'t use server rendering. We can\\'t do this without using server rendering due to cross-browser quirks. See ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('43') : void 0;\n\n    if (transaction.useCreateElement) {\n      while (container.lastChild) {\n        container.removeChild(container.lastChild);\n      }\n      DOMLazyTree.insertTreeBefore(container, markup, null);\n    } else {\n      setInnerHTML(container, markup);\n      ReactDOMComponentTree.precacheNode(instance, container.firstChild);\n    }\n\n    if (\"development\" !== 'production') {\n      var hostNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);\n      if (hostNode._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(hostNode._debugID, 'mount', markup.toString());\n      }\n    }\n  }\n};\n\nmodule.exports = ReactMount;\n},{\"10\":10,\"134\":134,\"139\":139,\"141\":141,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"27\":27,\"36\":36,\"41\":41,\"42\":42,\"46\":46,\"62\":62,\"68\":68,\"73\":73,\"74\":74,\"76\":76,\"8\":8,\"87\":87,\"94\":94,\"95\":95}],78:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChild\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactReconciler = _dereq_(87);\nvar ReactChildReconciler = _dereq_(28);\n\nvar emptyFunction = _dereq_(153);\nvar flattenChildren = _dereq_(123);\nvar invariant = _dereq_(161);\n\n/**\n * Make an update for markup to be rendered and inserted at a supplied index.\n *\n * @param {string} markup Markup that renders into an element.\n * @param {number} toIndex Destination index.\n * @private\n */\nfunction makeInsertMarkup(markup, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.INSERT_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for moving an existing element to another index.\n *\n * @param {number} fromIndex Source index of the existing element.\n * @param {number} toIndex Destination index of the element.\n * @private\n */\nfunction makeMove(child, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.MOVE_EXISTING,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: ReactReconciler.getHostNode(child),\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for removing an element at an index.\n *\n * @param {number} fromIndex Index of the element to remove.\n * @private\n */\nfunction makeRemove(child, node) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.REMOVE_NODE,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: node,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the markup of a node.\n *\n * @param {string} markup Markup that renders into an element.\n * @private\n */\nfunction makeSetMarkup(markup) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.SET_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the text content.\n *\n * @param {string} textContent Text content to set.\n * @private\n */\nfunction makeTextContent(textContent) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.TEXT_CONTENT,\n    content: textContent,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Push an update, if any, onto the queue. Creates a new queue if none is\n * passed and always returns the queue. Mutative.\n */\nfunction enqueue(queue, update) {\n  if (update) {\n    queue = queue || [];\n    queue.push(update);\n  }\n  return queue;\n}\n\n/**\n * Processes any enqueued updates.\n *\n * @private\n */\nfunction processQueue(inst, updateQueue) {\n  ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue);\n}\n\nvar setParentForInstrumentation = emptyFunction;\nvar setChildrenForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  var getDebugID = function (inst) {\n    if (!inst._debugID) {\n      // Check for ART-like instances. TODO: This is silly/gross.\n      var internal;\n      if (internal = ReactInstanceMap.get(inst)) {\n        inst = internal;\n      }\n    }\n    return inst._debugID;\n  };\n  setParentForInstrumentation = function (child) {\n    if (child._debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetParent(child._debugID, getDebugID(this));\n    }\n  };\n  setChildrenForInstrumentation = function (children) {\n    var debugID = getDebugID(this);\n    // TODO: React Native empty components are also multichild.\n    // This means they still get into this method but don't have _debugID.\n    if (debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetChildren(debugID, children ? Object.keys(children).map(function (key) {\n        return children[key]._debugID;\n      }) : []);\n    }\n  };\n}\n\n/**\n * ReactMultiChild are capable of reconciling multiple children.\n *\n * @class ReactMultiChild\n * @internal\n */\nvar ReactMultiChild = {\n\n  /**\n   * Provides common functionality for components that must reconcile multiple\n   * children. This is used by `ReactDOMComponent` to mount, update, and\n   * unmount child components.\n   *\n   * @lends {ReactMultiChild.prototype}\n   */\n  Mixin: {\n\n    _reconcilerInstantiateChildren: function (nestedChildren, transaction, context) {\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n        }\n      }\n      return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context);\n    },\n\n    _reconcilerUpdateChildren: function (prevChildren, nextNestedChildrenElements, removedNodes, transaction, context) {\n      var nextChildren;\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            nextChildren = flattenChildren(nextNestedChildrenElements, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n          ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n          return nextChildren;\n        }\n      }\n      nextChildren = flattenChildren(nextNestedChildrenElements);\n      ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n      return nextChildren;\n    },\n\n    /**\n     * Generates a \"mount image\" for each of the supplied children. In the case\n     * of `ReactDOMComponent`, a mount image is a string of markup.\n     *\n     * @param {?object} nestedChildren Nested child maps.\n     * @return {array} An array of mounted representations.\n     * @internal\n     */\n    mountChildren: function (nestedChildren, transaction, context) {\n      var children = this._reconcilerInstantiateChildren(nestedChildren, transaction, context);\n      this._renderedChildren = children;\n\n      var mountImages = [];\n      var index = 0;\n      for (var name in children) {\n        if (children.hasOwnProperty(name)) {\n          var child = children[name];\n          if (\"development\" !== 'production') {\n            setParentForInstrumentation.call(this, child);\n          }\n          var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n          child._mountIndex = index++;\n          mountImages.push(mountImage);\n        }\n      }\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, children);\n      }\n\n      return mountImages;\n    },\n\n    /**\n     * Replaces any rendered children with a text content string.\n     *\n     * @param {string} nextContent String of content.\n     * @internal\n     */\n    updateTextContent: function (nextContent) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      // Set new text content.\n      var updates = [makeTextContent(nextContent)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Replaces any rendered children with a markup string.\n     *\n     * @param {string} nextMarkup String of markup.\n     * @internal\n     */\n    updateMarkup: function (nextMarkup) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      var updates = [makeSetMarkup(nextMarkup)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Updates the rendered children with new children.\n     *\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @internal\n     */\n    updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      // Hook used by React ART\n      this._updateChildren(nextNestedChildrenElements, transaction, context);\n    },\n\n    /**\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @final\n     * @protected\n     */\n    _updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      var prevChildren = this._renderedChildren;\n      var removedNodes = {};\n      var nextChildren = this._reconcilerUpdateChildren(prevChildren, nextNestedChildrenElements, removedNodes, transaction, context);\n      if (!nextChildren && !prevChildren) {\n        return;\n      }\n      var updates = null;\n      var name;\n      // `nextIndex` will increment for each child in `nextChildren`, but\n      // `lastIndex` will be the last index visited in `prevChildren`.\n      var lastIndex = 0;\n      var nextIndex = 0;\n      var lastPlacedNode = null;\n      for (name in nextChildren) {\n        if (!nextChildren.hasOwnProperty(name)) {\n          continue;\n        }\n        var prevChild = prevChildren && prevChildren[name];\n        var nextChild = nextChildren[name];\n        if (prevChild === nextChild) {\n          updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));\n          lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n          prevChild._mountIndex = nextIndex;\n        } else {\n          if (prevChild) {\n            // Update `lastIndex` before `_mountIndex` gets unset by unmounting.\n            lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n            // The `removedNodes` loop below will actually remove the child.\n          }\n          // The child must be instantiated before it's mounted.\n          updates = enqueue(updates, this._mountChildAtIndex(nextChild, lastPlacedNode, nextIndex, transaction, context));\n        }\n        nextIndex++;\n        lastPlacedNode = ReactReconciler.getHostNode(nextChild);\n      }\n      // Remove children that are no longer present.\n      for (name in removedNodes) {\n        if (removedNodes.hasOwnProperty(name)) {\n          updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name]));\n        }\n      }\n      if (updates) {\n        processQueue(this, updates);\n      }\n      this._renderedChildren = nextChildren;\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, nextChildren);\n      }\n    },\n\n    /**\n     * Unmounts all rendered children. This should be used to clean up children\n     * when this component is unmounted. It does not actually perform any\n     * backend operations.\n     *\n     * @internal\n     */\n    unmountChildren: function (safely) {\n      var renderedChildren = this._renderedChildren;\n      ReactChildReconciler.unmountChildren(renderedChildren, safely);\n      this._renderedChildren = null;\n    },\n\n    /**\n     * Moves a child component to the supplied index.\n     *\n     * @param {ReactComponent} child Component to move.\n     * @param {number} toIndex Destination index of the element.\n     * @param {number} lastIndex Last index visited of the siblings of `child`.\n     * @protected\n     */\n    moveChild: function (child, afterNode, toIndex, lastIndex) {\n      // If the index of `child` is less than `lastIndex`, then it needs to\n      // be moved. Otherwise, we do not need to move it because a child will be\n      // inserted or moved before `child`.\n      if (child._mountIndex < lastIndex) {\n        return makeMove(child, afterNode, toIndex);\n      }\n    },\n\n    /**\n     * Creates a child component.\n     *\n     * @param {ReactComponent} child Component to create.\n     * @param {string} mountImage Markup to insert.\n     * @protected\n     */\n    createChild: function (child, afterNode, mountImage) {\n      return makeInsertMarkup(mountImage, afterNode, child._mountIndex);\n    },\n\n    /**\n     * Removes a child component.\n     *\n     * @param {ReactComponent} child Child to remove.\n     * @protected\n     */\n    removeChild: function (child, node) {\n      return makeRemove(child, node);\n    },\n\n    /**\n     * Mounts a child with the supplied name.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to mount.\n     * @param {string} name Name of the child.\n     * @param {number} index Index at which to insert the child.\n     * @param {ReactReconcileTransaction} transaction\n     * @private\n     */\n    _mountChildAtIndex: function (child, afterNode, index, transaction, context) {\n      var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n      child._mountIndex = index;\n      return this.createChild(child, afterNode, mountImage);\n    },\n\n    /**\n     * Unmounts a rendered child.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to unmount.\n     * @private\n     */\n    _unmountChild: function (child, node) {\n      var update = this.removeChild(child, node);\n      child._mountIndex = null;\n      return update;\n    }\n\n  }\n\n};\n\nmodule.exports = ReactMultiChild;\n},{\"123\":123,\"139\":139,\"153\":153,\"161\":161,\"28\":28,\"33\":33,\"36\":36,\"73\":73,\"74\":74,\"79\":79,\"87\":87}],79:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChildUpdateTypes\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\n/**\n * When a component's children are updated, a series of update configuration\n * objects are created in order to batch and serialize the required changes.\n *\n * Enumerates all the possible types of update configurations.\n *\n * @internal\n */\nvar ReactMultiChildUpdateTypes = keyMirror({\n  INSERT_MARKUP: null,\n  MOVE_EXISTING: null,\n  REMOVE_NODE: null,\n  SET_MARKUP: null,\n  TEXT_CONTENT: null\n});\n\nmodule.exports = ReactMultiChildUpdateTypes;\n},{\"164\":164}],80:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNodeTypes\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\nvar ReactNodeTypes = {\n  HOST: 0,\n  COMPOSITE: 1,\n  EMPTY: 2,\n\n  getType: function (node) {\n    if (node === null || node === false) {\n      return ReactNodeTypes.EMPTY;\n    } else if (ReactElement.isValidElement(node)) {\n      if (typeof node.type === 'function') {\n        return ReactNodeTypes.COMPOSITE;\n      } else {\n        return ReactNodeTypes.HOST;\n      }\n    }\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unexpected node: %s', node) : _prodInvariant('26', node) : void 0;\n  }\n};\n\nmodule.exports = ReactNodeTypes;\n},{\"139\":139,\"161\":161,\"62\":62}],81:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNoopUpdateQueue\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the abstract API for an update queue.\n */\nvar ReactNoopUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    return false;\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback) {},\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    warnNoop(publicInstance, 'forceUpdate');\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    warnNoop(publicInstance, 'replaceState');\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    warnNoop(publicInstance, 'setState');\n  }\n};\n\nmodule.exports = ReactNoopUpdateQueue;\n},{\"171\":171}],82:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactOwner\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * ReactOwners are capable of storing references to owned components.\n *\n * All components are capable of //being// referenced by owner components, but\n * only ReactOwner components are capable of //referencing// owned components.\n * The named reference is known as a \"ref\".\n *\n * Refs are available when mounted and updated during reconciliation.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return (\n *         <div onClick={this.handleClick}>\n *           <CustomComponent ref=\"custom\" />\n *         </div>\n *       );\n *     },\n *     handleClick: function() {\n *       this.refs.custom.handleClick();\n *     },\n *     componentDidMount: function() {\n *       this.refs.custom.initialize();\n *     }\n *   });\n *\n * Refs should rarely be used. When refs are used, they should only be done to\n * control data that is not handled by React's data flow.\n *\n * @class ReactOwner\n */\nvar ReactOwner = {\n\n  /**\n   * @param {?object} object\n   * @return {boolean} True if `object` is a valid owner.\n   * @final\n   */\n  isValidOwner: function (object) {\n    return !!(object && typeof object.attachRef === 'function' && typeof object.detachRef === 'function');\n  },\n\n  /**\n   * Adds a component by ref to an owner component.\n   *\n   * @param {ReactComponent} component Component to reference.\n   * @param {string} ref Name by which to refer to the component.\n   * @param {ReactOwner} owner Component on which to record the ref.\n   * @final\n   * @internal\n   */\n  addComponentAsRefTo: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('119') : void 0;\n    owner.attachRef(ref, component);\n  },\n\n  /**\n   * Removes a component by ref from an owner component.\n   *\n   * @param {ReactComponent} component Component to dereference.\n   * @param {string} ref Name of the ref to remove.\n   * @param {ReactOwner} owner Component on which the ref is recorded.\n   * @final\n   * @internal\n   */\n  removeComponentAsRefFrom: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('120') : void 0;\n    var ownerPublicInstance = owner.getPublicInstance();\n    // Check that `component`'s owner is still alive and that `component` is still the current ref\n    // because we do not want to detach the ref if another component stole it.\n    if (ownerPublicInstance && ownerPublicInstance.refs[ref] === component.getPublicInstance()) {\n      owner.detachRef(ref);\n    }\n  }\n\n};\n\nmodule.exports = ReactOwner;\n},{\"139\":139,\"161\":161}],83:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocationNames\n */\n\n'use strict';\n\nvar ReactPropTypeLocationNames = {};\n\nif (\"development\" !== 'production') {\n  ReactPropTypeLocationNames = {\n    prop: 'prop',\n    context: 'context',\n    childContext: 'child context'\n  };\n}\n\nmodule.exports = ReactPropTypeLocationNames;\n},{}],84:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocations\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar ReactPropTypeLocations = keyMirror({\n  prop: null,\n  context: null,\n  childContext: null\n});\n\nmodule.exports = ReactPropTypeLocations;\n},{\"164\":164}],85:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypes\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar emptyFunction = _dereq_(153);\nvar getIteratorFn = _dereq_(130);\n\n/**\n * Collection of methods that allow declaration and validation of props that are\n * supplied to React components. Example usage:\n *\n *   var Props = require('ReactPropTypes');\n *   var MyArticle = React.createClass({\n *     propTypes: {\n *       // An optional string prop named \"description\".\n *       description: Props.string,\n *\n *       // A required enum prop named \"category\".\n *       category: Props.oneOf(['News','Photos']).isRequired,\n *\n *       // A prop named \"dialog\" that requires an instance of Dialog.\n *       dialog: Props.instanceOf(Dialog).isRequired\n *     },\n *     render: function() { ... }\n *   });\n *\n * A more formal specification of how these methods are used:\n *\n *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)\n *   decl := ReactPropTypes.{type}(.isRequired)?\n *\n * Each and every declaration produces a function with the same signature. This\n * allows the creation of custom validation functions. For example:\n *\n *  var MyLink = React.createClass({\n *    propTypes: {\n *      // An optional string or URI prop named \"href\".\n *      href: function(props, propName, componentName) {\n *        var propValue = props[propName];\n *        if (propValue != null && typeof propValue !== 'string' &&\n *            !(propValue instanceof URI)) {\n *          return new Error(\n *            'Expected a string or an URI for ' + propName + ' in ' +\n *            componentName\n *          );\n *        }\n *      }\n *    },\n *    render: function() {...}\n *  });\n *\n * @internal\n */\n\nvar ANONYMOUS = '<<anonymous>>';\n\nvar ReactPropTypes = {\n  array: createPrimitiveTypeChecker('array'),\n  bool: createPrimitiveTypeChecker('boolean'),\n  func: createPrimitiveTypeChecker('function'),\n  number: createPrimitiveTypeChecker('number'),\n  object: createPrimitiveTypeChecker('object'),\n  string: createPrimitiveTypeChecker('string'),\n  symbol: createPrimitiveTypeChecker('symbol'),\n\n  any: createAnyTypeChecker(),\n  arrayOf: createArrayOfTypeChecker,\n  element: createElementTypeChecker(),\n  instanceOf: createInstanceTypeChecker,\n  node: createNodeChecker(),\n  objectOf: createObjectOfTypeChecker,\n  oneOf: createEnumTypeChecker,\n  oneOfType: createUnionTypeChecker,\n  shape: createShapeTypeChecker\n};\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n/*eslint-disable no-self-compare*/\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n/*eslint-enable no-self-compare*/\n\nfunction createChainableTypeChecker(validate) {\n  function checkType(isRequired, props, propName, componentName, location, propFullName) {\n    componentName = componentName || ANONYMOUS;\n    propFullName = propFullName || propName;\n    if (props[propName] == null) {\n      var locationName = ReactPropTypeLocationNames[location];\n      if (isRequired) {\n        return new Error('Required ' + locationName + ' `' + propFullName + '` was not specified in ' + ('`' + componentName + '`.'));\n      }\n      return null;\n    } else {\n      return validate(props, propName, componentName, location, propFullName);\n    }\n  }\n\n  var chainedCheckType = checkType.bind(null, false);\n  chainedCheckType.isRequired = checkType.bind(null, true);\n\n  return chainedCheckType;\n}\n\nfunction createPrimitiveTypeChecker(expectedType) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== expectedType) {\n      var locationName = ReactPropTypeLocationNames[location];\n      // `propValue` being instance of, say, date/regexp, pass the 'object'\n      // check, but we can offer a more precise error message here rather than\n      // 'of type `object`'.\n      var preciseType = getPreciseType(propValue);\n\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createAnyTypeChecker() {\n  return createChainableTypeChecker(emptyFunction.thatReturns(null));\n}\n\nfunction createArrayOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');\n    }\n    var propValue = props[propName];\n    if (!Array.isArray(propValue)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var propType = getPropType(propValue);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));\n    }\n    for (var i = 0; i < propValue.length; i++) {\n      var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']');\n      if (error instanceof Error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createElementTypeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!ReactElement.isValidElement(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a single ReactElement.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createInstanceTypeChecker(expectedClass) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!(props[propName] instanceof expectedClass)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var expectedClassName = expectedClass.name || ANONYMOUS;\n      var actualClassName = getClassName(props[propName]);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createEnumTypeChecker(expectedValues) {\n  if (!Array.isArray(expectedValues)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOf, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    for (var i = 0; i < expectedValues.length; i++) {\n      if (is(propValue, expectedValues[i])) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    var valuesString = JSON.stringify(expectedValues);\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createObjectOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');\n    }\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));\n    }\n    for (var key in propValue) {\n      if (propValue.hasOwnProperty(key)) {\n        var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key);\n        if (error instanceof Error) {\n          return error;\n        }\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createUnionTypeChecker(arrayOfTypeCheckers) {\n  if (!Array.isArray(arrayOfTypeCheckers)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOfType, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n      var checker = arrayOfTypeCheckers[i];\n      if (checker(props, propName, componentName, location, propFullName) == null) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createNodeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!isNode(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createShapeTypeChecker(shapeTypes) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n    }\n    for (var key in shapeTypes) {\n      var checker = shapeTypes[key];\n      if (!checker) {\n        continue;\n      }\n      var error = checker(propValue, key, componentName, location, propFullName + '.' + key);\n      if (error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction isNode(propValue) {\n  switch (typeof propValue) {\n    case 'number':\n    case 'string':\n    case 'undefined':\n      return true;\n    case 'boolean':\n      return !propValue;\n    case 'object':\n      if (Array.isArray(propValue)) {\n        return propValue.every(isNode);\n      }\n      if (propValue === null || ReactElement.isValidElement(propValue)) {\n        return true;\n      }\n\n      var iteratorFn = getIteratorFn(propValue);\n      if (iteratorFn) {\n        var iterator = iteratorFn.call(propValue);\n        var step;\n        if (iteratorFn !== propValue.entries) {\n          while (!(step = iterator.next()).done) {\n            if (!isNode(step.value)) {\n              return false;\n            }\n          }\n        } else {\n          // Iterator will provide entry [k,v] tuples rather than values.\n          while (!(step = iterator.next()).done) {\n            var entry = step.value;\n            if (entry) {\n              if (!isNode(entry[1])) {\n                return false;\n              }\n            }\n          }\n        }\n      } else {\n        return false;\n      }\n\n      return true;\n    default:\n      return false;\n  }\n}\n\nfunction isSymbol(propType, propValue) {\n  // Native Symbol.\n  if (propType === 'symbol') {\n    return true;\n  }\n\n  // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'\n  if (propValue['@@toStringTag'] === 'Symbol') {\n    return true;\n  }\n\n  // Fallback for non-spec compliant Symbols which are polyfilled.\n  if (typeof Symbol === 'function' && propValue instanceof Symbol) {\n    return true;\n  }\n\n  return false;\n}\n\n// Equivalent of `typeof` but with special handling for array and regexp.\nfunction getPropType(propValue) {\n  var propType = typeof propValue;\n  if (Array.isArray(propValue)) {\n    return 'array';\n  }\n  if (propValue instanceof RegExp) {\n    // Old webkits (at least until Android 4.0) return 'function' rather than\n    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/\n    // passes PropTypes.object.\n    return 'object';\n  }\n  if (isSymbol(propType, propValue)) {\n    return 'symbol';\n  }\n  return propType;\n}\n\n// This handles more types than `getPropType`. Only used for error messages.\n// See `createPrimitiveTypeChecker`.\nfunction getPreciseType(propValue) {\n  var propType = getPropType(propValue);\n  if (propType === 'object') {\n    if (propValue instanceof Date) {\n      return 'date';\n    } else if (propValue instanceof RegExp) {\n      return 'regexp';\n    }\n  }\n  return propType;\n}\n\n// Returns class name of the object, if any.\nfunction getClassName(propValue) {\n  if (!propValue.constructor || !propValue.constructor.name) {\n    return ANONYMOUS;\n  }\n  return propValue.constructor.name;\n}\n\nmodule.exports = ReactPropTypes;\n},{\"130\":130,\"153\":153,\"62\":62,\"83\":83}],86:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconcileTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactInputSelection = _dereq_(72);\nvar ReactInstrumentation = _dereq_(74);\nvar Transaction = _dereq_(113);\nvar ReactUpdateQueue = _dereq_(94);\n\n/**\n * Ensures that, when possible, the selection range (currently selected text\n * input) is not disturbed by performing the transaction.\n */\nvar SELECTION_RESTORATION = {\n  /**\n   * @return {Selection} Selection information.\n   */\n  initialize: ReactInputSelection.getSelectionInformation,\n  /**\n   * @param {Selection} sel Selection information returned from `initialize`.\n   */\n  close: ReactInputSelection.restoreSelection\n};\n\n/**\n * Suppresses events (blur/focus) that could be inadvertently dispatched due to\n * high level DOM manipulations (like temporarily removing a text input from the\n * DOM).\n */\nvar EVENT_SUPPRESSION = {\n  /**\n   * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before\n   * the reconciliation.\n   */\n  initialize: function () {\n    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();\n    ReactBrowserEventEmitter.setEnabled(false);\n    return currentlyEnabled;\n  },\n\n  /**\n   * @param {boolean} previouslyEnabled Enabled status of\n   *   `ReactBrowserEventEmitter` before the reconciliation occurred. `close`\n   *   restores the previous value.\n   */\n  close: function (previouslyEnabled) {\n    ReactBrowserEventEmitter.setEnabled(previouslyEnabled);\n  }\n};\n\n/**\n * Provides a queue for collecting `componentDidMount` and\n * `componentDidUpdate` callbacks during the transaction.\n */\nvar ON_DOM_READY_QUEUEING = {\n  /**\n   * Initializes the internal `onDOMReady` queue.\n   */\n  initialize: function () {\n    this.reactMountReady.reset();\n  },\n\n  /**\n   * After DOM is flushed, invoke all registered `onDOMReady` callbacks.\n   */\n  close: function () {\n    this.reactMountReady.notifyAll();\n  }\n};\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\n/**\n * Currently:\n * - The order that these are listed in the transaction is critical:\n * - Suppresses events.\n * - Restores selection range.\n *\n * Future:\n * - Restore document/overflow scroll positions that were unintentionally\n *   modified via DOM insertions above the top viewport boundary.\n * - Implement/integrate with customized constraint based layout system and keep\n *   track of which dimensions must be remeasured.\n *\n * @class ReactReconcileTransaction\n */\nfunction ReactReconcileTransaction(useCreateElement) {\n  this.reinitializeTransaction();\n  // Only server-side rendering really needs this option (see\n  // `ReactServerRendering`), but server-side uses\n  // `ReactServerRenderingTransaction` instead. This option is here so that it's\n  // accessible and defaults to false when `ReactDOMComponent` and\n  // `ReactDOMTextComponent` checks it in `mountComponent`.`\n  this.renderToStaticMarkup = false;\n  this.reactMountReady = CallbackQueue.getPooled(null);\n  this.useCreateElement = useCreateElement;\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array<object>} List of operation wrap procedures.\n   *   TODO: convert to array<TransactionWrapper>\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return this.reactMountReady;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return ReactUpdateQueue;\n  },\n\n  /**\n   * Save current transaction state -- if the return value from this method is\n   * passed to `rollback`, the transaction will be reset to that state.\n   */\n  checkpoint: function () {\n    // reactMountReady is the our only stateful wrapper\n    return this.reactMountReady.checkpoint();\n  },\n\n  rollback: function (checkpoint) {\n    this.reactMountReady.rollback(checkpoint);\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {\n    CallbackQueue.release(this.reactMountReady);\n    this.reactMountReady = null;\n  }\n};\n\n_assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactReconcileTransaction);\n\nmodule.exports = ReactReconcileTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"27\":27,\"5\":5,\"72\":72,\"74\":74,\"94\":94}],87:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconciler\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactRef = _dereq_(88);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\n\n/**\n * Helper to call ReactRef.attachRefs with this composite component, split out\n * to avoid allocations in the transaction mount-ready queue.\n */\nfunction attachRefs() {\n  ReactRef.attachRefs(this, this._currentElement);\n}\n\nvar ReactReconciler = {\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} the containing host component instance\n   * @param {?object} info about the host container\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (internalInstance, transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeMountComponent(internalInstance._debugID, internalInstance._currentElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'mountComponent');\n      }\n    }\n    var markup = internalInstance.mountComponent(transaction, hostParent, hostContainerInfo, context);\n    if (internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'mountComponent');\n        ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID);\n      }\n    }\n    return markup;\n  },\n\n  /**\n   * Returns a value that can be passed to\n   * ReactComponentEnvironment.replaceNodeWithMarkup.\n   */\n  getHostNode: function (internalInstance) {\n    return internalInstance.getHostNode();\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (internalInstance, safely) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n      }\n    }\n    ReactRef.detachRefs(internalInstance, internalInstance._currentElement);\n    internalInstance.unmountComponent(safely);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n        ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Update a component using a new element.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @internal\n   */\n  receiveComponent: function (internalInstance, nextElement, transaction, context) {\n    var prevElement = internalInstance._currentElement;\n\n    if (nextElement === prevElement && context === internalInstance._context) {\n      // Since elements are immutable after the owner is rendered,\n      // we can do a cheap identity compare here to determine if this is a\n      // superfluous reconcile. It's possible for state to be mutable but such\n      // change should trigger an update of the owner which would recreate\n      // the element. We explicitly check for the existence of an owner since\n      // it's possible for an element created outside a composite to be\n      // deeply mutated and reused.\n\n      // TODO: Bailing out early is just a perf optimization right?\n      // TODO: Removing the return statement should affect correctness?\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, nextElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n      }\n    }\n\n    var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);\n\n    if (refsChanged) {\n      ReactRef.detachRefs(internalInstance, prevElement);\n    }\n\n    internalInstance.receiveComponent(nextElement, transaction, context);\n\n    if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Flush any dirty changes in a component.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (internalInstance, transaction, updateBatchNumber) {\n    if (internalInstance._updateBatchNumber !== updateBatchNumber) {\n      // The component's enqueued batch number should always be the current\n      // batch or the following one.\n      !(internalInstance._updateBatchNumber == null || internalInstance._updateBatchNumber === updateBatchNumber + 1) ? \"development\" !== 'production' ? invariant(false, 'performUpdateIfNecessary: Unexpected batch number (current %s, pending %s)', updateBatchNumber, internalInstance._updateBatchNumber) : _prodInvariant('121', updateBatchNumber, internalInstance._updateBatchNumber) : void 0;\n      return;\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, internalInstance._currentElement);\n      }\n    }\n    internalInstance.performUpdateIfNecessary(transaction);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactReconciler;\n},{\"139\":139,\"161\":161,\"74\":74,\"88\":88}],88:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactRef\n */\n\n'use strict';\n\nvar ReactOwner = _dereq_(82);\n\nvar ReactRef = {};\n\nfunction attachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(component.getPublicInstance());\n  } else {\n    // Legacy ref\n    ReactOwner.addComponentAsRefTo(component, ref, owner);\n  }\n}\n\nfunction detachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(null);\n  } else {\n    // Legacy ref\n    ReactOwner.removeComponentAsRefFrom(component, ref, owner);\n  }\n}\n\nReactRef.attachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    attachRef(ref, instance, element._owner);\n  }\n};\n\nReactRef.shouldUpdateRefs = function (prevElement, nextElement) {\n  // If either the owner or a `ref` has changed, make sure the newest owner\n  // has stored a reference to `this`, and the previous owner (if different)\n  // has forgotten the reference to `this`. We use the element instead\n  // of the public this.props because the post processing cannot determine\n  // a ref. The ref conceptually lives on the element.\n\n  // TODO: Should this even be possible? The owner cannot change because\n  // it's forbidden by shouldUpdateReactComponent. The ref can change\n  // if you swap the keys of but not the refs. Reconsider where this check\n  // is made. It probably belongs where the key checking and\n  // instantiateReactComponent is done.\n\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n\n  return(\n    // This has a few false positives w/r/t empty components.\n    prevEmpty || nextEmpty || nextElement._owner !== prevElement._owner || nextElement.ref !== prevElement.ref\n  );\n};\n\nReactRef.detachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    detachRef(ref, instance, element._owner);\n  }\n};\n\nmodule.exports = ReactRef;\n},{\"82\":82}],89:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerBatchingStrategy\n */\n\n'use strict';\n\nvar ReactServerBatchingStrategy = {\n  isBatchingUpdates: false,\n  batchedUpdates: function (callback) {\n    // Don't do anything here. During the server rendering we don't want to\n    // schedule any updates. We will simply ignore them.\n  }\n};\n\nmodule.exports = ReactServerBatchingStrategy;\n},{}],90:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRendering\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactElement = _dereq_(62);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactServerBatchingStrategy = _dereq_(89);\nvar ReactServerRenderingTransaction = _dereq_(91);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\n\n/**\n * @param {ReactElement} element\n * @return {string} the HTML markup\n */\nfunction renderToStringImpl(element, makeStaticMarkup) {\n  var transaction;\n  try {\n    ReactUpdates.injection.injectBatchingStrategy(ReactServerBatchingStrategy);\n\n    transaction = ReactServerRenderingTransaction.getPooled(makeStaticMarkup);\n\n    return transaction.perform(function () {\n      var componentInstance = instantiateReactComponent(element, true);\n      var markup = ReactReconciler.mountComponent(componentInstance, transaction, null, ReactDOMContainerInfo(), emptyObject);\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onUnmountComponent(componentInstance._debugID);\n      }\n      if (!makeStaticMarkup) {\n        markup = ReactMarkupChecksum.addChecksumToMarkup(markup);\n      }\n      return markup;\n    }, null);\n  } finally {\n    ReactServerRenderingTransaction.release(transaction);\n    // Revert to the DOM batching strategy since these two renderers\n    // currently share these stateful modules.\n    ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n  }\n}\n\n/**\n * Render a ReactElement to its initial HTML. This should only be used on the\n * server.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostring\n */\nfunction renderToString(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToString(): You must pass a valid ReactElement.') : _prodInvariant('46') : void 0;\n  return renderToStringImpl(element, false);\n}\n\n/**\n * Similar to renderToString, except this doesn't create extra DOM attributes\n * such as data-react-id that React uses internally.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostaticmarkup\n */\nfunction renderToStaticMarkup(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToStaticMarkup(): You must pass a valid ReactElement.') : _prodInvariant('47') : void 0;\n  return renderToStringImpl(element, true);\n}\n\nmodule.exports = {\n  renderToString: renderToString,\n  renderToStaticMarkup: renderToStaticMarkup\n};\n},{\"134\":134,\"139\":139,\"154\":154,\"161\":161,\"42\":42,\"60\":60,\"62\":62,\"74\":74,\"76\":76,\"87\":87,\"89\":89,\"91\":91,\"95\":95}],91:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRenderingTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\nvar Transaction = _dereq_(113);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactServerUpdateQueue = _dereq_(92);\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\nvar noopCallbackQueue = {\n  enqueue: function () {}\n};\n\n/**\n * @class ReactServerRenderingTransaction\n * @param {boolean} renderToStaticMarkup\n */\nfunction ReactServerRenderingTransaction(renderToStaticMarkup) {\n  this.reinitializeTransaction();\n  this.renderToStaticMarkup = renderToStaticMarkup;\n  this.useCreateElement = false;\n  this.updateQueue = new ReactServerUpdateQueue(this);\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array} Empty list of operation wrap procedures.\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return noopCallbackQueue;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return this.updateQueue;\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {},\n\n  checkpoint: function () {},\n\n  rollback: function () {}\n};\n\n_assign(ReactServerRenderingTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactServerRenderingTransaction);\n\nmodule.exports = ReactServerRenderingTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"74\":74,\"92\":92}],92:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerUpdateQueue\n * \n */\n\n'use strict';\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar ReactUpdateQueue = _dereq_(94);\nvar Transaction = _dereq_(113);\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounting component. ' + 'This usually means you called %s() outside componentWillMount() on the server. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the update queue used for server rendering.\n * It delegates to ReactUpdateQueue while server rendering is in progress and\n * switches to ReactNoopUpdateQueue after the transaction has completed.\n * @class ReactServerUpdateQueue\n * @param {Transaction} transaction\n */\n\nvar ReactServerUpdateQueue = function () {\n  /* :: transaction: Transaction; */\n\n  function ReactServerUpdateQueue(transaction) {\n    _classCallCheck(this, ReactServerUpdateQueue);\n\n    this.transaction = transaction;\n  }\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n\n\n  ReactServerUpdateQueue.prototype.isMounted = function isMounted(publicInstance) {\n    return false;\n  };\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueCallback = function enqueueCallback(publicInstance, callback, callerName) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueCallback(publicInstance, callback, callerName);\n    }\n  };\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueForceUpdate = function enqueueForceUpdate(publicInstance) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueForceUpdate(publicInstance);\n    } else {\n      warnNoop(publicInstance, 'forceUpdate');\n    }\n  };\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} completeState Next state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueReplaceState = function enqueueReplaceState(publicInstance, completeState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueReplaceState(publicInstance, completeState);\n    } else {\n      warnNoop(publicInstance, 'replaceState');\n    }\n  };\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} partialState Next partial state to be merged with state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueSetState = function enqueueSetState(publicInstance, partialState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueSetState(publicInstance, partialState);\n    } else {\n      warnNoop(publicInstance, 'setState');\n    }\n  };\n\n  return ReactServerUpdateQueue;\n}();\n\nmodule.exports = ReactServerUpdateQueue;\n},{\"113\":113,\"171\":171,\"94\":94}],93:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUMDEntry\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactDOM = _dereq_(37);\nvar ReactDOMServer = _dereq_(54);\nvar React = _dereq_(26);\n\n// `version` will be added here by ReactIsomorphic.\nvar ReactUMDEntry = _assign({\n  __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOM,\n  __SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOMServer\n}, React);\n\nmodule.exports = ReactUMDEntry;\n},{\"172\":172,\"26\":26,\"37\":37,\"54\":54}],94:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdateQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nfunction enqueueUpdate(internalInstance) {\n  ReactUpdates.enqueueUpdate(internalInstance);\n}\n\nfunction formatUnexpectedArgument(arg) {\n  var type = typeof arg;\n  if (type !== 'object') {\n    return type;\n  }\n  var displayName = arg.constructor && arg.constructor.name || type;\n  var keys = Object.keys(arg);\n  if (keys.length > 0 && keys.length < 20) {\n    return displayName + ' (keys: ' + keys.join(', ') + ')';\n  }\n  return displayName;\n}\n\nfunction getInternalInstanceReadyForUpdate(publicInstance, callerName) {\n  var internalInstance = ReactInstanceMap.get(publicInstance);\n  if (!internalInstance) {\n    if (\"development\" !== 'production') {\n      // Only warn when we have a callerName. Otherwise we should be silent.\n      // We're probably calling from enqueueCallback. We don't want to warn\n      // there because we already warned for the corresponding lifecycle method.\n      \"development\" !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor.displayName) : void 0;\n    }\n    return null;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition (such as ' + 'within `render` or another component\\'s constructor). Render methods ' + 'should be a pure function of props and state; constructor ' + 'side-effects are an anti-pattern, but can be moved to ' + '`componentWillMount`.', callerName) : void 0;\n  }\n\n  return internalInstance;\n}\n\n/**\n * ReactUpdateQueue allows for state updates to be scheduled into a later\n * reconciliation step.\n */\nvar ReactUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    if (\"development\" !== 'production') {\n      var owner = ReactCurrentOwner.current;\n      if (owner !== null) {\n        \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n        owner._warnedAboutRefsInRender = true;\n      }\n    }\n    var internalInstance = ReactInstanceMap.get(publicInstance);\n    if (internalInstance) {\n      // During componentWillMount and render this will still be null but after\n      // that will always render to something. At least for now. So we can use\n      // this hack.\n      return !!internalInstance._renderedComponent;\n    } else {\n      return false;\n    }\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @param {string} callerName Name of the calling function in the public API.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback, callerName) {\n    ReactUpdateQueue.validateCallback(callback, callerName);\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);\n\n    // Previously we would throw an error if we didn't have an internal\n    // instance. Since we want to make it a no-op instead, we mirror the same\n    // behavior we have in other enqueue* methods.\n    // We also need to ignore callbacks in componentWillMount. See\n    // enqueueUpdates.\n    if (!internalInstance) {\n      return null;\n    }\n\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    // TODO: The callback here is ignored when setState is called from\n    // componentWillMount. Either fix it or disallow doing so completely in\n    // favor of getInitialState. Alternatively, we can disallow\n    // componentWillMount during server-side rendering.\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueCallbackInternal: function (internalInstance, callback) {\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'forceUpdate');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingForceUpdate = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingStateQueue = [completeState];\n    internalInstance._pendingReplaceState = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetState();\n      \"development\" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;\n    }\n\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);\n    queue.push(partialState);\n\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueElementInternal: function (internalInstance, nextElement, nextContext) {\n    internalInstance._pendingElement = nextElement;\n    // TODO: introduce _pendingContext instead of setting it directly.\n    internalInstance._context = nextContext;\n    enqueueUpdate(internalInstance);\n  },\n\n  validateCallback: function (callback, callerName) {\n    !(!callback || typeof callback === 'function') ? \"development\" !== 'production' ? invariant(false, '%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.', callerName, formatUnexpectedArgument(callback)) : _prodInvariant('122', callerName, formatUnexpectedArgument(callback)) : void 0;\n  }\n\n};\n\nmodule.exports = ReactUpdateQueue;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"73\":73,\"74\":74,\"95\":95}],95:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdates\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactReconciler = _dereq_(87);\nvar Transaction = _dereq_(113);\n\nvar invariant = _dereq_(161);\n\nvar dirtyComponents = [];\nvar updateBatchNumber = 0;\nvar asapCallbackQueue = CallbackQueue.getPooled();\nvar asapEnqueued = false;\n\nvar batchingStrategy = null;\n\nfunction ensureInjected() {\n  !(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching strategy') : _prodInvariant('123') : void 0;\n}\n\nvar NESTED_UPDATES = {\n  initialize: function () {\n    this.dirtyComponentsLength = dirtyComponents.length;\n  },\n  close: function () {\n    if (this.dirtyComponentsLength !== dirtyComponents.length) {\n      // Additional updates were enqueued by componentDidUpdate handlers or\n      // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run\n      // these new updates so that if A's componentDidUpdate calls setState on\n      // B, B will update before the callback A's updater provided when calling\n      // setState.\n      dirtyComponents.splice(0, this.dirtyComponentsLength);\n      flushBatchedUpdates();\n    } else {\n      dirtyComponents.length = 0;\n    }\n  }\n};\n\nvar UPDATE_QUEUEING = {\n  initialize: function () {\n    this.callbackQueue.reset();\n  },\n  close: function () {\n    this.callbackQueue.notifyAll();\n  }\n};\n\nvar TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];\n\nfunction ReactUpdatesFlushTransaction() {\n  this.reinitializeTransaction();\n  this.dirtyComponentsLength = null;\n  this.callbackQueue = CallbackQueue.getPooled();\n  this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */true);\n}\n\n_assign(ReactUpdatesFlushTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  destructor: function () {\n    this.dirtyComponentsLength = null;\n    CallbackQueue.release(this.callbackQueue);\n    this.callbackQueue = null;\n    ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);\n    this.reconcileTransaction = null;\n  },\n\n  perform: function (method, scope, a) {\n    // Essentially calls `this.reconcileTransaction.perform(method, scope, a)`\n    // with this transaction's wrappers around it.\n    return Transaction.Mixin.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a);\n  }\n});\n\nPooledClass.addPoolingTo(ReactUpdatesFlushTransaction);\n\nfunction batchedUpdates(callback, a, b, c, d, e) {\n  ensureInjected();\n  batchingStrategy.batchedUpdates(callback, a, b, c, d, e);\n}\n\n/**\n * Array comparator for ReactComponents by mount ordering.\n *\n * @param {ReactComponent} c1 first component you're comparing\n * @param {ReactComponent} c2 second component you're comparing\n * @return {number} Return value usable by Array.prototype.sort().\n */\nfunction mountOrderComparator(c1, c2) {\n  return c1._mountOrder - c2._mountOrder;\n}\n\nfunction runBatchedUpdates(transaction) {\n  var len = transaction.dirtyComponentsLength;\n  !(len === dirtyComponents.length) ? \"development\" !== 'production' ? invariant(false, 'Expected flush transaction\\'s stored dirty-components length (%s) to match dirty-components array length (%s).', len, dirtyComponents.length) : _prodInvariant('124', len, dirtyComponents.length) : void 0;\n\n  // Since reconciling a component higher in the owner hierarchy usually (not\n  // always -- see shouldComponentUpdate()) will reconcile children, reconcile\n  // them before their children by sorting the array.\n  dirtyComponents.sort(mountOrderComparator);\n\n  // Any updates enqueued while reconciling must be performed after this entire\n  // batch. Otherwise, if dirtyComponents is [A, B] where A has children B and\n  // C, B could update twice in a single batch if C's render enqueues an update\n  // to B (since B would have already updated, we should skip it, and the only\n  // way we can know to do so is by checking the batch counter).\n  updateBatchNumber++;\n\n  for (var i = 0; i < len; i++) {\n    // If a component is unmounted before pending changes apply, it will still\n    // be here, but we assume that it has cleared its _pendingCallbacks and\n    // that performUpdateIfNecessary is a noop.\n    var component = dirtyComponents[i];\n\n    // If performUpdateIfNecessary happens to enqueue any new updates, we\n    // shouldn't execute the callbacks until the next render happens, so\n    // stash the callbacks first\n    var callbacks = component._pendingCallbacks;\n    component._pendingCallbacks = null;\n\n    var markerName;\n    if (ReactFeatureFlags.logTopLevelRenders) {\n      var namedComponent = component;\n      // Duck type TopLevelWrapper. This is probably always true.\n      if (component._currentElement.props === component._renderedComponent._currentElement) {\n        namedComponent = component._renderedComponent;\n      }\n      markerName = 'React update: ' + namedComponent.getName();\n      console.time(markerName);\n    }\n\n    ReactReconciler.performUpdateIfNecessary(component, transaction.reconcileTransaction, updateBatchNumber);\n\n    if (markerName) {\n      console.timeEnd(markerName);\n    }\n\n    if (callbacks) {\n      for (var j = 0; j < callbacks.length; j++) {\n        transaction.callbackQueue.enqueue(callbacks[j], component.getPublicInstance());\n      }\n    }\n  }\n}\n\nvar flushBatchedUpdates = function () {\n  // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents\n  // array and perform any updates enqueued by mount-ready handlers (i.e.,\n  // componentDidUpdate) but we need to check here too in order to catch\n  // updates enqueued by setState callbacks and asap calls.\n  while (dirtyComponents.length || asapEnqueued) {\n    if (dirtyComponents.length) {\n      var transaction = ReactUpdatesFlushTransaction.getPooled();\n      transaction.perform(runBatchedUpdates, null, transaction);\n      ReactUpdatesFlushTransaction.release(transaction);\n    }\n\n    if (asapEnqueued) {\n      asapEnqueued = false;\n      var queue = asapCallbackQueue;\n      asapCallbackQueue = CallbackQueue.getPooled();\n      queue.notifyAll();\n      CallbackQueue.release(queue);\n    }\n  }\n};\n\n/**\n * Mark a component as needing a rerender, adding an optional callback to a\n * list of functions which will be executed once the rerender occurs.\n */\nfunction enqueueUpdate(component) {\n  ensureInjected();\n\n  // Various parts of our code (such as ReactCompositeComponent's\n  // _renderValidatedComponent) assume that calls to render aren't nested;\n  // verify that that's the case. (This is called by each top-level update\n  // function, like setState, forceUpdate, etc.; creation and\n  // destruction of top-level components is guarded in ReactMount.)\n\n  if (!batchingStrategy.isBatchingUpdates) {\n    batchingStrategy.batchedUpdates(enqueueUpdate, component);\n    return;\n  }\n\n  dirtyComponents.push(component);\n  if (component._updateBatchNumber == null) {\n    component._updateBatchNumber = updateBatchNumber + 1;\n  }\n}\n\n/**\n * Enqueue a callback to be run at the end of the current batching cycle. Throws\n * if no updates are currently being performed.\n */\nfunction asap(callback, context) {\n  !batchingStrategy.isBatchingUpdates ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates.asap: Can\\'t enqueue an asap callback in a context whereupdates are not being batched.') : _prodInvariant('125') : void 0;\n  asapCallbackQueue.enqueue(callback, context);\n  asapEnqueued = true;\n}\n\nvar ReactUpdatesInjection = {\n  injectReconcileTransaction: function (ReconcileTransaction) {\n    !ReconcileTransaction ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : _prodInvariant('126') : void 0;\n    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;\n  },\n\n  injectBatchingStrategy: function (_batchingStrategy) {\n    !_batchingStrategy ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : _prodInvariant('127') : void 0;\n    !(typeof _batchingStrategy.batchedUpdates === 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : _prodInvariant('128') : void 0;\n    !(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : _prodInvariant('129') : void 0;\n    batchingStrategy = _batchingStrategy;\n  }\n};\n\nvar ReactUpdates = {\n  /**\n   * React references `ReactReconcileTransaction` using this property in order\n   * to allow dependency injection.\n   *\n   * @internal\n   */\n  ReactReconcileTransaction: null,\n\n  batchedUpdates: batchedUpdates,\n  enqueueUpdate: enqueueUpdate,\n  flushBatchedUpdates: flushBatchedUpdates,\n  injection: ReactUpdatesInjection,\n  asap: asap\n};\n\nmodule.exports = ReactUpdates;\n},{\"113\":113,\"139\":139,\"161\":161,\"172\":172,\"25\":25,\"5\":5,\"68\":68,\"87\":87}],96:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactVersion\n */\n\n'use strict';\n\nmodule.exports = '15.2.1';\n},{}],97:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SVGDOMPropertyConfig\n */\n\n'use strict';\n\nvar NS = {\n  xlink: 'http://www.w3.org/1999/xlink',\n  xml: 'http://www.w3.org/XML/1998/namespace'\n};\n\n// We use attributes for everything SVG so let's avoid some duplication and run\n// code instead.\n// The following are all specified in the HTML config already so we exclude here.\n// - class (as className)\n// - color\n// - height\n// - id\n// - lang\n// - max\n// - media\n// - method\n// - min\n// - name\n// - style\n// - target\n// - type\n// - width\nvar ATTRS = {\n  accentHeight: 'accent-height',\n  accumulate: 0,\n  additive: 0,\n  alignmentBaseline: 'alignment-baseline',\n  allowReorder: 'allowReorder',\n  alphabetic: 0,\n  amplitude: 0,\n  arabicForm: 'arabic-form',\n  ascent: 0,\n  attributeName: 'attributeName',\n  attributeType: 'attributeType',\n  autoReverse: 'autoReverse',\n  azimuth: 0,\n  baseFrequency: 'baseFrequency',\n  baseProfile: 'baseProfile',\n  baselineShift: 'baseline-shift',\n  bbox: 0,\n  begin: 0,\n  bias: 0,\n  by: 0,\n  calcMode: 'calcMode',\n  capHeight: 'cap-height',\n  clip: 0,\n  clipPath: 'clip-path',\n  clipRule: 'clip-rule',\n  clipPathUnits: 'clipPathUnits',\n  colorInterpolation: 'color-interpolation',\n  colorInterpolationFilters: 'color-interpolation-filters',\n  colorProfile: 'color-profile',\n  colorRendering: 'color-rendering',\n  contentScriptType: 'contentScriptType',\n  contentStyleType: 'contentStyleType',\n  cursor: 0,\n  cx: 0,\n  cy: 0,\n  d: 0,\n  decelerate: 0,\n  descent: 0,\n  diffuseConstant: 'diffuseConstant',\n  direction: 0,\n  display: 0,\n  divisor: 0,\n  dominantBaseline: 'dominant-baseline',\n  dur: 0,\n  dx: 0,\n  dy: 0,\n  edgeMode: 'edgeMode',\n  elevation: 0,\n  enableBackground: 'enable-background',\n  end: 0,\n  exponent: 0,\n  externalResourcesRequired: 'externalResourcesRequired',\n  fill: 0,\n  fillOpacity: 'fill-opacity',\n  fillRule: 'fill-rule',\n  filter: 0,\n  filterRes: 'filterRes',\n  filterUnits: 'filterUnits',\n  floodColor: 'flood-color',\n  floodOpacity: 'flood-opacity',\n  focusable: 0,\n  fontFamily: 'font-family',\n  fontSize: 'font-size',\n  fontSizeAdjust: 'font-size-adjust',\n  fontStretch: 'font-stretch',\n  fontStyle: 'font-style',\n  fontVariant: 'font-variant',\n  fontWeight: 'font-weight',\n  format: 0,\n  from: 0,\n  fx: 0,\n  fy: 0,\n  g1: 0,\n  g2: 0,\n  glyphName: 'glyph-name',\n  glyphOrientationHorizontal: 'glyph-orientation-horizontal',\n  glyphOrientationVertical: 'glyph-orientation-vertical',\n  glyphRef: 'glyphRef',\n  gradientTransform: 'gradientTransform',\n  gradientUnits: 'gradientUnits',\n  hanging: 0,\n  horizAdvX: 'horiz-adv-x',\n  horizOriginX: 'horiz-origin-x',\n  ideographic: 0,\n  imageRendering: 'image-rendering',\n  'in': 0,\n  in2: 0,\n  intercept: 0,\n  k: 0,\n  k1: 0,\n  k2: 0,\n  k3: 0,\n  k4: 0,\n  kernelMatrix: 'kernelMatrix',\n  kernelUnitLength: 'kernelUnitLength',\n  kerning: 0,\n  keyPoints: 'keyPoints',\n  keySplines: 'keySplines',\n  keyTimes: 'keyTimes',\n  lengthAdjust: 'lengthAdjust',\n  letterSpacing: 'letter-spacing',\n  lightingColor: 'lighting-color',\n  limitingConeAngle: 'limitingConeAngle',\n  local: 0,\n  markerEnd: 'marker-end',\n  markerMid: 'marker-mid',\n  markerStart: 'marker-start',\n  markerHeight: 'markerHeight',\n  markerUnits: 'markerUnits',\n  markerWidth: 'markerWidth',\n  mask: 0,\n  maskContentUnits: 'maskContentUnits',\n  maskUnits: 'maskUnits',\n  mathematical: 0,\n  mode: 0,\n  numOctaves: 'numOctaves',\n  offset: 0,\n  opacity: 0,\n  operator: 0,\n  order: 0,\n  orient: 0,\n  orientation: 0,\n  origin: 0,\n  overflow: 0,\n  overlinePosition: 'overline-position',\n  overlineThickness: 'overline-thickness',\n  paintOrder: 'paint-order',\n  panose1: 'panose-1',\n  pathLength: 'pathLength',\n  patternContentUnits: 'patternContentUnits',\n  patternTransform: 'patternTransform',\n  patternUnits: 'patternUnits',\n  pointerEvents: 'pointer-events',\n  points: 0,\n  pointsAtX: 'pointsAtX',\n  pointsAtY: 'pointsAtY',\n  pointsAtZ: 'pointsAtZ',\n  preserveAlpha: 'preserveAlpha',\n  preserveAspectRatio: 'preserveAspectRatio',\n  primitiveUnits: 'primitiveUnits',\n  r: 0,\n  radius: 0,\n  refX: 'refX',\n  refY: 'refY',\n  renderingIntent: 'rendering-intent',\n  repeatCount: 'repeatCount',\n  repeatDur: 'repeatDur',\n  requiredExtensions: 'requiredExtensions',\n  requiredFeatures: 'requiredFeatures',\n  restart: 0,\n  result: 0,\n  rotate: 0,\n  rx: 0,\n  ry: 0,\n  scale: 0,\n  seed: 0,\n  shapeRendering: 'shape-rendering',\n  slope: 0,\n  spacing: 0,\n  specularConstant: 'specularConstant',\n  specularExponent: 'specularExponent',\n  speed: 0,\n  spreadMethod: 'spreadMethod',\n  startOffset: 'startOffset',\n  stdDeviation: 'stdDeviation',\n  stemh: 0,\n  stemv: 0,\n  stitchTiles: 'stitchTiles',\n  stopColor: 'stop-color',\n  stopOpacity: 'stop-opacity',\n  strikethroughPosition: 'strikethrough-position',\n  strikethroughThickness: 'strikethrough-thickness',\n  string: 0,\n  stroke: 0,\n  strokeDasharray: 'stroke-dasharray',\n  strokeDashoffset: 'stroke-dashoffset',\n  strokeLinecap: 'stroke-linecap',\n  strokeLinejoin: 'stroke-linejoin',\n  strokeMiterlimit: 'stroke-miterlimit',\n  strokeOpacity: 'stroke-opacity',\n  strokeWidth: 'stroke-width',\n  surfaceScale: 'surfaceScale',\n  systemLanguage: 'systemLanguage',\n  tableValues: 'tableValues',\n  targetX: 'targetX',\n  targetY: 'targetY',\n  textAnchor: 'text-anchor',\n  textDecoration: 'text-decoration',\n  textRendering: 'text-rendering',\n  textLength: 'textLength',\n  to: 0,\n  transform: 0,\n  u1: 0,\n  u2: 0,\n  underlinePosition: 'underline-position',\n  underlineThickness: 'underline-thickness',\n  unicode: 0,\n  unicodeBidi: 'unicode-bidi',\n  unicodeRange: 'unicode-range',\n  unitsPerEm: 'units-per-em',\n  vAlphabetic: 'v-alphabetic',\n  vHanging: 'v-hanging',\n  vIdeographic: 'v-ideographic',\n  vMathematical: 'v-mathematical',\n  values: 0,\n  vectorEffect: 'vector-effect',\n  version: 0,\n  vertAdvY: 'vert-adv-y',\n  vertOriginX: 'vert-origin-x',\n  vertOriginY: 'vert-origin-y',\n  viewBox: 'viewBox',\n  viewTarget: 'viewTarget',\n  visibility: 0,\n  widths: 0,\n  wordSpacing: 'word-spacing',\n  writingMode: 'writing-mode',\n  x: 0,\n  xHeight: 'x-height',\n  x1: 0,\n  x2: 0,\n  xChannelSelector: 'xChannelSelector',\n  xlinkActuate: 'xlink:actuate',\n  xlinkArcrole: 'xlink:arcrole',\n  xlinkHref: 'xlink:href',\n  xlinkRole: 'xlink:role',\n  xlinkShow: 'xlink:show',\n  xlinkTitle: 'xlink:title',\n  xlinkType: 'xlink:type',\n  xmlBase: 'xml:base',\n  xmlLang: 'xml:lang',\n  xmlSpace: 'xml:space',\n  y: 0,\n  y1: 0,\n  y2: 0,\n  yChannelSelector: 'yChannelSelector',\n  z: 0,\n  zoomAndPan: 'zoomAndPan'\n};\n\nvar SVGDOMPropertyConfig = {\n  Properties: {},\n  DOMAttributeNamespaces: {\n    xlinkActuate: NS.xlink,\n    xlinkArcrole: NS.xlink,\n    xlinkHref: NS.xlink,\n    xlinkRole: NS.xlink,\n    xlinkShow: NS.xlink,\n    xlinkTitle: NS.xlink,\n    xlinkType: NS.xlink,\n    xmlBase: NS.xml,\n    xmlLang: NS.xml,\n    xmlSpace: NS.xml\n  },\n  DOMAttributeNames: {}\n};\n\nObject.keys(ATTRS).forEach(function (key) {\n  SVGDOMPropertyConfig.Properties[key] = 0;\n  if (ATTRS[key]) {\n    SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key];\n  }\n});\n\nmodule.exports = SVGDOMPropertyConfig;\n},{}],98:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SelectEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInputSelection = _dereq_(72);\nvar SyntheticEvent = _dereq_(104);\n\nvar getActiveElement = _dereq_(156);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11;\n\nvar eventTypes = {\n  select: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSelect: null }),\n      captured: keyOf({ onSelectCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange]\n  }\n};\n\nvar activeElement = null;\nvar activeElementInst = null;\nvar lastSelection = null;\nvar mouseDown = false;\n\n// Track whether a listener exists for this plugin. If none exist, we do\n// not extract events. See #3639.\nvar hasListener = false;\nvar ON_SELECT_KEY = keyOf({ onSelect: null });\n\n/**\n * Get an object which is a unique representation of the current selection.\n *\n * The return value will not be consistent across nodes or browsers, but\n * two identical selections on the same node will return identical objects.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getSelection(node) {\n  if ('selectionStart' in node && ReactInputSelection.hasSelectionCapabilities(node)) {\n    return {\n      start: node.selectionStart,\n      end: node.selectionEnd\n    };\n  } else if (window.getSelection) {\n    var selection = window.getSelection();\n    return {\n      anchorNode: selection.anchorNode,\n      anchorOffset: selection.anchorOffset,\n      focusNode: selection.focusNode,\n      focusOffset: selection.focusOffset\n    };\n  } else if (document.selection) {\n    var range = document.selection.createRange();\n    return {\n      parentElement: range.parentElement(),\n      text: range.text,\n      top: range.boundingTop,\n      left: range.boundingLeft\n    };\n  }\n}\n\n/**\n * Poll selection to see whether it's changed.\n *\n * @param {object} nativeEvent\n * @return {?SyntheticEvent}\n */\nfunction constructSelectEvent(nativeEvent, nativeEventTarget) {\n  // Ensure we have the right element, and that the user is not dragging a\n  // selection (this matches native `select` event behavior). In HTML5, select\n  // fires only on input and textarea thus if there's no focused element we\n  // won't dispatch.\n  if (mouseDown || activeElement == null || activeElement !== getActiveElement()) {\n    return null;\n  }\n\n  // Only fire when selection has actually changed.\n  var currentSelection = getSelection(activeElement);\n  if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {\n    lastSelection = currentSelection;\n\n    var syntheticEvent = SyntheticEvent.getPooled(eventTypes.select, activeElementInst, nativeEvent, nativeEventTarget);\n\n    syntheticEvent.type = 'select';\n    syntheticEvent.target = activeElement;\n\n    EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent);\n\n    return syntheticEvent;\n  }\n\n  return null;\n}\n\n/**\n * This plugin creates an `onSelect` event that normalizes select events\n * across form elements.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - contentEditable\n *\n * This differs from native browser implementations in the following ways:\n * - Fires on contentEditable fields as well as inputs.\n * - Fires for collapsed selection.\n * - Fires after user input.\n */\nvar SelectEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (!hasListener) {\n      return null;\n    }\n\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    switch (topLevelType) {\n      // Track the input node that has focus.\n      case topLevelTypes.topFocus:\n        if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {\n          activeElement = targetNode;\n          activeElementInst = targetInst;\n          lastSelection = null;\n        }\n        break;\n      case topLevelTypes.topBlur:\n        activeElement = null;\n        activeElementInst = null;\n        lastSelection = null;\n        break;\n\n      // Don't fire the event while the user is dragging. This matches the\n      // semantics of the native select event.\n      case topLevelTypes.topMouseDown:\n        mouseDown = true;\n        break;\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topMouseUp:\n        mouseDown = false;\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n\n      // Chrome and IE fire non-standard event when selection is changed (and\n      // sometimes when it hasn't). IE's event fires out of order with respect\n      // to key and input events on deletion, so we discard it.\n      //\n      // Firefox doesn't support selectionchange, so check selection status\n      // after each key entry. The selection changes after keydown and before\n      // keyup, but we check on keydown as well in the case of holding down a\n      // key, when multiple keydown events are fired but only one keyup is.\n      // This is also our approach for IE handling, for the reason above.\n      case topLevelTypes.topSelectionChange:\n        if (skipSelectionChangeEvent) {\n          break;\n        }\n      // falls through\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n    }\n\n    return null;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    if (registrationName === ON_SELECT_KEY) {\n      hasListener = true;\n    }\n  }\n};\n\nmodule.exports = SelectEventPlugin;\n},{\"104\":104,\"136\":136,\"147\":147,\"156\":156,\"16\":16,\"165\":165,\"170\":170,\"20\":20,\"41\":41,\"72\":72}],99:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SimpleEventPlugin\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar EventListener = _dereq_(146);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticAnimationEvent = _dereq_(100);\nvar SyntheticClipboardEvent = _dereq_(101);\nvar SyntheticEvent = _dereq_(104);\nvar SyntheticFocusEvent = _dereq_(105);\nvar SyntheticKeyboardEvent = _dereq_(107);\nvar SyntheticMouseEvent = _dereq_(108);\nvar SyntheticDragEvent = _dereq_(103);\nvar SyntheticTouchEvent = _dereq_(109);\nvar SyntheticTransitionEvent = _dereq_(110);\nvar SyntheticUIEvent = _dereq_(111);\nvar SyntheticWheelEvent = _dereq_(112);\n\nvar emptyFunction = _dereq_(153);\nvar getEventCharCode = _dereq_(125);\nvar invariant = _dereq_(161);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  abort: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAbort: true }),\n      captured: keyOf({ onAbortCapture: true })\n    }\n  },\n  animationEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationEnd: true }),\n      captured: keyOf({ onAnimationEndCapture: true })\n    }\n  },\n  animationIteration: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationIteration: true }),\n      captured: keyOf({ onAnimationIterationCapture: true })\n    }\n  },\n  animationStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationStart: true }),\n      captured: keyOf({ onAnimationStartCapture: true })\n    }\n  },\n  blur: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBlur: true }),\n      captured: keyOf({ onBlurCapture: true })\n    }\n  },\n  canPlay: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlay: true }),\n      captured: keyOf({ onCanPlayCapture: true })\n    }\n  },\n  canPlayThrough: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlayThrough: true }),\n      captured: keyOf({ onCanPlayThroughCapture: true })\n    }\n  },\n  click: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onClick: true }),\n      captured: keyOf({ onClickCapture: true })\n    }\n  },\n  contextMenu: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onContextMenu: true }),\n      captured: keyOf({ onContextMenuCapture: true })\n    }\n  },\n  copy: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCopy: true }),\n      captured: keyOf({ onCopyCapture: true })\n    }\n  },\n  cut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCut: true }),\n      captured: keyOf({ onCutCapture: true })\n    }\n  },\n  doubleClick: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDoubleClick: true }),\n      captured: keyOf({ onDoubleClickCapture: true })\n    }\n  },\n  drag: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrag: true }),\n      captured: keyOf({ onDragCapture: true })\n    }\n  },\n  dragEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnd: true }),\n      captured: keyOf({ onDragEndCapture: true })\n    }\n  },\n  dragEnter: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnter: true }),\n      captured: keyOf({ onDragEnterCapture: true })\n    }\n  },\n  dragExit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragExit: true }),\n      captured: keyOf({ onDragExitCapture: true })\n    }\n  },\n  dragLeave: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragLeave: true }),\n      captured: keyOf({ onDragLeaveCapture: true })\n    }\n  },\n  dragOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragOver: true }),\n      captured: keyOf({ onDragOverCapture: true })\n    }\n  },\n  dragStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragStart: true }),\n      captured: keyOf({ onDragStartCapture: true })\n    }\n  },\n  drop: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrop: true }),\n      captured: keyOf({ onDropCapture: true })\n    }\n  },\n  durationChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDurationChange: true }),\n      captured: keyOf({ onDurationChangeCapture: true })\n    }\n  },\n  emptied: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEmptied: true }),\n      captured: keyOf({ onEmptiedCapture: true })\n    }\n  },\n  encrypted: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEncrypted: true }),\n      captured: keyOf({ onEncryptedCapture: true })\n    }\n  },\n  ended: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEnded: true }),\n      captured: keyOf({ onEndedCapture: true })\n    }\n  },\n  error: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onError: true }),\n      captured: keyOf({ onErrorCapture: true })\n    }\n  },\n  focus: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onFocus: true }),\n      captured: keyOf({ onFocusCapture: true })\n    }\n  },\n  input: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInput: true }),\n      captured: keyOf({ onInputCapture: true })\n    }\n  },\n  invalid: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInvalid: true }),\n      captured: keyOf({ onInvalidCapture: true })\n    }\n  },\n  keyDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyDown: true }),\n      captured: keyOf({ onKeyDownCapture: true })\n    }\n  },\n  keyPress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyPress: true }),\n      captured: keyOf({ onKeyPressCapture: true })\n    }\n  },\n  keyUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyUp: true }),\n      captured: keyOf({ onKeyUpCapture: true })\n    }\n  },\n  load: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoad: true }),\n      captured: keyOf({ onLoadCapture: true })\n    }\n  },\n  loadedData: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedData: true }),\n      captured: keyOf({ onLoadedDataCapture: true })\n    }\n  },\n  loadedMetadata: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedMetadata: true }),\n      captured: keyOf({ onLoadedMetadataCapture: true })\n    }\n  },\n  loadStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadStart: true }),\n      captured: keyOf({ onLoadStartCapture: true })\n    }\n  },\n  // Note: We do not allow listening to mouseOver events. Instead, use the\n  // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`.\n  mouseDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseDown: true }),\n      captured: keyOf({ onMouseDownCapture: true })\n    }\n  },\n  mouseMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseMove: true }),\n      captured: keyOf({ onMouseMoveCapture: true })\n    }\n  },\n  mouseOut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOut: true }),\n      captured: keyOf({ onMouseOutCapture: true })\n    }\n  },\n  mouseOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOver: true }),\n      captured: keyOf({ onMouseOverCapture: true })\n    }\n  },\n  mouseUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseUp: true }),\n      captured: keyOf({ onMouseUpCapture: true })\n    }\n  },\n  paste: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPaste: true }),\n      captured: keyOf({ onPasteCapture: true })\n    }\n  },\n  pause: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPause: true }),\n      captured: keyOf({ onPauseCapture: true })\n    }\n  },\n  play: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlay: true }),\n      captured: keyOf({ onPlayCapture: true })\n    }\n  },\n  playing: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlaying: true }),\n      captured: keyOf({ onPlayingCapture: true })\n    }\n  },\n  progress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onProgress: true }),\n      captured: keyOf({ onProgressCapture: true })\n    }\n  },\n  rateChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onRateChange: true }),\n      captured: keyOf({ onRateChangeCapture: true })\n    }\n  },\n  reset: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onReset: true }),\n      captured: keyOf({ onResetCapture: true })\n    }\n  },\n  scroll: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onScroll: true }),\n      captured: keyOf({ onScrollCapture: true })\n    }\n  },\n  seeked: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeked: true }),\n      captured: keyOf({ onSeekedCapture: true })\n    }\n  },\n  seeking: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeking: true }),\n      captured: keyOf({ onSeekingCapture: true })\n    }\n  },\n  stalled: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onStalled: true }),\n      captured: keyOf({ onStalledCapture: true })\n    }\n  },\n  submit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSubmit: true }),\n      captured: keyOf({ onSubmitCapture: true })\n    }\n  },\n  suspend: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSuspend: true }),\n      captured: keyOf({ onSuspendCapture: true })\n    }\n  },\n  timeUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTimeUpdate: true }),\n      captured: keyOf({ onTimeUpdateCapture: true })\n    }\n  },\n  touchCancel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchCancel: true }),\n      captured: keyOf({ onTouchCancelCapture: true })\n    }\n  },\n  touchEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchEnd: true }),\n      captured: keyOf({ onTouchEndCapture: true })\n    }\n  },\n  touchMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchMove: true }),\n      captured: keyOf({ onTouchMoveCapture: true })\n    }\n  },\n  touchStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchStart: true }),\n      captured: keyOf({ onTouchStartCapture: true })\n    }\n  },\n  transitionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTransitionEnd: true }),\n      captured: keyOf({ onTransitionEndCapture: true })\n    }\n  },\n  volumeChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onVolumeChange: true }),\n      captured: keyOf({ onVolumeChangeCapture: true })\n    }\n  },\n  waiting: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWaiting: true }),\n      captured: keyOf({ onWaitingCapture: true })\n    }\n  },\n  wheel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWheel: true }),\n      captured: keyOf({ onWheelCapture: true })\n    }\n  }\n};\n\nvar topLevelEventsToDispatchConfig = {\n  topAbort: eventTypes.abort,\n  topAnimationEnd: eventTypes.animationEnd,\n  topAnimationIteration: eventTypes.animationIteration,\n  topAnimationStart: eventTypes.animationStart,\n  topBlur: eventTypes.blur,\n  topCanPlay: eventTypes.canPlay,\n  topCanPlayThrough: eventTypes.canPlayThrough,\n  topClick: eventTypes.click,\n  topContextMenu: eventTypes.contextMenu,\n  topCopy: eventTypes.copy,\n  topCut: eventTypes.cut,\n  topDoubleClick: eventTypes.doubleClick,\n  topDrag: eventTypes.drag,\n  topDragEnd: eventTypes.dragEnd,\n  topDragEnter: eventTypes.dragEnter,\n  topDragExit: eventTypes.dragExit,\n  topDragLeave: eventTypes.dragLeave,\n  topDragOver: eventTypes.dragOver,\n  topDragStart: eventTypes.dragStart,\n  topDrop: eventTypes.drop,\n  topDurationChange: eventTypes.durationChange,\n  topEmptied: eventTypes.emptied,\n  topEncrypted: eventTypes.encrypted,\n  topEnded: eventTypes.ended,\n  topError: eventTypes.error,\n  topFocus: eventTypes.focus,\n  topInput: eventTypes.input,\n  topInvalid: eventTypes.invalid,\n  topKeyDown: eventTypes.keyDown,\n  topKeyPress: eventTypes.keyPress,\n  topKeyUp: eventTypes.keyUp,\n  topLoad: eventTypes.load,\n  topLoadedData: eventTypes.loadedData,\n  topLoadedMetadata: eventTypes.loadedMetadata,\n  topLoadStart: eventTypes.loadStart,\n  topMouseDown: eventTypes.mouseDown,\n  topMouseMove: eventTypes.mouseMove,\n  topMouseOut: eventTypes.mouseOut,\n  topMouseOver: eventTypes.mouseOver,\n  topMouseUp: eventTypes.mouseUp,\n  topPaste: eventTypes.paste,\n  topPause: eventTypes.pause,\n  topPlay: eventTypes.play,\n  topPlaying: eventTypes.playing,\n  topProgress: eventTypes.progress,\n  topRateChange: eventTypes.rateChange,\n  topReset: eventTypes.reset,\n  topScroll: eventTypes.scroll,\n  topSeeked: eventTypes.seeked,\n  topSeeking: eventTypes.seeking,\n  topStalled: eventTypes.stalled,\n  topSubmit: eventTypes.submit,\n  topSuspend: eventTypes.suspend,\n  topTimeUpdate: eventTypes.timeUpdate,\n  topTouchCancel: eventTypes.touchCancel,\n  topTouchEnd: eventTypes.touchEnd,\n  topTouchMove: eventTypes.touchMove,\n  topTouchStart: eventTypes.touchStart,\n  topTransitionEnd: eventTypes.transitionEnd,\n  topVolumeChange: eventTypes.volumeChange,\n  topWaiting: eventTypes.waiting,\n  topWheel: eventTypes.wheel\n};\n\nfor (var type in topLevelEventsToDispatchConfig) {\n  topLevelEventsToDispatchConfig[type].dependencies = [type];\n}\n\nvar ON_CLICK_KEY = keyOf({ onClick: null });\nvar onClickListeners = {};\n\nvar SimpleEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];\n    if (!dispatchConfig) {\n      return null;\n    }\n    var EventConstructor;\n    switch (topLevelType) {\n      case topLevelTypes.topAbort:\n      case topLevelTypes.topCanPlay:\n      case topLevelTypes.topCanPlayThrough:\n      case topLevelTypes.topDurationChange:\n      case topLevelTypes.topEmptied:\n      case topLevelTypes.topEncrypted:\n      case topLevelTypes.topEnded:\n      case topLevelTypes.topError:\n      case topLevelTypes.topInput:\n      case topLevelTypes.topInvalid:\n      case topLevelTypes.topLoad:\n      case topLevelTypes.topLoadedData:\n      case topLevelTypes.topLoadedMetadata:\n      case topLevelTypes.topLoadStart:\n      case topLevelTypes.topPause:\n      case topLevelTypes.topPlay:\n      case topLevelTypes.topPlaying:\n      case topLevelTypes.topProgress:\n      case topLevelTypes.topRateChange:\n      case topLevelTypes.topReset:\n      case topLevelTypes.topSeeked:\n      case topLevelTypes.topSeeking:\n      case topLevelTypes.topStalled:\n      case topLevelTypes.topSubmit:\n      case topLevelTypes.topSuspend:\n      case topLevelTypes.topTimeUpdate:\n      case topLevelTypes.topVolumeChange:\n      case topLevelTypes.topWaiting:\n        // HTML Events\n        // @see http://www.w3.org/TR/html5/index.html#events-0\n        EventConstructor = SyntheticEvent;\n        break;\n      case topLevelTypes.topKeyPress:\n        // Firefox creates a keypress event for function keys too. This removes\n        // the unwanted keypress events. Enter is however both printable and\n        // non-printable. One would expect Tab to be as well (but it isn't).\n        if (getEventCharCode(nativeEvent) === 0) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        EventConstructor = SyntheticKeyboardEvent;\n        break;\n      case topLevelTypes.topBlur:\n      case topLevelTypes.topFocus:\n        EventConstructor = SyntheticFocusEvent;\n        break;\n      case topLevelTypes.topClick:\n        // Firefox creates a click event on right mouse clicks. This removes the\n        // unwanted click events.\n        if (nativeEvent.button === 2) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topDoubleClick:\n      case topLevelTypes.topMouseDown:\n      case topLevelTypes.topMouseMove:\n      case topLevelTypes.topMouseOut:\n      case topLevelTypes.topMouseOver:\n      case topLevelTypes.topMouseUp:\n        EventConstructor = SyntheticMouseEvent;\n        break;\n      case topLevelTypes.topDrag:\n      case topLevelTypes.topDragEnd:\n      case topLevelTypes.topDragEnter:\n      case topLevelTypes.topDragExit:\n      case topLevelTypes.topDragLeave:\n      case topLevelTypes.topDragOver:\n      case topLevelTypes.topDragStart:\n      case topLevelTypes.topDrop:\n        EventConstructor = SyntheticDragEvent;\n        break;\n      case topLevelTypes.topTouchCancel:\n      case topLevelTypes.topTouchEnd:\n      case topLevelTypes.topTouchMove:\n      case topLevelTypes.topTouchStart:\n        EventConstructor = SyntheticTouchEvent;\n        break;\n      case topLevelTypes.topAnimationEnd:\n      case topLevelTypes.topAnimationIteration:\n      case topLevelTypes.topAnimationStart:\n        EventConstructor = SyntheticAnimationEvent;\n        break;\n      case topLevelTypes.topTransitionEnd:\n        EventConstructor = SyntheticTransitionEvent;\n        break;\n      case topLevelTypes.topScroll:\n        EventConstructor = SyntheticUIEvent;\n        break;\n      case topLevelTypes.topWheel:\n        EventConstructor = SyntheticWheelEvent;\n        break;\n      case topLevelTypes.topCopy:\n      case topLevelTypes.topCut:\n      case topLevelTypes.topPaste:\n        EventConstructor = SyntheticClipboardEvent;\n        break;\n    }\n    !EventConstructor ? \"development\" !== 'production' ? invariant(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : _prodInvariant('86', topLevelType) : void 0;\n    var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);\n    EventPropagators.accumulateTwoPhaseDispatches(event);\n    return event;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    // Mobile Safari does not fire properly bubble click events on\n    // non-interactive elements, which means delegated click listeners do not\n    // fire. The workaround for this bug involves attaching an empty click\n    // listener on the target node.\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      if (!onClickListeners[id]) {\n        onClickListeners[id] = EventListener.listen(node, 'click', emptyFunction);\n      }\n    }\n  },\n\n  willDeleteListener: function (inst, registrationName) {\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      onClickListeners[id].remove();\n      delete onClickListeners[id];\n    }\n  }\n\n};\n\nmodule.exports = SimpleEventPlugin;\n},{\"100\":100,\"101\":101,\"103\":103,\"104\":104,\"105\":105,\"107\":107,\"108\":108,\"109\":109,\"110\":110,\"111\":111,\"112\":112,\"125\":125,\"139\":139,\"146\":146,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"20\":20,\"41\":41}],100:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticAnimationEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface\n * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent\n */\nvar AnimationEventInterface = {\n  animationName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);\n\nmodule.exports = SyntheticAnimationEvent;\n},{\"104\":104}],101:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticClipboardEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/clipboard-apis/\n */\nvar ClipboardEventInterface = {\n  clipboardData: function (event) {\n    return 'clipboardData' in event ? event.clipboardData : window.clipboardData;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);\n\nmodule.exports = SyntheticClipboardEvent;\n},{\"104\":104}],102:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticCompositionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents\n */\nvar CompositionEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);\n\nmodule.exports = SyntheticCompositionEvent;\n},{\"104\":104}],103:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticDragEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface DragEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar DragEventInterface = {\n  dataTransfer: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);\n\nmodule.exports = SyntheticDragEvent;\n},{\"108\":108}],104:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticEvent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar didWarnForAddedNewProperty = false;\nvar isProxySupported = typeof Proxy === 'function';\n\nvar shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar EventInterface = {\n  type: null,\n  target: null,\n  // currentTarget is set when dispatching; no use in copying it here\n  currentTarget: emptyFunction.thatReturnsNull,\n  eventPhase: null,\n  bubbles: null,\n  cancelable: null,\n  timeStamp: function (event) {\n    return event.timeStamp || Date.now();\n  },\n  defaultPrevented: null,\n  isTrusted: null\n};\n\n/**\n * Synthetic events are dispatched by event plugins, typically in response to a\n * top-level event delegation handler.\n *\n * These systems should generally use pooling to reduce the frequency of garbage\n * collection. The system should check `isPersistent` to determine whether the\n * event should be released into the pool after being dispatched. Users that\n * need a persisted event should invoke `persist`.\n *\n * Synthetic events (and subclasses) implement the DOM Level 3 Events API by\n * normalizing browser quirks. Subclasses do not necessarily have to implement a\n * DOM interface; custom application-specific events can also subclass this.\n *\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {*} targetInst Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @param {DOMEventTarget} nativeEventTarget Target node.\n */\nfunction SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {\n  if (\"development\" !== 'production') {\n    // these have a getter/setter for warnings\n    delete this.nativeEvent;\n    delete this.preventDefault;\n    delete this.stopPropagation;\n  }\n\n  this.dispatchConfig = dispatchConfig;\n  this._targetInst = targetInst;\n  this.nativeEvent = nativeEvent;\n\n  var Interface = this.constructor.Interface;\n  for (var propName in Interface) {\n    if (!Interface.hasOwnProperty(propName)) {\n      continue;\n    }\n    if (\"development\" !== 'production') {\n      delete this[propName]; // this has a getter/setter for warnings\n    }\n    var normalize = Interface[propName];\n    if (normalize) {\n      this[propName] = normalize(nativeEvent);\n    } else {\n      if (propName === 'target') {\n        this.target = nativeEventTarget;\n      } else {\n        this[propName] = nativeEvent[propName];\n      }\n    }\n  }\n\n  var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;\n  if (defaultPrevented) {\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  } else {\n    this.isDefaultPrevented = emptyFunction.thatReturnsFalse;\n  }\n  this.isPropagationStopped = emptyFunction.thatReturnsFalse;\n  return this;\n}\n\n_assign(SyntheticEvent.prototype, {\n\n  preventDefault: function () {\n    this.defaultPrevented = true;\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.preventDefault) {\n      event.preventDefault();\n    } else {\n      event.returnValue = false;\n    }\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  },\n\n  stopPropagation: function () {\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.stopPropagation) {\n      event.stopPropagation();\n    } else {\n      event.cancelBubble = true;\n    }\n    this.isPropagationStopped = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * We release all dispatched `SyntheticEvent`s after each event loop, adding\n   * them back into the pool. This allows a way to hold onto a reference that\n   * won't be added back into the pool.\n   */\n  persist: function () {\n    this.isPersistent = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * Checks if this event should be released back into the pool.\n   *\n   * @return {boolean} True if this should not be released, false otherwise.\n   */\n  isPersistent: emptyFunction.thatReturnsFalse,\n\n  /**\n   * `PooledClass` looks for `destructor` on each instance it releases.\n   */\n  destructor: function () {\n    var Interface = this.constructor.Interface;\n    for (var propName in Interface) {\n      if (\"development\" !== 'production') {\n        Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));\n      } else {\n        this[propName] = null;\n      }\n    }\n    for (var i = 0; i < shouldBeReleasedProperties.length; i++) {\n      this[shouldBeReleasedProperties[i]] = null;\n    }\n    if (\"development\" !== 'production') {\n      Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));\n      Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction));\n      Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction));\n    }\n  }\n\n});\n\nSyntheticEvent.Interface = EventInterface;\n\nif (\"development\" !== 'production') {\n  if (isProxySupported) {\n    /*eslint-disable no-func-assign */\n    SyntheticEvent = new Proxy(SyntheticEvent, {\n      construct: function (target, args) {\n        return this.apply(target, Object.create(target.prototype), args);\n      },\n      apply: function (constructor, that, args) {\n        return new Proxy(constructor.apply(that, args), {\n          set: function (target, prop, value) {\n            if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {\n              \"development\" !== 'production' ? warning(didWarnForAddedNewProperty || target.isPersistent(), 'This synthetic event is reused for performance reasons. If you\\'re ' + 'seeing this, you\\'re adding a new property in the synthetic event object. ' + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;\n              didWarnForAddedNewProperty = true;\n            }\n            target[prop] = value;\n            return true;\n          }\n        });\n      }\n    });\n    /*eslint-enable no-func-assign */\n  }\n}\n/**\n * Helper to reduce boilerplate when creating subclasses.\n *\n * @param {function} Class\n * @param {?object} Interface\n */\nSyntheticEvent.augmentClass = function (Class, Interface) {\n  var Super = this;\n\n  var E = function () {};\n  E.prototype = Super.prototype;\n  var prototype = new E();\n\n  _assign(prototype, Class.prototype);\n  Class.prototype = prototype;\n  Class.prototype.constructor = Class;\n\n  Class.Interface = _assign({}, Super.Interface, Interface);\n  Class.augmentClass = Super.augmentClass;\n\n  PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);\n};\n\nPooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);\n\nmodule.exports = SyntheticEvent;\n\n/**\n  * Helper to nullify syntheticEvent instance properties when destructing\n  *\n  * @param {object} SyntheticEvent\n  * @param {String} propName\n  * @return {object} defineProperty object\n  */\nfunction getPooledWarningPropertyDefinition(propName, getVal) {\n  var isFunction = typeof getVal === 'function';\n  return {\n    configurable: true,\n    set: set,\n    get: get\n  };\n\n  function set(val) {\n    var action = isFunction ? 'setting the method' : 'setting the property';\n    warn(action, 'This is effectively a no-op');\n    return val;\n  }\n\n  function get() {\n    var action = isFunction ? 'accessing the method' : 'accessing the property';\n    var result = isFunction ? 'This is a no-op function' : 'This is set to null';\n    warn(action, result);\n    return getVal;\n  }\n\n  function warn(action, result) {\n    var warningCondition = false;\n    \"development\" !== 'production' ? warning(warningCondition, 'This synthetic event is reused for performance reasons. If you\\'re seeing this, ' + 'you\\'re %s `%s` on a released/nullified synthetic event. %s. ' + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;\n  }\n}\n},{\"153\":153,\"171\":171,\"172\":172,\"25\":25}],105:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticFocusEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\n/**\n * @interface FocusEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar FocusEventInterface = {\n  relatedTarget: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);\n\nmodule.exports = SyntheticFocusEvent;\n},{\"111\":111}],106:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticInputEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105\n *      /#events-inputevents\n */\nvar InputEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface);\n\nmodule.exports = SyntheticInputEvent;\n},{\"104\":104}],107:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticKeyboardEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventCharCode = _dereq_(125);\nvar getEventKey = _dereq_(126);\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface KeyboardEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar KeyboardEventInterface = {\n  key: getEventKey,\n  location: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  repeat: null,\n  locale: null,\n  getModifierState: getEventModifierState,\n  // Legacy Interface\n  charCode: function (event) {\n    // `charCode` is the result of a KeyPress event and represents the value of\n    // the actual printable character.\n\n    // KeyPress is deprecated, but its replacement is not yet final and not\n    // implemented in any major browser. Only KeyPress has charCode.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    return 0;\n  },\n  keyCode: function (event) {\n    // `keyCode` is the result of a KeyDown/Up event and represents the value of\n    // physical keyboard key.\n\n    // The actual meaning of the value depends on the users' keyboard layout\n    // which cannot be detected. Assuming that it is a US keyboard layout\n    // provides a surprisingly accurate mapping for US and European users.\n    // Due to this, it is left to the user to implement at this time.\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  },\n  which: function (event) {\n    // `which` is an alias for either `keyCode` or `charCode` depending on the\n    // type of the event.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);\n\nmodule.exports = SyntheticKeyboardEvent;\n},{\"111\":111,\"125\":125,\"126\":126,\"127\":127}],108:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticMouseEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\nvar ViewportMetrics = _dereq_(114);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface MouseEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar MouseEventInterface = {\n  screenX: null,\n  screenY: null,\n  clientX: null,\n  clientY: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  getModifierState: getEventModifierState,\n  button: function (event) {\n    // Webkit, Firefox, IE9+\n    // which:  1 2 3\n    // button: 0 1 2 (standard)\n    var button = event.button;\n    if ('which' in event) {\n      return button;\n    }\n    // IE<9\n    // which:  undefined\n    // button: 0 0 0\n    // button: 1 4 2 (onmouseup)\n    return button === 2 ? 2 : button === 4 ? 1 : 0;\n  },\n  buttons: null,\n  relatedTarget: function (event) {\n    return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);\n  },\n  // \"Proprietary\" Interface.\n  pageX: function (event) {\n    return 'pageX' in event ? event.pageX : event.clientX + ViewportMetrics.currentScrollLeft;\n  },\n  pageY: function (event) {\n    return 'pageY' in event ? event.pageY : event.clientY + ViewportMetrics.currentScrollTop;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);\n\nmodule.exports = SyntheticMouseEvent;\n},{\"111\":111,\"114\":114,\"127\":127}],109:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTouchEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface TouchEvent\n * @see http://www.w3.org/TR/touch-events/\n */\nvar TouchEventInterface = {\n  touches: null,\n  targetTouches: null,\n  changedTouches: null,\n  altKey: null,\n  metaKey: null,\n  ctrlKey: null,\n  shiftKey: null,\n  getModifierState: getEventModifierState\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);\n\nmodule.exports = SyntheticTouchEvent;\n},{\"111\":111,\"127\":127}],110:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTransitionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent\n */\nvar TransitionEventInterface = {\n  propertyName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);\n\nmodule.exports = SyntheticTransitionEvent;\n},{\"104\":104}],111:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticUIEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\n\n/**\n * @interface UIEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar UIEventInterface = {\n  view: function (event) {\n    if (event.view) {\n      return event.view;\n    }\n\n    var target = getEventTarget(event);\n    if (target.window === target) {\n      // target is a window object\n      return target;\n    }\n\n    var doc = target.ownerDocument;\n    // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n    if (doc) {\n      return doc.defaultView || doc.parentWindow;\n    } else {\n      return window;\n    }\n  },\n  detail: function (event) {\n    return event.detail || 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);\n\nmodule.exports = SyntheticUIEvent;\n},{\"104\":104,\"128\":128}],112:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticWheelEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface WheelEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar WheelEventInterface = {\n  deltaX: function (event) {\n    return 'deltaX' in event ? event.deltaX :\n    // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).\n    'wheelDeltaX' in event ? -event.wheelDeltaX : 0;\n  },\n  deltaY: function (event) {\n    return 'deltaY' in event ? event.deltaY :\n    // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).\n    'wheelDeltaY' in event ? -event.wheelDeltaY :\n    // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).\n    'wheelDelta' in event ? -event.wheelDelta : 0;\n  },\n  deltaZ: null,\n\n  // Browsers without \"deltaMode\" is reporting in raw wheel delta where one\n  // notch on the scroll is always +/- 120, roughly equivalent to pixels.\n  // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or\n  // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.\n  deltaMode: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticMouseEvent}\n */\nfunction SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);\n\nmodule.exports = SyntheticWheelEvent;\n},{\"108\":108}],113:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Transaction\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * `Transaction` creates a black box that is able to wrap any method such that\n * certain invariants are maintained before and after the method is invoked\n * (Even if an exception is thrown while invoking the wrapped method). Whoever\n * instantiates a transaction can provide enforcers of the invariants at\n * creation time. The `Transaction` class itself will supply one additional\n * automatic invariant for you - the invariant that any transaction instance\n * should not be run while it is already being run. You would typically create a\n * single instance of a `Transaction` for reuse multiple times, that potentially\n * is used to wrap several different methods. Wrappers are extremely simple -\n * they only require implementing two methods.\n *\n * <pre>\n *                       wrappers (injected at creation time)\n *                                      +        +\n *                                      |        |\n *                    +-----------------|--------|--------------+\n *                    |                 v        |              |\n *                    |      +---------------+   |              |\n *                    |   +--|    wrapper1   |---|----+         |\n *                    |   |  +---------------+   v    |         |\n *                    |   |          +-------------+  |         |\n *                    |   |     +----|   wrapper2  |--------+   |\n *                    |   |     |    +-------------+  |     |   |\n *                    |   |     |                     |     |   |\n *                    |   v     v                     v     v   | wrapper\n *                    | +---+ +---+   +---------+   +---+ +---+ | invariants\n * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained\n * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | +---+ +---+   +---------+   +---+ +---+ |\n *                    |  initialize                    close    |\n *                    +-----------------------------------------+\n * </pre>\n *\n * Use cases:\n * - Preserving the input selection ranges before/after reconciliation.\n *   Restoring selection even in the event of an unexpected error.\n * - Deactivating events while rearranging the DOM, preventing blurs/focuses,\n *   while guaranteeing that afterwards, the event system is reactivated.\n * - Flushing a queue of collected DOM mutations to the main UI thread after a\n *   reconciliation takes place in a worker thread.\n * - Invoking any collected `componentDidUpdate` callbacks after rendering new\n *   content.\n * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue\n *   to preserve the `scrollTop` (an automatic scroll aware DOM).\n * - (Future use case): Layout calculations before and after DOM updates.\n *\n * Transactional plugin API:\n * - A module that has an `initialize` method that returns any precomputation.\n * - and a `close` method that accepts the precomputation. `close` is invoked\n *   when the wrapped process is completed, or has failed.\n *\n * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules\n * that implement `initialize` and `close`.\n * @return {Transaction} Single transaction for reuse in thread.\n *\n * @class Transaction\n */\nvar Mixin = {\n  /**\n   * Sets up this instance so that it is prepared for collecting metrics. Does\n   * so such that this setup method may be used on an instance that is already\n   * initialized, in a way that does not consume additional memory upon reuse.\n   * That can be useful if you decide to make your subclass of this mixin a\n   * \"PooledClass\".\n   */\n  reinitializeTransaction: function () {\n    this.transactionWrappers = this.getTransactionWrappers();\n    if (this.wrapperInitData) {\n      this.wrapperInitData.length = 0;\n    } else {\n      this.wrapperInitData = [];\n    }\n    this._isInTransaction = false;\n  },\n\n  _isInTransaction: false,\n\n  /**\n   * @abstract\n   * @return {Array<TransactionWrapper>} Array of transaction wrappers.\n   */\n  getTransactionWrappers: null,\n\n  isInTransaction: function () {\n    return !!this._isInTransaction;\n  },\n\n  /**\n   * Executes the function within a safety window. Use this for the top level\n   * methods that result in large amounts of computation/mutations that would\n   * need to be safety checked. The optional arguments helps prevent the need\n   * to bind in many cases.\n   *\n   * @param {function} method Member of scope to call.\n   * @param {Object} scope Scope to invoke from.\n   * @param {Object?=} a Argument to pass to the method.\n   * @param {Object?=} b Argument to pass to the method.\n   * @param {Object?=} c Argument to pass to the method.\n   * @param {Object?=} d Argument to pass to the method.\n   * @param {Object?=} e Argument to pass to the method.\n   * @param {Object?=} f Argument to pass to the method.\n   *\n   * @return {*} Return value from `method`.\n   */\n  perform: function (method, scope, a, b, c, d, e, f) {\n    !!this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.perform(...): Cannot initialize a transaction when there is already an outstanding transaction.') : _prodInvariant('27') : void 0;\n    var errorThrown;\n    var ret;\n    try {\n      this._isInTransaction = true;\n      // Catching errors makes debugging more difficult, so we start with\n      // errorThrown set to true before setting it to false after calling\n      // close -- if it's still set to true in the finally block, it means\n      // one of these calls threw.\n      errorThrown = true;\n      this.initializeAll(0);\n      ret = method.call(scope, a, b, c, d, e, f);\n      errorThrown = false;\n    } finally {\n      try {\n        if (errorThrown) {\n          // If `method` throws, prefer to show that stack trace over any thrown\n          // by invoking `closeAll`.\n          try {\n            this.closeAll(0);\n          } catch (err) {}\n        } else {\n          // Since `method` didn't throw, we don't want to silence the exception\n          // here.\n          this.closeAll(0);\n        }\n      } finally {\n        this._isInTransaction = false;\n      }\n    }\n    return ret;\n  },\n\n  initializeAll: function (startIndex) {\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      try {\n        // Catching errors makes debugging more difficult, so we start with the\n        // OBSERVED_ERROR state before overwriting it with the real return value\n        // of initialize -- if it's still set to OBSERVED_ERROR in the finally\n        // block, it means wrapper.initialize threw.\n        this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;\n        this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null;\n      } finally {\n        if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {\n          // The initializer for wrapper i threw an error; initialize the\n          // remaining wrappers but silence any exceptions from them to ensure\n          // that the first error is the one to bubble up.\n          try {\n            this.initializeAll(i + 1);\n          } catch (err) {}\n        }\n      }\n    }\n  },\n\n  /**\n   * Invokes each of `this.transactionWrappers.close[i]` functions, passing into\n   * them the respective return values of `this.transactionWrappers.init[i]`\n   * (`close`rs that correspond to initializers that failed will not be\n   * invoked).\n   */\n  closeAll: function (startIndex) {\n    !this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') : _prodInvariant('28') : void 0;\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      var initData = this.wrapperInitData[i];\n      var errorThrown;\n      try {\n        // Catching errors makes debugging more difficult, so we start with\n        // errorThrown set to true before setting it to false after calling\n        // close -- if it's still set to true in the finally block, it means\n        // wrapper.close threw.\n        errorThrown = true;\n        if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) {\n          wrapper.close.call(this, initData);\n        }\n        errorThrown = false;\n      } finally {\n        if (errorThrown) {\n          // The closer for wrapper i threw an error; close the remaining\n          // wrappers but silence any exceptions from them to ensure that the\n          // first error is the one to bubble up.\n          try {\n            this.closeAll(i + 1);\n          } catch (e) {}\n        }\n      }\n    }\n    this.wrapperInitData.length = 0;\n  }\n};\n\nvar Transaction = {\n\n  Mixin: Mixin,\n\n  /**\n   * Token to look for to determine if an error occurred.\n   */\n  OBSERVED_ERROR: {}\n\n};\n\nmodule.exports = Transaction;\n},{\"139\":139,\"161\":161}],114:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ViewportMetrics\n */\n\n'use strict';\n\nvar ViewportMetrics = {\n\n  currentScrollLeft: 0,\n\n  currentScrollTop: 0,\n\n  refreshScrollValues: function (scrollPosition) {\n    ViewportMetrics.currentScrollLeft = scrollPosition.x;\n    ViewportMetrics.currentScrollTop = scrollPosition.y;\n  }\n\n};\n\nmodule.exports = ViewportMetrics;\n},{}],115:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule accumulateInto\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Accumulates items that must not be null or undefined into the first one. This\n * is used to conserve memory by avoiding array allocations, and thus sacrifices\n * API cleanness. Since `current` can be null before being passed in and not\n * null after this function, make sure to assign it back to `current`:\n *\n * `a = accumulateInto(a, b);`\n *\n * This API should be sparingly used. Try `accumulate` for something cleaner.\n *\n * @return {*|array<*>} An accumulation of items.\n */\n\nfunction accumulateInto(current, next) {\n  !(next != null) ? \"development\" !== 'production' ? invariant(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : _prodInvariant('30') : void 0;\n\n  if (current == null) {\n    return next;\n  }\n\n  // Both are not empty. Warning: Never call x.concat(y) when you are not\n  // certain that x is an Array (x could be a string with concat method).\n  if (Array.isArray(current)) {\n    if (Array.isArray(next)) {\n      current.push.apply(current, next);\n      return current;\n    }\n    current.push(next);\n    return current;\n  }\n\n  if (Array.isArray(next)) {\n    // A bit too dangerous to mutate `next`.\n    return [current].concat(next);\n  }\n\n  return [current, next];\n}\n\nmodule.exports = accumulateInto;\n},{\"139\":139,\"161\":161}],116:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule adler32\n * \n */\n\n'use strict';\n\nvar MOD = 65521;\n\n// adler32 is not cryptographically strong, and is only used to sanity check that\n// markup generated on the server matches the markup generated on the client.\n// This implementation (a modified version of the SheetJS version) has been optimized\n// for our use case, at the expense of conforming to the adler32 specification\n// for non-ascii inputs.\nfunction adler32(data) {\n  var a = 1;\n  var b = 0;\n  var i = 0;\n  var l = data.length;\n  var m = l & ~0x3;\n  while (i < m) {\n    var n = Math.min(i + 4096, m);\n    for (; i < n; i += 4) {\n      b += (a += data.charCodeAt(i)) + (a += data.charCodeAt(i + 1)) + (a += data.charCodeAt(i + 2)) + (a += data.charCodeAt(i + 3));\n    }\n    a %= MOD;\n    b %= MOD;\n  }\n  for (; i < l; i++) {\n    b += a += data.charCodeAt(i);\n  }\n  a %= MOD;\n  b %= MOD;\n  return a | b << 16;\n}\n\nmodule.exports = adler32;\n},{}],117:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule canDefineProperty\n */\n\n'use strict';\n\nvar canDefineProperty = false;\nif (\"development\" !== 'production') {\n  try {\n    Object.defineProperty({}, 'x', { get: function () {} });\n    canDefineProperty = true;\n  } catch (x) {\n    // IE will fail on defineProperty\n  }\n}\n\nmodule.exports = canDefineProperty;\n},{}],118:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule checkReactTypeSpec\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar loggedTypeFailures = {};\n\n/**\n * Assert that the values match with the type specs.\n * Error messages are memorized and will only be shown once.\n *\n * @param {object} typeSpecs Map of name to a ReactPropType\n * @param {object} values Runtime values that need to be type-checked\n * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n * @param {string} componentName Name of the component for error messages.\n * @param {?object} element The React element that is being type-checked\n * @param {?number} debugID The React component instance that is being type-checked\n * @private\n */\nfunction checkReactTypeSpec(typeSpecs, values, location, componentName, element, debugID) {\n  for (var typeSpecName in typeSpecs) {\n    if (typeSpecs.hasOwnProperty(typeSpecName)) {\n      var error;\n      // Prop type validation may throw. In case they do, we don't want to\n      // fail the render phase where it didn't fail before. So we log it.\n      // After these have been cleaned up, we'll let them throw.\n      try {\n        // This is intentionally an invariant that gets caught. It's the same\n        // behavior as without this statement except with a better message.\n        !(typeof typeSpecs[typeSpecName] === 'function') ? \"development\" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : _prodInvariant('84', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : void 0;\n        error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location);\n      } catch (ex) {\n        error = ex;\n      }\n      \"development\" !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName, typeof error) : void 0;\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var componentStackInfo = '';\n\n        if (\"development\" !== 'production') {\n          var ReactComponentTreeDevtool = _dereq_(34);\n          if (debugID !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getStackAddendumByID(debugID);\n          } else if (element !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getCurrentStackAddendum(element);\n          }\n        }\n\n        \"development\" !== 'production' ? warning(false, 'Failed %s type: %s%s', location, error.message, componentStackInfo) : void 0;\n      }\n    }\n  }\n}\n\nmodule.exports = checkReactTypeSpec;\n},{\"139\":139,\"161\":161,\"171\":171,\"34\":34,\"83\":83}],119:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule createMicrosoftUnsafeLocalFunction\n */\n\n/* globals MSApp */\n\n'use strict';\n\n/**\n * Create a function which has 'unsafe' privileges (required by windows8 apps)\n */\n\nvar createMicrosoftUnsafeLocalFunction = function (func) {\n  if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {\n    return function (arg0, arg1, arg2, arg3) {\n      MSApp.execUnsafeLocalFunction(function () {\n        return func(arg0, arg1, arg2, arg3);\n      });\n    };\n  } else {\n    return func;\n  }\n};\n\nmodule.exports = createMicrosoftUnsafeLocalFunction;\n},{}],120:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule dangerousStyleValue\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar warning = _dereq_(171);\n\nvar isUnitlessNumber = CSSProperty.isUnitlessNumber;\nvar styleWarnings = {};\n\n/**\n * Convert a value into the proper css writable value. The style name `name`\n * should be logical (no hyphens), as specified\n * in `CSSProperty.isUnitlessNumber`.\n *\n * @param {string} name CSS property name such as `topMargin`.\n * @param {*} value CSS property value such as `10px`.\n * @param {ReactDOMComponent} component\n * @return {string} Normalized style value with dimensions applied.\n */\nfunction dangerousStyleValue(name, value, component) {\n  // Note that we've removed escapeTextForBrowser() calls here since the\n  // whole string will be escaped when the attribute is injected into\n  // the markup. If you provide unsafe user data here they can inject\n  // arbitrary CSS which may be problematic (I couldn't repro this):\n  // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet\n  // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/\n  // This is not an XSS hole but instead a potential CSS injection issue\n  // which has lead to a greater discussion about how we're going to\n  // trust URLs moving forward. See #2115901\n\n  var isEmpty = value == null || typeof value === 'boolean' || value === '';\n  if (isEmpty) {\n    return '';\n  }\n\n  var isNonNumeric = isNaN(value);\n  if (isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {\n    return '' + value; // cast to string\n  }\n\n  if (typeof value === 'string') {\n    if (\"development\" !== 'production') {\n      // Allow '0' to pass through without warning. 0 is already special and\n      // doesn't require units, so we don't need to warn about it.\n      if (component && value !== '0') {\n        var owner = component._currentElement._owner;\n        var ownerName = owner ? owner.getName() : null;\n        if (ownerName && !styleWarnings[ownerName]) {\n          styleWarnings[ownerName] = {};\n        }\n        var warned = false;\n        if (ownerName) {\n          var warnings = styleWarnings[ownerName];\n          warned = warnings[name];\n          if (!warned) {\n            warnings[name] = true;\n          }\n        }\n        if (!warned) {\n          \"development\" !== 'production' ? warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' + 'for CSS property `%s` (value: `%s`) which will be treated ' + 'as a unitless number in a future version of React.', component._currentElement.type, ownerName || 'unknown', name, value) : void 0;\n        }\n      }\n    }\n    value = value.trim();\n  }\n  return value + 'px';\n}\n\nmodule.exports = dangerousStyleValue;\n},{\"171\":171,\"3\":3}],121:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * Based on the escape-html library, which is used under the MIT License below:\n *\n * Copyright (c) 2012-2013 TJ Holowaychuk\n * Copyright (c) 2015 Andreas Lubbe\n * Copyright (c) 2015 Tiancheng \"Timothy\" Gu\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * @providesModule escapeTextContentForBrowser\n */\n\n'use strict';\n\n// code copied and modified from escape-html\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param  {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n  var str = '' + string;\n  var match = matchHtmlRegExp.exec(str);\n\n  if (!match) {\n    return str;\n  }\n\n  var escape;\n  var html = '';\n  var index = 0;\n  var lastIndex = 0;\n\n  for (index = match.index; index < str.length; index++) {\n    switch (str.charCodeAt(index)) {\n      case 34:\n        // \"\n        escape = '&quot;';\n        break;\n      case 38:\n        // &\n        escape = '&amp;';\n        break;\n      case 39:\n        // '\n        escape = '&#x27;'; // modified from escape-html; used to be '&#39'\n        break;\n      case 60:\n        // <\n        escape = '&lt;';\n        break;\n      case 62:\n        // >\n        escape = '&gt;';\n        break;\n      default:\n        continue;\n    }\n\n    if (lastIndex !== index) {\n      html += str.substring(lastIndex, index);\n    }\n\n    lastIndex = index + 1;\n    html += escape;\n  }\n\n  return lastIndex !== index ? html + str.substring(lastIndex, index) : html;\n}\n// end code copied and modified from escape-html\n\n/**\n * Escapes text to prevent scripting attacks.\n *\n * @param {*} text Text value to escape.\n * @return {string} An escaped string.\n */\nfunction escapeTextContentForBrowser(text) {\n  if (typeof text === 'boolean' || typeof text === 'number') {\n    // this shortcircuit helps perf for types that we know will never have\n    // special characters, especially given that this function is used often\n    // for numeric dom ids.\n    return '' + text;\n  }\n  return escapeHtml(text);\n}\n\nmodule.exports = escapeTextContentForBrowser;\n},{}],122:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule findDOMNode\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstanceMap = _dereq_(73);\n\nvar getHostComponentFromComposite = _dereq_(129);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Returns the DOM node rendered by this element.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode\n *\n * @param {ReactComponent|DOMElement} componentOrElement\n * @return {?DOMElement} The root node of this element.\n */\nfunction findDOMNode(componentOrElement) {\n  if (\"development\" !== 'production') {\n    var owner = ReactCurrentOwner.current;\n    if (owner !== null) {\n      \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n      owner._warnedAboutRefsInRender = true;\n    }\n  }\n  if (componentOrElement == null) {\n    return null;\n  }\n  if (componentOrElement.nodeType === 1) {\n    return componentOrElement;\n  }\n\n  var inst = ReactInstanceMap.get(componentOrElement);\n  if (inst) {\n    inst = getHostComponentFromComposite(inst);\n    return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null;\n  }\n\n  if (typeof componentOrElement.render === 'function') {\n    !false ? \"development\" !== 'production' ? invariant(false, 'findDOMNode was called on an unmounted component.') : _prodInvariant('44') : void 0;\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', Object.keys(componentOrElement)) : _prodInvariant('45', Object.keys(componentOrElement)) : void 0;\n  }\n}\n\nmodule.exports = findDOMNode;\n},{\"129\":129,\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"41\":41,\"73\":73}],123:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule flattenChildren\n * \n */\n\n'use strict';\n\nvar KeyEscapeUtils = _dereq_(23);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\n/**\n * @param {function} traverseContext Context passed through traversal.\n * @param {?ReactComponent} child React child component.\n * @param {!string} name String name of key path to child.\n * @param {number=} selfDebugID Optional debugID of the current internal instance.\n */\nfunction flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID) {\n  // We found a component instance.\n  if (traverseContext && typeof traverseContext === 'object') {\n    var result = traverseContext;\n    var keyUnique = result[name] === undefined;\n    if (\"development\" !== 'production') {\n      var ReactComponentTreeDevtool = _dereq_(34);\n      \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n    }\n    if (keyUnique && child != null) {\n      result[name] = child;\n    }\n  }\n}\n\n/**\n * Flattens children that are typically specified as `props.children`. Any null\n * children will not be included in the resulting object.\n * @return {!object} flattened children keyed by name.\n */\nfunction flattenChildren(children, selfDebugID) {\n  if (children == null) {\n    return children;\n  }\n  var result = {};\n\n  if (\"development\" !== 'production') {\n    traverseAllChildren(children, function (traverseContext, child, name) {\n      return flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID);\n    }, result);\n  } else {\n    traverseAllChildren(children, flattenSingleChildIntoContext, result);\n  }\n  return result;\n}\n\nmodule.exports = flattenChildren;\n},{\"144\":144,\"171\":171,\"23\":23,\"34\":34}],124:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule forEachAccumulated\n * \n */\n\n'use strict';\n\n/**\n * @param {array} arr an \"accumulation\" of items which is either an Array or\n * a single item. Useful when paired with the `accumulate` module. This is a\n * simple utility that allows us to reason about a collection of items, but\n * handling the case when there is exactly one item (and we do not need to\n * allocate an array).\n */\n\nfunction forEachAccumulated(arr, cb, scope) {\n  if (Array.isArray(arr)) {\n    arr.forEach(cb, scope);\n  } else if (arr) {\n    cb.call(scope, arr);\n  }\n}\n\nmodule.exports = forEachAccumulated;\n},{}],125:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventCharCode\n */\n\n'use strict';\n\n/**\n * `charCode` represents the actual \"character code\" and is safe to use with\n * `String.fromCharCode`. As such, only keys that correspond to printable\n * characters produce a valid `charCode`, the only exception to this is Enter.\n * The Tab-key is considered non-printable and does not have a `charCode`,\n * presumably because it does not produce a tab-character in browsers.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {number} Normalized `charCode` property.\n */\n\nfunction getEventCharCode(nativeEvent) {\n  var charCode;\n  var keyCode = nativeEvent.keyCode;\n\n  if ('charCode' in nativeEvent) {\n    charCode = nativeEvent.charCode;\n\n    // FF does not set `charCode` for the Enter-key, check against `keyCode`.\n    if (charCode === 0 && keyCode === 13) {\n      charCode = 13;\n    }\n  } else {\n    // IE8 does not implement `charCode`, but `keyCode` has the correct value.\n    charCode = keyCode;\n  }\n\n  // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.\n  // Must not discard the (non-)printable Enter-key.\n  if (charCode >= 32 || charCode === 13) {\n    return charCode;\n  }\n\n  return 0;\n}\n\nmodule.exports = getEventCharCode;\n},{}],126:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventKey\n */\n\n'use strict';\n\nvar getEventCharCode = _dereq_(125);\n\n/**\n * Normalization of deprecated HTML5 `key` values\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar normalizeKey = {\n  'Esc': 'Escape',\n  'Spacebar': ' ',\n  'Left': 'ArrowLeft',\n  'Up': 'ArrowUp',\n  'Right': 'ArrowRight',\n  'Down': 'ArrowDown',\n  'Del': 'Delete',\n  'Win': 'OS',\n  'Menu': 'ContextMenu',\n  'Apps': 'ContextMenu',\n  'Scroll': 'ScrollLock',\n  'MozPrintableKey': 'Unidentified'\n};\n\n/**\n * Translation from legacy `keyCode` to HTML5 `key`\n * Only special keys supported, all others depend on keyboard layout or browser\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar translateToKey = {\n  8: 'Backspace',\n  9: 'Tab',\n  12: 'Clear',\n  13: 'Enter',\n  16: 'Shift',\n  17: 'Control',\n  18: 'Alt',\n  19: 'Pause',\n  20: 'CapsLock',\n  27: 'Escape',\n  32: ' ',\n  33: 'PageUp',\n  34: 'PageDown',\n  35: 'End',\n  36: 'Home',\n  37: 'ArrowLeft',\n  38: 'ArrowUp',\n  39: 'ArrowRight',\n  40: 'ArrowDown',\n  45: 'Insert',\n  46: 'Delete',\n  112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',\n  118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12',\n  144: 'NumLock',\n  145: 'ScrollLock',\n  224: 'Meta'\n};\n\n/**\n * @param {object} nativeEvent Native browser event.\n * @return {string} Normalized `key` property.\n */\nfunction getEventKey(nativeEvent) {\n  if (nativeEvent.key) {\n    // Normalize inconsistent values reported by browsers due to\n    // implementations of a working draft specification.\n\n    // FireFox implements `key` but returns `MozPrintableKey` for all\n    // printable characters (normalized to `Unidentified`), ignore it.\n    var key = normalizeKey[nativeEvent.key] || nativeEvent.key;\n    if (key !== 'Unidentified') {\n      return key;\n    }\n  }\n\n  // Browser does not implement `key`, polyfill as much of it as we can.\n  if (nativeEvent.type === 'keypress') {\n    var charCode = getEventCharCode(nativeEvent);\n\n    // The enter-key is technically both printable and non-printable and can\n    // thus be captured by `keypress`, no other non-printable key should.\n    return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);\n  }\n  if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {\n    // While user keyboard layout determines the actual meaning of each\n    // `keyCode` value, almost all function keys have a universal value.\n    return translateToKey[nativeEvent.keyCode] || 'Unidentified';\n  }\n  return '';\n}\n\nmodule.exports = getEventKey;\n},{\"125\":125}],127:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventModifierState\n */\n\n'use strict';\n\n/**\n * Translation from modifier key to the associated property in the event.\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers\n */\n\nvar modifierKeyToProp = {\n  'Alt': 'altKey',\n  'Control': 'ctrlKey',\n  'Meta': 'metaKey',\n  'Shift': 'shiftKey'\n};\n\n// IE8 does not implement getModifierState so we simply map it to the only\n// modifier keys exposed by the event itself, does not support Lock-keys.\n// Currently, all major browsers except Chrome seems to support Lock-keys.\nfunction modifierStateGetter(keyArg) {\n  var syntheticEvent = this;\n  var nativeEvent = syntheticEvent.nativeEvent;\n  if (nativeEvent.getModifierState) {\n    return nativeEvent.getModifierState(keyArg);\n  }\n  var keyProp = modifierKeyToProp[keyArg];\n  return keyProp ? !!nativeEvent[keyProp] : false;\n}\n\nfunction getEventModifierState(nativeEvent) {\n  return modifierStateGetter;\n}\n\nmodule.exports = getEventModifierState;\n},{}],128:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventTarget\n */\n\n'use strict';\n\n/**\n * Gets the target node from a native browser event by accounting for\n * inconsistencies in browser DOM APIs.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {DOMEventTarget} Target node.\n */\n\nfunction getEventTarget(nativeEvent) {\n  var target = nativeEvent.target || nativeEvent.srcElement || window;\n\n  // Normalize SVG <use> element events #4963\n  if (target.correspondingUseElement) {\n    target = target.correspondingUseElement;\n  }\n\n  // Safari may fire events on text nodes (Node.TEXT_NODE is 3).\n  // @see http://www.quirksmode.org/js/events_properties.html\n  return target.nodeType === 3 ? target.parentNode : target;\n}\n\nmodule.exports = getEventTarget;\n},{}],129:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getHostComponentFromComposite\n */\n\n'use strict';\n\nvar ReactNodeTypes = _dereq_(80);\n\nfunction getHostComponentFromComposite(inst) {\n  var type;\n\n  while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {\n    inst = inst._renderedComponent;\n  }\n\n  if (type === ReactNodeTypes.HOST) {\n    return inst._renderedComponent;\n  } else if (type === ReactNodeTypes.EMPTY) {\n    return null;\n  }\n}\n\nmodule.exports = getHostComponentFromComposite;\n},{\"80\":80}],130:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getIteratorFn\n * \n */\n\n'use strict';\n\n/* global Symbol */\n\nvar ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.\n\n/**\n * Returns the iterator method function contained on the iterable object.\n *\n * Be sure to invoke the function with the iterable as context:\n *\n *     var iteratorFn = getIteratorFn(myIterable);\n *     if (iteratorFn) {\n *       var iterator = iteratorFn.call(myIterable);\n *       ...\n *     }\n *\n * @param {?object} maybeIterable\n * @return {?function}\n */\nfunction getIteratorFn(maybeIterable) {\n  var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);\n  if (typeof iteratorFn === 'function') {\n    return iteratorFn;\n  }\n}\n\nmodule.exports = getIteratorFn;\n},{}],131:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getNodeForCharacterOffset\n */\n\n'use strict';\n\n/**\n * Given any node return the first leaf node without children.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {DOMElement|DOMTextNode}\n */\n\nfunction getLeafNode(node) {\n  while (node && node.firstChild) {\n    node = node.firstChild;\n  }\n  return node;\n}\n\n/**\n * Get the next sibling within a container. This will walk up the\n * DOM if a node's siblings have been exhausted.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {?DOMElement|DOMTextNode}\n */\nfunction getSiblingNode(node) {\n  while (node) {\n    if (node.nextSibling) {\n      return node.nextSibling;\n    }\n    node = node.parentNode;\n  }\n}\n\n/**\n * Get object describing the nodes which contain characters at offset.\n *\n * @param {DOMElement|DOMTextNode} root\n * @param {number} offset\n * @return {?object}\n */\nfunction getNodeForCharacterOffset(root, offset) {\n  var node = getLeafNode(root);\n  var nodeStart = 0;\n  var nodeEnd = 0;\n\n  while (node) {\n    if (node.nodeType === 3) {\n      nodeEnd = nodeStart + node.textContent.length;\n\n      if (nodeStart <= offset && nodeEnd >= offset) {\n        return {\n          node: node,\n          offset: offset - nodeStart\n        };\n      }\n\n      nodeStart = nodeEnd;\n    }\n\n    node = getLeafNode(getSiblingNode(node));\n  }\n}\n\nmodule.exports = getNodeForCharacterOffset;\n},{}],132:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getTextContentAccessor\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar contentKey = null;\n\n/**\n * Gets the key used to access text content on a DOM node.\n *\n * @return {?string} Key used to access text content.\n * @internal\n */\nfunction getTextContentAccessor() {\n  if (!contentKey && ExecutionEnvironment.canUseDOM) {\n    // Prefer textContent to innerText because many browsers support both but\n    // SVG <text> elements don't support innerText even when <div> does.\n    contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';\n  }\n  return contentKey;\n}\n\nmodule.exports = getTextContentAccessor;\n},{\"147\":147}],133:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getVendorPrefixedEventName\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\n/**\n * Generate a mapping of standard vendor prefixes using the defined style property and event name.\n *\n * @param {string} styleProp\n * @param {string} eventName\n * @returns {object}\n */\nfunction makePrefixMap(styleProp, eventName) {\n  var prefixes = {};\n\n  prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();\n  prefixes['Webkit' + styleProp] = 'webkit' + eventName;\n  prefixes['Moz' + styleProp] = 'moz' + eventName;\n  prefixes['ms' + styleProp] = 'MS' + eventName;\n  prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();\n\n  return prefixes;\n}\n\n/**\n * A list of event names to a configurable list of vendor prefixes.\n */\nvar vendorPrefixes = {\n  animationend: makePrefixMap('Animation', 'AnimationEnd'),\n  animationiteration: makePrefixMap('Animation', 'AnimationIteration'),\n  animationstart: makePrefixMap('Animation', 'AnimationStart'),\n  transitionend: makePrefixMap('Transition', 'TransitionEnd')\n};\n\n/**\n * Event names that have already been detected and prefixed (if applicable).\n */\nvar prefixedEventNames = {};\n\n/**\n * Element to check for prefixes on.\n */\nvar style = {};\n\n/**\n * Bootstrap if a DOM exists.\n */\nif (ExecutionEnvironment.canUseDOM) {\n  style = document.createElement('div').style;\n\n  // On some platforms, in particular some releases of Android 4.x,\n  // the un-prefixed \"animation\" and \"transition\" properties are defined on the\n  // style object but the events that fire will still be prefixed, so we need\n  // to check if the un-prefixed events are usable, and if not remove them from the map.\n  if (!('AnimationEvent' in window)) {\n    delete vendorPrefixes.animationend.animation;\n    delete vendorPrefixes.animationiteration.animation;\n    delete vendorPrefixes.animationstart.animation;\n  }\n\n  // Same as above\n  if (!('TransitionEvent' in window)) {\n    delete vendorPrefixes.transitionend.transition;\n  }\n}\n\n/**\n * Attempts to determine the correct vendor prefixed event name.\n *\n * @param {string} eventName\n * @returns {string}\n */\nfunction getVendorPrefixedEventName(eventName) {\n  if (prefixedEventNames[eventName]) {\n    return prefixedEventNames[eventName];\n  } else if (!vendorPrefixes[eventName]) {\n    return eventName;\n  }\n\n  var prefixMap = vendorPrefixes[eventName];\n\n  for (var styleProp in prefixMap) {\n    if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {\n      return prefixedEventNames[eventName] = prefixMap[styleProp];\n    }\n  }\n\n  return '';\n}\n\nmodule.exports = getVendorPrefixedEventName;\n},{\"147\":147}],134:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule instantiateReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactCompositeComponent = _dereq_(35);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactHostComponent = _dereq_(69);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n// To avoid a cyclic dependency, we create the final class in this module\nvar ReactCompositeComponentWrapper = function (element) {\n  this.construct(element);\n};\n_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent.Mixin, {\n  _instantiateReactComponent: instantiateReactComponent\n});\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nfunction getDisplayName(instance) {\n  var element = instance._currentElement;\n  if (element == null) {\n    return '#empty';\n  } else if (typeof element === 'string' || typeof element === 'number') {\n    return '#text';\n  } else if (typeof element.type === 'string') {\n    return element.type;\n  } else if (instance.getName) {\n    return instance.getName() || 'Unknown';\n  } else {\n    return element.type.displayName || element.type.name || 'Unknown';\n  }\n}\n\n/**\n * Check if the type reference is a known internal type. I.e. not a user\n * provided composite type.\n *\n * @param {function} type\n * @return {boolean} Returns true if this is a valid internal type.\n */\nfunction isInternalComponentType(type) {\n  return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';\n}\n\nvar nextDebugID = 1;\n\n/**\n * Given a ReactNode, create an instance that will actually be mounted.\n *\n * @param {ReactNode} node\n * @param {boolean} shouldHaveDebugID\n * @return {object} A new instance of the element's constructor.\n * @protected\n */\nfunction instantiateReactComponent(node, shouldHaveDebugID) {\n  var instance;\n\n  if (node === null || node === false) {\n    instance = ReactEmptyComponent.create(instantiateReactComponent);\n  } else if (typeof node === 'object') {\n    var element = node;\n    !(element && (typeof element.type === 'function' || typeof element.type === 'string')) ? \"development\" !== 'production' ? invariant(false, 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : _prodInvariant('130', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : void 0;\n\n    // Special case string values\n    if (typeof element.type === 'string') {\n      instance = ReactHostComponent.createInternalComponent(element);\n    } else if (isInternalComponentType(element.type)) {\n      // This is temporarily available for custom components that are not string\n      // representations. I.e. ART. Once those are updated to use the string\n      // representation, we can drop this code path.\n      instance = new element.type(element);\n\n      // We renamed this. Allow the old name for compat. :(\n      if (!instance.getHostNode) {\n        instance.getHostNode = instance.getNativeNode;\n      }\n    } else {\n      instance = new ReactCompositeComponentWrapper(element);\n    }\n  } else if (typeof node === 'string' || typeof node === 'number') {\n    instance = ReactHostComponent.createInstanceForText(node);\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : _prodInvariant('131', typeof node) : void 0;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getHostNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;\n  }\n\n  // These two fields are used by the DOM and ART diffing algorithms\n  // respectively. Instead of using expandos on components, we should be\n  // storing the state needed by the diffing algorithms elsewhere.\n  instance._mountIndex = 0;\n  instance._mountImage = null;\n\n  if (\"development\" !== 'production') {\n    if (shouldHaveDebugID) {\n      var debugID = nextDebugID++;\n      instance._debugID = debugID;\n      var displayName = getDisplayName(instance);\n      ReactInstrumentation.debugTool.onSetDisplayName(debugID, displayName);\n      var owner = node && node._owner;\n      if (owner) {\n        ReactInstrumentation.debugTool.onSetOwner(debugID, owner._debugID);\n      }\n    } else {\n      instance._debugID = 0;\n    }\n  }\n\n  // Internal instances should fully constructed at this point, so they should\n  // not get any new fields added to them at this point.\n  if (\"development\" !== 'production') {\n    if (Object.preventExtensions) {\n      Object.preventExtensions(instance);\n    }\n  }\n\n  return instance;\n}\n\nmodule.exports = instantiateReactComponent;\n},{\"139\":139,\"161\":161,\"171\":171,\"172\":172,\"35\":35,\"64\":64,\"69\":69,\"74\":74}],135:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isEventSupported\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar useHasFeature;\nif (ExecutionEnvironment.canUseDOM) {\n  useHasFeature = document.implementation && document.implementation.hasFeature &&\n  // always returns true in newer browsers as per the standard.\n  // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature\n  document.implementation.hasFeature('', '') !== true;\n}\n\n/**\n * Checks if an event is supported in the current execution environment.\n *\n * NOTE: This will not work correctly for non-generic events such as `change`,\n * `reset`, `load`, `error`, and `select`.\n *\n * Borrows from Modernizr.\n *\n * @param {string} eventNameSuffix Event name, e.g. \"click\".\n * @param {?boolean} capture Check if the capture phase is supported.\n * @return {boolean} True if the event is supported.\n * @internal\n * @license Modernizr 3.0.0pre (Custom Build) | MIT\n */\nfunction isEventSupported(eventNameSuffix, capture) {\n  if (!ExecutionEnvironment.canUseDOM || capture && !('addEventListener' in document)) {\n    return false;\n  }\n\n  var eventName = 'on' + eventNameSuffix;\n  var isSupported = eventName in document;\n\n  if (!isSupported) {\n    var element = document.createElement('div');\n    element.setAttribute(eventName, 'return;');\n    isSupported = typeof element[eventName] === 'function';\n  }\n\n  if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {\n    // This is the only way to test support for the `wheel` event in IE9+.\n    isSupported = document.implementation.hasFeature('Events.wheel', '3.0');\n  }\n\n  return isSupported;\n}\n\nmodule.exports = isEventSupported;\n},{\"147\":147}],136:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isTextInputElement\n * \n */\n\n'use strict';\n\n/**\n * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary\n */\n\nvar supportedInputTypes = {\n  'color': true,\n  'date': true,\n  'datetime': true,\n  'datetime-local': true,\n  'email': true,\n  'month': true,\n  'number': true,\n  'password': true,\n  'range': true,\n  'search': true,\n  'tel': true,\n  'text': true,\n  'time': true,\n  'url': true,\n  'week': true\n};\n\nfunction isTextInputElement(elem) {\n  var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n\n  if (nodeName === 'input') {\n    return !!supportedInputTypes[elem.type];\n  }\n\n  if (nodeName === 'textarea') {\n    return true;\n  }\n\n  return false;\n}\n\nmodule.exports = isTextInputElement;\n},{}],137:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule onlyChild\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\n/**\n * Returns the first child in a collection of children and verifies that there\n * is only one child in the collection.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.only\n *\n * The current implementation of this function assumes that a single child gets\n * passed without a wrapper, but the purpose of this helper function is to\n * abstract away the particular structure of children.\n *\n * @param {?object} children Child collection structure.\n * @return {ReactElement} The first and only `ReactElement` contained in the\n * structure.\n */\nfunction onlyChild(children) {\n  !ReactElement.isValidElement(children) ? \"development\" !== 'production' ? invariant(false, 'onlyChild must be passed a children with exactly one child.') : _prodInvariant('23') : void 0;\n  return children;\n}\n\nmodule.exports = onlyChild;\n},{\"139\":139,\"161\":161,\"62\":62}],138:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule quoteAttributeValueForBrowser\n */\n\n'use strict';\n\nvar escapeTextContentForBrowser = _dereq_(121);\n\n/**\n * Escapes attribute value to prevent scripting attacks.\n *\n * @param {*} value Value to escape.\n * @return {string} An escaped string.\n */\nfunction quoteAttributeValueForBrowser(value) {\n  return '\"' + escapeTextContentForBrowser(value) + '\"';\n}\n\nmodule.exports = quoteAttributeValueForBrowser;\n},{\"121\":121}],139:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule reactProdInvariant\n * \n */\n'use strict';\n\n/**\n * WARNING: DO NOT manually require this module.\n * This is a replacement for `invariant(...)` used by the error code system\n * and will _only_ be required by the corresponding babel pass.\n * It always throws.\n */\n\nfunction reactProdInvariant(code) {\n  var argCount = arguments.length - 1;\n\n  var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;\n\n  for (var argIdx = 0; argIdx < argCount; argIdx++) {\n    message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);\n  }\n\n  message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';\n\n  var error = new Error(message);\n  error.name = 'Invariant Violation';\n  error.framesToPop = 1; // we don't care about reactProdInvariant's own frame\n\n  throw error;\n}\n\nmodule.exports = reactProdInvariant;\n},{}],140:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n* @providesModule renderSubtreeIntoContainer\n*/\n\n'use strict';\n\nvar ReactMount = _dereq_(77);\n\nmodule.exports = ReactMount.renderSubtreeIntoContainer;\n},{\"77\":77}],141:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setInnerHTML\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar DOMNamespaces = _dereq_(9);\n\nvar WHITESPACE_TEST = /^[ \\r\\n\\t\\f]/;\nvar NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \\r\\n\\t\\f\\/>]/;\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\n\n// SVG temp container for IE lacking innerHTML\nvar reusableSVGContainer;\n\n/**\n * Set the innerHTML property of a node, ensuring that whitespace is preserved\n * even in IE8.\n *\n * @param {DOMElement} node\n * @param {string} html\n * @internal\n */\nvar setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {\n  // IE does not have innerHTML for SVG nodes, so instead we inject the\n  // new markup in a temp node and then move the child nodes across into\n  // the target node\n  if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {\n    reusableSVGContainer = reusableSVGContainer || document.createElement('div');\n    reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';\n    var newNodes = reusableSVGContainer.firstChild.childNodes;\n    for (var i = 0; i < newNodes.length; i++) {\n      node.appendChild(newNodes[i]);\n    }\n  } else {\n    node.innerHTML = html;\n  }\n});\n\nif (ExecutionEnvironment.canUseDOM) {\n  // IE8: When updating a just created node with innerHTML only leading\n  // whitespace is removed. When updating an existing node with innerHTML\n  // whitespace in root TextNodes is also collapsed.\n  // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html\n\n  // Feature detection; only IE8 is known to behave improperly like this.\n  var testElement = document.createElement('div');\n  testElement.innerHTML = ' ';\n  if (testElement.innerHTML === '') {\n    setInnerHTML = function (node, html) {\n      // Magic theory: IE8 supposedly differentiates between added and updated\n      // nodes when processing innerHTML, innerHTML on updated nodes suffers\n      // from worse whitespace behavior. Re-adding a node like this triggers\n      // the initial and more favorable whitespace behavior.\n      // TODO: What to do on a detached node?\n      if (node.parentNode) {\n        node.parentNode.replaceChild(node, node);\n      }\n\n      // We also implement a workaround for non-visible tags disappearing into\n      // thin air on IE8, this only happens if there is no visible text\n      // in-front of the non-visible tags. Piggyback on the whitespace fix\n      // and simply check if any non-visible tags appear in the source.\n      if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {\n        // Recover leading whitespace by temporarily prepending any character.\n        // \\uFEFF has the potential advantage of being zero-width/invisible.\n        // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode\n        // in hopes that this is preserved even if \"\\uFEFF\" is transformed to\n        // the actual Unicode character (by Babel, for example).\n        // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216\n        node.innerHTML = String.fromCharCode(0xFEFF) + html;\n\n        // deleteData leaves an empty `TextNode` which offsets the index of all\n        // children. Definitely want to avoid this.\n        var textNode = node.firstChild;\n        if (textNode.data.length === 1) {\n          node.removeChild(textNode);\n        } else {\n          textNode.deleteData(0, 1);\n        }\n      } else {\n        node.innerHTML = html;\n      }\n    };\n  }\n  testElement = null;\n}\n\nmodule.exports = setInnerHTML;\n},{\"119\":119,\"147\":147,\"9\":9}],142:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setTextContent\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar setInnerHTML = _dereq_(141);\n\n/**\n * Set the textContent property of a node, ensuring that whitespace is preserved\n * even in IE8. innerText is a poor substitute for textContent and, among many\n * issues, inserts <br> instead of the literal newline chars. innerHTML behaves\n * as it should.\n *\n * @param {DOMElement} node\n * @param {string} text\n * @internal\n */\nvar setTextContent = function (node, text) {\n  if (text) {\n    var firstChild = node.firstChild;\n\n    if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {\n      firstChild.nodeValue = text;\n      return;\n    }\n  }\n  node.textContent = text;\n};\n\nif (ExecutionEnvironment.canUseDOM) {\n  if (!('textContent' in document.documentElement)) {\n    setTextContent = function (node, text) {\n      setInnerHTML(node, escapeTextContentForBrowser(text));\n    };\n  }\n}\n\nmodule.exports = setTextContent;\n},{\"121\":121,\"141\":141,\"147\":147}],143:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule shouldUpdateReactComponent\n */\n\n'use strict';\n\n/**\n * Given a `prevElement` and `nextElement`, determines if the existing\n * instance should be updated as opposed to being destroyed or replaced by a new\n * instance. Both arguments are elements. This ensures that this logic can\n * operate on stateless trees without any backing instance.\n *\n * @param {?object} prevElement\n * @param {?object} nextElement\n * @return {boolean} True if the existing instance should be updated.\n * @protected\n */\n\nfunction shouldUpdateReactComponent(prevElement, nextElement) {\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n  if (prevEmpty || nextEmpty) {\n    return prevEmpty === nextEmpty;\n  }\n\n  var prevType = typeof prevElement;\n  var nextType = typeof nextElement;\n  if (prevType === 'string' || prevType === 'number') {\n    return nextType === 'string' || nextType === 'number';\n  } else {\n    return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key;\n  }\n}\n\nmodule.exports = shouldUpdateReactComponent;\n},{}],144:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule traverseAllChildren\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\n\nvar getIteratorFn = _dereq_(130);\nvar invariant = _dereq_(161);\nvar KeyEscapeUtils = _dereq_(23);\nvar warning = _dereq_(171);\n\nvar SEPARATOR = '.';\nvar SUBSEPARATOR = ':';\n\n/**\n * TODO: Test that a single child and an array with one item have the same key\n * pattern.\n */\n\nvar didWarnAboutMaps = false;\n\n/**\n * Generate a key string that identifies a component within a set.\n *\n * @param {*} component A component that could contain a manual key.\n * @param {number} index Index that is used if a manual key is not provided.\n * @return {string}\n */\nfunction getComponentKey(component, index) {\n  // Do some typechecking here since we call this blindly. We want to ensure\n  // that we don't block potential future ES APIs.\n  if (component && typeof component === 'object' && component.key != null) {\n    // Explicit key\n    return KeyEscapeUtils.escape(component.key);\n  }\n  // Implicit key determined by the index in the set\n  return index.toString(36);\n}\n\n/**\n * @param {?*} children Children tree container.\n * @param {!string} nameSoFar Name of the key path so far.\n * @param {!function} callback Callback to invoke with each child found.\n * @param {?*} traverseContext Used to pass information throughout the traversal\n * process.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {\n  var type = typeof children;\n\n  if (type === 'undefined' || type === 'boolean') {\n    // All of the above are perceived as null.\n    children = null;\n  }\n\n  if (children === null || type === 'string' || type === 'number' || ReactElement.isValidElement(children)) {\n    callback(traverseContext, children,\n    // If it's the only child, treat the name as if it was wrapped in an array\n    // so that it's consistent if the number of children grows.\n    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);\n    return 1;\n  }\n\n  var child;\n  var nextName;\n  var subtreeCount = 0; // Count of children found in the current subtree.\n  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;\n\n  if (Array.isArray(children)) {\n    for (var i = 0; i < children.length; i++) {\n      child = children[i];\n      nextName = nextNamePrefix + getComponentKey(child, i);\n      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n    }\n  } else {\n    var iteratorFn = getIteratorFn(children);\n    if (iteratorFn) {\n      var iterator = iteratorFn.call(children);\n      var step;\n      if (iteratorFn !== children.entries) {\n        var ii = 0;\n        while (!(step = iterator.next()).done) {\n          child = step.value;\n          nextName = nextNamePrefix + getComponentKey(child, ii++);\n          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n        }\n      } else {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : void 0;\n          didWarnAboutMaps = true;\n        }\n        // Iterator will provide entry [k,v] tuples rather than values.\n        while (!(step = iterator.next()).done) {\n          var entry = step.value;\n          if (entry) {\n            child = entry[1];\n            nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);\n            subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n          }\n        }\n      }\n    } else if (type === 'object') {\n      var addendum = '';\n      if (\"development\" !== 'production') {\n        addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';\n        if (children._isReactElement) {\n          addendum = ' It looks like you\\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.';\n        }\n        if (ReactCurrentOwner.current) {\n          var name = ReactCurrentOwner.current.getName();\n          if (name) {\n            addendum += ' Check the render method of `' + name + '`.';\n          }\n        }\n      }\n      var childrenString = String(children);\n      !false ? \"development\" !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0;\n    }\n  }\n\n  return subtreeCount;\n}\n\n/**\n * Traverses children that are typically specified as `props.children`, but\n * might also be specified through attributes:\n *\n * - `traverseAllChildren(this.props.children, ...)`\n * - `traverseAllChildren(this.props.leftPanelChildren, ...)`\n *\n * The `traverseContext` is an optional argument that is passed through the\n * entire traversal. It can be used to store accumulations or anything else that\n * the callback might find relevant.\n *\n * @param {?*} children Children tree object.\n * @param {!function} callback To invoke upon traversing each child.\n * @param {?*} traverseContext Context for traversal.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildren(children, callback, traverseContext) {\n  if (children == null) {\n    return 0;\n  }\n\n  return traverseAllChildrenImpl(children, '', callback, traverseContext);\n}\n\nmodule.exports = traverseAllChildren;\n},{\"130\":130,\"139\":139,\"161\":161,\"171\":171,\"23\":23,\"36\":36,\"62\":62}],145:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule validateDOMNesting\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar validateDOMNesting = emptyFunction;\n\nif (\"development\" !== 'production') {\n  // This validation code was written based on the HTML5 parsing spec:\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  //\n  // Note: this does not catch all invalid nesting, nor does it try to (as it's\n  // not clear what practical benefit doing so provides); instead, we warn only\n  // for cases where the parser will give a parse tree differing from what React\n  // intended. For example, <b><div></div></b> is invalid but we don't warn\n  // because it still parses correctly; we do warn for other cases like nested\n  // <p> tags where the beginning of the second element implicitly closes the\n  // first, causing a confusing mess.\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#special\n  var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point\n  // TODO: Distinguish by namespace here -- for <title>, including it here\n  // errs on the side of fewer warnings\n  'foreignObject', 'desc', 'title'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope\n  var buttonScopeTags = inScopeTags.concat(['button']);\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags\n  var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];\n\n  var emptyAncestorInfo = {\n    current: null,\n\n    formTag: null,\n    aTagInScope: null,\n    buttonTagInScope: null,\n    nobrTagInScope: null,\n    pTagInButtonScope: null,\n\n    listItemTagAutoclosing: null,\n    dlItemTagAutoclosing: null\n  };\n\n  var updatedAncestorInfo = function (oldInfo, tag, instance) {\n    var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);\n    var info = { tag: tag, instance: instance };\n\n    if (inScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.aTagInScope = null;\n      ancestorInfo.buttonTagInScope = null;\n      ancestorInfo.nobrTagInScope = null;\n    }\n    if (buttonScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.pTagInButtonScope = null;\n    }\n\n    // See rules for 'li', 'dd', 'dt' start tags in\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {\n      ancestorInfo.listItemTagAutoclosing = null;\n      ancestorInfo.dlItemTagAutoclosing = null;\n    }\n\n    ancestorInfo.current = info;\n\n    if (tag === 'form') {\n      ancestorInfo.formTag = info;\n    }\n    if (tag === 'a') {\n      ancestorInfo.aTagInScope = info;\n    }\n    if (tag === 'button') {\n      ancestorInfo.buttonTagInScope = info;\n    }\n    if (tag === 'nobr') {\n      ancestorInfo.nobrTagInScope = info;\n    }\n    if (tag === 'p') {\n      ancestorInfo.pTagInButtonScope = info;\n    }\n    if (tag === 'li') {\n      ancestorInfo.listItemTagAutoclosing = info;\n    }\n    if (tag === 'dd' || tag === 'dt') {\n      ancestorInfo.dlItemTagAutoclosing = info;\n    }\n\n    return ancestorInfo;\n  };\n\n  /**\n   * Returns whether\n   */\n  var isTagValidWithParent = function (tag, parentTag) {\n    // First, let's check if we're in an unusual parsing mode...\n    switch (parentTag) {\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect\n      case 'select':\n        return tag === 'option' || tag === 'optgroup' || tag === '#text';\n      case 'optgroup':\n        return tag === 'option' || tag === '#text';\n      // Strictly speaking, seeing an <option> doesn't mean we're in a <select>\n      // but\n      case 'option':\n        return tag === '#text';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption\n      // No special behavior since these rules fall back to \"in body\" mode for\n      // all except special table nodes which cause bad parsing behavior anyway.\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr\n      case 'tr':\n        return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody\n      case 'tbody':\n      case 'thead':\n      case 'tfoot':\n        return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup\n      case 'colgroup':\n        return tag === 'col' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable\n      case 'table':\n        return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead\n      case 'head':\n        return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element\n      case 'html':\n        return tag === 'head' || tag === 'body';\n      case '#document':\n        return tag === 'html';\n    }\n\n    // Probably in the \"in body\" parsing mode, so we outlaw only tag combos\n    // where the parsing rules cause implicit opens or closes to be added.\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    switch (tag) {\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';\n\n      case 'rp':\n      case 'rt':\n        return impliedEndTags.indexOf(parentTag) === -1;\n\n      case 'body':\n      case 'caption':\n      case 'col':\n      case 'colgroup':\n      case 'frame':\n      case 'head':\n      case 'html':\n      case 'tbody':\n      case 'td':\n      case 'tfoot':\n      case 'th':\n      case 'thead':\n      case 'tr':\n        // These tags are only valid with a few parents that have special child\n        // parsing rules -- if we're down here, then none of those matched and\n        // so we allow it only if we don't know what the parent is, as all other\n        // cases are invalid.\n        return parentTag == null;\n    }\n\n    return true;\n  };\n\n  /**\n   * Returns whether\n   */\n  var findInvalidAncestorForTag = function (tag, ancestorInfo) {\n    switch (tag) {\n      case 'address':\n      case 'article':\n      case 'aside':\n      case 'blockquote':\n      case 'center':\n      case 'details':\n      case 'dialog':\n      case 'dir':\n      case 'div':\n      case 'dl':\n      case 'fieldset':\n      case 'figcaption':\n      case 'figure':\n      case 'footer':\n      case 'header':\n      case 'hgroup':\n      case 'main':\n      case 'menu':\n      case 'nav':\n      case 'ol':\n      case 'p':\n      case 'section':\n      case 'summary':\n      case 'ul':\n\n      case 'pre':\n      case 'listing':\n\n      case 'table':\n\n      case 'hr':\n\n      case 'xmp':\n\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return ancestorInfo.pTagInButtonScope;\n\n      case 'form':\n        return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;\n\n      case 'li':\n        return ancestorInfo.listItemTagAutoclosing;\n\n      case 'dd':\n      case 'dt':\n        return ancestorInfo.dlItemTagAutoclosing;\n\n      case 'button':\n        return ancestorInfo.buttonTagInScope;\n\n      case 'a':\n        // Spec says something about storing a list of markers, but it sounds\n        // equivalent to this check.\n        return ancestorInfo.aTagInScope;\n\n      case 'nobr':\n        return ancestorInfo.nobrTagInScope;\n    }\n\n    return null;\n  };\n\n  /**\n   * Given a ReactCompositeComponent instance, return a list of its recursive\n   * owners, starting at the root and ending with the instance itself.\n   */\n  var findOwnerStack = function (instance) {\n    if (!instance) {\n      return [];\n    }\n\n    var stack = [];\n    do {\n      stack.push(instance);\n    } while (instance = instance._currentElement._owner);\n    stack.reverse();\n    return stack;\n  };\n\n  var didWarn = {};\n\n  validateDOMNesting = function (childTag, childInstance, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n\n    var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;\n    var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);\n    var problematic = invalidParent || invalidAncestor;\n\n    if (problematic) {\n      var ancestorTag = problematic.tag;\n      var ancestorInstance = problematic.instance;\n\n      var childOwner = childInstance && childInstance._currentElement._owner;\n      var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;\n\n      var childOwners = findOwnerStack(childOwner);\n      var ancestorOwners = findOwnerStack(ancestorOwner);\n\n      var minStackLen = Math.min(childOwners.length, ancestorOwners.length);\n      var i;\n\n      var deepestCommon = -1;\n      for (i = 0; i < minStackLen; i++) {\n        if (childOwners[i] === ancestorOwners[i]) {\n          deepestCommon = i;\n        } else {\n          break;\n        }\n      }\n\n      var UNKNOWN = '(unknown)';\n      var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ownerInfo = [].concat(\n      // If the parent and child instances have a common owner ancestor, start\n      // with that -- otherwise we just start with the parent's owners.\n      deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,\n      // If we're warning about an invalid (non-parent) ancestry, add '...'\n      invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');\n\n      var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;\n      if (didWarn[warnKey]) {\n        return;\n      }\n      didWarn[warnKey] = true;\n\n      var tagDisplayName = childTag;\n      if (childTag !== '#text') {\n        tagDisplayName = '<' + childTag + '>';\n      }\n\n      if (invalidParent) {\n        var info = '';\n        if (ancestorTag === 'table' && childTag === 'tr') {\n          info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';\n        }\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>. ' + 'See %s.%s', tagDisplayName, ancestorTag, ownerInfo, info) : void 0;\n      } else {\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;\n      }\n    }\n  };\n\n  validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;\n\n  // For testing\n  validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n    return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);\n  };\n}\n\nmodule.exports = validateDOMNesting;\n},{\"153\":153,\"171\":171,\"172\":172}],146:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * @typechecks\n */\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Upstream version of event listener. Does not take into account specific\n * nature of platform.\n */\nvar EventListener = {\n  /**\n   * Listen to DOM events during the bubble phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  listen: function listen(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, false);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, false);\n        }\n      };\n    } else if (target.attachEvent) {\n      target.attachEvent('on' + eventType, callback);\n      return {\n        remove: function remove() {\n          target.detachEvent('on' + eventType, callback);\n        }\n      };\n    }\n  },\n\n  /**\n   * Listen to DOM events during the capture phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  capture: function capture(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, true);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, true);\n        }\n      };\n    } else {\n      if (\"development\" !== 'production') {\n        console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');\n      }\n      return {\n        remove: emptyFunction\n      };\n    }\n  },\n\n  registerDefault: function registerDefault() {}\n};\n\nmodule.exports = EventListener;\n},{\"153\":153}],147:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);\n\n/**\n * Simple, lightweight module assisting with the detection and context of\n * Worker. Helps avoid circular dependencies and allows code to reason about\n * whether or not they are in a Worker, even if they never include the main\n * `ReactWorker` dependency.\n */\nvar ExecutionEnvironment = {\n\n  canUseDOM: canUseDOM,\n\n  canUseWorkers: typeof Worker !== 'undefined',\n\n  canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),\n\n  canUseViewport: canUseDOM && !!window.screen,\n\n  isInWorker: !canUseDOM // For now, this is true - might change in the future.\n\n};\n\nmodule.exports = ExecutionEnvironment;\n},{}],148:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _hyphenPattern = /-(.)/g;\n\n/**\n * Camelcases a hyphenated string, for example:\n *\n *   > camelize('background-color')\n *   < \"backgroundColor\"\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelize(string) {\n  return string.replace(_hyphenPattern, function (_, character) {\n    return character.toUpperCase();\n  });\n}\n\nmodule.exports = camelize;\n},{}],149:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar camelize = _dereq_(148);\n\nvar msPattern = /^-ms-/;\n\n/**\n * Camelcases a hyphenated CSS property name, for example:\n *\n *   > camelizeStyleName('background-color')\n *   < \"backgroundColor\"\n *   > camelizeStyleName('-moz-transition')\n *   < \"MozTransition\"\n *   > camelizeStyleName('-ms-transition')\n *   < \"msTransition\"\n *\n * As Andi Smith suggests\n * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix\n * is converted to lowercase `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelizeStyleName(string) {\n  return camelize(string.replace(msPattern, 'ms-'));\n}\n\nmodule.exports = camelizeStyleName;\n},{\"148\":148}],150:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nvar isTextNode = _dereq_(163);\n\n/*eslint-disable no-bitwise */\n\n/**\n * Checks if a given DOM node contains or is another DOM node.\n */\nfunction containsNode(outerNode, innerNode) {\n  if (!outerNode || !innerNode) {\n    return false;\n  } else if (outerNode === innerNode) {\n    return true;\n  } else if (isTextNode(outerNode)) {\n    return false;\n  } else if (isTextNode(innerNode)) {\n    return containsNode(outerNode, innerNode.parentNode);\n  } else if ('contains' in outerNode) {\n    return outerNode.contains(innerNode);\n  } else if (outerNode.compareDocumentPosition) {\n    return !!(outerNode.compareDocumentPosition(innerNode) & 16);\n  } else {\n    return false;\n  }\n}\n\nmodule.exports = containsNode;\n},{\"163\":163}],151:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar invariant = _dereq_(161);\n\n/**\n * Convert array-like objects to arrays.\n *\n * This API assumes the caller knows the contents of the data type. For less\n * well defined inputs use createArrayFromMixed.\n *\n * @param {object|function|filelist} obj\n * @return {array}\n */\nfunction toArray(obj) {\n  var length = obj.length;\n\n  // Some browsers builtin objects can report typeof 'function' (e.g. NodeList\n  // in old versions of Safari).\n  !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? \"development\" !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0;\n\n  !(typeof length === 'number') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0;\n\n  !(length === 0 || length - 1 in obj) ? \"development\" !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0;\n\n  !(typeof obj.callee !== 'function') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object can\\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0;\n\n  // Old IE doesn't give collections access to hasOwnProperty. Assume inputs\n  // without method will throw during the slice call and skip straight to the\n  // fallback.\n  if (obj.hasOwnProperty) {\n    try {\n      return Array.prototype.slice.call(obj);\n    } catch (e) {\n      // IE < 9 does not support Array#slice on collections objects\n    }\n  }\n\n  // Fall back to copying key by key. This assumes all keys have a value,\n  // so will not preserve sparsely populated inputs.\n  var ret = Array(length);\n  for (var ii = 0; ii < length; ii++) {\n    ret[ii] = obj[ii];\n  }\n  return ret;\n}\n\n/**\n * Perform a heuristic test to determine if an object is \"array-like\".\n *\n *   A monk asked Joshu, a Zen master, \"Has a dog Buddha nature?\"\n *   Joshu replied: \"Mu.\"\n *\n * This function determines if its argument has \"array nature\": it returns\n * true if the argument is an actual array, an `arguments' object, or an\n * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).\n *\n * It will return false for other array-like objects like Filelist.\n *\n * @param {*} obj\n * @return {boolean}\n */\nfunction hasArrayNature(obj) {\n  return(\n    // not null/false\n    !!obj && (\n    // arrays are objects, NodeLists are functions in Safari\n    typeof obj == 'object' || typeof obj == 'function') &&\n    // quacks like an array\n    'length' in obj &&\n    // not window\n    !('setInterval' in obj) &&\n    // no DOM node should be considered an array-like\n    // a 'select' element has 'length' and 'item' properties on IE8\n    typeof obj.nodeType != 'number' && (\n    // a real array\n    Array.isArray(obj) ||\n    // arguments\n    'callee' in obj ||\n    // HTMLCollection/NodeList\n    'item' in obj)\n  );\n}\n\n/**\n * Ensure that the argument is an array by wrapping it in an array if it is not.\n * Creates a copy of the argument if it is already an array.\n *\n * This is mostly useful idiomatically:\n *\n *   var createArrayFromMixed = require('createArrayFromMixed');\n *\n *   function takesOneOrMoreThings(things) {\n *     things = createArrayFromMixed(things);\n *     ...\n *   }\n *\n * This allows you to treat `things' as an array, but accept scalars in the API.\n *\n * If you need to convert an array-like object, like `arguments`, into an array\n * use toArray instead.\n *\n * @param {*} obj\n * @return {array}\n */\nfunction createArrayFromMixed(obj) {\n  if (!hasArrayNature(obj)) {\n    return [obj];\n  } else if (Array.isArray(obj)) {\n    return obj.slice();\n  } else {\n    return toArray(obj);\n  }\n}\n\nmodule.exports = createArrayFromMixed;\n},{\"161\":161}],152:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/*eslint-disable fb-www/unsafe-html*/\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createArrayFromMixed = _dereq_(151);\nvar getMarkupWrap = _dereq_(157);\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to render all markup.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Pattern used by `getNodeName`.\n */\nvar nodeNamePattern = /^\\s*<(\\w+)/;\n\n/**\n * Extracts the `nodeName` of the first element in a string of markup.\n *\n * @param {string} markup String of markup.\n * @return {?string} Node name of the supplied markup.\n */\nfunction getNodeName(markup) {\n  var nodeNameMatch = markup.match(nodeNamePattern);\n  return nodeNameMatch && nodeNameMatch[1].toLowerCase();\n}\n\n/**\n * Creates an array containing the nodes rendered from the supplied markup. The\n * optionally supplied `handleScript` function will be invoked once for each\n * <script> element that is rendered. If no `handleScript` function is supplied,\n * an exception is thrown if any <script> elements are rendered.\n *\n * @param {string} markup A string of valid HTML markup.\n * @param {?function} handleScript Invoked once for each rendered <script>.\n * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.\n */\nfunction createNodesFromMarkup(markup, handleScript) {\n  var node = dummyNode;\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;\n  var nodeName = getNodeName(markup);\n\n  var wrap = nodeName && getMarkupWrap(nodeName);\n  if (wrap) {\n    node.innerHTML = wrap[1] + markup + wrap[2];\n\n    var wrapDepth = wrap[0];\n    while (wrapDepth--) {\n      node = node.lastChild;\n    }\n  } else {\n    node.innerHTML = markup;\n  }\n\n  var scripts = node.getElementsByTagName('script');\n  if (scripts.length) {\n    !handleScript ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;\n    createArrayFromMixed(scripts).forEach(handleScript);\n  }\n\n  var nodes = Array.from(node.childNodes);\n  while (node.lastChild) {\n    node.removeChild(node.lastChild);\n  }\n  return nodes;\n}\n\nmodule.exports = createNodesFromMarkup;\n},{\"147\":147,\"151\":151,\"157\":157,\"161\":161}],153:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nfunction makeEmptyFunction(arg) {\n  return function () {\n    return arg;\n  };\n}\n\n/**\n * This function accepts and discards inputs; it has no side effects. This is\n * primarily useful idiomatically for overridable function endpoints which\n * always need to be callable, since JS lacks a null-call idiom ala Cocoa.\n */\nvar emptyFunction = function emptyFunction() {};\n\nemptyFunction.thatReturns = makeEmptyFunction;\nemptyFunction.thatReturnsFalse = makeEmptyFunction(false);\nemptyFunction.thatReturnsTrue = makeEmptyFunction(true);\nemptyFunction.thatReturnsNull = makeEmptyFunction(null);\nemptyFunction.thatReturnsThis = function () {\n  return this;\n};\nemptyFunction.thatReturnsArgument = function (arg) {\n  return arg;\n};\n\nmodule.exports = emptyFunction;\n},{}],154:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyObject = {};\n\nif (\"development\" !== 'production') {\n  Object.freeze(emptyObject);\n}\n\nmodule.exports = emptyObject;\n},{}],155:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * @param {DOMElement} node input/textarea to focus\n */\n\nfunction focusNode(node) {\n  // IE8 can throw \"Can't move focus to the control because it is invisible,\n  // not enabled, or of a type that does not accept the focus.\" for all kinds of\n  // reasons that are too expensive and fragile to test.\n  try {\n    node.focus();\n  } catch (e) {}\n}\n\nmodule.exports = focusNode;\n},{}],156:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/* eslint-disable fb-www/typeof-undefined */\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n */\nfunction getActiveElement() /*?DOMElement*/{\n  if (typeof document === 'undefined') {\n    return null;\n  }\n  try {\n    return document.activeElement || document.body;\n  } catch (e) {\n    return document.body;\n  }\n}\n\nmodule.exports = getActiveElement;\n},{}],157:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/*eslint-disable fb-www/unsafe-html */\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to detect which wraps are necessary.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Some browsers cannot use `innerHTML` to render certain elements standalone,\n * so we wrap them, render the wrapped nodes, then extract the desired node.\n *\n * In IE8, certain elements cannot render alone, so wrap all elements ('*').\n */\n\nvar shouldWrap = {};\n\nvar selectWrap = [1, '<select multiple=\"true\">', '</select>'];\nvar tableWrap = [1, '<table>', '</table>'];\nvar trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];\n\nvar svgWrap = [1, '<svg xmlns=\"http://www.w3.org/2000/svg\">', '</svg>'];\n\nvar markupWrap = {\n  '*': [1, '?<div>', '</div>'],\n\n  'area': [1, '<map>', '</map>'],\n  'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],\n  'legend': [1, '<fieldset>', '</fieldset>'],\n  'param': [1, '<object>', '</object>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n\n  'optgroup': selectWrap,\n  'option': selectWrap,\n\n  'caption': tableWrap,\n  'colgroup': tableWrap,\n  'tbody': tableWrap,\n  'tfoot': tableWrap,\n  'thead': tableWrap,\n\n  'td': trWrap,\n  'th': trWrap\n};\n\n// Initialize the SVG elements since we know they'll always need to be wrapped\n// consistently. If they are created inside a <div> they will be initialized in\n// the wrong namespace (and will not display).\nvar svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];\nsvgElements.forEach(function (nodeName) {\n  markupWrap[nodeName] = svgWrap;\n  shouldWrap[nodeName] = true;\n});\n\n/**\n * Gets the markup wrap configuration for the supplied `nodeName`.\n *\n * NOTE: This lazily detects which wraps are necessary for the current browser.\n *\n * @param {string} nodeName Lowercase `nodeName`.\n * @return {?array} Markup wrap configuration, if applicable.\n */\nfunction getMarkupWrap(nodeName) {\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;\n  if (!markupWrap.hasOwnProperty(nodeName)) {\n    nodeName = '*';\n  }\n  if (!shouldWrap.hasOwnProperty(nodeName)) {\n    if (nodeName === '*') {\n      dummyNode.innerHTML = '<link />';\n    } else {\n      dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';\n    }\n    shouldWrap[nodeName] = !dummyNode.firstChild;\n  }\n  return shouldWrap[nodeName] ? markupWrap[nodeName] : null;\n}\n\nmodule.exports = getMarkupWrap;\n},{\"147\":147,\"161\":161}],158:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\n/**\n * Gets the scroll position of the supplied element or window.\n *\n * The return values are unbounded, unlike `getScrollPosition`. This means they\n * may be negative or exceed the element boundaries (which is possible using\n * inertial scrolling).\n *\n * @param {DOMWindow|DOMElement} scrollable\n * @return {object} Map with `x` and `y` keys.\n */\n\nfunction getUnboundedScrollPosition(scrollable) {\n  if (scrollable === window) {\n    return {\n      x: window.pageXOffset || document.documentElement.scrollLeft,\n      y: window.pageYOffset || document.documentElement.scrollTop\n    };\n  }\n  return {\n    x: scrollable.scrollLeft,\n    y: scrollable.scrollTop\n  };\n}\n\nmodule.exports = getUnboundedScrollPosition;\n},{}],159:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _uppercasePattern = /([A-Z])/g;\n\n/**\n * Hyphenates a camelcased string, for example:\n *\n *   > hyphenate('backgroundColor')\n *   < \"background-color\"\n *\n * For CSS style names, use `hyphenateStyleName` instead which works properly\n * with all vendor prefixes, including `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenate(string) {\n  return string.replace(_uppercasePattern, '-$1').toLowerCase();\n}\n\nmodule.exports = hyphenate;\n},{}],160:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar hyphenate = _dereq_(159);\n\nvar msPattern = /^ms-/;\n\n/**\n * Hyphenates a camelcased CSS property name, for example:\n *\n *   > hyphenateStyleName('backgroundColor')\n *   < \"background-color\"\n *   > hyphenateStyleName('MozTransition')\n *   < \"-moz-transition\"\n *   > hyphenateStyleName('msTransition')\n *   < \"-ms-transition\"\n *\n * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix\n * is converted to `-ms-`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenateStyleName(string) {\n  return hyphenate(string).replace(msPattern, '-ms-');\n}\n\nmodule.exports = hyphenateStyleName;\n},{\"159\":159}],161:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * Use invariant() to assert state which your program assumes to be true.\n *\n * Provide sprintf-style format (only %s is supported) and arguments\n * to provide information about what broke and what you were\n * expecting.\n *\n * The invariant message will be stripped in production, but the invariant\n * will remain to ensure logic does not differ in production.\n */\n\nfunction invariant(condition, format, a, b, c, d, e, f) {\n  if (\"development\" !== 'production') {\n    if (format === undefined) {\n      throw new Error('invariant requires an error message argument');\n    }\n  }\n\n  if (!condition) {\n    var error;\n    if (format === undefined) {\n      error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');\n    } else {\n      var args = [a, b, c, d, e, f];\n      var argIndex = 0;\n      error = new Error(format.replace(/%s/g, function () {\n        return args[argIndex++];\n      }));\n      error.name = 'Invariant Violation';\n    }\n\n    error.framesToPop = 1; // we don't care about invariant's own frame\n    throw error;\n  }\n}\n\nmodule.exports = invariant;\n},{}],162:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM node.\n */\nfunction isNode(object) {\n  return !!(object && (typeof Node === 'function' ? object instanceof Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));\n}\n\nmodule.exports = isNode;\n},{}],163:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar isNode = _dereq_(162);\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM text node.\n */\nfunction isTextNode(object) {\n  return isNode(object) && object.nodeType == 3;\n}\n\nmodule.exports = isTextNode;\n},{\"162\":162}],164:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks static-only\n */\n\n'use strict';\n\nvar invariant = _dereq_(161);\n\n/**\n * Constructs an enumeration with keys equal to their value.\n *\n * For example:\n *\n *   var COLORS = keyMirror({blue: null, red: null});\n *   var myColor = COLORS.blue;\n *   var isColorValid = !!COLORS[myColor];\n *\n * The last line could not be performed if the values of the generated enum were\n * not equal to their keys.\n *\n *   Input:  {key1: val1, key2: val2}\n *   Output: {key1: key1, key2: key2}\n *\n * @param {object} obj\n * @return {object}\n */\nvar keyMirror = function keyMirror(obj) {\n  var ret = {};\n  var key;\n  !(obj instanceof Object && !Array.isArray(obj)) ? \"development\" !== 'production' ? invariant(false, 'keyMirror(...): Argument must be an object.') : invariant(false) : void 0;\n  for (key in obj) {\n    if (!obj.hasOwnProperty(key)) {\n      continue;\n    }\n    ret[key] = key;\n  }\n  return ret;\n};\n\nmodule.exports = keyMirror;\n},{\"161\":161}],165:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/**\n * Allows extraction of a minified key. Let's the build system minify keys\n * without losing the ability to dynamically use key strings as values\n * themselves. Pass in an object with a single key/val pair and it will return\n * you the string key of that single record. Suppose you want to grab the\n * value for a key 'className' inside of an object. Key/val minification may\n * have aliased that key to be 'xa12'. keyOf({className: null}) will return\n * 'xa12' in that case. Resolve keys you want to use once at startup time, then\n * reuse those resolutions.\n */\nvar keyOf = function keyOf(oneKeyObj) {\n  var key;\n  for (key in oneKeyObj) {\n    if (!oneKeyObj.hasOwnProperty(key)) {\n      continue;\n    }\n    return key;\n  }\n  return null;\n};\n\nmodule.exports = keyOf;\n},{}],166:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Executes the provided `callback` once for each enumerable own property in the\n * object and constructs a new object from the results. The `callback` is\n * invoked with three arguments:\n *\n *  - the property value\n *  - the property name\n *  - the object being traversed\n *\n * Properties that are added after the call to `mapObject` will not be visited\n * by `callback`. If the values of existing properties are changed, the value\n * passed to `callback` will be the value at the time `mapObject` visits them.\n * Properties that are deleted before being visited are not visited.\n *\n * @grep function objectMap()\n * @grep function objMap()\n *\n * @param {?object} object\n * @param {function} callback\n * @param {*} context\n * @return {?object}\n */\nfunction mapObject(object, callback, context) {\n  if (!object) {\n    return null;\n  }\n  var result = {};\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result[name] = callback.call(context, object[name], name, object);\n    }\n  }\n  return result;\n}\n\nmodule.exports = mapObject;\n},{}],167:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n * @typechecks static-only\n */\n\n'use strict';\n\n/**\n * Memoizes the return value of a function that accepts one string argument.\n */\n\nfunction memoizeStringOnly(callback) {\n  var cache = {};\n  return function (string) {\n    if (!cache.hasOwnProperty(string)) {\n      cache[string] = callback.call(this, string);\n    }\n    return cache[string];\n  };\n}\n\nmodule.exports = memoizeStringOnly;\n},{}],168:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performance;\n\nif (ExecutionEnvironment.canUseDOM) {\n  performance = window.performance || window.msPerformance || window.webkitPerformance;\n}\n\nmodule.exports = performance || {};\n},{\"147\":147}],169:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar performance = _dereq_(168);\n\nvar performanceNow;\n\n/**\n * Detect if we can use `window.performance.now()` and gracefully fallback to\n * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now\n * because of Facebook's testing infrastructure.\n */\nif (performance.now) {\n  performanceNow = function performanceNow() {\n    return performance.now();\n  };\n} else {\n  performanceNow = function performanceNow() {\n    return Date.now();\n  };\n}\n\nmodule.exports = performanceNow;\n},{\"168\":168}],170:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n * \n */\n\n/*eslint-disable no-self-compare */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n\n/**\n * Performs equality by iterating through keys on an object and returning false\n * when any key has values which are not strictly equal between the arguments.\n * Returns true when the values of all keys are strictly equal.\n */\nfunction shallowEqual(objA, objB) {\n  if (is(objA, objB)) {\n    return true;\n  }\n\n  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n    return false;\n  }\n\n  var keysA = Object.keys(objA);\n  var keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (var i = 0; i < keysA.length; i++) {\n    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nmodule.exports = shallowEqual;\n},{}],171:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-2015, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Similar to invariant but only logs a warning if the condition is not met.\n * This can be used to log issues in development environments in critical\n * paths. Removing the logging code for production environments will keep the\n * same logic and follow the same code paths.\n */\n\nvar warning = emptyFunction;\n\nif (\"development\" !== 'production') {\n  warning = function warning(condition, format) {\n    for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n      args[_key - 2] = arguments[_key];\n    }\n\n    if (format === undefined) {\n      throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');\n    }\n\n    if (format.indexOf('Failed Composite propType: ') === 0) {\n      return; // Ignore CompositeComponent proptype check.\n    }\n\n    if (!condition) {\n      var argIndex = 0;\n      var message = 'Warning: ' + format.replace(/%s/g, function () {\n        return args[argIndex++];\n      });\n      if (typeof console !== 'undefined') {\n        console.error(message);\n      }\n      try {\n        // --- Welcome to debugging React ---\n        // This error was thrown as a convenience so that you can use this stack\n        // to find the callsite that caused this warning to fire.\n        throw new Error(message);\n      } catch (x) {}\n    }\n  };\n}\n\nmodule.exports = warning;\n},{\"153\":153}],172:[function(_dereq_,module,exports){\n'use strict';\n/* eslint-disable no-unused-vars */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc');  // eslint-disable-line\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (e) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (Object.getOwnPropertySymbols) {\n\t\t\tsymbols = Object.getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n\n},{}]},{},[93])(93)\n});"
  },
  {
    "path": "30-jstraining/demos/react-lifecycle-demo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"jquery.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\"></div>\n    <script type=\"text/babel\">\n  class MyList extends React.Component {\n    constructor(...args) {\n      super(...args);\n      this.state = {\n        loading: true,\n        error: null,\n        data: null\n      };\n    }\n\n    componentDidMount() {\n      const url = 'https://api.github.com/search/repositories?q=javascript&sort=stars';\n      $.getJSON(url)\n       .done(\n        (value) => this.setState({\n          loading: false,\n          data: value\n        })\n      ).fail(\n        (jqXHR, textStatus) => this.setState({\n          loading: false,\n          error: jqXHR.status\n        })\n      );\n    }\n\n    render() {\n      if (this.state.loading) {\n        return <span>Loading...</span>;\n      } else if (this.state.error !== null) {\n        return <span>Error: {this.state.error}</span>;\n      } else {\n        /* 你的代码填入这里 */\n        return (\n          <div>\n            <p>API 数据获取成功</p>\n            <p>改写代码，将结果显示在这里</p>\n          </div>\n        );\n      }\n    }\n  };\n\n  ReactDOM.render(\n    <MyList/>,\n    document.getElementById('example')\n  );\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/react-lifecycle-demo/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.11.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2015-04-28T16:19Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper window is present,\n\t\t// execute the factory and get jQuery\n\t\t// For environments that do not inherently posses a window with a document\n\t\t// (such as Node.js), expose a jQuery-making factory as module.exports\n\t\t// This accentuates the need for the creation of a real window\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Can't do this because several apps including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n// Support: Firefox 18+\n//\n\nvar deletedIds = [];\n\nvar slice = deletedIds.slice;\n\nvar concat = deletedIds.concat;\n\nvar push = deletedIds.push;\n\nvar indexOf = deletedIds.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n\tversion = \"1.11.3\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android<4.1, IE<9\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: deletedIds.sort,\n\tsplice: deletedIds.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar src, copyIsArray, copy, name, options, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\t/* jshint eqeqeq: false */\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\treturn !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\tvar key;\n\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Handle iteration over inherited properties before own properties.\n\t\tif ( support.ownLast ) {\n\t\t\tfor ( key in obj ) {\n\t\t\t\treturn hasOwn.call( obj, key );\n\t\t\t}\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && jQuery.trim( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android<4.1, IE<9\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\twhile ( j < len ) {\n\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)\n\t\tif ( len !== len ) {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: function() {\n\t\treturn +( new Date() );\n\t},\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\n\t// Support: iOS 8.2 (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = \"length\" in obj && obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\tnodeType = context.nodeType;\n\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\tif ( !seed && documentIsHTML ) {\n\n\t\t// Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType !== 1 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = attrs.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\tparent = doc.defaultView;\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Support tests\n\t---------------------------------------------------------------------- */\n\tdocumentIsHTML = !isXML( doc );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\f]' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = doc.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn doc;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (oldCache = outerCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\touterCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is no seed and only one group\n\tif ( match.length === 1 ) {\n\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"<input/>\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t});\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t});\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;\n\t});\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t}));\n};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tret = [],\n\t\t\tself = this,\n\t\t\tlen = self.length;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], true) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n});\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tret = jQuery.unique( ret );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tret = ret.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\nvar rnotwhite = (/\\S+/g);\n\n\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\n\t\t\t\t\t} else if ( !(--remaining) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\n\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( !document.body ) {\n\t\t\treturn setTimeout( jQuery.ready );\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n});\n\n/**\n * Clean-up method for dom ready events\n */\nfunction detach() {\n\tif ( document.addEventListener ) {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\twindow.removeEventListener( \"load\", completed, false );\n\n\t} else {\n\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\twindow.detachEvent( \"onload\", completed );\n\t}\n}\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\tif ( document.addEventListener || event.type === \"load\" || document.readyState === \"complete\" ) {\n\t\tdetach();\n\t\tjQuery.ready();\n\t}\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\n\t\t// If IE event model is used\n\t\t} else {\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", completed );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t(function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll(\"left\");\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\treturn setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// detach all dom ready events\n\t\t\t\t\t\tdetach();\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n\nvar strundefined = typeof undefined;\n\n\n\n// Support: IE<9\n// Iteration over object's inherited properties before its own\nvar i;\nfor ( i in jQuery( support ) ) {\n\tbreak;\n}\nsupport.ownLast = i !== \"0\";\n\n// Note: most support tests are defined in their respective modules.\n// false until the test is run\nsupport.inlineBlockNeedsLayout = false;\n\n// Execute ASAP in case we need to set body.style.zoom\njQuery(function() {\n\t// Minified: var a,b,c,d\n\tvar val, div, body, container;\n\n\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\tif ( !body || !body.style ) {\n\t\t// Return for frameset docs that don't have a body\n\t\treturn;\n\t}\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tcontainer = document.createElement( \"div\" );\n\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\tbody.appendChild( container ).appendChild( div );\n\n\tif ( typeof div.style.zoom !== strundefined ) {\n\t\t// Support: IE<8\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\tdiv.style.cssText = \"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\";\n\n\t\tsupport.inlineBlockNeedsLayout = val = div.offsetWidth === 3;\n\t\tif ( val ) {\n\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t// Support: IE<8\n\t\t\tbody.style.zoom = 1;\n\t\t}\n\t}\n\n\tbody.removeChild( container );\n});\n\n\n\n\n(function() {\n\tvar div = document.createElement( \"div\" );\n\n\t// Execute the test only if not already executed in another module.\n\tif (support.deleteExpando == null) {\n\t\t// Support: IE<9\n\t\tsupport.deleteExpando = true;\n\t\ttry {\n\t\t\tdelete div.test;\n\t\t} catch( e ) {\n\t\t\tsupport.deleteExpando = false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n})();\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( elem ) {\n\tvar noData = jQuery.noData[ (elem.nodeName + \" \").toLowerCase() ],\n\t\tnodeType = +elem.nodeType || 1;\n\n\t// Do not set data on non-element DOM nodes because it will not be cleared (#8335).\n\treturn nodeType !== 1 && nodeType !== 9 ?\n\t\tfalse :\n\n\t\t// Nodes accept data unless otherwise specified; rejection can be conditional\n\t\t!noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n};\n\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar ret, thisCache,\n\t\tinternalKey = jQuery.expando,\n\n\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t// can't GC object references properly across the DOM-JS boundary\n\t\tisNode = elem.nodeType,\n\n\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t// attached directly to the object so GC can occur automatically\n\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t// Avoid doing any more work than we need to when trying to get data on an\n\t// object that has no data at all\n\tif ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === \"string\" ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t// ends up in the global cache\n\t\tif ( isNode ) {\n\t\t\tid = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;\n\t\t} else {\n\t\t\tid = internalKey;\n\t\t}\n\t}\n\n\tif ( !cache[ id ] ) {\n\t\t// Avoid exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tcache[ id ] = isNode ? {} : { toJSON: jQuery.noop };\n\t}\n\n\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t// shallow copied over onto the existing cache\n\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\tif ( pvt ) {\n\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t} else {\n\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t}\n\t}\n\n\tthisCache = cache[ id ];\n\n\t// jQuery data() is stored in a separate object inside the object's internal data\n\t// cache in order to avoid key collisions between internal data and user-defined\n\t// data.\n\tif ( !pvt ) {\n\t\tif ( !thisCache.data ) {\n\t\t\tthisCache.data = {};\n\t\t}\n\n\t\tthisCache = thisCache.data;\n\t}\n\n\tif ( data !== undefined ) {\n\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t}\n\n\t// Check for both converted-to-camel and non-converted data property names\n\t// If a data property was specified\n\tif ( typeof name === \"string\" ) {\n\n\t\t// First Try to find as-is property data\n\t\tret = thisCache[ name ];\n\n\t\t// Test for null|undefined property data\n\t\tif ( ret == null ) {\n\n\t\t\t// Try to find the camelCased property\n\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t}\n\t} else {\n\t\tret = thisCache;\n\t}\n\n\treturn ret;\n}\n\nfunction internalRemoveData( elem, name, pvt ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar thisCache, i,\n\t\tisNode = elem.nodeType,\n\n\t\t// See jQuery.data for more information\n\t\tcache = isNode ? jQuery.cache : elem,\n\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t// If there is already no cache entry for this object, there is no\n\t// purpose in continuing\n\tif ( !cache[ id ] ) {\n\t\treturn;\n\t}\n\n\tif ( name ) {\n\n\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\tif ( thisCache ) {\n\n\t\t\t// Support array or space separated string names for data keys\n\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split(\" \");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = name.concat( jQuery.map( name, jQuery.camelCase ) );\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t}\n\n\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t// and let the cache object itself get destroyed\n\t\t\tif ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// See jQuery.data for more information\n\tif ( !pvt ) {\n\t\tdelete cache[ id ].data;\n\n\t\t// Don't destroy the parent cache unless the internal data object\n\t\t// had been the only thing left in it\n\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Destroy the cache\n\tif ( isNode ) {\n\t\tjQuery.cleanData( [ elem ], true );\n\n\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t/* jshint eqeqeq: false */\n\t} else if ( support.deleteExpando || cache != cache.window ) {\n\t\t/* jshint eqeqeq: true */\n\t\tdelete cache[ id ];\n\n\t// When all else fails, null\n\t} else {\n\t\tcache[ id ] = null;\n\t}\n}\n\njQuery.extend({\n\tcache: {},\n\n\t// The following elements (space-suffixed to avoid Object.prototype collisions)\n\t// throw uncatchable exceptions if you attempt to set expando properties\n\tnoData: {\n\t\t\"applet \": true,\n\t\t\"embed \": true,\n\t\t// ...but Flash objects (which have this classid) *can* handle expandos\n\t\t\"object \": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name );\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data, true );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name, true );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[0],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Special expections of .data basically thwart jQuery.access,\n\t\t// so implement the relevant behavior ourselves\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn arguments.length > 1 ?\n\n\t\t\t// Sets one value\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t}) :\n\n\t\t\t// Gets one value\n\t\t\t// Try to fetch any internally stored data first\n\t\t\telem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\n\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray(data) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tjQuery._removeData( elem, type + \"queue\" );\n\t\t\t\tjQuery._removeData( elem, key );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar pnum = (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlength = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n};\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\t// Minified: var a,b,c\n\tvar input = document.createElement( \"input\" ),\n\t\tdiv = document.createElement( \"div\" ),\n\t\tfragment = document.createDocumentFragment();\n\n\t// Setup\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t// IE strips leading whitespace when .innerHTML is used\n\tsupport.leadingWhitespace = div.firstChild.nodeType === 3;\n\n\t// Make sure that tbody elements aren't automatically inserted\n\t// IE will insert them into empty tables\n\tsupport.tbody = !div.getElementsByTagName( \"tbody\" ).length;\n\n\t// Make sure that link elements get serialized correctly by innerHTML\n\t// This requires a wrapper element in IE\n\tsupport.htmlSerialize = !!div.getElementsByTagName( \"link\" ).length;\n\n\t// Makes sure cloning an html5 element does not cause problems\n\t// Where outerHTML is undefined, this still works\n\tsupport.html5Clone =\n\t\tdocument.createElement( \"nav\" ).cloneNode( true ).outerHTML !== \"<:nav></:nav>\";\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tinput.type = \"checkbox\";\n\tinput.checked = true;\n\tfragment.appendChild( input );\n\tsupport.appendChecked = input.checked;\n\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\t// Support: IE6-IE11+\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tfragment.appendChild( div );\n\tdiv.innerHTML = \"<input type='radio' checked='checked' name='t'/>\";\n\n\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n\t// old WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<9\n\t// Opera does not clone events (and typeof div.attachEvent === undefined).\n\t// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()\n\tsupport.noCloneEvent = true;\n\tif ( div.attachEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\n\t\tdiv.cloneNode( true ).click();\n\t}\n\n\t// Execute the test only if not already executed in another module.\n\tif (support.deleteExpando == null) {\n\t\t// Support: IE<9\n\t\tsupport.deleteExpando = true;\n\t\ttry {\n\t\t\tdelete div.test;\n\t\t} catch( e ) {\n\t\t\tsupport.deleteExpando = false;\n\t\t}\n\t}\n})();\n\n\n(function() {\n\tvar i, eventName,\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)\n\tfor ( i in { submit: true, change: true, focusin: true }) {\n\t\teventName = \"on\" + i;\n\n\t\tif ( !(support[ i + \"Bubbles\" ] = eventName in window) ) {\n\t\t\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)\n\t\t\tdiv.setAttribute( eventName, \"t\" );\n\t\t\tsupport[ i + \"Bubbles\" ] = div.attributes[ eventName ].expando === false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n})();\n\n\nvar rformElems = /^(?:input|select|textarea)$/i,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\t\tvar tmp, events, t, handleObjIn,\n\t\t\tspecial, eventHandle, handleObj,\n\t\t\thandlers, type, namespaces, origType,\n\t\t\telemData = jQuery._data( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\t\tvar j, handleObj, tmp,\n\t\t\torigCount, t, events,\n\t\t\tspecial, handlers, type,\n\t\t\tnamespaces, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery._removeData( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\tvar handle, ontype, cur,\n\t\t\tbubbleType, special, tmp, i,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && jQuery.acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\ttry {\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486,#12518)\n\t\t\t\t\t\t// only reproducible on winXP IE8 native, not IE9 in IE8 mode\n\t\t\t\t\t}\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, ret, handleObj, matched, j,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( jQuery._data( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar sel, handleObj, matches, i,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\t/* jshint eqeqeq: false */\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\t/* jshint eqeqeq: true */\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== \"click\") ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Fix target property (#1925)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Support: Chrome 23+, Safari?\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar body, eventDoc, doc,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// If we error on focus to hidden element (#1486, #12518),\n\t\t\t\t\t\t// let .trigger() run the handlers\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( jQuery.nodeName( this, \"input\" ) && this.type === \"checkbox\" && this.click ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8\n\t\t\t// detachEvent needed property on element, by name of that event, to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === strundefined ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\t\t\t\t// Support: IE < 9, Android < 4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If preventDefault exists, run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// Support: IE\n\t\t// Otherwise set the returnValue property of the original event to false\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// If stopPropagation exists, run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Set the cancelBubble property of the original event to true\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !jQuery._data( form, \"submitBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( form, \"submitBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"changeBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( elem, \"changeBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = jQuery._data( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tjQuery._data( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = jQuery._data( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tjQuery._removeData( doc, fix );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery._data( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar type, origFn;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\t\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\tparam: [ 1, \"<object>\", \"</object>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\t_default: support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\"  ]\n\t},\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !tag || jQuery.nodeName( elem, tag ) ) {\n\t\t\t\tfound.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( found, getAll( elem, tag ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], found ) :\n\t\tfound;\n}\n\n// Used in buildFragment, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\n// Support: IE<8\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement(\"tbody\") ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = (jQuery.find.attr( elem, \"type\" ) !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\tif ( match ) {\n\t\telem.type = match[1];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar elem,\n\t\ti = 0;\n\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\tjQuery._data( elem, \"globalEval\", !refElements || jQuery._data( refElements[i], \"globalEval\" ) );\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction fixCloneNodeIssues( src, dest ) {\n\tvar nodeName, e, data;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 copies events bound via attachEvent when using cloneNode.\n\tif ( !support.noCloneEvent && dest[ jQuery.expando ] ) {\n\t\tdata = jQuery._data( dest );\n\n\t\tfor ( e in data.events ) {\n\t\t\tjQuery.removeEvent( dest, e, data.handle );\n\t\t}\n\n\t\t// Event data gets referenced instead of copied if the expando gets copied too\n\t\tdest.removeAttribute( jQuery.expando );\n\t}\n\n\t// IE blanks contents when cloning scripts, and tries to evaluate newly-set text\n\tif ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdisableScript( dest ).text = src.text;\n\t\trestoreScript( dest );\n\n\t// IE6-10 improperly clones children of object elements using classid.\n\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t} else if ( nodeName === \"object\" ) {\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.defaultSelected = dest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( (!support.noCloneEvent || !support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\t// Fix all IE cloning issues\n\t\t\tfor ( i = 0; (node = srcElements[i]) != null; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tfixCloneNodeIssues( node, destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0; (node = srcElements[i]) != null; i++ ) {\n\t\t\t\t\tcloneCopyEvent( node, destElements[i] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\tdestElements = srcElements = node = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar j, elem, contains,\n\t\t\ttmp, tag, tbody, wrap,\n\t\t\tl = elems.length,\n\n\t\t\t// Ensure a safe fragment\n\t\t\tsafe = createSafeFragment( context ),\n\n\t\t\tnodes = [],\n\t\t\ti = 0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || safe.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = (rtagName.exec( elem ) || [ \"\", \"\" ])[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\n\t\t\t\t\ttmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[2];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[0];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Manually add leading whitespace removed by IE\n\t\t\t\t\tif ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\twrap[1] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t\t0;\n\n\t\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( (tbody = elem.childNodes[j]), \"tbody\" ) && !tbody.childNodes.length ) {\n\t\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\t\ttmp = safe.lastChild;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fix #11356: Clear elements from fragment\n\t\tif ( tmp ) {\n\t\t\tsafe.removeChild( tmp );\n\t\t}\n\n\t\t// Reset defaultChecked for any radios and checkboxes\n\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\tif ( !support.appendChecked ) {\n\t\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t\t}\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( safe.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttmp = null;\n\n\t\treturn safe;\n\t},\n\n\tcleanData: function( elems, /* internal */ acceptData ) {\n\t\tvar elem, type, id, data,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tdeleteExpando = support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( acceptData || jQuery.acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t\t\t\t// we must handle all of these cases\n\t\t\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\t\t\tdelete elem[ internalKey ];\n\n\t\t\t\t\t\t} else if ( typeof elem.removeAttribute !== strundefined ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdeletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\n\t\t\t// If this is a select, ensure that it displays empty (#12336)\n\t\t\t// Support: IE<9\n\t\t\tif ( elem.options && jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\telem.options.length = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map(function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ (rtagName.exec( value ) || [ \"\", \"\" ])[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar first, node, hasScripts,\n\t\t\tscripts, doc, fragment,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[0],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[0] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[i], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!jQuery._data( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( ( node.text || node.textContent || node.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\t\tfragment = first = null;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone(true);\n\t\t\tjQuery( insert[i] )[ original ]( elems );\n\n\t\t\t// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar style,\n\t\telem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?\n\n\t\t\t// Use of this method is a temporary fix (more like optmization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\tstyle.display : jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = (iframe || jQuery( \"<iframe frameborder='0' width='0' height='0'/>\" )).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;\n\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\n\n\n(function() {\n\tvar shrinkWrapBlocksVal;\n\n\tsupport.shrinkWrapBlocks = function() {\n\t\tif ( shrinkWrapBlocksVal != null ) {\n\t\t\treturn shrinkWrapBlocksVal;\n\t\t}\n\n\t\t// Will be changed later if needed.\n\t\tshrinkWrapBlocksVal = false;\n\n\t\t// Minified: var b,c,d\n\t\tvar div, body, container;\n\n\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\tif ( !body || !body.style ) {\n\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Setup\n\t\tdiv = document.createElement( \"div\" );\n\t\tcontainer = document.createElement( \"div\" );\n\t\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE6\n\t\t// Check if elements with layout shrink-wrap their children\n\t\tif ( typeof div.style.zoom !== strundefined ) {\n\t\t\t// Reset CSS: box-sizing; display; margin; border\n\t\t\tdiv.style.cssText =\n\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;\" +\n\t\t\t\t\"padding:1px;width:1px;zoom:1\";\n\t\t\tdiv.appendChild( document.createElement( \"div\" ) ).style.width = \"5px\";\n\t\t\tshrinkWrapBlocksVal = div.offsetWidth !== 3;\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\treturn shrinkWrapBlocksVal;\n\t};\n\n})();\nvar rmargin = (/^margin/);\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\n\n\nvar getStyles, curCSS,\n\trposition = /^(top|right|bottom|left)$/;\n\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tif ( elem.ownerDocument.defaultView.opener ) {\n\t\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t\t}\n\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\tcurCSS = function( elem, name, computed ) {\n\t\tvar width, minWidth, maxWidth, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\n\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;\n\n\t\tif ( computed ) {\n\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\";\n\t};\n} else if ( document.documentElement.currentStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.currentStyle;\n\t};\n\n\tcurCSS = function( elem, name, computed ) {\n\t\tvar left, rs, rsLeft, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\t\tret = computed ? computed[ name ] : undefined;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trs = elem.runtimeStyle;\n\t\t\trsLeft = rs && rs.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\" || \"auto\";\n\t};\n}\n\n\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tvar condition = conditionFn();\n\n\t\t\tif ( condition == null ) {\n\t\t\t\t// The test was not ready at this point; screw the hook this time\n\t\t\t\t// but check again when needed next time.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( condition ) {\n\t\t\t\t// Hook not needed (or it's not possible to use it due to missing dependency),\n\t\t\t\t// remove it.\n\t\t\t\t// Since there are no other hooks for marginRight, remove the whole object.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\n\t\t\treturn (this.get = hookFn).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\n(function() {\n\t// Minified: var b,c,d,e,f,g, h,i\n\tvar div, style, a, pixelPositionVal, boxSizingReliableVal,\n\t\treliableHiddenOffsetsVal, reliableMarginRightVal;\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\tstyle = a && a.style;\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !style ) {\n\t\treturn;\n\t}\n\n\tstyle.cssText = \"float:left;opacity:.5\";\n\n\t// Support: IE<9\n\t// Make sure that element opacity exists (as opposed to filter)\n\tsupport.opacity = style.opacity === \"0.5\";\n\n\t// Verify style float existence\n\t// (IE uses styleFloat instead of cssFloat)\n\tsupport.cssFloat = !!style.cssFloat;\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Support: Firefox<29, Android 2.3\n\t// Vendor-prefix box-sizing\n\tsupport.boxSizing = style.boxSizing === \"\" || style.MozBoxSizing === \"\" ||\n\t\tstyle.WebkitBoxSizing === \"\";\n\n\tjQuery.extend(support, {\n\t\treliableHiddenOffsets: function() {\n\t\t\tif ( reliableHiddenOffsetsVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableHiddenOffsetsVal;\n\t\t},\n\n\t\tboxSizingReliable: function() {\n\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\n\t\tpixelPosition: function() {\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn pixelPositionVal;\n\t\t},\n\n\t\t// Support: Android 2.3\n\t\treliableMarginRight: function() {\n\t\t\tif ( reliableMarginRightVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableMarginRightVal;\n\t\t}\n\t});\n\n\tfunction computeStyleTests() {\n\t\t// Minified: var b,c,d,j\n\t\tvar div, body, container, contents;\n\n\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\tif ( !body || !body.style ) {\n\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Setup\n\t\tdiv = document.createElement( \"div\" );\n\t\tcontainer = document.createElement( \"div\" );\n\t\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\tdiv.style.cssText =\n\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;\" +\n\t\t\t\"box-sizing:border-box;display:block;margin-top:1%;top:1%;\" +\n\t\t\t\"border:1px;padding:1px;width:4px;position:absolute\";\n\n\t\t// Support: IE<9\n\t\t// Assume reasonable values in the absence of getComputedStyle\n\t\tpixelPositionVal = boxSizingReliableVal = false;\n\t\treliableMarginRightVal = true;\n\n\t\t// Check for getComputedStyle so that this code is not run in IE<9.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tpixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tboxSizingReliableVal =\n\t\t\t\t( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Support: Android 2.3\n\t\t\t// Div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container (#3333)\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tcontents = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\tcontents.style.cssText = div.style.cssText =\n\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\tcontents.style.marginRight = contents.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\treliableMarginRightVal =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );\n\n\t\t\tdiv.removeChild( contents );\n\t\t}\n\n\t\t// Support: IE8\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\tcontents = div.getElementsByTagName( \"td\" );\n\t\tcontents[ 0 ].style.cssText = \"margin:0;border:0;padding:0;display:none\";\n\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\tif ( reliableHiddenOffsetsVal ) {\n\t\t\tcontents[ 0 ].style.display = \"\";\n\t\t\tcontents[ 1 ].style.display = \"none\";\n\t\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\t}\n\n\t\tbody.removeChild( container );\n\t}\n\n})();\n\n\n// A method for quickly swapping in/out CSS properties to get correct calculations.\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar\n\t\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/,\n\n\t// swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + pnum + \")\", \"i\" ),\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\tjQuery._data( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set. See: #7116\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight (for every problematic property) identical functions\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf(\"background\") === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\n\t\t\t\t// Support: IE\n\t\t\t\t// Swallow errors from 'invalid' CSS values (#5509)\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar num, val, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n});\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) && elem.offsetWidth === 0 ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tsupport.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\nif ( !support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\t// if value === \"\", then remove inline opacity #12685\n\t\t\tif ( ( value >= 1 || value === \"\" ) &&\n\t\t\t\t\tjQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there is no filter style applied in a css rule or unset inline opacity, we are done\n\t\t\t\tif ( value === \"\" || currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE <=9\n// Panic based approach to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t}\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +target ) &&\n\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( start && start[ 3 ] !== unit ) {\n\t\t\t\t// Trust units reported by jQuery.css\n\t\t\t\tunit = unit || start[ 3 ];\n\n\t\t\t\t// Make sure we update the tween properties later on\n\t\t\t\tparts = parts || [];\n\n\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\tstart = +target || 1;\n\n\t\t\t\tdo {\n\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n\t\t\t\t\t// Use a string for doubling factor so we don't accidentally see scale as unchanged below\n\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t// Adjust and apply\n\t\t\t\t\tstart = start / scale;\n\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t}\n\n\t\t\t// Update tween properties\n\t\t\tif ( parts ) {\n\t\t\t\tstart = tween.start = +start || +target || 0;\n\t\t\t\ttween.unit = unit;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[ 1 ] ?\n\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n\t\t\t\t\t+parts[ 2 ];\n\t\t\t}\n\n\t\t\treturn tween;\n\t\t} ]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( (tween = collection[ index ].call( animation, prop, value )) ) {\n\n\t\t\t// we're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = jQuery._data( elem, \"fxshow\" );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tjQuery._data( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !support.shrinkWrapBlocks() ) {\n\t\t\tanim.always(function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t});\n\t\t}\n\t}\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = jQuery._data( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\t\t\tjQuery._removeData( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( (display === \"none\" ? defaultDisplay( elem.nodeName ) : display) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || jQuery._data( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = jQuery._data( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\tclearTimeout( timeout );\n\t\t};\n\t});\n};\n\n\n(function() {\n\t// Minified: var a,b,c,d,e\n\tvar input, div, select, a, opt;\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\n\t// First batch of tests.\n\tselect = document.createElement(\"select\");\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName(\"input\")[ 0 ];\n\n\ta.style.cssText = \"top:1px\";\n\n\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\tsupport.getSetAttribute = div.className !== \"t\";\n\n\t// Get the style information from getAttribute\n\t// (IE uses .cssText instead)\n\tsupport.style = /top/.test( a.getAttribute(\"style\") );\n\n\t// Make sure that URLs aren't manipulated\n\t// (IE normalizes it by default)\n\tsupport.hrefNormalized = a.getAttribute(\"href\") === \"/a\";\n\n\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\tsupport.checkOn = !!input.value;\n\n\t// Make sure that a selected-by-default option has a working selected property.\n\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\tsupport.optSelected = opt.selected;\n\n\t// Tests for enctype support on a form (#6743)\n\tsupport.enctype = !!document.createElement(\"form\").enctype;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE8 only\n\t// Check if we can trust getAttribute(\"value\")\n\tinput = document.createElement( \"input\" );\n\tinput.setAttribute( \"value\", \"\" );\n\tsupport.input = input.getAttribute( \"value\" ) === \"\";\n\n\t// Check if an input maintains its value after becoming a radio\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n})();\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend({\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\tjQuery.trim( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// oldIE doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\tif ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {\n\n\t\t\t\t\t\t// Support: IE6\n\t\t\t\t\t\t// When new option element is added to select box we need to\n\t\t\t\t\t\t// force reflow of newly added node in order to workaround delay\n\t\t\t\t\t\t// of initialization properties\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\toption.selected = optionSet = true;\n\n\t\t\t\t\t\t} catch ( _ ) {\n\n\t\t\t\t\t\t\t// Will be executed only in IE6\n\t\t\t\t\t\t\toption.scrollHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\toption.selected = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\n\t\t\t\treturn options;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Radios and checkboxes getter/setter\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\t// Support: Webkit\n\t\t\t// \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t};\n\t}\n});\n\n\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = support.getSetAttribute,\n\tgetSetInput = support.input;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\tif ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate)\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] =\n\t\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to default in case type is set after value during creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t// IE<8 needs the *property* name\n\t\t\telem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );\n\n\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t} else {\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\n\t\t}\n\n\t\treturn name;\n\t}\n};\n\n// Retrieve booleans specially\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret, handle;\n\t\t\tif ( !isXML ) {\n\t\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\t\thandle = attrHandle[ name ];\n\t\t\t\tattrHandle[ name ] = ret;\n\t\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t\tattrHandle[ name ] = handle;\n\t\t\t}\n\t\t\treturn ret;\n\t\t} :\n\t\tfunction( elem, name, isXML ) {\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn elem[ jQuery.camelCase( \"default-\" + name ) ] ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n});\n\n// fix oldIE attroperties\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.defaultValue = value;\n\t\t\t} else {\n\t\t\t\t// Use nodeHook if defined (#1954); otherwise setAttribute is fine\n\t\t\t\treturn nodeHook && nodeHook.set( elem, value, name );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = {\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\telem.setAttributeNode(\n\t\t\t\t\t(ret = elem.ownerDocument.createAttribute( name ))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.value = value += \"\";\n\n\t\t\t// Break association with cloned elements by also using setAttribute (#9646)\n\t\t\tif ( name === \"value\" || value === elem.getAttribute( name ) ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Some attributes are constructed with empty-string values when not defined\n\tattrHandle.id = attrHandle.name = attrHandle.coords =\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret;\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn (ret = elem.getAttributeNode( name )) && ret.value !== \"\" ?\n\t\t\t\t\tret.value :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n\n\t// Fixing value retrieval on a button requires this module\n\tjQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret && ret.specified ) {\n\t\t\t\treturn ret.value;\n\t\t\t}\n\t\t},\n\t\tset: nodeHook.set\n\t};\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tset: function( elem, value, name ) {\n\t\t\tnodeHook.set( elem, value === \"\" ? false : value, name );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\nif ( !support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Note: IE uppercases css property names, but if we were to .toLowerCase()\n\t\t\t// .cssText, that would destroy case senstitivity in URL's, like in \"background\"\n\t\t\treturn elem.style.cssText || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend({\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\treturn hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n\t\t\t\tret :\n\t\t\t\t( elem[ name ] = value );\n\n\t\t} else {\n\t\t\treturn hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ?\n\t\t\t\tret :\n\t\t\t\telem[ name ];\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\treturn tabindex ?\n\t\t\t\t\tparseInt( tabindex, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Some attributes require a special call on IE\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !support.hrefNormalized ) {\n\t// href/src property should get the full normalized URL (#10299/#12915)\n\tjQuery.each([ \"href\", \"src\" ], function( i, name ) {\n\t\tjQuery.propHooks[ name ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.getAttribute( name, 4 );\n\t\t\t}\n\t\t};\n\t});\n}\n\n// Support: Safari, IE9+\n// mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n// IE6/7 call enctype encoding\nif ( !support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n\n\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\njQuery.fn.extend({\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n});\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.extend({\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n\n\nvar nonce = jQuery.now();\n\nvar rquery = (/\\?/);\n\n\n\nvar rvalidtokens = /(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;\n\njQuery.parseJSON = function( data ) {\n\t// Attempt to parse using the native JSON parser first\n\tif ( window.JSON && window.JSON.parse ) {\n\t\t// Support: Android 2.3\n\t\t// Workaround failure to string-cast null input\n\t\treturn window.JSON.parse( data + \"\" );\n\t}\n\n\tvar requireNonComma,\n\t\tdepth = null,\n\t\tstr = jQuery.trim( data + \"\" );\n\n\t// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains\n\t// after removing valid tokens\n\treturn str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {\n\n\t\t// Force termination if we see a misplaced comma\n\t\tif ( requireNonComma && comma ) {\n\t\t\tdepth = 0;\n\t\t}\n\n\t\t// Perform no more replacements after returning to outermost depth\n\t\tif ( depth === 0 ) {\n\t\t\treturn token;\n\t\t}\n\n\t\t// Commas must not follow \"[\", \"{\", or \",\"\n\t\trequireNonComma = open || comma;\n\n\t\t// Determine new depth\n\t\t// array/object open (\"[\" or \"{\"): depth += true - false (increment)\n\t\t// array/object close (\"]\" or \"}\"): depth += false - true (decrement)\n\t\t// other cases (\",\" or primitive): depth += true - true (numeric cast)\n\t\tdepth += !close - !open;\n\n\t\t// Remove this token\n\t\treturn \"\";\n\t}) ) ?\n\t\t( Function( \"return \" + str ) )() :\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n};\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml, tmp;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\ttry {\n\t\tif ( window.DOMParser ) { // Standard\n\t\t\ttmp = new DOMParser();\n\t\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\txml.async = \"false\";\n\t\t\txml.loadXML( data );\n\t\t}\n\t} catch( e ) {\n\t\txml = undefined;\n\t}\n\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat(\"*\");\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType.charAt( 0 ) === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar deep, key,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\tvar firstDataType, ct, finalDataType, type,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\ttransport,\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t});\n};\n\n\njQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\n\n\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||\n\t\t(!support.reliableHiddenOffsets() &&\n\t\t\t((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n};\n\njQuery.expr.filters.visible = function( elem ) {\n\treturn !jQuery.expr.filters.hidden( elem );\n};\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function() {\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function() {\n\t\t\tvar type = this.type;\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?\n\t// Support: IE6+\n\tfunction() {\n\n\t\t// XHR cannot access local files, always use ActiveX for that case\n\t\treturn !this.isLocal &&\n\n\t\t\t// Support: IE7-8\n\t\t\t// oldIE XHR does not support non-RFC2616 methods (#13240)\n\t\t\t// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx\n\t\t\t// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9\n\t\t\t// Although this check for six methods instead of eight\n\t\t\t// since IE also does not support \"trace\" and \"connect\"\n\t\t\t/^(get|post|head|put|delete|options)$/i.test( this.type ) &&\n\n\t\t\tcreateStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE<10\n// Open requests must be manually aborted on unload (#5280)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t});\n}\n\n// Determine support properties\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport(function( options ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !options.crossDomain || support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\t\t\t\t\tvar i,\n\t\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set headers\n\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// IE's ActiveXObject throws a 'Type Mismatch' exception when setting\n\t\t\t\t\t\t// request header to a null-value.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// To keep consistent with other XHR implementations, cast the value\n\t\t\t\t\t\t// to string and ignore `undefined`.\n\t\t\t\t\t\tif ( headers[ i ] !== undefined ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] + \"\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( options.hasContent && options.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\t\t\t\t\t\tvar status, statusText, responses;\n\n\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\t\t\t\t\t\t\t// Clean up\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = undefined;\n\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\n\t\t\t\t\t\t\t// Abort manually if needed\n\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\tstatus = xhr.status;\n\n\t\t\t\t\t\t\t\t// Support: IE<10\n\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\tif ( !status && options.isLocal && !options.crossDomain ) {\n\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, xhr.getAllResponseHeaders() );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !options.async ) {\n\t\t\t\t\t\t// if we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\tsetTimeout( callback );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Add to the list of active xhr callbacks\n\t\t\t\t\t\txhr.onreadystatechange = xhrCallbacks[ id ] = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback( undefined, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch( e ) {}\n}\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || jQuery(\"head\")[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement(\"script\");\n\n\t\t\t\tscript.async = true;\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( script.parentNode ) {\n\t\t\t\t\t\t\tscript.parentNode.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = null;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( undefined, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// data: string of html\n// context (optional): If specified, the fragment will be created in this context, defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\tcontext = context || document;\n\n\tvar parsed = rsingleTag.exec( data ),\n\t\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[1] ) ];\n\t}\n\n\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, response, type,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = jQuery.trim( url.slice( off, url.length ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n});\n\n\n\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t}).length;\n};\n\n\n\n\n\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\tjQuery.inArray(\"auto\", [ curCSSTop, curCSSLeft ] ) > -1;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend({\n\toffset: function( options ) {\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each(function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t});\n\t\t}\n\n\t\tvar docElem, win,\n\t\t\tbox = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ],\n\t\t\tdoc = elem && elem.ownerDocument;\n\n\t\tif ( !doc ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure it's not a disconnected DOM node\n\t\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box;\n\t\t}\n\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\t// BlackBerry 5, iOS 3 (original iPhone)\n\t\tif ( typeof elem.getBoundingClientRect !== strundefined ) {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t}\n\t\twin = getWindow( doc );\n\t\treturn {\n\t\t\ttop: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\n\t\t};\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\tparentOffset = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ];\n\n\t\t// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// we assume that getBoundingClientRect is available when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top  += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true)\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\ttop ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// getComputedStyle returns percent when specified for top/left/bottom/right\n// rather than make the css module depend on the offset module, we just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n});\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t});\n}\n\n\n\n\nvar\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in\n// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === strundefined ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n\n}));\n"
  },
  {
    "path": "30-jstraining/demos/react-lifecycle-demo/react-dom.js",
    "content": "/**\n * ReactDOM v15.2.1\n *\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js\n;(function(f) {\n  // CommonJS\n  if (typeof exports === \"object\" && typeof module !== \"undefined\") {\n    module.exports = f(require('react'));\n\n  // RequireJS\n  } else if (typeof define === \"function\" && define.amd) {\n    define(['react'], f);\n\n  // <script>\n  } else {\n    var g;\n    if (typeof window !== \"undefined\") {\n      g = window;\n    } else if (typeof global !== \"undefined\") {\n      g = global;\n    } else if (typeof self !== \"undefined\") {\n      g = self;\n    } else {\n      // works providing we're not in \"use strict\";\n      // needed for Java 8 Nashorn\n      // see https://github.com/facebook/react/issues/3037\n      g = this;\n    }\n    g.ReactDOM = f(g.React);\n  }\n\n})(function(React) {\n  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n});\n"
  },
  {
    "path": "30-jstraining/demos/react-lifecycle-demo/react.js",
    "content": " /**\n  * React v15.2.1\n  */\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule AutoFocusUtils\n */\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar focusNode = _dereq_(155);\n\nvar AutoFocusUtils = {\n  focusDOMComponent: function () {\n    focusNode(ReactDOMComponentTree.getNodeFromInstance(this));\n  }\n};\n\nmodule.exports = AutoFocusUtils;\n},{\"155\":155,\"41\":41}],2:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule BeforeInputEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar FallbackCompositionState = _dereq_(21);\nvar SyntheticCompositionEvent = _dereq_(102);\nvar SyntheticInputEvent = _dereq_(106);\n\nvar keyOf = _dereq_(165);\n\nvar END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space\nvar START_KEYCODE = 229;\n\nvar canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;\n\nvar documentMode = null;\nif (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {\n  documentMode = document.documentMode;\n}\n\n// Webkit offers a very useful `textInput` event that can be used to\n// directly represent `beforeInput`. The IE `textinput` event is not as\n// useful, so we don't use it.\nvar canUseTextInputEvent = ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode && !isPresto();\n\n// In IE9+, we have access to composition events, but the data supplied\n// by the native compositionend event may be incorrect. Japanese ideographic\n// spaces, for instance (\\u3000) are not recorded correctly.\nvar useFallbackCompositionData = ExecutionEnvironment.canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);\n\n/**\n * Opera <= 12 includes TextEvent in window, but does not fire\n * text input events. Rely on keypress instead.\n */\nfunction isPresto() {\n  var opera = window.opera;\n  return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12;\n}\n\nvar SPACEBAR_CODE = 32;\nvar SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\n// Events and their corresponding property names.\nvar eventTypes = {\n  beforeInput: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBeforeInput: null }),\n      captured: keyOf({ onBeforeInputCapture: null })\n    },\n    dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste]\n  },\n  compositionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionEnd: null }),\n      captured: keyOf({ onCompositionEndCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionEnd, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionStart: null }),\n      captured: keyOf({ onCompositionStartCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionStart, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  },\n  compositionUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCompositionUpdate: null }),\n      captured: keyOf({ onCompositionUpdateCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topCompositionUpdate, topLevelTypes.topKeyDown, topLevelTypes.topKeyPress, topLevelTypes.topKeyUp, topLevelTypes.topMouseDown]\n  }\n};\n\n// Track whether we've ever handled a keypress on the space key.\nvar hasSpaceKeypress = false;\n\n/**\n * Return whether a native keypress event is assumed to be a command.\n * This is required because Firefox fires `keypress` events for key commands\n * (cut, copy, select-all, etc.) even though no character is inserted.\n */\nfunction isKeypressCommand(nativeEvent) {\n  return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&\n  // ctrlKey && altKey is equivalent to AltGr, and is not a command.\n  !(nativeEvent.ctrlKey && nativeEvent.altKey);\n}\n\n/**\n * Translate native top level events into event types.\n *\n * @param {string} topLevelType\n * @return {object}\n */\nfunction getCompositionEventType(topLevelType) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionStart:\n      return eventTypes.compositionStart;\n    case topLevelTypes.topCompositionEnd:\n      return eventTypes.compositionEnd;\n    case topLevelTypes.topCompositionUpdate:\n      return eventTypes.compositionUpdate;\n  }\n}\n\n/**\n * Does our fallback best-guess model think this event signifies that\n * composition has begun?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionStart(topLevelType, nativeEvent) {\n  return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE;\n}\n\n/**\n * Does our fallback mode think that this event is the end of composition?\n *\n * @param {string} topLevelType\n * @param {object} nativeEvent\n * @return {boolean}\n */\nfunction isFallbackCompositionEnd(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topKeyUp:\n      // Command keys insert or clear IME input.\n      return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;\n    case topLevelTypes.topKeyDown:\n      // Expect IME keyCode on each keydown. If we get any other\n      // code we must have exited earlier.\n      return nativeEvent.keyCode !== START_KEYCODE;\n    case topLevelTypes.topKeyPress:\n    case topLevelTypes.topMouseDown:\n    case topLevelTypes.topBlur:\n      // Events are not possible without cancelling IME.\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Google Input Tools provides composition data via a CustomEvent,\n * with the `data` property populated in the `detail` object. If this\n * is available on the event object, use it. If not, this is a plain\n * composition event and we have nothing special to extract.\n *\n * @param {object} nativeEvent\n * @return {?string}\n */\nfunction getDataFromCustomEvent(nativeEvent) {\n  var detail = nativeEvent.detail;\n  if (typeof detail === 'object' && 'data' in detail) {\n    return detail.data;\n  }\n  return null;\n}\n\n// Track the current IME composition fallback object, if any.\nvar currentComposition = null;\n\n/**\n * @return {?object} A SyntheticCompositionEvent.\n */\nfunction extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var eventType;\n  var fallbackData;\n\n  if (canUseCompositionEvent) {\n    eventType = getCompositionEventType(topLevelType);\n  } else if (!currentComposition) {\n    if (isFallbackCompositionStart(topLevelType, nativeEvent)) {\n      eventType = eventTypes.compositionStart;\n    }\n  } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n    eventType = eventTypes.compositionEnd;\n  }\n\n  if (!eventType) {\n    return null;\n  }\n\n  if (useFallbackCompositionData) {\n    // The current composition is stored statically and must not be\n    // overwritten while composition continues.\n    if (!currentComposition && eventType === eventTypes.compositionStart) {\n      currentComposition = FallbackCompositionState.getPooled(nativeEventTarget);\n    } else if (eventType === eventTypes.compositionEnd) {\n      if (currentComposition) {\n        fallbackData = currentComposition.getData();\n      }\n    }\n  }\n\n  var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);\n\n  if (fallbackData) {\n    // Inject data generated from fallback path into the synthetic event.\n    // This matches the property of native CompositionEventInterface.\n    event.data = fallbackData;\n  } else {\n    var customData = getDataFromCustomEvent(nativeEvent);\n    if (customData !== null) {\n      event.data = customData;\n    }\n  }\n\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The string corresponding to this `beforeInput` event.\n */\nfunction getNativeBeforeInputChars(topLevelType, nativeEvent) {\n  switch (topLevelType) {\n    case topLevelTypes.topCompositionEnd:\n      return getDataFromCustomEvent(nativeEvent);\n    case topLevelTypes.topKeyPress:\n      /**\n       * If native `textInput` events are available, our goal is to make\n       * use of them. However, there is a special case: the spacebar key.\n       * In Webkit, preventing default on a spacebar `textInput` event\n       * cancels character insertion, but it *also* causes the browser\n       * to fall back to its default spacebar behavior of scrolling the\n       * page.\n       *\n       * Tracking at:\n       * https://code.google.com/p/chromium/issues/detail?id=355103\n       *\n       * To avoid this issue, use the keypress event as if no `textInput`\n       * event is available.\n       */\n      var which = nativeEvent.which;\n      if (which !== SPACEBAR_CODE) {\n        return null;\n      }\n\n      hasSpaceKeypress = true;\n      return SPACEBAR_CHAR;\n\n    case topLevelTypes.topTextInput:\n      // Record the characters to be added to the DOM.\n      var chars = nativeEvent.data;\n\n      // If it's a spacebar character, assume that we have already handled\n      // it at the keypress level and bail immediately. Android Chrome\n      // doesn't give us keycodes, so we need to blacklist it.\n      if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {\n        return null;\n      }\n\n      return chars;\n\n    default:\n      // For other native event types, do nothing.\n      return null;\n  }\n}\n\n/**\n * For browsers that do not provide the `textInput` event, extract the\n * appropriate string to use for SyntheticInputEvent.\n *\n * @param {string} topLevelType Record from `EventConstants`.\n * @param {object} nativeEvent Native browser event.\n * @return {?string} The fallback string for this `beforeInput` event.\n */\nfunction getFallbackBeforeInputChars(topLevelType, nativeEvent) {\n  // If we are currently composing (IME) and using a fallback to do so,\n  // try to extract the composed characters from the fallback object.\n  if (currentComposition) {\n    if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) {\n      var chars = currentComposition.getData();\n      FallbackCompositionState.release(currentComposition);\n      currentComposition = null;\n      return chars;\n    }\n    return null;\n  }\n\n  switch (topLevelType) {\n    case topLevelTypes.topPaste:\n      // If a paste event occurs after a keypress, throw out the input\n      // chars. Paste events should not lead to BeforeInput events.\n      return null;\n    case topLevelTypes.topKeyPress:\n      /**\n       * As of v27, Firefox may fire keypress events even when no character\n       * will be inserted. A few possibilities:\n       *\n       * - `which` is `0`. Arrow keys, Esc key, etc.\n       *\n       * - `which` is the pressed key code, but no char is available.\n       *   Ex: 'AltGr + d` in Polish. There is no modified character for\n       *   this key combination and no character is inserted into the\n       *   document, but FF fires the keypress for char code `100` anyway.\n       *   No `input` event will occur.\n       *\n       * - `which` is the pressed key code, but a command combination is\n       *   being used. Ex: `Cmd+C`. No character is inserted, and no\n       *   `input` event will occur.\n       */\n      if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {\n        return String.fromCharCode(nativeEvent.which);\n      }\n      return null;\n    case topLevelTypes.topCompositionEnd:\n      return useFallbackCompositionData ? null : nativeEvent.data;\n    default:\n      return null;\n  }\n}\n\n/**\n * Extract a SyntheticInputEvent for `beforeInput`, based on either native\n * `textInput` or fallback behavior.\n *\n * @return {?object} A SyntheticInputEvent.\n */\nfunction extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n  var chars;\n\n  if (canUseTextInputEvent) {\n    chars = getNativeBeforeInputChars(topLevelType, nativeEvent);\n  } else {\n    chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);\n  }\n\n  // If no characters are being inserted, no BeforeInput event should\n  // be fired.\n  if (!chars) {\n    return null;\n  }\n\n  var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);\n\n  event.data = chars;\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n  return event;\n}\n\n/**\n * Create an `onBeforeInput` event to match\n * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.\n *\n * This event plugin is based on the native `textInput` event\n * available in Chrome, Safari, Opera, and IE. This event fires after\n * `onKeyPress` and `onCompositionEnd`, but before `onInput`.\n *\n * `beforeInput` is spec'd but not implemented in any browsers, and\n * the `input` event does not provide any useful information about what has\n * actually been added, contrary to the spec. Thus, `textInput` is the best\n * available event to identify the characters that have actually been inserted\n * into the target node.\n *\n * This plugin is also responsible for emitting `composition` events, thus\n * allowing us to share composition fallback code for both `beforeInput` and\n * `composition` event types.\n */\nvar BeforeInputEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];\n  }\n};\n\nmodule.exports = BeforeInputEventPlugin;\n},{\"102\":102,\"106\":106,\"147\":147,\"16\":16,\"165\":165,\"20\":20,\"21\":21}],3:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSProperty\n */\n\n'use strict';\n\n/**\n * CSS properties which accept numbers but are not in units of \"px\".\n */\n\nvar isUnitlessNumber = {\n  animationIterationCount: true,\n  borderImageOutset: true,\n  borderImageSlice: true,\n  borderImageWidth: true,\n  boxFlex: true,\n  boxFlexGroup: true,\n  boxOrdinalGroup: true,\n  columnCount: true,\n  flex: true,\n  flexGrow: true,\n  flexPositive: true,\n  flexShrink: true,\n  flexNegative: true,\n  flexOrder: true,\n  gridRow: true,\n  gridColumn: true,\n  fontWeight: true,\n  lineClamp: true,\n  lineHeight: true,\n  opacity: true,\n  order: true,\n  orphans: true,\n  tabSize: true,\n  widows: true,\n  zIndex: true,\n  zoom: true,\n\n  // SVG-related properties\n  fillOpacity: true,\n  floodOpacity: true,\n  stopOpacity: true,\n  strokeDasharray: true,\n  strokeDashoffset: true,\n  strokeMiterlimit: true,\n  strokeOpacity: true,\n  strokeWidth: true\n};\n\n/**\n * @param {string} prefix vendor-specific prefix, eg: Webkit\n * @param {string} key style name, eg: transitionDuration\n * @return {string} style name prefixed with `prefix`, properly camelCased, eg:\n * WebkitTransitionDuration\n */\nfunction prefixKey(prefix, key) {\n  return prefix + key.charAt(0).toUpperCase() + key.substring(1);\n}\n\n/**\n * Support style names that may come passed in prefixed by adding permutations\n * of vendor prefixes.\n */\nvar prefixes = ['Webkit', 'ms', 'Moz', 'O'];\n\n// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an\n// infinite loop, because it iterates over the newly added props too.\nObject.keys(isUnitlessNumber).forEach(function (prop) {\n  prefixes.forEach(function (prefix) {\n    isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];\n  });\n});\n\n/**\n * Most style properties can be unset by doing .style[prop] = '' but IE8\n * doesn't like doing that with shorthand properties so for the properties that\n * IE8 breaks on, which are listed here, we instead unset each of the\n * individual properties. See http://bugs.jquery.com/ticket/12385.\n * The 4-value 'clock' properties like margin, padding, border-width seem to\n * behave without any problems. Curiously, list-style works too without any\n * special prodding.\n */\nvar shorthandPropertyExpansions = {\n  background: {\n    backgroundAttachment: true,\n    backgroundColor: true,\n    backgroundImage: true,\n    backgroundPositionX: true,\n    backgroundPositionY: true,\n    backgroundRepeat: true\n  },\n  backgroundPosition: {\n    backgroundPositionX: true,\n    backgroundPositionY: true\n  },\n  border: {\n    borderWidth: true,\n    borderStyle: true,\n    borderColor: true\n  },\n  borderBottom: {\n    borderBottomWidth: true,\n    borderBottomStyle: true,\n    borderBottomColor: true\n  },\n  borderLeft: {\n    borderLeftWidth: true,\n    borderLeftStyle: true,\n    borderLeftColor: true\n  },\n  borderRight: {\n    borderRightWidth: true,\n    borderRightStyle: true,\n    borderRightColor: true\n  },\n  borderTop: {\n    borderTopWidth: true,\n    borderTopStyle: true,\n    borderTopColor: true\n  },\n  font: {\n    fontStyle: true,\n    fontVariant: true,\n    fontWeight: true,\n    fontSize: true,\n    lineHeight: true,\n    fontFamily: true\n  },\n  outline: {\n    outlineWidth: true,\n    outlineStyle: true,\n    outlineColor: true\n  }\n};\n\nvar CSSProperty = {\n  isUnitlessNumber: isUnitlessNumber,\n  shorthandPropertyExpansions: shorthandPropertyExpansions\n};\n\nmodule.exports = CSSProperty;\n},{}],4:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CSSPropertyOperations\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactInstrumentation = _dereq_(74);\n\nvar camelizeStyleName = _dereq_(149);\nvar dangerousStyleValue = _dereq_(120);\nvar hyphenateStyleName = _dereq_(160);\nvar memoizeStringOnly = _dereq_(167);\nvar warning = _dereq_(171);\n\nvar processStyleName = memoizeStringOnly(function (styleName) {\n  return hyphenateStyleName(styleName);\n});\n\nvar hasShorthandPropertyBug = false;\nvar styleFloatAccessor = 'cssFloat';\nif (ExecutionEnvironment.canUseDOM) {\n  var tempStyle = document.createElement('div').style;\n  try {\n    // IE8 throws \"Invalid argument.\" if resetting shorthand style properties.\n    tempStyle.font = '';\n  } catch (e) {\n    hasShorthandPropertyBug = true;\n  }\n  // IE8 only supports accessing cssFloat (standard) as styleFloat\n  if (document.documentElement.style.cssFloat === undefined) {\n    styleFloatAccessor = 'styleFloat';\n  }\n}\n\nif (\"development\" !== 'production') {\n  // 'msTransform' is correct, but the other prefixes should be capitalized\n  var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;\n\n  // style values shouldn't contain a semicolon\n  var badStyleValueWithSemicolonPattern = /;\\s*$/;\n\n  var warnedStyleNames = {};\n  var warnedStyleValues = {};\n  var warnedForNaNValue = false;\n\n  var warnHyphenatedStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnBadVendoredStyleName = function (name, owner) {\n    if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {\n      return;\n    }\n\n    warnedStyleNames[name] = true;\n    \"development\" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0;\n  };\n\n  var warnStyleValueWithSemicolon = function (name, value, owner) {\n    if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {\n      return;\n    }\n\n    warnedStyleValues[value] = true;\n    \"development\" !== 'production' ? warning(false, 'Style property values shouldn\\'t contain a semicolon.%s ' + 'Try \"%s: %s\" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;\n  };\n\n  var warnStyleValueIsNaN = function (name, value, owner) {\n    if (warnedForNaNValue) {\n      return;\n    }\n\n    warnedForNaNValue = true;\n    \"development\" !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0;\n  };\n\n  var checkRenderMessage = function (owner) {\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' Check the render method of `' + name + '`.';\n      }\n    }\n    return '';\n  };\n\n  /**\n   * @param {string} name\n   * @param {*} value\n   * @param {ReactDOMComponent} component\n   */\n  var warnValidStyle = function (name, value, component) {\n    var owner;\n    if (component) {\n      owner = component._currentElement._owner;\n    }\n    if (name.indexOf('-') > -1) {\n      warnHyphenatedStyleName(name, owner);\n    } else if (badVendoredStyleNamePattern.test(name)) {\n      warnBadVendoredStyleName(name, owner);\n    } else if (badStyleValueWithSemicolonPattern.test(value)) {\n      warnStyleValueWithSemicolon(name, value, owner);\n    }\n\n    if (typeof value === 'number' && isNaN(value)) {\n      warnStyleValueIsNaN(name, value, owner);\n    }\n  };\n}\n\n/**\n * Operations for dealing with CSS properties.\n */\nvar CSSPropertyOperations = {\n\n  /**\n   * Serializes a mapping of style properties for use as inline styles:\n   *\n   *   > createMarkupForStyles({width: '200px', height: 0})\n   *   \"width:200px;height:0;\"\n   *\n   * Undefined values are ignored so that declarative programming is easier.\n   * The result should be HTML-escaped before insertion into the DOM.\n   *\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   * @return {?string}\n   */\n  createMarkupForStyles: function (styles, component) {\n    var serialized = '';\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      var styleValue = styles[styleName];\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styleValue, component);\n      }\n      if (styleValue != null) {\n        serialized += processStyleName(styleName) + ':';\n        serialized += dangerousStyleValue(styleName, styleValue, component) + ';';\n      }\n    }\n    return serialized || null;\n  },\n\n  /**\n   * Sets the value for multiple styles on a node.  If a value is specified as\n   * '' (empty string), the corresponding style property will be unset.\n   *\n   * @param {DOMElement} node\n   * @param {object} styles\n   * @param {ReactDOMComponent} component\n   */\n  setValueForStyles: function (node, styles, component) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onHostOperation(component._debugID, 'update styles', styles);\n    }\n\n    var style = node.style;\n    for (var styleName in styles) {\n      if (!styles.hasOwnProperty(styleName)) {\n        continue;\n      }\n      if (\"development\" !== 'production') {\n        warnValidStyle(styleName, styles[styleName], component);\n      }\n      var styleValue = dangerousStyleValue(styleName, styles[styleName], component);\n      if (styleName === 'float' || styleName === 'cssFloat') {\n        styleName = styleFloatAccessor;\n      }\n      if (styleValue) {\n        style[styleName] = styleValue;\n      } else {\n        var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];\n        if (expansion) {\n          // Shorthand property that IE8 won't like unsetting, so unset each\n          // component to placate it\n          for (var individualStyleName in expansion) {\n            style[individualStyleName] = '';\n          }\n        } else {\n          style[styleName] = '';\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = CSSPropertyOperations;\n},{\"120\":120,\"147\":147,\"149\":149,\"160\":160,\"167\":167,\"171\":171,\"3\":3,\"74\":74}],5:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule CallbackQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar invariant = _dereq_(161);\n\n/**\n * A specialized pseudo-event module to help keep track of components waiting to\n * be notified when their DOM representations are available for use.\n *\n * This implements `PooledClass`, so you should never need to instantiate this.\n * Instead, use `CallbackQueue.getPooled()`.\n *\n * @class ReactMountReady\n * @implements PooledClass\n * @internal\n */\nfunction CallbackQueue() {\n  this._callbacks = null;\n  this._contexts = null;\n}\n\n_assign(CallbackQueue.prototype, {\n\n  /**\n   * Enqueues a callback to be invoked when `notifyAll` is invoked.\n   *\n   * @param {function} callback Invoked when `notifyAll` is invoked.\n   * @param {?object} context Context to call `callback` with.\n   * @internal\n   */\n  enqueue: function (callback, context) {\n    this._callbacks = this._callbacks || [];\n    this._contexts = this._contexts || [];\n    this._callbacks.push(callback);\n    this._contexts.push(context);\n  },\n\n  /**\n   * Invokes all enqueued callbacks and clears the queue. This is invoked after\n   * the DOM representation of a component has been created or updated.\n   *\n   * @internal\n   */\n  notifyAll: function () {\n    var callbacks = this._callbacks;\n    var contexts = this._contexts;\n    if (callbacks) {\n      !(callbacks.length === contexts.length) ? \"development\" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : _prodInvariant('24') : void 0;\n      this._callbacks = null;\n      this._contexts = null;\n      for (var i = 0; i < callbacks.length; i++) {\n        callbacks[i].call(contexts[i]);\n      }\n      callbacks.length = 0;\n      contexts.length = 0;\n    }\n  },\n\n  checkpoint: function () {\n    return this._callbacks ? this._callbacks.length : 0;\n  },\n\n  rollback: function (len) {\n    if (this._callbacks) {\n      this._callbacks.length = len;\n      this._contexts.length = len;\n    }\n  },\n\n  /**\n   * Resets the internal queue.\n   *\n   * @internal\n   */\n  reset: function () {\n    this._callbacks = null;\n    this._contexts = null;\n  },\n\n  /**\n   * `PooledClass` looks for this.\n   */\n  destructor: function () {\n    this.reset();\n  }\n\n});\n\nPooledClass.addPoolingTo(CallbackQueue);\n\nmodule.exports = CallbackQueue;\n},{\"139\":139,\"161\":161,\"172\":172,\"25\":25}],6:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ChangeEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\nvar isEventSupported = _dereq_(135);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  change: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onChange: null }),\n      captured: keyOf({ onChangeCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topSelectionChange]\n  }\n};\n\n/**\n * For IE shims\n */\nvar activeElement = null;\nvar activeElementInst = null;\nvar activeElementValue = null;\nvar activeElementValueProp = null;\n\n/**\n * SECTION: handle `change` event\n */\nfunction shouldUseChangeEvent(elem) {\n  var nodeName = elem.nodeName && elem.nodeName.toLowerCase();\n  return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';\n}\n\nvar doesChangeEventBubble = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // See `handleChange` comment below\n  doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8);\n}\n\nfunction manualDispatchChangeEvent(nativeEvent) {\n  var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent));\n  EventPropagators.accumulateTwoPhaseDispatches(event);\n\n  // If change and propertychange bubbled, we'd just bind to it like all the\n  // other events and have it go through ReactBrowserEventEmitter. Since it\n  // doesn't, we manually listen for the events and so we have to enqueue and\n  // process the abstract event manually.\n  //\n  // Batching is necessary here in order to ensure that all event handlers run\n  // before the next rerender (including event handlers attached to ancestor\n  // elements instead of directly on the input). Without this, controlled\n  // components don't work properly in conjunction with event bubbling because\n  // the component is rerendered and the value reverted before all the event\n  // handlers can run. See https://github.com/facebook/react/issues/708.\n  ReactUpdates.batchedUpdates(runEventInBatch, event);\n}\n\nfunction runEventInBatch(event) {\n  EventPluginHub.enqueueEvents(event);\n  EventPluginHub.processEventQueue(false);\n}\n\nfunction startWatchingForChangeEventIE8(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElement.attachEvent('onchange', manualDispatchChangeEvent);\n}\n\nfunction stopWatchingForChangeEventIE8() {\n  if (!activeElement) {\n    return;\n  }\n  activeElement.detachEvent('onchange', manualDispatchChangeEvent);\n  activeElement = null;\n  activeElementInst = null;\n}\n\nfunction getTargetInstForChangeEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topChange) {\n    return targetInst;\n  }\n}\nfunction handleEventsForChangeEventIE8(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForChangeEventIE8();\n    startWatchingForChangeEventIE8(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForChangeEventIE8();\n  }\n}\n\n/**\n * SECTION: handle `input` event\n */\nvar isInputEventSupported = false;\nif (ExecutionEnvironment.canUseDOM) {\n  // IE9 claims to support the input event but fails to trigger it when\n  // deleting text, so we ignore its input events.\n  // IE10+ fire input events to often, such when a placeholder\n  // changes or when an input with a placeholder is focused.\n  isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 11);\n}\n\n/**\n * (For IE <=11) Replacement getter/setter for the `value` property that gets\n * set on the active element.\n */\nvar newValueProp = {\n  get: function () {\n    return activeElementValueProp.get.call(this);\n  },\n  set: function (val) {\n    // Cast to a string so we can do equality checks.\n    activeElementValue = '' + val;\n    activeElementValueProp.set.call(this, val);\n  }\n};\n\n/**\n * (For IE <=11) Starts tracking propertychange events on the passed-in element\n * and override the value property so that we can distinguish user events from\n * value changes in JS.\n */\nfunction startWatchingForValueChange(target, targetInst) {\n  activeElement = target;\n  activeElementInst = targetInst;\n  activeElementValue = target.value;\n  activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value');\n\n  // Not guarded in a canDefineProperty check: IE8 supports defineProperty only\n  // on DOM elements\n  Object.defineProperty(activeElement, 'value', newValueProp);\n  if (activeElement.attachEvent) {\n    activeElement.attachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.addEventListener('propertychange', handlePropertyChange, false);\n  }\n}\n\n/**\n * (For IE <=11) Removes the event listeners from the currently-tracked element,\n * if any exists.\n */\nfunction stopWatchingForValueChange() {\n  if (!activeElement) {\n    return;\n  }\n\n  // delete restores the original property definition\n  delete activeElement.value;\n\n  if (activeElement.detachEvent) {\n    activeElement.detachEvent('onpropertychange', handlePropertyChange);\n  } else {\n    activeElement.removeEventListener('propertychange', handlePropertyChange, false);\n  }\n\n  activeElement = null;\n  activeElementInst = null;\n  activeElementValue = null;\n  activeElementValueProp = null;\n}\n\n/**\n * (For IE <=11) Handles a propertychange event, sending a `change` event if\n * the value of the active element has changed.\n */\nfunction handlePropertyChange(nativeEvent) {\n  if (nativeEvent.propertyName !== 'value') {\n    return;\n  }\n  var value = nativeEvent.srcElement.value;\n  if (value === activeElementValue) {\n    return;\n  }\n  activeElementValue = value;\n\n  manualDispatchChangeEvent(nativeEvent);\n}\n\n/**\n * If a `change` event should be fired, returns the target's ID.\n */\nfunction getTargetInstForInputEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topInput) {\n    // In modern browsers (i.e., not IE8 or IE9), the input event is exactly\n    // what we want so fall through here and trigger an abstract event\n    return targetInst;\n  }\n}\n\nfunction handleEventsForInputEventIE(topLevelType, target, targetInst) {\n  if (topLevelType === topLevelTypes.topFocus) {\n    // In IE8, we can capture almost all .value changes by adding a\n    // propertychange handler and looking for events with propertyName\n    // equal to 'value'\n    // In IE9-11, propertychange fires for most input events but is buggy and\n    // doesn't fire when text is deleted, but conveniently, selectionchange\n    // appears to fire in all of the remaining cases so we catch those and\n    // forward the event if the value has changed\n    // In either case, we don't want to call the event handler if the value\n    // is changed from JS so we redefine a setter for `.value` that updates\n    // our activeElementValue variable, allowing us to ignore those changes\n    //\n    // stopWatching() should be a noop here but we call it just in case we\n    // missed a blur event somehow.\n    stopWatchingForValueChange();\n    startWatchingForValueChange(target, targetInst);\n  } else if (topLevelType === topLevelTypes.topBlur) {\n    stopWatchingForValueChange();\n  }\n}\n\n// For IE8 and IE9.\nfunction getTargetInstForInputEventIE(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) {\n    // On the selectionchange event, the target is just document which isn't\n    // helpful for us so just check activeElement instead.\n    //\n    // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire\n    // propertychange on the first input event after setting `value` from a\n    // script and fires only keydown, keypress, keyup. Catching keyup usually\n    // gets it and catching keydown lets us fire an event for the first\n    // keystroke if user does a key repeat (it'll be a little delayed: right\n    // before the second keystroke). Other input methods (e.g., paste) seem to\n    // fire selectionchange normally.\n    if (activeElement && activeElement.value !== activeElementValue) {\n      activeElementValue = activeElement.value;\n      return activeElementInst;\n    }\n  }\n}\n\n/**\n * SECTION: handle `click` event\n */\nfunction shouldUseClickEvent(elem) {\n  // Use the `click` event to detect changes to checkbox and radio inputs.\n  // This approach works across all browsers, whereas `change` does not fire\n  // until `blur` in IE8.\n  return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');\n}\n\nfunction getTargetInstForClickEvent(topLevelType, targetInst) {\n  if (topLevelType === topLevelTypes.topClick) {\n    return targetInst;\n  }\n}\n\n/**\n * This plugin creates an `onChange` event that normalizes change events\n * across form elements. This event fires at a time when it's possible to\n * change the element's value without seeing a flicker.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - select\n */\nvar ChangeEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    var getTargetInstFunc, handleEventFunc;\n    if (shouldUseChangeEvent(targetNode)) {\n      if (doesChangeEventBubble) {\n        getTargetInstFunc = getTargetInstForChangeEvent;\n      } else {\n        handleEventFunc = handleEventsForChangeEventIE8;\n      }\n    } else if (isTextInputElement(targetNode)) {\n      if (isInputEventSupported) {\n        getTargetInstFunc = getTargetInstForInputEvent;\n      } else {\n        getTargetInstFunc = getTargetInstForInputEventIE;\n        handleEventFunc = handleEventsForInputEventIE;\n      }\n    } else if (shouldUseClickEvent(targetNode)) {\n      getTargetInstFunc = getTargetInstForClickEvent;\n    }\n\n    if (getTargetInstFunc) {\n      var inst = getTargetInstFunc(topLevelType, targetInst);\n      if (inst) {\n        var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget);\n        event.type = 'change';\n        EventPropagators.accumulateTwoPhaseDispatches(event);\n        return event;\n      }\n    }\n\n    if (handleEventFunc) {\n      handleEventFunc(topLevelType, targetNode, targetInst);\n    }\n  }\n\n};\n\nmodule.exports = ChangeEventPlugin;\n},{\"104\":104,\"128\":128,\"135\":135,\"136\":136,\"147\":147,\"16\":16,\"165\":165,\"17\":17,\"20\":20,\"41\":41,\"95\":95}],7:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMChildrenOperations\n */\n\n'use strict';\n\nvar DOMLazyTree = _dereq_(8);\nvar Danger = _dereq_(12);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setInnerHTML = _dereq_(141);\nvar setTextContent = _dereq_(142);\n\nfunction getNodeAfter(parentNode, node) {\n  // Special case for text components, which return [open, close] comments\n  // from getHostNode.\n  if (Array.isArray(node)) {\n    node = node[1];\n  }\n  return node ? node.nextSibling : parentNode.firstChild;\n}\n\n/**\n * Inserts `childNode` as a child of `parentNode` at the `index`.\n *\n * @param {DOMElement} parentNode Parent node in which to insert.\n * @param {DOMElement} childNode Child node to insert.\n * @param {number} index Index at which to insert the child.\n * @internal\n */\nvar insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) {\n  // We rely exclusively on `insertBefore(node, null)` instead of also using\n  // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so\n  // we are careful to use `null`.)\n  parentNode.insertBefore(childNode, referenceNode);\n});\n\nfunction insertLazyTreeChildAt(parentNode, childTree, referenceNode) {\n  DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);\n}\n\nfunction moveChild(parentNode, childNode, referenceNode) {\n  if (Array.isArray(childNode)) {\n    moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);\n  } else {\n    insertChildAt(parentNode, childNode, referenceNode);\n  }\n}\n\nfunction removeChild(parentNode, childNode) {\n  if (Array.isArray(childNode)) {\n    var closingComment = childNode[1];\n    childNode = childNode[0];\n    removeDelimitedText(parentNode, childNode, closingComment);\n    parentNode.removeChild(closingComment);\n  }\n  parentNode.removeChild(childNode);\n}\n\nfunction moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) {\n  var node = openingComment;\n  while (true) {\n    var nextNode = node.nextSibling;\n    insertChildAt(parentNode, node, referenceNode);\n    if (node === closingComment) {\n      break;\n    }\n    node = nextNode;\n  }\n}\n\nfunction removeDelimitedText(parentNode, startNode, closingComment) {\n  while (true) {\n    var node = startNode.nextSibling;\n    if (node === closingComment) {\n      // The closing comment is removed by ReactMultiChild.\n      break;\n    } else {\n      parentNode.removeChild(node);\n    }\n  }\n}\n\nfunction replaceDelimitedText(openingComment, closingComment, stringText) {\n  var parentNode = openingComment.parentNode;\n  var nodeAfterComment = openingComment.nextSibling;\n  if (nodeAfterComment === closingComment) {\n    // There are no text nodes between the opening and closing comments; insert\n    // a new one if stringText isn't empty.\n    if (stringText) {\n      insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment);\n    }\n  } else {\n    if (stringText) {\n      // Set the text content of the first node after the opening comment, and\n      // remove all following nodes up until the closing comment.\n      setTextContent(nodeAfterComment, stringText);\n      removeDelimitedText(parentNode, nodeAfterComment, closingComment);\n    } else {\n      removeDelimitedText(parentNode, openingComment, closingComment);\n    }\n  }\n\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID, 'replace text', stringText);\n  }\n}\n\nvar dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup;\nif (\"development\" !== 'production') {\n  dangerouslyReplaceNodeWithMarkup = function (oldChild, markup, prevInstance) {\n    Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup);\n    if (prevInstance._debugID !== 0) {\n      ReactInstrumentation.debugTool.onHostOperation(prevInstance._debugID, 'replace with', markup.toString());\n    } else {\n      var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node);\n      if (nextInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(nextInstance._debugID, 'mount', markup.toString());\n      }\n    }\n  };\n}\n\n/**\n * Operations for updating with DOM children.\n */\nvar DOMChildrenOperations = {\n\n  dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,\n\n  replaceDelimitedText: replaceDelimitedText,\n\n  /**\n   * Updates a component's children by processing a series of updates. The\n   * update configurations are each expected to have a `parentNode` property.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  processUpdates: function (parentNode, updates) {\n    if (\"development\" !== 'production') {\n      var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID;\n    }\n\n    for (var k = 0; k < updates.length; k++) {\n      var update = updates[k];\n      switch (update.type) {\n        case ReactMultiChildUpdateTypes.INSERT_MARKUP:\n          insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'insert child', { toIndex: update.toIndex, content: update.content.toString() });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.MOVE_EXISTING:\n          moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode));\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'move child', { fromIndex: update.fromIndex, toIndex: update.toIndex });\n          }\n          break;\n        case ReactMultiChildUpdateTypes.SET_MARKUP:\n          setInnerHTML(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace children', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.TEXT_CONTENT:\n          setTextContent(parentNode, update.content);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace text', update.content.toString());\n          }\n          break;\n        case ReactMultiChildUpdateTypes.REMOVE_NODE:\n          removeChild(parentNode, update.fromNode);\n          if (\"development\" !== 'production') {\n            ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'remove child', { fromIndex: update.fromIndex });\n          }\n          break;\n      }\n    }\n  }\n\n};\n\nmodule.exports = DOMChildrenOperations;\n},{\"119\":119,\"12\":12,\"141\":141,\"142\":142,\"41\":41,\"74\":74,\"79\":79,\"8\":8}],8:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMLazyTree\n */\n\n'use strict';\n\nvar DOMNamespaces = _dereq_(9);\nvar setInnerHTML = _dereq_(141);\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\nvar setTextContent = _dereq_(142);\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\n/**\n * In IE (8-11) and Edge, appending nodes with no children is dramatically\n * faster than appending a full subtree, so we essentially queue up the\n * .appendChild calls here and apply them so each node is added to its parent\n * before any children are added.\n *\n * In other browsers, doing so is slower or neutral compared to the other order\n * (in Firefox, twice as slow) so we only do this inversion in IE.\n *\n * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.\n */\nvar enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\\bEdge\\/\\d/.test(navigator.userAgent);\n\nfunction insertTreeChildren(tree) {\n  if (!enableLazy) {\n    return;\n  }\n  var node = tree.node;\n  var children = tree.children;\n  if (children.length) {\n    for (var i = 0; i < children.length; i++) {\n      insertTreeBefore(node, children[i], null);\n    }\n  } else if (tree.html != null) {\n    setInnerHTML(node, tree.html);\n  } else if (tree.text != null) {\n    setTextContent(node, tree.text);\n  }\n}\n\nvar insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {\n  // DocumentFragments aren't actually part of the DOM after insertion so\n  // appending children won't update the DOM. We need to ensure the fragment\n  // is properly populated first, breaking out of our lazy approach for just\n  // this level. Also, some <object> plugins (like Flash Player) will read\n  // <param> nodes immediately upon insertion into the DOM, so <object>\n  // must also be populated prior to insertion into the DOM.\n  if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) {\n    insertTreeChildren(tree);\n    parentNode.insertBefore(tree.node, referenceNode);\n  } else {\n    parentNode.insertBefore(tree.node, referenceNode);\n    insertTreeChildren(tree);\n  }\n});\n\nfunction replaceChildWithTree(oldNode, newTree) {\n  oldNode.parentNode.replaceChild(newTree.node, oldNode);\n  insertTreeChildren(newTree);\n}\n\nfunction queueChild(parentTree, childTree) {\n  if (enableLazy) {\n    parentTree.children.push(childTree);\n  } else {\n    parentTree.node.appendChild(childTree.node);\n  }\n}\n\nfunction queueHTML(tree, html) {\n  if (enableLazy) {\n    tree.html = html;\n  } else {\n    setInnerHTML(tree.node, html);\n  }\n}\n\nfunction queueText(tree, text) {\n  if (enableLazy) {\n    tree.text = text;\n  } else {\n    setTextContent(tree.node, text);\n  }\n}\n\nfunction toString() {\n  return this.node.nodeName;\n}\n\nfunction DOMLazyTree(node) {\n  return {\n    node: node,\n    children: [],\n    html: null,\n    text: null,\n    toString: toString\n  };\n}\n\nDOMLazyTree.insertTreeBefore = insertTreeBefore;\nDOMLazyTree.replaceChildWithTree = replaceChildWithTree;\nDOMLazyTree.queueChild = queueChild;\nDOMLazyTree.queueHTML = queueHTML;\nDOMLazyTree.queueText = queueText;\n\nmodule.exports = DOMLazyTree;\n},{\"119\":119,\"141\":141,\"142\":142,\"9\":9}],9:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMNamespaces\n */\n\n'use strict';\n\nvar DOMNamespaces = {\n  html: 'http://www.w3.org/1999/xhtml',\n  mathml: 'http://www.w3.org/1998/Math/MathML',\n  svg: 'http://www.w3.org/2000/svg'\n};\n\nmodule.exports = DOMNamespaces;\n},{}],10:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMProperty\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nfunction checkMask(value, bitmask) {\n  return (value & bitmask) === bitmask;\n}\n\nvar DOMPropertyInjection = {\n  /**\n   * Mapping from normalized, camelcased property names to a configuration that\n   * specifies how the associated DOM property should be accessed or rendered.\n   */\n  MUST_USE_PROPERTY: 0x1,\n  HAS_BOOLEAN_VALUE: 0x4,\n  HAS_NUMERIC_VALUE: 0x8,\n  HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,\n  HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,\n\n  /**\n   * Inject some specialized knowledge about the DOM. This takes a config object\n   * with the following properties:\n   *\n   * isCustomAttribute: function that given an attribute name will return true\n   * if it can be inserted into the DOM verbatim. Useful for data-* or aria-*\n   * attributes where it's impossible to enumerate all of the possible\n   * attribute names,\n   *\n   * Properties: object mapping DOM property name to one of the\n   * DOMPropertyInjection constants or null. If your attribute isn't in here,\n   * it won't get written to the DOM.\n   *\n   * DOMAttributeNames: object mapping React attribute name to the DOM\n   * attribute name. Attribute names not specified use the **lowercase**\n   * normalized name.\n   *\n   * DOMAttributeNamespaces: object mapping React attribute name to the DOM\n   * attribute namespace URL. (Attribute names not specified use no namespace.)\n   *\n   * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties.\n   * Property names not specified use the normalized name.\n   *\n   * DOMMutationMethods: Properties that require special mutation methods. If\n   * `value` is undefined, the mutation method should unset the property.\n   *\n   * @param {object} domPropertyConfig the config as described above.\n   */\n  injectDOMPropertyConfig: function (domPropertyConfig) {\n    var Injection = DOMPropertyInjection;\n    var Properties = domPropertyConfig.Properties || {};\n    var DOMAttributeNamespaces = domPropertyConfig.DOMAttributeNamespaces || {};\n    var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {};\n    var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};\n    var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};\n\n    if (domPropertyConfig.isCustomAttribute) {\n      DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute);\n    }\n\n    for (var propName in Properties) {\n      !!DOMProperty.properties.hasOwnProperty(propName) ? \"development\" !== 'production' ? invariant(false, 'injectDOMPropertyConfig(...): You\\'re trying to inject DOM property \\'%s\\' which has already been injected. You may be accidentally injecting the same DOM property config twice, or you may be injecting two configs that have conflicting property names.', propName) : _prodInvariant('48', propName) : void 0;\n\n      var lowerCased = propName.toLowerCase();\n      var propConfig = Properties[propName];\n\n      var propertyInfo = {\n        attributeName: lowerCased,\n        attributeNamespace: null,\n        propertyName: propName,\n        mutationMethod: null,\n\n        mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),\n        hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),\n        hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),\n        hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),\n        hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE)\n      };\n      !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? \"development\" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : _prodInvariant('50', propName) : void 0;\n\n      if (\"development\" !== 'production') {\n        DOMProperty.getPossibleStandardName[lowerCased] = propName;\n      }\n\n      if (DOMAttributeNames.hasOwnProperty(propName)) {\n        var attributeName = DOMAttributeNames[propName];\n        propertyInfo.attributeName = attributeName;\n        if (\"development\" !== 'production') {\n          DOMProperty.getPossibleStandardName[attributeName] = propName;\n        }\n      }\n\n      if (DOMAttributeNamespaces.hasOwnProperty(propName)) {\n        propertyInfo.attributeNamespace = DOMAttributeNamespaces[propName];\n      }\n\n      if (DOMPropertyNames.hasOwnProperty(propName)) {\n        propertyInfo.propertyName = DOMPropertyNames[propName];\n      }\n\n      if (DOMMutationMethods.hasOwnProperty(propName)) {\n        propertyInfo.mutationMethod = DOMMutationMethods[propName];\n      }\n\n      DOMProperty.properties[propName] = propertyInfo;\n    }\n  }\n};\n\n/* eslint-disable max-len */\nvar ATTRIBUTE_NAME_START_CHAR = ':A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\n/* eslint-enable max-len */\n\n/**\n * DOMProperty exports lookup objects that can be used like functions:\n *\n *   > DOMProperty.isValid['id']\n *   true\n *   > DOMProperty.isValid['foobar']\n *   undefined\n *\n * Although this may be confusing, it performs better in general.\n *\n * @see http://jsperf.com/key-exists\n * @see http://jsperf.com/key-missing\n */\nvar DOMProperty = {\n\n  ID_ATTRIBUTE_NAME: 'data-reactid',\n  ROOT_ATTRIBUTE_NAME: 'data-reactroot',\n\n  ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,\n  ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR + '\\\\-.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040',\n\n  /**\n   * Map from property \"standard name\" to an object with info about how to set\n   * the property in the DOM. Each object contains:\n   *\n   * attributeName:\n   *   Used when rendering markup or with `*Attribute()`.\n   * attributeNamespace\n   * propertyName:\n   *   Used on DOM node instances. (This includes properties that mutate due to\n   *   external factors.)\n   * mutationMethod:\n   *   If non-null, used instead of the property or `setAttribute()` after\n   *   initial render.\n   * mustUseProperty:\n   *   Whether the property must be accessed and mutated as an object property.\n   * hasBooleanValue:\n   *   Whether the property should be removed when set to a falsey value.\n   * hasNumericValue:\n   *   Whether the property must be numeric or parse as a numeric and should be\n   *   removed when set to a falsey value.\n   * hasPositiveNumericValue:\n   *   Whether the property must be positive numeric or parse as a positive\n   *   numeric and should be removed when set to a falsey value.\n   * hasOverloadedBooleanValue:\n   *   Whether the property can be used as a flag as well as with a value.\n   *   Removed when strictly equal to false; present without a value when\n   *   strictly equal to true; present with a value otherwise.\n   */\n  properties: {},\n\n  /**\n   * Mapping from lowercase property names to the properly cased version, used\n   * to warn in the case of missing properties. Available only in __DEV__.\n   * @type {Object}\n   */\n  getPossibleStandardName: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * All of the isCustomAttribute() functions that have been injected.\n   */\n  _isCustomAttributeFunctions: [],\n\n  /**\n   * Checks whether a property name is a custom attribute.\n   * @method\n   */\n  isCustomAttribute: function (attributeName) {\n    for (var i = 0; i < DOMProperty._isCustomAttributeFunctions.length; i++) {\n      var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];\n      if (isCustomAttributeFn(attributeName)) {\n        return true;\n      }\n    }\n    return false;\n  },\n\n  injection: DOMPropertyInjection\n};\n\nmodule.exports = DOMProperty;\n},{\"139\":139,\"161\":161}],11:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DOMPropertyOperations\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInstrumentation = _dereq_(49);\nvar ReactInstrumentation = _dereq_(74);\n\nvar quoteAttributeValueForBrowser = _dereq_(138);\nvar warning = _dereq_(171);\n\nvar VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');\nvar illegalAttributeNameCache = {};\nvar validatedAttributeNameCache = {};\n\nfunction isAttributeNameSafe(attributeName) {\n  if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {\n    return true;\n  }\n  if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {\n    return false;\n  }\n  if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {\n    validatedAttributeNameCache[attributeName] = true;\n    return true;\n  }\n  illegalAttributeNameCache[attributeName] = true;\n  \"development\" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;\n  return false;\n}\n\nfunction shouldIgnoreValue(propertyInfo, value) {\n  return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;\n}\n\n/**\n * Operations for dealing with DOM properties.\n */\nvar DOMPropertyOperations = {\n\n  /**\n   * Creates markup for the ID property.\n   *\n   * @param {string} id Unescaped ID.\n   * @return {string} Markup string.\n   */\n  createMarkupForID: function (id) {\n    return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);\n  },\n\n  setAttributeForID: function (node, id) {\n    node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);\n  },\n\n  createMarkupForRoot: function () {\n    return DOMProperty.ROOT_ATTRIBUTE_NAME + '=\"\"';\n  },\n\n  setAttributeForRoot: function (node) {\n    node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');\n  },\n\n  /**\n   * Creates markup for a property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {?string} Markup string, or null if the property was invalid.\n   */\n  createMarkupForProperty: function (name, value) {\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onCreateMarkupForProperty(name, value);\n    }\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      if (shouldIgnoreValue(propertyInfo, value)) {\n        return '';\n      }\n      var attributeName = propertyInfo.attributeName;\n      if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n        return attributeName + '=\"\"';\n      }\n      return attributeName + '=' + quoteAttributeValueForBrowser(value);\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      if (value == null) {\n        return '';\n      }\n      return name + '=' + quoteAttributeValueForBrowser(value);\n    }\n    return null;\n  },\n\n  /**\n   * Creates markup for a custom property.\n   *\n   * @param {string} name\n   * @param {*} value\n   * @return {string} Markup string, or empty string if the property was invalid.\n   */\n  createMarkupForCustomAttribute: function (name, value) {\n    if (!isAttributeNameSafe(name) || value == null) {\n      return '';\n    }\n    return name + '=' + quoteAttributeValueForBrowser(value);\n  },\n\n  /**\n   * Sets the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   * @param {*} value\n   */\n  setValueForProperty: function (node, name, value) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, value);\n      } else if (shouldIgnoreValue(propertyInfo, value)) {\n        this.deleteValueForProperty(node, name);\n        return;\n      } else if (propertyInfo.mustUseProperty) {\n        // Contrary to `setAttribute`, object properties are properly\n        // `toString`ed by IE8/9.\n        node[propertyInfo.propertyName] = value;\n      } else {\n        var attributeName = propertyInfo.attributeName;\n        var namespace = propertyInfo.attributeNamespace;\n        // `setAttribute` with objects becomes only `[object]` in IE8/9,\n        // ('' + value) makes it output the correct toString()-value.\n        if (namespace) {\n          node.setAttributeNS(namespace, attributeName, '' + value);\n        } else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {\n          node.setAttribute(attributeName, '');\n        } else {\n          node.setAttribute(attributeName, '' + value);\n        }\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      DOMPropertyOperations.setValueForAttribute(node, name, value);\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onSetValueForProperty(node, name, value);\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  setValueForAttribute: function (node, name, value) {\n    if (!isAttributeNameSafe(name)) {\n      return;\n    }\n    if (value == null) {\n      node.removeAttribute(name);\n    } else {\n      node.setAttribute(name, '' + value);\n    }\n\n    if (\"development\" !== 'production') {\n      var payload = {};\n      payload[name] = value;\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);\n    }\n  },\n\n  /**\n   * Deletes an attributes from a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForAttribute: function (node, name) {\n    node.removeAttribute(name);\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  },\n\n  /**\n   * Deletes the value for a property on a node.\n   *\n   * @param {DOMElement} node\n   * @param {string} name\n   */\n  deleteValueForProperty: function (node, name) {\n    var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;\n    if (propertyInfo) {\n      var mutationMethod = propertyInfo.mutationMethod;\n      if (mutationMethod) {\n        mutationMethod(node, undefined);\n      } else if (propertyInfo.mustUseProperty) {\n        var propName = propertyInfo.propertyName;\n        if (propertyInfo.hasBooleanValue) {\n          node[propName] = false;\n        } else {\n          node[propName] = '';\n        }\n      } else {\n        node.removeAttribute(propertyInfo.attributeName);\n      }\n    } else if (DOMProperty.isCustomAttribute(name)) {\n      node.removeAttribute(name);\n    }\n\n    if (\"development\" !== 'production') {\n      ReactDOMInstrumentation.debugTool.onDeleteValueForProperty(node, name);\n      ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);\n    }\n  }\n\n};\n\nmodule.exports = DOMPropertyOperations;\n},{\"10\":10,\"138\":138,\"171\":171,\"41\":41,\"49\":49,\"74\":74}],12:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Danger\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createNodesFromMarkup = _dereq_(152);\nvar emptyFunction = _dereq_(153);\nvar invariant = _dereq_(161);\n\nvar Danger = {\n\n  /**\n   * Replaces a node with a string of markup at its current position within its\n   * parent. The markup must render into a single root node.\n   *\n   * @param {DOMElement} oldChild Child node to replace.\n   * @param {string} markup Markup to render in place of the child node.\n   * @internal\n   */\n  dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) {\n    !ExecutionEnvironment.canUseDOM ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('56') : void 0;\n    !markup ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : _prodInvariant('57') : void 0;\n    !(oldChild.nodeName !== 'HTML') ? \"development\" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().') : _prodInvariant('58') : void 0;\n\n    if (typeof markup === 'string') {\n      var newChild = createNodesFromMarkup(markup, emptyFunction)[0];\n      oldChild.parentNode.replaceChild(newChild, oldChild);\n    } else {\n      DOMLazyTree.replaceChildWithTree(oldChild, markup);\n    }\n  }\n\n};\n\nmodule.exports = Danger;\n},{\"139\":139,\"147\":147,\"152\":152,\"153\":153,\"161\":161,\"8\":8}],13:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DefaultEventPluginOrder\n */\n\n'use strict';\n\nvar keyOf = _dereq_(165);\n\n/**\n * Module that is injectable into `EventPluginHub`, that specifies a\n * deterministic ordering of `EventPlugin`s. A convenient way to reason about\n * plugins, without having to package every one of them. This is better than\n * having plugins be ordered in the same order that they are injected because\n * that ordering would be influenced by the packaging order.\n * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that\n * preventing default on events is convenient in `SimpleEventPlugin` handlers.\n */\nvar DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })];\n\nmodule.exports = DefaultEventPluginOrder;\n},{\"165\":165}],14:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule DisabledInputUtils\n */\n\n'use strict';\n\nvar disableableMouseListenerNames = {\n  onClick: true,\n  onDoubleClick: true,\n  onMouseDown: true,\n  onMouseMove: true,\n  onMouseUp: true,\n\n  onClickCapture: true,\n  onDoubleClickCapture: true,\n  onMouseDownCapture: true,\n  onMouseMoveCapture: true,\n  onMouseUpCapture: true\n};\n\n/**\n * Implements a host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar DisabledInputUtils = {\n  getHostProps: function (inst, props) {\n    if (!props.disabled) {\n      return props;\n    }\n\n    // Copy the props, except the mouse listeners\n    var hostProps = {};\n    for (var key in props) {\n      if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) {\n        hostProps[key] = props[key];\n      }\n    }\n\n    return hostProps;\n  }\n};\n\nmodule.exports = DisabledInputUtils;\n},{}],15:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EnterLeaveEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticMouseEvent = _dereq_(108);\n\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  mouseEnter: {\n    registrationName: keyOf({ onMouseEnter: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  },\n  mouseLeave: {\n    registrationName: keyOf({ onMouseLeave: null }),\n    dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]\n  }\n};\n\nvar EnterLeaveEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  /**\n   * For almost every interaction we care about, there will be both a top-level\n   * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that\n   * we do not extract duplicate events. However, moving the mouse into the\n   * browser from outside will not fire a `mouseout` event. In this case, we use\n   * the `mouseover` top-level event.\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {\n      return null;\n    }\n    if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) {\n      // Must not be a mouse in or mouse out - ignoring.\n      return null;\n    }\n\n    var win;\n    if (nativeEventTarget.window === nativeEventTarget) {\n      // `nativeEventTarget` is probably a window object.\n      win = nativeEventTarget;\n    } else {\n      // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n      var doc = nativeEventTarget.ownerDocument;\n      if (doc) {\n        win = doc.defaultView || doc.parentWindow;\n      } else {\n        win = window;\n      }\n    }\n\n    var from;\n    var to;\n    if (topLevelType === topLevelTypes.topMouseOut) {\n      from = targetInst;\n      var related = nativeEvent.relatedTarget || nativeEvent.toElement;\n      to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;\n    } else {\n      // Moving to a node from outside the window.\n      from = null;\n      to = targetInst;\n    }\n\n    if (from === to) {\n      // Nothing pertains to our managed components.\n      return null;\n    }\n\n    var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);\n    var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);\n\n    var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);\n    leave.type = 'mouseleave';\n    leave.target = fromNode;\n    leave.relatedTarget = toNode;\n\n    var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);\n    enter.type = 'mouseenter';\n    enter.target = toNode;\n    enter.relatedTarget = fromNode;\n\n    EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);\n\n    return [leave, enter];\n  }\n\n};\n\nmodule.exports = EnterLeaveEventPlugin;\n},{\"108\":108,\"16\":16,\"165\":165,\"20\":20,\"41\":41}],16:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventConstants\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar PropagationPhases = keyMirror({ bubbled: null, captured: null });\n\n/**\n * Types of raw signals from the browser caught at the top level.\n */\nvar topLevelTypes = keyMirror({\n  topAbort: null,\n  topAnimationEnd: null,\n  topAnimationIteration: null,\n  topAnimationStart: null,\n  topBlur: null,\n  topCanPlay: null,\n  topCanPlayThrough: null,\n  topChange: null,\n  topClick: null,\n  topCompositionEnd: null,\n  topCompositionStart: null,\n  topCompositionUpdate: null,\n  topContextMenu: null,\n  topCopy: null,\n  topCut: null,\n  topDoubleClick: null,\n  topDrag: null,\n  topDragEnd: null,\n  topDragEnter: null,\n  topDragExit: null,\n  topDragLeave: null,\n  topDragOver: null,\n  topDragStart: null,\n  topDrop: null,\n  topDurationChange: null,\n  topEmptied: null,\n  topEncrypted: null,\n  topEnded: null,\n  topError: null,\n  topFocus: null,\n  topInput: null,\n  topInvalid: null,\n  topKeyDown: null,\n  topKeyPress: null,\n  topKeyUp: null,\n  topLoad: null,\n  topLoadedData: null,\n  topLoadedMetadata: null,\n  topLoadStart: null,\n  topMouseDown: null,\n  topMouseMove: null,\n  topMouseOut: null,\n  topMouseOver: null,\n  topMouseUp: null,\n  topPaste: null,\n  topPause: null,\n  topPlay: null,\n  topPlaying: null,\n  topProgress: null,\n  topRateChange: null,\n  topReset: null,\n  topScroll: null,\n  topSeeked: null,\n  topSeeking: null,\n  topSelectionChange: null,\n  topStalled: null,\n  topSubmit: null,\n  topSuspend: null,\n  topTextInput: null,\n  topTimeUpdate: null,\n  topTouchCancel: null,\n  topTouchEnd: null,\n  topTouchMove: null,\n  topTouchStart: null,\n  topTransitionEnd: null,\n  topVolumeChange: null,\n  topWaiting: null,\n  topWheel: null\n});\n\nvar EventConstants = {\n  topLevelTypes: topLevelTypes,\n  PropagationPhases: PropagationPhases\n};\n\nmodule.exports = EventConstants;\n},{\"164\":164}],17:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginHub\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventPluginRegistry = _dereq_(18);\nvar EventPluginUtils = _dereq_(19);\nvar ReactErrorUtils = _dereq_(65);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar invariant = _dereq_(161);\n\n/**\n * Internal store for event listeners\n */\nvar listenerBank = {};\n\n/**\n * Internal queue of events that have accumulated their dispatches and are\n * waiting to have their dispatches executed.\n */\nvar eventQueue = null;\n\n/**\n * Dispatches an event and releases it back into the pool, unless persistent.\n *\n * @param {?object} event Synthetic event to be dispatched.\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @private\n */\nvar executeDispatchesAndRelease = function (event, simulated) {\n  if (event) {\n    EventPluginUtils.executeDispatchesInOrder(event, simulated);\n\n    if (!event.isPersistent()) {\n      event.constructor.release(event);\n    }\n  }\n};\nvar executeDispatchesAndReleaseSimulated = function (e) {\n  return executeDispatchesAndRelease(e, true);\n};\nvar executeDispatchesAndReleaseTopLevel = function (e) {\n  return executeDispatchesAndRelease(e, false);\n};\n\n/**\n * This is a unified interface for event plugins to be installed and configured.\n *\n * Event plugins can implement the following properties:\n *\n *   `extractEvents` {function(string, DOMEventTarget, string, object): *}\n *     Required. When a top-level event is fired, this method is expected to\n *     extract synthetic events that will in turn be queued and dispatched.\n *\n *   `eventTypes` {object}\n *     Optional, plugins that fire events must publish a mapping of registration\n *     names that are used to register listeners. Values of this mapping must\n *     be objects that contain `registrationName` or `phasedRegistrationNames`.\n *\n *   `executeDispatch` {function(object, function, string)}\n *     Optional, allows plugins to override how an event gets dispatched. By\n *     default, the listener is simply invoked.\n *\n * Each plugin that is injected into `EventsPluginHub` is immediately operable.\n *\n * @public\n */\nvar EventPluginHub = {\n\n  /**\n   * Methods for injecting dependencies.\n   */\n  injection: {\n\n    /**\n     * @param {array} InjectedEventPluginOrder\n     * @public\n     */\n    injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,\n\n    /**\n     * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n     */\n    injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName\n\n  },\n\n  /**\n   * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {function} listener The callback to store.\n   */\n  putListener: function (inst, registrationName, listener) {\n    !(typeof listener === 'function') ? \"development\" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : _prodInvariant('94', registrationName, typeof listener) : void 0;\n\n    var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});\n    bankForRegistrationName[inst._rootNodeID] = listener;\n\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.didPutListener) {\n      PluginModule.didPutListener(inst, registrationName, listener);\n    }\n  },\n\n  /**\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @return {?function} The stored callback.\n   */\n  getListener: function (inst, registrationName) {\n    var bankForRegistrationName = listenerBank[registrationName];\n    return bankForRegistrationName && bankForRegistrationName[inst._rootNodeID];\n  },\n\n  /**\n   * Deletes a listener from the registration bank.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   */\n  deleteListener: function (inst, registrationName) {\n    var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n    if (PluginModule && PluginModule.willDeleteListener) {\n      PluginModule.willDeleteListener(inst, registrationName);\n    }\n\n    var bankForRegistrationName = listenerBank[registrationName];\n    // TODO: This should never be null -- when is it?\n    if (bankForRegistrationName) {\n      delete bankForRegistrationName[inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Deletes all listeners for the DOM element with the supplied ID.\n   *\n   * @param {object} inst The instance, which is the source of events.\n   */\n  deleteAllListeners: function (inst) {\n    for (var registrationName in listenerBank) {\n      if (!listenerBank.hasOwnProperty(registrationName)) {\n        continue;\n      }\n\n      if (!listenerBank[registrationName][inst._rootNodeID]) {\n        continue;\n      }\n\n      var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];\n      if (PluginModule && PluginModule.willDeleteListener) {\n        PluginModule.willDeleteListener(inst, registrationName);\n      }\n\n      delete listenerBank[registrationName][inst._rootNodeID];\n    }\n  },\n\n  /**\n   * Allows registered plugins an opportunity to extract events from top-level\n   * native browser events.\n   *\n   * @return {*} An accumulation of synthetic events.\n   * @internal\n   */\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events;\n    var plugins = EventPluginRegistry.plugins;\n    for (var i = 0; i < plugins.length; i++) {\n      // Not every plugin in the ordering may be loaded at runtime.\n      var possiblePlugin = plugins[i];\n      if (possiblePlugin) {\n        var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n        if (extractedEvents) {\n          events = accumulateInto(events, extractedEvents);\n        }\n      }\n    }\n    return events;\n  },\n\n  /**\n   * Enqueues a synthetic event that should be dispatched when\n   * `processEventQueue` is invoked.\n   *\n   * @param {*} events An accumulation of synthetic events.\n   * @internal\n   */\n  enqueueEvents: function (events) {\n    if (events) {\n      eventQueue = accumulateInto(eventQueue, events);\n    }\n  },\n\n  /**\n   * Dispatches all synthetic events on the event queue.\n   *\n   * @internal\n   */\n  processEventQueue: function (simulated) {\n    // Set `eventQueue` to null before processing it so that we can tell if more\n    // events get enqueued while processing.\n    var processingEventQueue = eventQueue;\n    eventQueue = null;\n    if (simulated) {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);\n    } else {\n      forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);\n    }\n    !!eventQueue ? \"development\" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : _prodInvariant('95') : void 0;\n    // This would be a good time to rethrow if any of the event handlers threw.\n    ReactErrorUtils.rethrowCaughtError();\n  },\n\n  /**\n   * These are needed for tests only. Do not use!\n   */\n  __purge: function () {\n    listenerBank = {};\n  },\n\n  __getListenerBank: function () {\n    return listenerBank;\n  }\n\n};\n\nmodule.exports = EventPluginHub;\n},{\"115\":115,\"124\":124,\"139\":139,\"161\":161,\"18\":18,\"19\":19,\"65\":65}],18:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginRegistry\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Injectable ordering of event plugins.\n */\nvar EventPluginOrder = null;\n\n/**\n * Injectable mapping from names to event plugin modules.\n */\nvar namesToPlugins = {};\n\n/**\n * Recomputes the plugin list using the injected plugins and plugin ordering.\n *\n * @private\n */\nfunction recomputePluginOrdering() {\n  if (!EventPluginOrder) {\n    // Wait until an `EventPluginOrder` is injected.\n    return;\n  }\n  for (var pluginName in namesToPlugins) {\n    var PluginModule = namesToPlugins[pluginName];\n    var pluginIndex = EventPluginOrder.indexOf(pluginName);\n    !(pluginIndex > -1) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0;\n    if (EventPluginRegistry.plugins[pluginIndex]) {\n      continue;\n    }\n    !PluginModule.extractEvents ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0;\n    EventPluginRegistry.plugins[pluginIndex] = PluginModule;\n    var publishedEvents = PluginModule.eventTypes;\n    for (var eventName in publishedEvents) {\n      !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('98', eventName, pluginName) : void 0;\n    }\n  }\n}\n\n/**\n * Publishes an event so that it can be dispatched by the supplied plugin.\n *\n * @param {object} dispatchConfig Dispatch configuration for the event.\n * @param {object} PluginModule Plugin publishing the event.\n * @return {boolean} True if the event was successfully published.\n * @private\n */\nfunction publishEventForPlugin(dispatchConfig, PluginModule, eventName) {\n  !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0;\n  EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;\n\n  var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;\n  if (phasedRegistrationNames) {\n    for (var phaseName in phasedRegistrationNames) {\n      if (phasedRegistrationNames.hasOwnProperty(phaseName)) {\n        var phasedRegistrationName = phasedRegistrationNames[phaseName];\n        publishRegistrationName(phasedRegistrationName, PluginModule, eventName);\n      }\n    }\n    return true;\n  } else if (dispatchConfig.registrationName) {\n    publishRegistrationName(dispatchConfig.registrationName, PluginModule, eventName);\n    return true;\n  }\n  return false;\n}\n\n/**\n * Publishes a registration name that is used to identify dispatched events and\n * can be used with `EventPluginHub.putListener` to register listeners.\n *\n * @param {string} registrationName Registration name to add.\n * @param {object} PluginModule Plugin publishing the event.\n * @private\n */\nfunction publishRegistrationName(registrationName, PluginModule, eventName) {\n  !!EventPluginRegistry.registrationNameModules[registrationName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0;\n  EventPluginRegistry.registrationNameModules[registrationName] = PluginModule;\n  EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies;\n\n  if (\"development\" !== 'production') {\n    var lowerCasedName = registrationName.toLowerCase();\n    EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;\n\n    if (registrationName === 'onDoubleClick') {\n      EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;\n    }\n  }\n}\n\n/**\n * Registers plugins so that they can extract and dispatch events.\n *\n * @see {EventPluginHub}\n */\nvar EventPluginRegistry = {\n\n  /**\n   * Ordered list of injected plugins.\n   */\n  plugins: [],\n\n  /**\n   * Mapping from event name to dispatch config\n   */\n  eventNameDispatchConfigs: {},\n\n  /**\n   * Mapping from registration name to plugin module\n   */\n  registrationNameModules: {},\n\n  /**\n   * Mapping from registration name to event name\n   */\n  registrationNameDependencies: {},\n\n  /**\n   * Mapping from lowercase registration names to the properly cased version,\n   * used to warn in the case of missing event handlers. Available\n   * only in __DEV__.\n   * @type {Object}\n   */\n  possibleRegistrationNames: \"development\" !== 'production' ? {} : null,\n\n  /**\n   * Injects an ordering of plugins (by plugin name). This allows the ordering\n   * to be decoupled from injection of the actual plugins so that ordering is\n   * always deterministic regardless of packaging, on-the-fly injection, etc.\n   *\n   * @param {array} InjectedEventPluginOrder\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginOrder}\n   */\n  injectEventPluginOrder: function (InjectedEventPluginOrder) {\n    !!EventPluginOrder ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : _prodInvariant('101') : void 0;\n    // Clone the ordering so it cannot be dynamically mutated.\n    EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);\n    recomputePluginOrdering();\n  },\n\n  /**\n   * Injects plugins to be used by `EventPluginHub`. The plugin names must be\n   * in the ordering injected by `injectEventPluginOrder`.\n   *\n   * Plugins can be injected as part of page initialization or on-the-fly.\n   *\n   * @param {object} injectedNamesToPlugins Map from names to plugin modules.\n   * @internal\n   * @see {EventPluginHub.injection.injectEventPluginsByName}\n   */\n  injectEventPluginsByName: function (injectedNamesToPlugins) {\n    var isOrderingDirty = false;\n    for (var pluginName in injectedNamesToPlugins) {\n      if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {\n        continue;\n      }\n      var PluginModule = injectedNamesToPlugins[pluginName];\n      if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== PluginModule) {\n        !!namesToPlugins[pluginName] ? \"development\" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0;\n        namesToPlugins[pluginName] = PluginModule;\n        isOrderingDirty = true;\n      }\n    }\n    if (isOrderingDirty) {\n      recomputePluginOrdering();\n    }\n  },\n\n  /**\n   * Looks up the plugin for the supplied event.\n   *\n   * @param {object} event A synthetic event.\n   * @return {?object} The plugin that created the supplied event.\n   * @internal\n   */\n  getPluginModuleForEvent: function (event) {\n    var dispatchConfig = event.dispatchConfig;\n    if (dispatchConfig.registrationName) {\n      return EventPluginRegistry.registrationNameModules[dispatchConfig.registrationName] || null;\n    }\n    for (var phase in dispatchConfig.phasedRegistrationNames) {\n      if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) {\n        continue;\n      }\n      var PluginModule = EventPluginRegistry.registrationNameModules[dispatchConfig.phasedRegistrationNames[phase]];\n      if (PluginModule) {\n        return PluginModule;\n      }\n    }\n    return null;\n  },\n\n  /**\n   * Exposed for unit testing.\n   * @private\n   */\n  _resetEventPlugins: function () {\n    EventPluginOrder = null;\n    for (var pluginName in namesToPlugins) {\n      if (namesToPlugins.hasOwnProperty(pluginName)) {\n        delete namesToPlugins[pluginName];\n      }\n    }\n    EventPluginRegistry.plugins.length = 0;\n\n    var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs;\n    for (var eventName in eventNameDispatchConfigs) {\n      if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {\n        delete eventNameDispatchConfigs[eventName];\n      }\n    }\n\n    var registrationNameModules = EventPluginRegistry.registrationNameModules;\n    for (var registrationName in registrationNameModules) {\n      if (registrationNameModules.hasOwnProperty(registrationName)) {\n        delete registrationNameModules[registrationName];\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames;\n      for (var lowerCasedName in possibleRegistrationNames) {\n        if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) {\n          delete possibleRegistrationNames[lowerCasedName];\n        }\n      }\n    }\n  }\n\n};\n\nmodule.exports = EventPluginRegistry;\n},{\"139\":139,\"161\":161}],19:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPluginUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar ReactErrorUtils = _dereq_(65);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Injected dependencies:\n */\n\n/**\n * - `ComponentTree`: [required] Module that can convert between React instances\n *   and actual node references.\n */\nvar ComponentTree;\nvar TreeTraversal;\nvar injection = {\n  injectComponentTree: function (Injected) {\n    ComponentTree = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;\n    }\n  },\n  injectTreeTraversal: function (Injected) {\n    TreeTraversal = Injected;\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;\n    }\n  }\n};\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nfunction isEndish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel;\n}\n\nfunction isMoveish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove;\n}\nfunction isStartish(topLevelType) {\n  return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart;\n}\n\nvar validateEventDispatches;\nif (\"development\" !== 'production') {\n  validateEventDispatches = function (event) {\n    var dispatchListeners = event._dispatchListeners;\n    var dispatchInstances = event._dispatchInstances;\n\n    var listenersIsArr = Array.isArray(dispatchListeners);\n    var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;\n\n    var instancesIsArr = Array.isArray(dispatchInstances);\n    var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;\n\n    \"development\" !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;\n  };\n}\n\n/**\n * Dispatch the event to the listener.\n * @param {SyntheticEvent} event SyntheticEvent to handle\n * @param {boolean} simulated If the event is simulated (changes exn behavior)\n * @param {function} listener Application-level callback\n * @param {*} inst Internal component instance\n */\nfunction executeDispatch(event, simulated, listener, inst) {\n  var type = event.type || 'unknown-event';\n  event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);\n  if (simulated) {\n    ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);\n  } else {\n    ReactErrorUtils.invokeGuardedCallback(type, listener, event);\n  }\n  event.currentTarget = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches.\n */\nfunction executeDispatchesInOrder(event, simulated) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);\n    }\n  } else if (dispatchListeners) {\n    executeDispatch(event, simulated, dispatchListeners, dispatchInstances);\n  }\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n}\n\n/**\n * Standard/simple iteration through an event's collected dispatches, but stops\n * at the first dispatch execution returning true, and returns that id.\n *\n * @return {?string} id of the first dispatch execution who's listener returns\n * true, or null if no listener returned true.\n */\nfunction executeDispatchesInOrderStopAtTrueImpl(event) {\n  var dispatchListeners = event._dispatchListeners;\n  var dispatchInstances = event._dispatchInstances;\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  if (Array.isArray(dispatchListeners)) {\n    for (var i = 0; i < dispatchListeners.length; i++) {\n      if (event.isPropagationStopped()) {\n        break;\n      }\n      // Listeners and Instances are two parallel arrays that are always in sync.\n      if (dispatchListeners[i](event, dispatchInstances[i])) {\n        return dispatchInstances[i];\n      }\n    }\n  } else if (dispatchListeners) {\n    if (dispatchListeners(event, dispatchInstances)) {\n      return dispatchInstances;\n    }\n  }\n  return null;\n}\n\n/**\n * @see executeDispatchesInOrderStopAtTrueImpl\n */\nfunction executeDispatchesInOrderStopAtTrue(event) {\n  var ret = executeDispatchesInOrderStopAtTrueImpl(event);\n  event._dispatchInstances = null;\n  event._dispatchListeners = null;\n  return ret;\n}\n\n/**\n * Execution of a \"direct\" dispatch - there must be at most one dispatch\n * accumulated on the event or it is considered an error. It doesn't really make\n * sense for an event with multiple dispatches (bubbled) to keep track of the\n * return values at each dispatch execution, but it does tend to make sense when\n * dealing with \"direct\" dispatches.\n *\n * @return {*} The return value of executing the single dispatch.\n */\nfunction executeDirectDispatch(event) {\n  if (\"development\" !== 'production') {\n    validateEventDispatches(event);\n  }\n  var dispatchListener = event._dispatchListeners;\n  var dispatchInstance = event._dispatchInstances;\n  !!Array.isArray(dispatchListener) ? \"development\" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0;\n  event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;\n  var res = dispatchListener ? dispatchListener(event) : null;\n  event.currentTarget = null;\n  event._dispatchListeners = null;\n  event._dispatchInstances = null;\n  return res;\n}\n\n/**\n * @param {SyntheticEvent} event\n * @return {boolean} True iff number of dispatches accumulated is greater than 0.\n */\nfunction hasDispatches(event) {\n  return !!event._dispatchListeners;\n}\n\n/**\n * General utilities that are useful in creating custom Event Plugins.\n */\nvar EventPluginUtils = {\n  isEndish: isEndish,\n  isMoveish: isMoveish,\n  isStartish: isStartish,\n\n  executeDirectDispatch: executeDirectDispatch,\n  executeDispatchesInOrder: executeDispatchesInOrder,\n  executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,\n  hasDispatches: hasDispatches,\n\n  getInstanceFromNode: function (node) {\n    return ComponentTree.getInstanceFromNode(node);\n  },\n  getNodeFromInstance: function (node) {\n    return ComponentTree.getNodeFromInstance(node);\n  },\n  isAncestor: function (a, b) {\n    return TreeTraversal.isAncestor(a, b);\n  },\n  getLowestCommonAncestor: function (a, b) {\n    return TreeTraversal.getLowestCommonAncestor(a, b);\n  },\n  getParentInstance: function (inst) {\n    return TreeTraversal.getParentInstance(inst);\n  },\n  traverseTwoPhase: function (target, fn, arg) {\n    return TreeTraversal.traverseTwoPhase(target, fn, arg);\n  },\n  traverseEnterLeave: function (from, to, fn, argFrom, argTo) {\n    return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);\n  },\n\n  injection: injection\n};\n\nmodule.exports = EventPluginUtils;\n},{\"139\":139,\"16\":16,\"161\":161,\"171\":171,\"65\":65}],20:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule EventPropagators\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\n\nvar accumulateInto = _dereq_(115);\nvar forEachAccumulated = _dereq_(124);\nvar warning = _dereq_(171);\n\nvar PropagationPhases = EventConstants.PropagationPhases;\nvar getListener = EventPluginHub.getListener;\n\n/**\n * Some event types have a notion of different registration names for different\n * \"phases\" of propagation. This finds listeners by a given phase.\n */\nfunction listenerAtPhase(inst, event, propagationPhase) {\n  var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];\n  return getListener(inst, registrationName);\n}\n\n/**\n * Tags a `SyntheticEvent` with dispatched listeners. Creating this function\n * here, allows us to not have to bind or create functions for each event.\n * Mutating the event's members allows us to not have to create a wrapping\n * \"dispatch\" object that pairs the event with the listener.\n */\nfunction accumulateDirectionalDispatches(inst, upwards, event) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;\n  }\n  var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured;\n  var listener = listenerAtPhase(inst, event, phase);\n  if (listener) {\n    event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n    event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n  }\n}\n\n/**\n * Collect dispatches (must be entirely collected before dispatching - see unit\n * tests). Lazily allocate the array to conserve memory.  We must loop through\n * each event and perform the traversal for each one. We cannot perform a\n * single traversal for the entire collection of events because each event may\n * have a different target.\n */\nfunction accumulateTwoPhaseDispatchesSingle(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.\n */\nfunction accumulateTwoPhaseDispatchesSingleSkipTarget(event) {\n  if (event && event.dispatchConfig.phasedRegistrationNames) {\n    var targetInst = event._targetInst;\n    var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;\n    EventPluginUtils.traverseTwoPhase(parentInst, accumulateDirectionalDispatches, event);\n  }\n}\n\n/**\n * Accumulates without regard to direction, does not look for phased\n * registration names. Same as `accumulateDirectDispatchesSingle` but without\n * requiring that the `dispatchMarker` be the same as the dispatched ID.\n */\nfunction accumulateDispatches(inst, ignoredDirection, event) {\n  if (event && event.dispatchConfig.registrationName) {\n    var registrationName = event.dispatchConfig.registrationName;\n    var listener = getListener(inst, registrationName);\n    if (listener) {\n      event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);\n      event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);\n    }\n  }\n}\n\n/**\n * Accumulates dispatches on an `SyntheticEvent`, but only for the\n * `dispatchMarker`.\n * @param {SyntheticEvent} event\n */\nfunction accumulateDirectDispatchesSingle(event) {\n  if (event && event.dispatchConfig.registrationName) {\n    accumulateDispatches(event._targetInst, null, event);\n  }\n}\n\nfunction accumulateTwoPhaseDispatches(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);\n}\n\nfunction accumulateTwoPhaseDispatchesSkipTarget(events) {\n  forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);\n}\n\nfunction accumulateEnterLeaveDispatches(leave, enter, from, to) {\n  EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);\n}\n\nfunction accumulateDirectDispatches(events) {\n  forEachAccumulated(events, accumulateDirectDispatchesSingle);\n}\n\n/**\n * A small set of propagation patterns, each of which will accept a small amount\n * of information, and generate a set of \"dispatch ready event objects\" - which\n * are sets of events that have already been annotated with a set of dispatched\n * listener functions/ids. The API is designed this way to discourage these\n * propagation strategies from actually executing the dispatches, since we\n * always want to collect the entire set of dispatches before executing event a\n * single one.\n *\n * @constructor EventPropagators\n */\nvar EventPropagators = {\n  accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,\n  accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,\n  accumulateDirectDispatches: accumulateDirectDispatches,\n  accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches\n};\n\nmodule.exports = EventPropagators;\n},{\"115\":115,\"124\":124,\"16\":16,\"17\":17,\"171\":171,\"19\":19}],21:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule FallbackCompositionState\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * This helper class stores information about text content of a target node,\n * allowing comparison of content before and after a given event.\n *\n * Identify the node where selection currently begins, then observe\n * both its text content and its current position in the DOM. Since the\n * browser may natively replace the target node during composition, we can\n * use its position to find its replacement.\n *\n * @param {DOMEventTarget} root\n */\nfunction FallbackCompositionState(root) {\n  this._root = root;\n  this._startText = this.getText();\n  this._fallbackText = null;\n}\n\n_assign(FallbackCompositionState.prototype, {\n  destructor: function () {\n    this._root = null;\n    this._startText = null;\n    this._fallbackText = null;\n  },\n\n  /**\n   * Get current text of input.\n   *\n   * @return {string}\n   */\n  getText: function () {\n    if ('value' in this._root) {\n      return this._root.value;\n    }\n    return this._root[getTextContentAccessor()];\n  },\n\n  /**\n   * Determine the differing substring between the initially stored\n   * text content and the current content.\n   *\n   * @return {string}\n   */\n  getData: function () {\n    if (this._fallbackText) {\n      return this._fallbackText;\n    }\n\n    var start;\n    var startValue = this._startText;\n    var startLength = startValue.length;\n    var end;\n    var endValue = this.getText();\n    var endLength = endValue.length;\n\n    for (start = 0; start < startLength; start++) {\n      if (startValue[start] !== endValue[start]) {\n        break;\n      }\n    }\n\n    var minEnd = startLength - start;\n    for (end = 1; end <= minEnd; end++) {\n      if (startValue[startLength - end] !== endValue[endLength - end]) {\n        break;\n      }\n    }\n\n    var sliceTail = end > 1 ? 1 - end : undefined;\n    this._fallbackText = endValue.slice(start, sliceTail);\n    return this._fallbackText;\n  }\n});\n\nPooledClass.addPoolingTo(FallbackCompositionState);\n\nmodule.exports = FallbackCompositionState;\n},{\"132\":132,\"172\":172,\"25\":25}],22:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule HTMLDOMPropertyConfig\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\n\nvar MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;\nvar HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;\nvar HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;\nvar HAS_POSITIVE_NUMERIC_VALUE = DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;\nvar HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;\n\nvar HTMLDOMPropertyConfig = {\n  isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')),\n  Properties: {\n    /**\n     * Standard Properties\n     */\n    accept: 0,\n    acceptCharset: 0,\n    accessKey: 0,\n    action: 0,\n    allowFullScreen: HAS_BOOLEAN_VALUE,\n    allowTransparency: 0,\n    alt: 0,\n    async: HAS_BOOLEAN_VALUE,\n    autoComplete: 0,\n    // autoFocus is polyfilled/normalized by AutoFocusUtils\n    // autoFocus: HAS_BOOLEAN_VALUE,\n    autoPlay: HAS_BOOLEAN_VALUE,\n    capture: HAS_BOOLEAN_VALUE,\n    cellPadding: 0,\n    cellSpacing: 0,\n    charSet: 0,\n    challenge: 0,\n    checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    cite: 0,\n    classID: 0,\n    className: 0,\n    cols: HAS_POSITIVE_NUMERIC_VALUE,\n    colSpan: 0,\n    content: 0,\n    contentEditable: 0,\n    contextMenu: 0,\n    controls: HAS_BOOLEAN_VALUE,\n    coords: 0,\n    crossOrigin: 0,\n    data: 0, // For `<object />` acts as `src`.\n    dateTime: 0,\n    'default': HAS_BOOLEAN_VALUE,\n    defer: HAS_BOOLEAN_VALUE,\n    dir: 0,\n    disabled: HAS_BOOLEAN_VALUE,\n    download: HAS_OVERLOADED_BOOLEAN_VALUE,\n    draggable: 0,\n    encType: 0,\n    form: 0,\n    formAction: 0,\n    formEncType: 0,\n    formMethod: 0,\n    formNoValidate: HAS_BOOLEAN_VALUE,\n    formTarget: 0,\n    frameBorder: 0,\n    headers: 0,\n    height: 0,\n    hidden: HAS_BOOLEAN_VALUE,\n    high: 0,\n    href: 0,\n    hrefLang: 0,\n    htmlFor: 0,\n    httpEquiv: 0,\n    icon: 0,\n    id: 0,\n    inputMode: 0,\n    integrity: 0,\n    is: 0,\n    keyParams: 0,\n    keyType: 0,\n    kind: 0,\n    label: 0,\n    lang: 0,\n    list: 0,\n    loop: HAS_BOOLEAN_VALUE,\n    low: 0,\n    manifest: 0,\n    marginHeight: 0,\n    marginWidth: 0,\n    max: 0,\n    maxLength: 0,\n    media: 0,\n    mediaGroup: 0,\n    method: 0,\n    min: 0,\n    minLength: 0,\n    // Caution; `option.selected` is not updated if `select.multiple` is\n    // disabled with `removeAttribute`.\n    multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    name: 0,\n    nonce: 0,\n    noValidate: HAS_BOOLEAN_VALUE,\n    open: HAS_BOOLEAN_VALUE,\n    optimum: 0,\n    pattern: 0,\n    placeholder: 0,\n    poster: 0,\n    preload: 0,\n    profile: 0,\n    radioGroup: 0,\n    readOnly: HAS_BOOLEAN_VALUE,\n    rel: 0,\n    required: HAS_BOOLEAN_VALUE,\n    reversed: HAS_BOOLEAN_VALUE,\n    role: 0,\n    rows: HAS_POSITIVE_NUMERIC_VALUE,\n    rowSpan: HAS_NUMERIC_VALUE,\n    sandbox: 0,\n    scope: 0,\n    scoped: HAS_BOOLEAN_VALUE,\n    scrolling: 0,\n    seamless: HAS_BOOLEAN_VALUE,\n    selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,\n    shape: 0,\n    size: HAS_POSITIVE_NUMERIC_VALUE,\n    sizes: 0,\n    span: HAS_POSITIVE_NUMERIC_VALUE,\n    spellCheck: 0,\n    src: 0,\n    srcDoc: 0,\n    srcLang: 0,\n    srcSet: 0,\n    start: HAS_NUMERIC_VALUE,\n    step: 0,\n    style: 0,\n    summary: 0,\n    tabIndex: 0,\n    target: 0,\n    title: 0,\n    // Setting .type throws on non-<input> tags\n    type: 0,\n    useMap: 0,\n    value: 0,\n    width: 0,\n    wmode: 0,\n    wrap: 0,\n\n    /**\n     * RDFa Properties\n     */\n    about: 0,\n    datatype: 0,\n    inlist: 0,\n    prefix: 0,\n    // property is also supported for OpenGraph in meta tags.\n    property: 0,\n    resource: 0,\n    'typeof': 0,\n    vocab: 0,\n\n    /**\n     * Non-standard Properties\n     */\n    // autoCapitalize and autoCorrect are supported in Mobile Safari for\n    // keyboard hints.\n    autoCapitalize: 0,\n    autoCorrect: 0,\n    // autoSave allows WebKit/Blink to persist values of input fields on page reloads\n    autoSave: 0,\n    // color is for Safari mask-icon link\n    color: 0,\n    // itemProp, itemScope, itemType are for\n    // Microdata support. See http://schema.org/docs/gs.html\n    itemProp: 0,\n    itemScope: HAS_BOOLEAN_VALUE,\n    itemType: 0,\n    // itemID and itemRef are for Microdata support as well but\n    // only specified in the WHATWG spec document. See\n    // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api\n    itemID: 0,\n    itemRef: 0,\n    // results show looking glass icon and recent searches on input\n    // search fields in WebKit/Blink\n    results: 0,\n    // IE-only attribute that specifies security restrictions on an iframe\n    // as an alternative to the sandbox attribute on IE<10\n    security: 0,\n    // IE-only attribute that controls focus behavior\n    unselectable: 0\n  },\n  DOMAttributeNames: {\n    acceptCharset: 'accept-charset',\n    className: 'class',\n    htmlFor: 'for',\n    httpEquiv: 'http-equiv'\n  },\n  DOMPropertyNames: {}\n};\n\nmodule.exports = HTMLDOMPropertyConfig;\n},{\"10\":10}],23:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule KeyEscapeUtils\n * \n */\n\n'use strict';\n\n/**\n * Escape and wrap key so it is safe to use as a reactid\n *\n * @param {string} key to be escaped.\n * @return {string} the escaped key.\n */\n\nfunction escape(key) {\n  var escapeRegex = /[=:]/g;\n  var escaperLookup = {\n    '=': '=0',\n    ':': '=2'\n  };\n  var escapedString = ('' + key).replace(escapeRegex, function (match) {\n    return escaperLookup[match];\n  });\n\n  return '$' + escapedString;\n}\n\n/**\n * Unescape and unwrap key for human-readable display\n *\n * @param {string} key to unescape.\n * @return {string} the unescaped key.\n */\nfunction unescape(key) {\n  var unescapeRegex = /(=0|=2)/g;\n  var unescaperLookup = {\n    '=0': '=',\n    '=2': ':'\n  };\n  var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);\n\n  return ('' + keySubstring).replace(unescapeRegex, function (match) {\n    return unescaperLookup[match];\n  });\n}\n\nvar KeyEscapeUtils = {\n  escape: escape,\n  unescape: unescape\n};\n\nmodule.exports = KeyEscapeUtils;\n},{}],24:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule LinkedValueUtils\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypes = _dereq_(85);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar hasReadOnlyValue = {\n  'button': true,\n  'checkbox': true,\n  'image': true,\n  'hidden': true,\n  'radio': true,\n  'reset': true,\n  'submit': true\n};\n\nfunction _assertSingleLink(inputProps) {\n  !(inputProps.checkedLink == null || inputProps.valueLink == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don\\'t want to use valueLink and vice versa.') : _prodInvariant('87') : void 0;\n}\nfunction _assertValueLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.value == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don\\'t want to use valueLink.') : _prodInvariant('88') : void 0;\n}\n\nfunction _assertCheckedLink(inputProps) {\n  _assertSingleLink(inputProps);\n  !(inputProps.checked == null && inputProps.onChange == null) ? \"development\" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don\\'t want to use checkedLink') : _prodInvariant('89') : void 0;\n}\n\nvar propTypes = {\n  value: function (props, propName, componentName) {\n    if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  checked: function (props, propName, componentName) {\n    if (!props[propName] || props.onChange || props.readOnly || props.disabled) {\n      return null;\n    }\n    return new Error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.');\n  },\n  onChange: ReactPropTypes.func\n};\n\nvar loggedTypeFailures = {};\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Provide a linked `value` attribute for controlled forms. You should not use\n * this outside of the ReactDOM controlled form components.\n */\nvar LinkedValueUtils = {\n  checkPropTypes: function (tagName, props, owner) {\n    for (var propName in propTypes) {\n      if (propTypes.hasOwnProperty(propName)) {\n        var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop);\n      }\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var addendum = getDeclarationErrorAddendum(owner);\n        \"development\" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0;\n      }\n    }\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current value of the input either from value prop or link.\n   */\n  getValue: function (inputProps) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.value;\n    }\n    return inputProps.value;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @return {*} current checked status of the input either from checked prop\n   *             or link.\n   */\n  getChecked: function (inputProps) {\n    if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.value;\n    }\n    return inputProps.checked;\n  },\n\n  /**\n   * @param {object} inputProps Props for form component\n   * @param {SyntheticEvent} event change event to handle\n   */\n  executeOnChange: function (inputProps, event) {\n    if (inputProps.valueLink) {\n      _assertValueLink(inputProps);\n      return inputProps.valueLink.requestChange(event.target.value);\n    } else if (inputProps.checkedLink) {\n      _assertCheckedLink(inputProps);\n      return inputProps.checkedLink.requestChange(event.target.checked);\n    } else if (inputProps.onChange) {\n      return inputProps.onChange.call(undefined, event);\n    }\n  }\n};\n\nmodule.exports = LinkedValueUtils;\n},{\"139\":139,\"161\":161,\"171\":171,\"84\":84,\"85\":85}],25:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule PooledClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Static poolers. Several custom versions for each potential number of\n * arguments. A completely generic pooler is easy to implement, but would\n * require accessing the `arguments` object. In each of these, `this` refers to\n * the Class itself, not an instance. If any others are needed, simply add them\n * here, or in their own files.\n */\nvar oneArgumentPooler = function (copyFieldsFrom) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, copyFieldsFrom);\n    return instance;\n  } else {\n    return new Klass(copyFieldsFrom);\n  }\n};\n\nvar twoArgumentPooler = function (a1, a2) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2);\n    return instance;\n  } else {\n    return new Klass(a1, a2);\n  }\n};\n\nvar threeArgumentPooler = function (a1, a2, a3) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3);\n  }\n};\n\nvar fourArgumentPooler = function (a1, a2, a3, a4) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4);\n  }\n};\n\nvar fiveArgumentPooler = function (a1, a2, a3, a4, a5) {\n  var Klass = this;\n  if (Klass.instancePool.length) {\n    var instance = Klass.instancePool.pop();\n    Klass.call(instance, a1, a2, a3, a4, a5);\n    return instance;\n  } else {\n    return new Klass(a1, a2, a3, a4, a5);\n  }\n};\n\nvar standardReleaser = function (instance) {\n  var Klass = this;\n  !(instance instanceof Klass) ? \"development\" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0;\n  instance.destructor();\n  if (Klass.instancePool.length < Klass.poolSize) {\n    Klass.instancePool.push(instance);\n  }\n};\n\nvar DEFAULT_POOL_SIZE = 10;\nvar DEFAULT_POOLER = oneArgumentPooler;\n\n/**\n * Augments `CopyConstructor` to be a poolable class, augmenting only the class\n * itself (statically) not adding any prototypical fields. Any CopyConstructor\n * you give this may have a `poolSize` property, and will look for a\n * prototypical `destructor` on instances.\n *\n * @param {Function} CopyConstructor Constructor that can be used to reset.\n * @param {Function} pooler Customizable pooler.\n */\nvar addPoolingTo = function (CopyConstructor, pooler) {\n  var NewKlass = CopyConstructor;\n  NewKlass.instancePool = [];\n  NewKlass.getPooled = pooler || DEFAULT_POOLER;\n  if (!NewKlass.poolSize) {\n    NewKlass.poolSize = DEFAULT_POOL_SIZE;\n  }\n  NewKlass.release = standardReleaser;\n  return NewKlass;\n};\n\nvar PooledClass = {\n  addPoolingTo: addPoolingTo,\n  oneArgumentPooler: oneArgumentPooler,\n  twoArgumentPooler: twoArgumentPooler,\n  threeArgumentPooler: threeArgumentPooler,\n  fourArgumentPooler: fourArgumentPooler,\n  fiveArgumentPooler: fiveArgumentPooler\n};\n\nmodule.exports = PooledClass;\n},{\"139\":139,\"161\":161}],26:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule React\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactComponent = _dereq_(31);\nvar ReactClass = _dereq_(30);\nvar ReactDOMFactories = _dereq_(45);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypes = _dereq_(85);\nvar ReactVersion = _dereq_(96);\n\nvar onlyChild = _dereq_(137);\nvar warning = _dereq_(171);\n\nvar createElement = ReactElement.createElement;\nvar createFactory = ReactElement.createFactory;\nvar cloneElement = ReactElement.cloneElement;\n\nif (\"development\" !== 'production') {\n  var ReactElementValidator = _dereq_(63);\n  createElement = ReactElementValidator.createElement;\n  createFactory = ReactElementValidator.createFactory;\n  cloneElement = ReactElementValidator.cloneElement;\n}\n\nvar __spread = _assign;\n\nif (\"development\" !== 'production') {\n  var warned = false;\n  __spread = function () {\n    \"development\" !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;\n    warned = true;\n    return _assign.apply(null, arguments);\n  };\n}\n\nvar React = {\n\n  // Modern\n\n  Children: {\n    map: ReactChildren.map,\n    forEach: ReactChildren.forEach,\n    count: ReactChildren.count,\n    toArray: ReactChildren.toArray,\n    only: onlyChild\n  },\n\n  Component: ReactComponent,\n\n  createElement: createElement,\n  cloneElement: cloneElement,\n  isValidElement: ReactElement.isValidElement,\n\n  // Classic\n\n  PropTypes: ReactPropTypes,\n  createClass: ReactClass.createClass,\n  createFactory: createFactory,\n  createMixin: function (mixin) {\n    // Currently a noop. Will be used to validate and trace mixins.\n    return mixin;\n  },\n\n  // This looks DOM specific but these are actually isomorphic helpers\n  // since they are just generating DOM strings.\n  DOM: ReactDOMFactories,\n\n  version: ReactVersion,\n\n  // Deprecated hook for JSX spread, don't use this for anything.\n  __spread: __spread\n};\n\nmodule.exports = React;\n},{\"137\":137,\"171\":171,\"172\":172,\"29\":29,\"30\":30,\"31\":31,\"45\":45,\"62\":62,\"63\":63,\"85\":85,\"96\":96}],27:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactBrowserEventEmitter\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventConstants = _dereq_(16);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactEventEmitterMixin = _dereq_(66);\nvar ViewportMetrics = _dereq_(114);\n\nvar getVendorPrefixedEventName = _dereq_(133);\nvar isEventSupported = _dereq_(135);\n\n/**\n * Summary of `ReactBrowserEventEmitter` event handling:\n *\n *  - Top-level delegation is used to trap most native browser events. This\n *    may only occur in the main thread and is the responsibility of\n *    ReactEventListener, which is injected and can therefore support pluggable\n *    event sources. This is the only work that occurs in the main thread.\n *\n *  - We normalize and de-duplicate events to account for browser quirks. This\n *    may be done in the worker thread.\n *\n *  - Forward these native events (with the associated top-level type used to\n *    trap it) to `EventPluginHub`, which in turn will ask plugins if they want\n *    to extract any synthetic events.\n *\n *  - The `EventPluginHub` will then process each event by annotating them with\n *    \"dispatches\", a sequence of listeners and IDs that care about that event.\n *\n *  - The `EventPluginHub` then dispatches the events.\n *\n * Overview of React and the event system:\n *\n * +------------+    .\n * |    DOM     |    .\n * +------------+    .\n *       |           .\n *       v           .\n * +------------+    .\n * | ReactEvent |    .\n * |  Listener  |    .\n * +------------+    .                         +-----------+\n *       |           .               +--------+|SimpleEvent|\n *       |           .               |         |Plugin     |\n * +-----|------+    .               v         +-----------+\n * |     |      |    .    +--------------+                    +------------+\n * |     +-----------.--->|EventPluginHub|                    |    Event   |\n * |            |    .    |              |     +-----------+  | Propagators|\n * | ReactEvent |    .    |              |     |TapEvent   |  |------------|\n * |  Emitter   |    .    |              |<---+|Plugin     |  |other plugin|\n * |            |    .    |              |     +-----------+  |  utilities |\n * |     +-----------.--->|              |                    +------------+\n * |     |      |    .    +--------------+\n * +-----|------+    .                ^        +-----------+\n *       |           .                |        |Enter/Leave|\n *       +           .                +-------+|Plugin     |\n * +-------------+   .                         +-----------+\n * | application |   .\n * |-------------|   .\n * |             |   .\n * |             |   .\n * +-------------+   .\n *                   .\n *    React Core     .  General Purpose Event Plugin System\n */\n\nvar hasEventPageXY;\nvar alreadyListeningTo = {};\nvar isMonitoringScrollValue = false;\nvar reactTopListenersCounter = 0;\n\n// For events like 'submit' which don't consistently bubble (which we trap at a\n// lower node than `document`), binding at `document` would cause duplicate\n// events so we don't include them here\nvar topEventMapping = {\n  topAbort: 'abort',\n  topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',\n  topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',\n  topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',\n  topBlur: 'blur',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topChange: 'change',\n  topClick: 'click',\n  topCompositionEnd: 'compositionend',\n  topCompositionStart: 'compositionstart',\n  topCompositionUpdate: 'compositionupdate',\n  topContextMenu: 'contextmenu',\n  topCopy: 'copy',\n  topCut: 'cut',\n  topDoubleClick: 'dblclick',\n  topDrag: 'drag',\n  topDragEnd: 'dragend',\n  topDragEnter: 'dragenter',\n  topDragExit: 'dragexit',\n  topDragLeave: 'dragleave',\n  topDragOver: 'dragover',\n  topDragStart: 'dragstart',\n  topDrop: 'drop',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topFocus: 'focus',\n  topInput: 'input',\n  topKeyDown: 'keydown',\n  topKeyPress: 'keypress',\n  topKeyUp: 'keyup',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topMouseDown: 'mousedown',\n  topMouseMove: 'mousemove',\n  topMouseOut: 'mouseout',\n  topMouseOver: 'mouseover',\n  topMouseUp: 'mouseup',\n  topPaste: 'paste',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topScroll: 'scroll',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topSelectionChange: 'selectionchange',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTextInput: 'textInput',\n  topTimeUpdate: 'timeupdate',\n  topTouchCancel: 'touchcancel',\n  topTouchEnd: 'touchend',\n  topTouchMove: 'touchmove',\n  topTouchStart: 'touchstart',\n  topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting',\n  topWheel: 'wheel'\n};\n\n/**\n * To ensure no conflicts with other potential React instances on the page\n */\nvar topListenersIDKey = '_reactListenersID' + String(Math.random()).slice(2);\n\nfunction getListeningForDocument(mountAt) {\n  // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty`\n  // directly.\n  if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) {\n    mountAt[topListenersIDKey] = reactTopListenersCounter++;\n    alreadyListeningTo[mountAt[topListenersIDKey]] = {};\n  }\n  return alreadyListeningTo[mountAt[topListenersIDKey]];\n}\n\n/**\n * `ReactBrowserEventEmitter` is used to attach top-level event listeners. For\n * example:\n *\n *   EventPluginHub.putListener('myID', 'onClick', myFunction);\n *\n * This would allocate a \"registration\" of `('onClick', myFunction)` on 'myID'.\n *\n * @internal\n */\nvar ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {\n\n  /**\n   * Injectable event backend\n   */\n  ReactEventListener: null,\n\n  injection: {\n    /**\n     * @param {object} ReactEventListener\n     */\n    injectReactEventListener: function (ReactEventListener) {\n      ReactEventListener.setHandleTopLevel(ReactBrowserEventEmitter.handleTopLevel);\n      ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;\n    }\n  },\n\n  /**\n   * Sets whether or not any created callbacks should be enabled.\n   *\n   * @param {boolean} enabled True if callbacks should be enabled.\n   */\n  setEnabled: function (enabled) {\n    if (ReactBrowserEventEmitter.ReactEventListener) {\n      ReactBrowserEventEmitter.ReactEventListener.setEnabled(enabled);\n    }\n  },\n\n  /**\n   * @return {boolean} True if callbacks are enabled.\n   */\n  isEnabled: function () {\n    return !!(ReactBrowserEventEmitter.ReactEventListener && ReactBrowserEventEmitter.ReactEventListener.isEnabled());\n  },\n\n  /**\n   * We listen for bubbled touch events on the document object.\n   *\n   * Firefox v8.01 (and possibly others) exhibited strange behavior when\n   * mounting `onmousemove` events at some node that was not the document\n   * element. The symptoms were that if your mouse is not moving over something\n   * contained within that mount point (for example on the background) the\n   * top-level listeners for `onmousemove` won't be called. However, if you\n   * register the `mousemove` on the document object, then it will of course\n   * catch all `mousemove`s. This along with iOS quirks, justifies restricting\n   * top-level listeners to the document object only, at least for these\n   * movement types of events and possibly all events.\n   *\n   * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html\n   *\n   * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but\n   * they bubble to document.\n   *\n   * @param {string} registrationName Name of listener (e.g. `onClick`).\n   * @param {object} contentDocumentHandle Document which owns the container\n   */\n  listenTo: function (registrationName, contentDocumentHandle) {\n    var mountAt = contentDocumentHandle;\n    var isListening = getListeningForDocument(mountAt);\n    var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName];\n\n    var topLevelTypes = EventConstants.topLevelTypes;\n    for (var i = 0; i < dependencies.length; i++) {\n      var dependency = dependencies[i];\n      if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {\n        if (dependency === topLevelTypes.topWheel) {\n          if (isEventSupported('wheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'wheel', mountAt);\n          } else if (isEventSupported('mousewheel')) {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'mousewheel', mountAt);\n          } else {\n            // Firefox needs to capture a different mouse scroll event.\n            // @see http://www.quirksmode.org/dom/events/tests/scroll.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topWheel, 'DOMMouseScroll', mountAt);\n          }\n        } else if (dependency === topLevelTypes.topScroll) {\n\n          if (isEventSupported('scroll', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topScroll, 'scroll', mountAt);\n          } else {\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topScroll, 'scroll', ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE);\n          }\n        } else if (dependency === topLevelTypes.topFocus || dependency === topLevelTypes.topBlur) {\n\n          if (isEventSupported('focus', true)) {\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topFocus, 'focus', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelTypes.topBlur, 'blur', mountAt);\n          } else if (isEventSupported('focusin')) {\n            // IE has `focusin` and `focusout` events which bubble.\n            // @see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topFocus, 'focusin', mountAt);\n            ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelTypes.topBlur, 'focusout', mountAt);\n          }\n\n          // to make sure blur and focus event listeners are only attached once\n          isListening[topLevelTypes.topBlur] = true;\n          isListening[topLevelTypes.topFocus] = true;\n        } else if (topEventMapping.hasOwnProperty(dependency)) {\n          ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(dependency, topEventMapping[dependency], mountAt);\n        }\n\n        isListening[dependency] = true;\n      }\n    }\n  },\n\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);\n  },\n\n  /**\n   * Listens to window scroll and resize events. We cache scroll values so that\n   * application code can access them without triggering reflows.\n   *\n   * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when\n   * pageX/pageY isn't supported (legacy browsers).\n   *\n   * NOTE: Scroll events do not bubble.\n   *\n   * @see http://www.quirksmode.org/dom/events/scroll.html\n   */\n  ensureScrollValueMonitoring: function () {\n    if (hasEventPageXY === undefined) {\n      hasEventPageXY = document.createEvent && 'pageX' in document.createEvent('MouseEvent');\n    }\n    if (!hasEventPageXY && !isMonitoringScrollValue) {\n      var refresh = ViewportMetrics.refreshScrollValues;\n      ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);\n      isMonitoringScrollValue = true;\n    }\n  }\n\n});\n\nmodule.exports = ReactBrowserEventEmitter;\n},{\"114\":114,\"133\":133,\"135\":135,\"16\":16,\"172\":172,\"18\":18,\"66\":66}],28:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildReconciler\n */\n\n'use strict';\n\nvar ReactReconciler = _dereq_(87);\n\nvar instantiateReactComponent = _dereq_(134);\nvar KeyEscapeUtils = _dereq_(23);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\nfunction instantiateChild(childInstances, child, name, selfDebugID) {\n  // We found a component instance.\n  var keyUnique = childInstances[name] === undefined;\n  if (\"development\" !== 'production') {\n    var ReactComponentTreeDevtool = _dereq_(34);\n    \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n  }\n  if (child != null && keyUnique) {\n    childInstances[name] = instantiateReactComponent(child, true);\n  }\n}\n\n/**\n * ReactChildReconciler provides helpers for initializing or updating a set of\n * children. Its output is suitable for passing it onto ReactMultiChild which\n * does diffed reordering and insertion.\n */\nvar ReactChildReconciler = {\n  /**\n   * Generates a \"mount image\" for each of the supplied children. In the case\n   * of `ReactDOMComponent`, a mount image is a string of markup.\n   *\n   * @param {?object} nestedChildNodes Nested child maps.\n   * @return {?object} A set of child instances.\n   * @internal\n   */\n  instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID // __DEV__ only\n  ) {\n    if (nestedChildNodes == null) {\n      return null;\n    }\n    var childInstances = {};\n\n    if (\"development\" !== 'production') {\n      traverseAllChildren(nestedChildNodes, function (childInsts, child, name) {\n        return instantiateChild(childInsts, child, name, selfDebugID);\n      }, childInstances);\n    } else {\n      traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);\n    }\n    return childInstances;\n  },\n\n  /**\n   * Updates the rendered children and returns a new set of children.\n   *\n   * @param {?object} prevChildren Previously initialized set of children.\n   * @param {?object} nextChildren Flat child element maps.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @return {?object} A new set of child instances.\n   * @internal\n   */\n  updateChildren: function (prevChildren, nextChildren, removedNodes, transaction, context) {\n    // We currently don't have a way to track moves here but if we use iterators\n    // instead of for..in we can zip the iterators and check if an item has\n    // moved.\n    // TODO: If nothing has changed, return the prevChildren object so that we\n    // can quickly bailout if nothing has changed.\n    if (!nextChildren && !prevChildren) {\n      return;\n    }\n    var name;\n    var prevChild;\n    for (name in nextChildren) {\n      if (!nextChildren.hasOwnProperty(name)) {\n        continue;\n      }\n      prevChild = prevChildren && prevChildren[name];\n      var prevElement = prevChild && prevChild._currentElement;\n      var nextElement = nextChildren[name];\n      if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {\n        ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);\n        nextChildren[name] = prevChild;\n      } else {\n        if (prevChild) {\n          removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n          ReactReconciler.unmountComponent(prevChild, false);\n        }\n        // The child must be instantiated before it's mounted.\n        var nextChildInstance = instantiateReactComponent(nextElement, true);\n        nextChildren[name] = nextChildInstance;\n      }\n    }\n    // Unmount children that are no longer present.\n    for (name in prevChildren) {\n      if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {\n        prevChild = prevChildren[name];\n        removedNodes[name] = ReactReconciler.getHostNode(prevChild);\n        ReactReconciler.unmountComponent(prevChild, false);\n      }\n    }\n  },\n\n  /**\n   * Unmounts all rendered children. This should be used to clean up children\n   * when this component is unmounted.\n   *\n   * @param {?object} renderedChildren Previously initialized set of children.\n   * @internal\n   */\n  unmountChildren: function (renderedChildren, safely) {\n    for (var name in renderedChildren) {\n      if (renderedChildren.hasOwnProperty(name)) {\n        var renderedChild = renderedChildren[name];\n        ReactReconciler.unmountComponent(renderedChild, safely);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactChildReconciler;\n},{\"134\":134,\"143\":143,\"144\":144,\"171\":171,\"23\":23,\"34\":34,\"87\":87}],29:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactChildren\n */\n\n'use strict';\n\nvar PooledClass = _dereq_(25);\nvar ReactElement = _dereq_(62);\n\nvar emptyFunction = _dereq_(153);\nvar traverseAllChildren = _dereq_(144);\n\nvar twoArgumentPooler = PooledClass.twoArgumentPooler;\nvar fourArgumentPooler = PooledClass.fourArgumentPooler;\n\nvar userProvidedKeyEscapeRegex = /\\/+/g;\nfunction escapeUserProvidedKey(text) {\n  return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * traversal. Allows avoiding binding callbacks.\n *\n * @constructor ForEachBookKeeping\n * @param {!function} forEachFunction Function to perform traversal with.\n * @param {?*} forEachContext Context to perform context with.\n */\nfunction ForEachBookKeeping(forEachFunction, forEachContext) {\n  this.func = forEachFunction;\n  this.context = forEachContext;\n  this.count = 0;\n}\nForEachBookKeeping.prototype.destructor = function () {\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);\n\nfunction forEachSingleChild(bookKeeping, child, name) {\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n  func.call(context, child, bookKeeping.count++);\n}\n\n/**\n * Iterates through children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach\n *\n * The provided forEachFunc(child, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} forEachFunc\n * @param {*} forEachContext Context for forEachContext.\n */\nfunction forEachChildren(children, forEachFunc, forEachContext) {\n  if (children == null) {\n    return children;\n  }\n  var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);\n  traverseAllChildren(children, forEachSingleChild, traverseContext);\n  ForEachBookKeeping.release(traverseContext);\n}\n\n/**\n * PooledClass representing the bookkeeping associated with performing a child\n * mapping. Allows avoiding binding callbacks.\n *\n * @constructor MapBookKeeping\n * @param {!*} mapResult Object containing the ordered map of results.\n * @param {!function} mapFunction Function to perform mapping with.\n * @param {?*} mapContext Context to perform mapping with.\n */\nfunction MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {\n  this.result = mapResult;\n  this.keyPrefix = keyPrefix;\n  this.func = mapFunction;\n  this.context = mapContext;\n  this.count = 0;\n}\nMapBookKeeping.prototype.destructor = function () {\n  this.result = null;\n  this.keyPrefix = null;\n  this.func = null;\n  this.context = null;\n  this.count = 0;\n};\nPooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);\n\nfunction mapSingleChildIntoContext(bookKeeping, child, childKey) {\n  var result = bookKeeping.result;\n  var keyPrefix = bookKeeping.keyPrefix;\n  var func = bookKeeping.func;\n  var context = bookKeeping.context;\n\n\n  var mappedChild = func.call(context, child, bookKeeping.count++);\n  if (Array.isArray(mappedChild)) {\n    mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);\n  } else if (mappedChild != null) {\n    if (ReactElement.isValidElement(mappedChild)) {\n      mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,\n      // Keep both the (mapped) and old keys if they differ, just as\n      // traverseAllChildren used to do for objects as children\n      keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);\n    }\n    result.push(mappedChild);\n  }\n}\n\nfunction mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {\n  var escapedPrefix = '';\n  if (prefix != null) {\n    escapedPrefix = escapeUserProvidedKey(prefix) + '/';\n  }\n  var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);\n  traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);\n  MapBookKeeping.release(traverseContext);\n}\n\n/**\n * Maps children that are typically specified as `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.map\n *\n * The provided mapFunction(child, key, index) will be called for each\n * leaf child.\n *\n * @param {?*} children Children tree container.\n * @param {function(*, int)} func The map function.\n * @param {*} context Context for mapFunction.\n * @return {object} Object containing the ordered map of results.\n */\nfunction mapChildren(children, func, context) {\n  if (children == null) {\n    return children;\n  }\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, func, context);\n  return result;\n}\n\nfunction forEachSingleChildDummy(traverseContext, child, name) {\n  return null;\n}\n\n/**\n * Count the number of children that are typically specified as\n * `props.children`.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.count\n *\n * @param {?*} children Children tree container.\n * @return {number} The number of children.\n */\nfunction countChildren(children, context) {\n  return traverseAllChildren(children, forEachSingleChildDummy, null);\n}\n\n/**\n * Flatten a children object (typically specified as `props.children`) and\n * return an array with appropriately re-keyed children.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray\n */\nfunction toArray(children) {\n  var result = [];\n  mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);\n  return result;\n}\n\nvar ReactChildren = {\n  forEach: forEachChildren,\n  map: mapChildren,\n  mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,\n  count: countChildren,\n  toArray: toArray\n};\n\nmodule.exports = ReactChildren;\n},{\"144\":144,\"153\":153,\"25\":25,\"62\":62}],30:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactClass\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponent = _dereq_(31);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactPropTypeLocationNames = _dereq_(83);\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar keyMirror = _dereq_(164);\nvar keyOf = _dereq_(165);\nvar warning = _dereq_(171);\n\nvar MIXINS_KEY = keyOf({ mixins: null });\n\n/**\n * Policies that describe methods in `ReactClassInterface`.\n */\nvar SpecPolicy = keyMirror({\n  /**\n   * These methods may be defined only once by the class specification or mixin.\n   */\n  DEFINE_ONCE: null,\n  /**\n   * These methods may be defined by both the class specification and mixins.\n   * Subsequent definitions will be chained. These methods must return void.\n   */\n  DEFINE_MANY: null,\n  /**\n   * These methods are overriding the base class.\n   */\n  OVERRIDE_BASE: null,\n  /**\n   * These methods are similar to DEFINE_MANY, except we assume they return\n   * objects. We try to merge the keys of the return values of all the mixed in\n   * functions. If there is a key conflict we throw.\n   */\n  DEFINE_MANY_MERGED: null\n});\n\nvar injectedMixins = [];\n\n/**\n * Composite components are higher-level components that compose other composite\n * or host components.\n *\n * To create a new type of `ReactClass`, pass a specification of\n * your new class to `React.createClass`. The only requirement of your class\n * specification is that you implement a `render` method.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return <div>Hello World</div>;\n *     }\n *   });\n *\n * The class specification supports a specific protocol of methods that have\n * special meaning (e.g. `render`). See `ReactClassInterface` for\n * more the comprehensive protocol. Any other properties and methods in the\n * class specification will be available on the prototype.\n *\n * @interface ReactClassInterface\n * @internal\n */\nvar ReactClassInterface = {\n\n  /**\n   * An array of Mixin objects to include when defining your component.\n   *\n   * @type {array}\n   * @optional\n   */\n  mixins: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * An object containing properties and methods that should be defined on\n   * the component's constructor instead of its prototype (static methods).\n   *\n   * @type {object}\n   * @optional\n   */\n  statics: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of prop types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  propTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types for this component.\n   *\n   * @type {object}\n   * @optional\n   */\n  contextTypes: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Definition of context types this component sets for its children.\n   *\n   * @type {object}\n   * @optional\n   */\n  childContextTypes: SpecPolicy.DEFINE_MANY,\n\n  // ==== Definition methods ====\n\n  /**\n   * Invoked when the component is mounted. Values in the mapping will be set on\n   * `this.props` if that prop is not specified (i.e. using an `in` check).\n   *\n   * This method is invoked before `getInitialState` and therefore cannot rely\n   * on `this.state` or use `this.setState`.\n   *\n   * @return {object}\n   * @optional\n   */\n  getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Invoked once before the component is mounted. The return value will be used\n   * as the initial value of `this.state`.\n   *\n   *   getInitialState: function() {\n   *     return {\n   *       isOn: false,\n   *       fooBaz: new BazFoo()\n   *     }\n   *   }\n   *\n   * @return {object}\n   * @optional\n   */\n  getInitialState: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * @return {object}\n   * @optional\n   */\n  getChildContext: SpecPolicy.DEFINE_MANY_MERGED,\n\n  /**\n   * Uses props from `this.props` and state from `this.state` to render the\n   * structure of the component.\n   *\n   * No guarantees are made about when or how often this method is invoked, so\n   * it must not have side effects.\n   *\n   *   render: function() {\n   *     var name = this.props.name;\n   *     return <div>Hello, {name}!</div>;\n   *   }\n   *\n   * @return {ReactComponent}\n   * @nosideeffects\n   * @required\n   */\n  render: SpecPolicy.DEFINE_ONCE,\n\n  // ==== Delegate methods ====\n\n  /**\n   * Invoked when the component is initially created and about to be mounted.\n   * This may have side effects, but any external subscriptions or data created\n   * by this method must be cleaned up in `componentWillUnmount`.\n   *\n   * @optional\n   */\n  componentWillMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component has been mounted and has a DOM representation.\n   * However, there is no guarantee that the DOM node is in the document.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been mounted (initialized and rendered) for the first time.\n   *\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidMount: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked before the component receives new props.\n   *\n   * Use this as an opportunity to react to a prop transition by updating the\n   * state using `this.setState`. Current props are accessed via `this.props`.\n   *\n   *   componentWillReceiveProps: function(nextProps, nextContext) {\n   *     this.setState({\n   *       likesIncreasing: nextProps.likeCount > this.props.likeCount\n   *     });\n   *   }\n   *\n   * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop\n   * transition may cause a state change, but the opposite is not true. If you\n   * need it, you are probably looking for `componentWillUpdate`.\n   *\n   * @param {object} nextProps\n   * @optional\n   */\n  componentWillReceiveProps: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked while deciding if the component should be updated as a result of\n   * receiving new props, state and/or context.\n   *\n   * Use this as an opportunity to `return false` when you're certain that the\n   * transition to the new props/state/context will not require a component\n   * update.\n   *\n   *   shouldComponentUpdate: function(nextProps, nextState, nextContext) {\n   *     return !equal(nextProps, this.props) ||\n   *       !equal(nextState, this.state) ||\n   *       !equal(nextContext, this.context);\n   *   }\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @return {boolean} True if the component should update.\n   * @optional\n   */\n  shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,\n\n  /**\n   * Invoked when the component is about to update due to a transition from\n   * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`\n   * and `nextContext`.\n   *\n   * Use this as an opportunity to perform preparation before an update occurs.\n   *\n   * NOTE: You **cannot** use `this.setState()` in this method.\n   *\n   * @param {object} nextProps\n   * @param {?object} nextState\n   * @param {?object} nextContext\n   * @param {ReactReconcileTransaction} transaction\n   * @optional\n   */\n  componentWillUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component's DOM representation has been updated.\n   *\n   * Use this as an opportunity to operate on the DOM when the component has\n   * been updated.\n   *\n   * @param {object} prevProps\n   * @param {?object} prevState\n   * @param {?object} prevContext\n   * @param {DOMElement} rootNode DOM element representing the component.\n   * @optional\n   */\n  componentDidUpdate: SpecPolicy.DEFINE_MANY,\n\n  /**\n   * Invoked when the component is about to be removed from its parent and have\n   * its DOM representation destroyed.\n   *\n   * Use this as an opportunity to deallocate any external resources.\n   *\n   * NOTE: There is no `componentDidUnmount` since your component will have been\n   * destroyed by that point.\n   *\n   * @optional\n   */\n  componentWillUnmount: SpecPolicy.DEFINE_MANY,\n\n  // ==== Advanced methods ====\n\n  /**\n   * Updates the component's currently mounted DOM representation.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   * @overridable\n   */\n  updateComponent: SpecPolicy.OVERRIDE_BASE\n\n};\n\n/**\n * Mapping from class specification keys to special processing functions.\n *\n * Although these are declared like instance properties in the specification\n * when defining classes using `React.createClass`, they are actually static\n * and are accessible on the constructor instead of the prototype. Despite\n * being static, they must be defined outside of the \"statics\" key under\n * which all other static methods are defined.\n */\nvar RESERVED_SPEC_KEYS = {\n  displayName: function (Constructor, displayName) {\n    Constructor.displayName = displayName;\n  },\n  mixins: function (Constructor, mixins) {\n    if (mixins) {\n      for (var i = 0; i < mixins.length; i++) {\n        mixSpecIntoComponent(Constructor, mixins[i]);\n      }\n    }\n  },\n  childContextTypes: function (Constructor, childContextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext);\n    }\n    Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes);\n  },\n  contextTypes: function (Constructor, contextTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context);\n    }\n    Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes);\n  },\n  /**\n   * Special case getDefaultProps which should move into statics but requires\n   * automatic merging.\n   */\n  getDefaultProps: function (Constructor, getDefaultProps) {\n    if (Constructor.getDefaultProps) {\n      Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps);\n    } else {\n      Constructor.getDefaultProps = getDefaultProps;\n    }\n  },\n  propTypes: function (Constructor, propTypes) {\n    if (\"development\" !== 'production') {\n      validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop);\n    }\n    Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes);\n  },\n  statics: function (Constructor, statics) {\n    mixStaticSpecIntoComponent(Constructor, statics);\n  },\n  autobind: function () {} };\n\n// noop\nfunction validateTypeDef(Constructor, typeDef, location) {\n  for (var propName in typeDef) {\n    if (typeDef.hasOwnProperty(propName)) {\n      // use a warning instead of an invariant so components\n      // don't show up in prod but only in __DEV__\n      \"development\" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0;\n    }\n  }\n}\n\nfunction validateMethodOverride(isAlreadyDefined, name) {\n  var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null;\n\n  // Disallow overriding of base class methods unless explicitly allowed.\n  if (ReactClassMixin.hasOwnProperty(name)) {\n    !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.', name) : _prodInvariant('73', name) : void 0;\n  }\n\n  // Disallow defining methods more than once unless explicitly allowed.\n  if (isAlreadyDefined) {\n    !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? \"development\" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('74', name) : void 0;\n  }\n}\n\n/**\n * Mixin helper which handles policy validation and reserved\n * specification keys when building React classes.\n */\nfunction mixSpecIntoComponent(Constructor, spec) {\n  if (!spec) {\n    return;\n  }\n\n  !(typeof spec !== 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component class or function as a mixin. Instead, just use a regular object.') : _prodInvariant('75') : void 0;\n  !!ReactElement.isValidElement(spec) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You\\'re attempting to use a component as a mixin. Instead, just use a regular object.') : _prodInvariant('76') : void 0;\n\n  var proto = Constructor.prototype;\n  var autoBindPairs = proto.__reactAutoBindPairs;\n\n  // By handling mixins before any other properties, we ensure the same\n  // chaining order is applied to methods with DEFINE_MANY policy, whether\n  // mixins are listed before or after these methods in the spec.\n  if (spec.hasOwnProperty(MIXINS_KEY)) {\n    RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);\n  }\n\n  for (var name in spec) {\n    if (!spec.hasOwnProperty(name)) {\n      continue;\n    }\n\n    if (name === MIXINS_KEY) {\n      // We have already handled mixins in a special case above.\n      continue;\n    }\n\n    var property = spec[name];\n    var isAlreadyDefined = proto.hasOwnProperty(name);\n    validateMethodOverride(isAlreadyDefined, name);\n\n    if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {\n      RESERVED_SPEC_KEYS[name](Constructor, property);\n    } else {\n      // Setup methods on prototype:\n      // The following member methods should not be automatically bound:\n      // 1. Expected ReactClass methods (in the \"interface\").\n      // 2. Overridden methods (that were mixed in).\n      var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);\n      var isFunction = typeof property === 'function';\n      var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;\n\n      if (shouldAutoBind) {\n        autoBindPairs.push(name, property);\n        proto[name] = property;\n      } else {\n        if (isAlreadyDefined) {\n          var specPolicy = ReactClassInterface[name];\n\n          // These cases should already be caught by validateMethodOverride.\n          !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? \"development\" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.', specPolicy, name) : _prodInvariant('77', specPolicy, name) : void 0;\n\n          // For methods which are defined more than once, call the existing\n          // methods before calling the new property, merging if appropriate.\n          if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {\n            proto[name] = createMergedResultFunction(proto[name], property);\n          } else if (specPolicy === SpecPolicy.DEFINE_MANY) {\n            proto[name] = createChainedFunction(proto[name], property);\n          }\n        } else {\n          proto[name] = property;\n          if (\"development\" !== 'production') {\n            // Add verbose displayName to the function, which helps when looking\n            // at profiling tools.\n            if (typeof property === 'function' && spec.displayName) {\n              proto[name].displayName = spec.displayName + '_' + name;\n            }\n          }\n        }\n      }\n    }\n  }\n}\n\nfunction mixStaticSpecIntoComponent(Constructor, statics) {\n  if (!statics) {\n    return;\n  }\n  for (var name in statics) {\n    var property = statics[name];\n    if (!statics.hasOwnProperty(name)) {\n      continue;\n    }\n\n    var isReserved = name in RESERVED_SPEC_KEYS;\n    !!isReserved ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved property, `%s`, that shouldn\\'t be on the \"statics\" key. Define it as an instance property instead; it will still be accessible on the constructor.', name) : _prodInvariant('78', name) : void 0;\n\n    var isInherited = name in Constructor;\n    !!isInherited ? \"development\" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('79', name) : void 0;\n    Constructor[name] = property;\n  }\n}\n\n/**\n * Merge two objects, but throw if both contain the same key.\n *\n * @param {object} one The first object, which is mutated.\n * @param {object} two The second object\n * @return {object} one after it has been mutated to contain everything in two.\n */\nfunction mergeIntoWithNoDuplicateKeys(one, two) {\n  !(one && two && typeof one === 'object' && typeof two === 'object') ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : _prodInvariant('80') : void 0;\n\n  for (var key in two) {\n    if (two.hasOwnProperty(key)) {\n      !(one[key] === undefined) ? \"development\" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.', key) : _prodInvariant('81', key) : void 0;\n      one[key] = two[key];\n    }\n  }\n  return one;\n}\n\n/**\n * Creates a function that invokes two functions and merges their return values.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createMergedResultFunction(one, two) {\n  return function mergedResult() {\n    var a = one.apply(this, arguments);\n    var b = two.apply(this, arguments);\n    if (a == null) {\n      return b;\n    } else if (b == null) {\n      return a;\n    }\n    var c = {};\n    mergeIntoWithNoDuplicateKeys(c, a);\n    mergeIntoWithNoDuplicateKeys(c, b);\n    return c;\n  };\n}\n\n/**\n * Creates a function that invokes two functions and ignores their return vales.\n *\n * @param {function} one Function to invoke first.\n * @param {function} two Function to invoke second.\n * @return {function} Function that invokes the two argument functions.\n * @private\n */\nfunction createChainedFunction(one, two) {\n  return function chainedFunction() {\n    one.apply(this, arguments);\n    two.apply(this, arguments);\n  };\n}\n\n/**\n * Binds a method to the component.\n *\n * @param {object} component Component whose method is going to be bound.\n * @param {function} method Method to be bound.\n * @return {function} The bound method.\n */\nfunction bindAutoBindMethod(component, method) {\n  var boundMethod = method.bind(component);\n  if (\"development\" !== 'production') {\n    boundMethod.__reactBoundContext = component;\n    boundMethod.__reactBoundMethod = method;\n    boundMethod.__reactBoundArguments = null;\n    var componentName = component.constructor.displayName;\n    var _bind = boundMethod.bind;\n    boundMethod.bind = function (newThis) {\n      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n        args[_key - 1] = arguments[_key];\n      }\n\n      // User is trying to bind() an autobound method; we effectively will\n      // ignore the value of \"this\" that the user is trying to use, so\n      // let's warn.\n      if (newThis !== component && newThis !== null) {\n        \"development\" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0;\n      } else if (!args.length) {\n        \"development\" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0;\n        return boundMethod;\n      }\n      var reboundMethod = _bind.apply(boundMethod, arguments);\n      reboundMethod.__reactBoundContext = component;\n      reboundMethod.__reactBoundMethod = method;\n      reboundMethod.__reactBoundArguments = args;\n      return reboundMethod;\n    };\n  }\n  return boundMethod;\n}\n\n/**\n * Binds all auto-bound methods in a component.\n *\n * @param {object} component Component whose method is going to be bound.\n */\nfunction bindAutoBindMethods(component) {\n  var pairs = component.__reactAutoBindPairs;\n  for (var i = 0; i < pairs.length; i += 2) {\n    var autoBindKey = pairs[i];\n    var method = pairs[i + 1];\n    component[autoBindKey] = bindAutoBindMethod(component, method);\n  }\n}\n\n/**\n * Add more to the ReactClass base class. These are all legacy features and\n * therefore not already part of the modern ReactComponent.\n */\nvar ReactClassMixin = {\n\n  /**\n   * TODO: This will be deprecated because state should always keep a consistent\n   * type signature and the only use case for this, is to avoid that.\n   */\n  replaceState: function (newState, callback) {\n    this.updater.enqueueReplaceState(this, newState);\n    if (callback) {\n      this.updater.enqueueCallback(this, callback, 'replaceState');\n    }\n  },\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function () {\n    return this.updater.isMounted(this);\n  }\n};\n\nvar ReactClassComponent = function () {};\n_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);\n\n/**\n * Module for creating composite components.\n *\n * @class ReactClass\n */\nvar ReactClass = {\n\n  /**\n   * Creates a composite component class given a class specification.\n   * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass\n   *\n   * @param {object} spec Class specification (which must define `render`).\n   * @return {function} Component constructor function.\n   * @public\n   */\n  createClass: function (spec) {\n    var Constructor = function (props, context, updater) {\n      // This constructor gets overridden by mocks. The argument is used\n      // by mocks to assert on what gets mounted.\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0;\n      }\n\n      // Wire up auto-binding\n      if (this.__reactAutoBindPairs.length) {\n        bindAutoBindMethods(this);\n      }\n\n      this.props = props;\n      this.context = context;\n      this.refs = emptyObject;\n      this.updater = updater || ReactNoopUpdateQueue;\n\n      this.state = null;\n\n      // ReactClasses doesn't have constructors. Instead, they use the\n      // getInitialState and componentWillMount methods for initialization.\n\n      var initialState = this.getInitialState ? this.getInitialState() : null;\n      if (\"development\" !== 'production') {\n        // We allow auto-mocks to proceed as if they're returning null.\n        if (initialState === undefined && this.getInitialState._isMockFunction) {\n          // This is probably bad practice. Consider warning here and\n          // deprecating this convenience.\n          initialState = null;\n        }\n      }\n      !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : _prodInvariant('82', Constructor.displayName || 'ReactCompositeComponent') : void 0;\n\n      this.state = initialState;\n    };\n    Constructor.prototype = new ReactClassComponent();\n    Constructor.prototype.constructor = Constructor;\n    Constructor.prototype.__reactAutoBindPairs = [];\n\n    injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));\n\n    mixSpecIntoComponent(Constructor, spec);\n\n    // Initialize the defaultProps property after all mixins have been merged.\n    if (Constructor.getDefaultProps) {\n      Constructor.defaultProps = Constructor.getDefaultProps();\n    }\n\n    if (\"development\" !== 'production') {\n      // This is a tag to indicate that the use of these method names is ok,\n      // since it's used with createClass. If it's not, then it's likely a\n      // mistake so we'll warn you to use the static property, property\n      // initializer or constructor respectively.\n      if (Constructor.getDefaultProps) {\n        Constructor.getDefaultProps.isReactClassApproved = {};\n      }\n      if (Constructor.prototype.getInitialState) {\n        Constructor.prototype.getInitialState.isReactClassApproved = {};\n      }\n    }\n\n    !Constructor.prototype.render ? \"development\" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : _prodInvariant('83') : void 0;\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0;\n    }\n\n    // Reduce time spent doing lookups by setting these on the prototype.\n    for (var methodName in ReactClassInterface) {\n      if (!Constructor.prototype[methodName]) {\n        Constructor.prototype[methodName] = null;\n      }\n    }\n\n    return Constructor;\n  },\n\n  injection: {\n    injectMixin: function (mixin) {\n      injectedMixins.push(mixin);\n    }\n  }\n\n};\n\nmodule.exports = ReactClass;\n},{\"139\":139,\"154\":154,\"161\":161,\"164\":164,\"165\":165,\"171\":171,\"172\":172,\"31\":31,\"62\":62,\"81\":81,\"83\":83,\"84\":84}],31:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactNoopUpdateQueue = _dereq_(81);\n\nvar canDefineProperty = _dereq_(117);\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Base class helpers for the updating state of a component.\n */\nfunction ReactComponent(props, context, updater) {\n  this.props = props;\n  this.context = context;\n  this.refs = emptyObject;\n  // We initialize the default updater but the real one gets injected by the\n  // renderer.\n  this.updater = updater || ReactNoopUpdateQueue;\n}\n\nReactComponent.prototype.isReactComponent = {};\n\n/**\n * Sets a subset of the state. Always use this to mutate\n * state. You should treat `this.state` as immutable.\n *\n * There is no guarantee that `this.state` will be immediately updated, so\n * accessing `this.state` after calling this method may return the old value.\n *\n * There is no guarantee that calls to `setState` will run synchronously,\n * as they may eventually be batched together.  You can provide an optional\n * callback that will be executed when the call to setState is actually\n * completed.\n *\n * When a function is provided to setState, it will be called at some point in\n * the future (not synchronously). It will be called with the up to date\n * component arguments (state, props, context). These values can be different\n * from this.* because your function may be called after receiveProps but before\n * shouldComponentUpdate, and this new state, props, and context will not yet be\n * assigned to this.\n *\n * @param {object|function} partialState Next partial state or function to\n *        produce next partial state to be merged with current state.\n * @param {?function} callback Called after state is updated.\n * @final\n * @protected\n */\nReactComponent.prototype.setState = function (partialState, callback) {\n  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? \"development\" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;\n  this.updater.enqueueSetState(this, partialState);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'setState');\n  }\n};\n\n/**\n * Forces an update. This should only be invoked when it is known with\n * certainty that we are **not** in a DOM transaction.\n *\n * You may want to call this when you know that some deeper aspect of the\n * component's state has changed but `setState` was not called.\n *\n * This will not invoke `shouldComponentUpdate`, but it will invoke\n * `componentWillUpdate` and `componentDidUpdate`.\n *\n * @param {?function} callback Called after update is complete.\n * @final\n * @protected\n */\nReactComponent.prototype.forceUpdate = function (callback) {\n  this.updater.enqueueForceUpdate(this);\n  if (callback) {\n    this.updater.enqueueCallback(this, callback, 'forceUpdate');\n  }\n};\n\n/**\n * Deprecated APIs. These APIs used to exist on classic React classes but since\n * we would like to deprecate them, we're not going to move them over to this\n * modern base class. Instead, we define a getter that warns if it's accessed.\n */\nif (\"development\" !== 'production') {\n  var deprecatedAPIs = {\n    isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],\n    replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']\n  };\n  var defineDeprecationWarning = function (methodName, info) {\n    if (canDefineProperty) {\n      Object.defineProperty(ReactComponent.prototype, methodName, {\n        get: function () {\n          \"development\" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0;\n          return undefined;\n        }\n      });\n    }\n  };\n  for (var fnName in deprecatedAPIs) {\n    if (deprecatedAPIs.hasOwnProperty(fnName)) {\n      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);\n    }\n  }\n}\n\nmodule.exports = ReactComponent;\n},{\"117\":117,\"139\":139,\"154\":154,\"161\":161,\"171\":171,\"81\":81}],32:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentBrowserEnvironment\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMIDOperations = _dereq_(47);\n\n/**\n * Abstracts away all functionality of the reconciler that requires knowledge of\n * the browser context. TODO: These callers should be refactored to avoid the\n * need for this injection.\n */\nvar ReactComponentBrowserEnvironment = {\n\n  processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,\n\n  replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup,\n\n  /**\n   * If a particular environment requires that some resources be cleaned up,\n   * specify this in the injected Mixin. In the DOM, we would likely want to\n   * purge any cached node ID lookups.\n   *\n   * @private\n   */\n  unmountIDFromEnvironment: function (rootNodeID) {}\n\n};\n\nmodule.exports = ReactComponentBrowserEnvironment;\n},{\"47\":47,\"7\":7}],33:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentEnvironment\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\nvar injected = false;\n\nvar ReactComponentEnvironment = {\n\n  /**\n   * Optionally injectable environment dependent cleanup hook. (server vs.\n   * browser etc). Example: A browser system caches DOM nodes based on component\n   * ID and must remove that cache entry when this instance is unmounted.\n   */\n  unmountIDFromEnvironment: null,\n\n  /**\n   * Optionally injectable hook for swapping out mount images in the middle of\n   * the tree.\n   */\n  replaceNodeWithMarkup: null,\n\n  /**\n   * Optionally injectable hook for processing a queue of child updates. Will\n   * later move into MultiChildComponents.\n   */\n  processChildrenUpdates: null,\n\n  injection: {\n    injectEnvironment: function (environment) {\n      !!injected ? \"development\" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0;\n      ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment;\n      ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;\n      ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;\n      injected = true;\n    }\n  }\n\n};\n\nmodule.exports = ReactComponentEnvironment;\n},{\"139\":139,\"161\":161}],34:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactComponentTreeDevtool\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar tree = {};\nvar unmountedIDs = {};\nvar rootIDs = {};\n\nfunction updateTree(id, update) {\n  if (!tree[id]) {\n    tree[id] = {\n      element: null,\n      parentID: null,\n      ownerID: null,\n      text: null,\n      childIDs: [],\n      displayName: 'Unknown',\n      isMounted: false,\n      updateCount: 0\n    };\n  }\n  update(tree[id]);\n}\n\nfunction purgeDeep(id) {\n  var item = tree[id];\n  if (item) {\n    var childIDs = item.childIDs;\n\n    delete tree[id];\n    childIDs.forEach(purgeDeep);\n  }\n}\n\nfunction describeComponentFrame(name, source, ownerName) {\n  return '\\n    in ' + name + (source ? ' (at ' + source.fileName.replace(/^.*[\\\\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');\n}\n\nfunction describeID(id) {\n  var name = ReactComponentTreeDevtool.getDisplayName(id);\n  var element = ReactComponentTreeDevtool.getElement(id);\n  var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n  var ownerName;\n  if (ownerID) {\n    ownerName = ReactComponentTreeDevtool.getDisplayName(ownerID);\n  }\n  \"development\" !== 'production' ? warning(element, 'ReactComponentTreeDevtool: Missing React element for debugID %s when ' + 'building stack', id) : void 0;\n  return describeComponentFrame(name, element && element._source, ownerName);\n}\n\nvar ReactComponentTreeDevtool = {\n  onSetDisplayName: function (id, displayName) {\n    updateTree(id, function (item) {\n      return item.displayName = displayName;\n    });\n  },\n  onSetChildren: function (id, nextChildIDs) {\n    updateTree(id, function (item) {\n      item.childIDs = nextChildIDs;\n\n      nextChildIDs.forEach(function (nextChildID) {\n        var nextChild = tree[nextChildID];\n        !nextChild ? \"development\" !== 'production' ? invariant(false, 'Expected devtool events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('68') : void 0;\n        !(nextChild.displayName != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetDisplayName() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('69') : void 0;\n        !(nextChild.childIDs != null || nextChild.text != null) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetChildren() or onSetText() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('70') : void 0;\n        !nextChild.isMounted ? \"development\" !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;\n        if (nextChild.parentID == null) {\n          nextChild.parentID = id;\n          // TODO: This shouldn't be necessary but mounting a new root during in\n          // componentWillMount currently causes not-yet-mounted components to\n          // be purged from our tree data so their parent ID is missing.\n        }\n        !(nextChild.parentID === id) ? \"development\" !== 'production' ? invariant(false, 'Expected onSetParent() and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('72', nextChildID, nextChild.parentID, id) : void 0;\n      });\n    });\n  },\n  onSetOwner: function (id, ownerID) {\n    updateTree(id, function (item) {\n      return item.ownerID = ownerID;\n    });\n  },\n  onSetParent: function (id, parentID) {\n    updateTree(id, function (item) {\n      return item.parentID = parentID;\n    });\n  },\n  onSetText: function (id, text) {\n    updateTree(id, function (item) {\n      return item.text = text;\n    });\n  },\n  onBeforeMountComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onBeforeUpdateComponent: function (id, element) {\n    updateTree(id, function (item) {\n      return item.element = element;\n    });\n  },\n  onMountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = true;\n    });\n  },\n  onMountRootComponent: function (id) {\n    rootIDs[id] = true;\n  },\n  onUpdateComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.updateCount++;\n    });\n  },\n  onUnmountComponent: function (id) {\n    updateTree(id, function (item) {\n      return item.isMounted = false;\n    });\n    unmountedIDs[id] = true;\n    delete rootIDs[id];\n  },\n  purgeUnmountedComponents: function () {\n    if (ReactComponentTreeDevtool._preventPurging) {\n      // Should only be used for testing.\n      return;\n    }\n\n    for (var id in unmountedIDs) {\n      purgeDeep(id);\n    }\n    unmountedIDs = {};\n  },\n  isMounted: function (id) {\n    var item = tree[id];\n    return item ? item.isMounted : false;\n  },\n  getCurrentStackAddendum: function (topElement) {\n    var info = '';\n    if (topElement) {\n      var type = topElement.type;\n      var name = typeof type === 'function' ? type.displayName || type.name : type;\n      var owner = topElement._owner;\n      info += describeComponentFrame(name || 'Unknown', topElement._source, owner && owner.getName());\n    }\n\n    var currentOwner = ReactCurrentOwner.current;\n    var id = currentOwner && currentOwner._debugID;\n\n    info += ReactComponentTreeDevtool.getStackAddendumByID(id);\n    return info;\n  },\n  getStackAddendumByID: function (id) {\n    var info = '';\n    while (id) {\n      info += describeID(id);\n      id = ReactComponentTreeDevtool.getParentID(id);\n    }\n    return info;\n  },\n  getChildIDs: function (id) {\n    var item = tree[id];\n    return item ? item.childIDs : [];\n  },\n  getDisplayName: function (id) {\n    var item = tree[id];\n    return item ? item.displayName : 'Unknown';\n  },\n  getElement: function (id) {\n    var item = tree[id];\n    return item ? item.element : null;\n  },\n  getOwnerID: function (id) {\n    var item = tree[id];\n    return item ? item.ownerID : null;\n  },\n  getParentID: function (id) {\n    var item = tree[id];\n    return item ? item.parentID : null;\n  },\n  getSource: function (id) {\n    var item = tree[id];\n    var element = item ? item.element : null;\n    var source = element != null ? element._source : null;\n    return source;\n  },\n  getText: function (id) {\n    var item = tree[id];\n    return item ? item.text : null;\n  },\n  getUpdateCount: function (id) {\n    var item = tree[id];\n    return item ? item.updateCount : 0;\n  },\n  getRootIDs: function () {\n    return Object.keys(rootIDs);\n  },\n  getRegisteredIDs: function () {\n    return Object.keys(tree);\n  }\n};\n\nmodule.exports = ReactComponentTreeDevtool;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36}],35:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCompositeComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\nvar ReactErrorUtils = _dereq_(65);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactNodeTypes = _dereq_(80);\nvar ReactPropTypeLocations = _dereq_(84);\nvar ReactReconciler = _dereq_(87);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar emptyObject = _dereq_(154);\nvar invariant = _dereq_(161);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nfunction StatelessComponent(Component) {}\nStatelessComponent.prototype.render = function () {\n  var Component = ReactInstanceMap.get(this)._currentElement.type;\n  var element = Component(this.props, this.context, this.updater);\n  warnIfInvalidElement(Component, element);\n  return element;\n};\n\nfunction warnIfInvalidElement(Component, element) {\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;\n    \"development\" !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0;\n  }\n}\n\nfunction invokeComponentDidMountWithTimer() {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n  publicInstance.componentDidMount();\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidMount');\n  }\n}\n\nfunction invokeComponentDidUpdateWithTimer(prevProps, prevState, prevContext) {\n  var publicInstance = this._instance;\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n  publicInstance.componentDidUpdate(prevProps, prevState, prevContext);\n  if (this._debugID !== 0) {\n    ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentDidUpdate');\n  }\n}\n\nfunction shouldConstruct(Component) {\n  return Component.prototype && Component.prototype.isReactComponent;\n}\n\n/**\n * ------------------ The Life-Cycle of a Composite Component ------------------\n *\n * - constructor: Initialization of state. The instance is now retained.\n *   - componentWillMount\n *   - render\n *   - [children's constructors]\n *     - [children's componentWillMount and render]\n *     - [children's componentDidMount]\n *     - componentDidMount\n *\n *       Update Phases:\n *       - componentWillReceiveProps (only called if parent updated)\n *       - shouldComponentUpdate\n *         - componentWillUpdate\n *           - render\n *           - [children's constructors or receive props phases]\n *         - componentDidUpdate\n *\n *     - componentWillUnmount\n *     - [children's componentWillUnmount]\n *   - [children destroyed]\n * - (destroyed): The instance is now blank, released by React and ready for GC.\n *\n * -----------------------------------------------------------------------------\n */\n\n/**\n * An incrementing ID assigned to each component when it is mounted. This is\n * used to enforce the order in which `ReactUpdates` updates dirty components.\n *\n * @private\n */\nvar nextMountID = 1;\n\n/**\n * @lends {ReactCompositeComponent.prototype}\n */\nvar ReactCompositeComponentMixin = {\n\n  /**\n   * Base constructor for all composite component.\n   *\n   * @param {ReactElement} element\n   * @final\n   * @internal\n   */\n  construct: function (element) {\n    this._currentElement = element;\n    this._rootNodeID = null;\n    this._instance = null;\n    this._hostParent = null;\n    this._hostContainerInfo = null;\n\n    // See ReactUpdateQueue\n    this._updateBatchNumber = null;\n    this._pendingElement = null;\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    this._renderedNodeType = null;\n    this._renderedComponent = null;\n    this._context = null;\n    this._mountOrder = 0;\n    this._topLevelWrapper = null;\n\n    // See ReactUpdates and ReactUpdateQueue.\n    this._pendingCallbacks = null;\n\n    // ComponentWillUnmount shall only be called once\n    this._calledComponentWillUnmount = false;\n\n    if (\"development\" !== 'production') {\n      this._warnedAboutRefsInRender = false;\n    }\n  },\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} hostParent\n   * @param {?object} hostContainerInfo\n   * @param {?object} context\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._context = context;\n    this._mountOrder = nextMountID++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var publicProps = this._currentElement.props;\n    var publicContext = this._processContext(context);\n\n    var Component = this._currentElement.type;\n\n    var updateQueue = transaction.getUpdateQueue();\n\n    // Initialize the public class\n    var inst = this._constructComponent(publicProps, publicContext, updateQueue);\n    var renderedElement;\n\n    // Support functional components\n    if (!shouldConstruct(Component) && (inst == null || inst.render == null)) {\n      renderedElement = inst;\n      warnIfInvalidElement(Component, renderedElement);\n      !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? \"development\" !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0;\n      inst = new StatelessComponent(Component);\n    }\n\n    if (\"development\" !== 'production') {\n      // This will throw later in _renderValidatedComponent, but add an early\n      // warning now to help debugging\n      if (inst.render == null) {\n        \"development\" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0;\n      }\n\n      var propsMutated = inst.props !== publicProps;\n      var componentName = Component.displayName || Component.name || 'Component';\n\n      \"development\" !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\\'s constructor was passed.', componentName, componentName) : void 0;\n    }\n\n    // These should be set up in the constructor, but as a convenience for\n    // simpler class abstractions, we set them up after the fact.\n    inst.props = publicProps;\n    inst.context = publicContext;\n    inst.refs = emptyObject;\n    inst.updater = updateQueue;\n\n    this._instance = inst;\n\n    // Store a reference from the instance back to the internal representation\n    ReactInstanceMap.set(inst, this);\n\n    if (\"development\" !== 'production') {\n      // Since plain JS classes are defined without any special initialization\n      // logic, we can not catch common errors early. Therefore, we have to\n      // catch them here, at initialization time, instead.\n      \"development\" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0;\n      \"development\" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0;\n    }\n\n    var initialState = inst.state;\n    if (initialState === undefined) {\n      inst.state = initialState = null;\n    }\n    !(typeof initialState === 'object' && !Array.isArray(initialState)) ? \"development\" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n\n    var markup;\n    if (inst.unstable_handleError) {\n      markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } else {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n\n    if (inst.componentDidMount) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);\n      }\n    }\n\n    return markup;\n  },\n\n  _constructComponent: function (publicProps, publicContext, updateQueue) {\n    if (\"development\" !== 'production') {\n      ReactCurrentOwner.current = this;\n      try {\n        return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n      } finally {\n        ReactCurrentOwner.current = null;\n      }\n    } else {\n      return this._constructComponentWithoutOwner(publicProps, publicContext, updateQueue);\n    }\n  },\n\n  _constructComponentWithoutOwner: function (publicProps, publicContext, updateQueue) {\n    var Component = this._currentElement.type;\n    var instanceOrElement;\n    if (shouldConstruct(Component)) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n      instanceOrElement = new Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'ctor');\n        }\n      }\n    } else {\n      // This can still be an instance in case of factory components\n      // but we'll count this as time spent rendering as the more common case.\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n      instanceOrElement = Component(publicProps, publicContext, updateQueue);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n        }\n      }\n    }\n    return instanceOrElement;\n  },\n\n  performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var markup;\n    var checkpoint = transaction.checkpoint();\n    try {\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    } catch (e) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onError();\n        }\n      }\n      // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint\n      transaction.rollback(checkpoint);\n      this._instance.unstable_handleError(e);\n      if (this._pendingStateQueue) {\n        this._instance.state = this._processPendingState(this._instance.props, this._instance.context);\n      }\n      checkpoint = transaction.checkpoint();\n\n      this._renderedComponent.unmountComponent(true);\n      transaction.rollback(checkpoint);\n\n      // Try again - we've informed the component about the error, so they can render an error message this time.\n      // If this throws again, the error will bubble up (and can be caught by a higher error boundary).\n      markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);\n    }\n    return markup;\n  },\n\n  performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {\n    var inst = this._instance;\n    if (inst.componentWillMount) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      inst.componentWillMount();\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillMount');\n        }\n      }\n      // When mounting, calls to `setState` by `componentWillMount` will set\n      // `this._pendingStateQueue` without triggering a re-render.\n      if (this._pendingStateQueue) {\n        inst.state = this._processPendingState(inst.props, inst.context);\n      }\n    }\n\n    // If not a stateless component, we now render\n    if (renderedElement === undefined) {\n      renderedElement = this._renderValidatedComponent();\n    }\n\n    var nodeType = ReactNodeTypes.getType(renderedElement);\n    this._renderedNodeType = nodeType;\n    var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n    );\n    this._renderedComponent = child;\n    if (\"development\" !== 'production') {\n      if (child._debugID !== 0 && this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n      }\n    }\n\n    var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context));\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n      }\n    }\n\n    return markup;\n  },\n\n  getHostNode: function () {\n    return ReactReconciler.getHostNode(this._renderedComponent);\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    if (!this._renderedComponent) {\n      return;\n    }\n    var inst = this._instance;\n\n    if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {\n      inst._calledComponentWillUnmount = true;\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n      if (safely) {\n        var name = this.getName() + '.componentWillUnmount()';\n        ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));\n      } else {\n        inst.componentWillUnmount();\n      }\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUnmount');\n        }\n      }\n    }\n\n    if (this._renderedComponent) {\n      ReactReconciler.unmountComponent(this._renderedComponent, safely);\n      this._renderedNodeType = null;\n      this._renderedComponent = null;\n      this._instance = null;\n    }\n\n    // Reset pending fields\n    // Even if this component is scheduled for another update in ReactUpdates,\n    // it would still be ignored because these fields are reset.\n    this._pendingStateQueue = null;\n    this._pendingReplaceState = false;\n    this._pendingForceUpdate = false;\n    this._pendingCallbacks = null;\n    this._pendingElement = null;\n\n    // These fields do not really need to be reset since this object is no\n    // longer accessible.\n    this._context = null;\n    this._rootNodeID = null;\n    this._topLevelWrapper = null;\n\n    // Delete the reference from the instance to this internal representation\n    // which allow the internals to be properly cleaned up even if the user\n    // leaks a reference to the public instance.\n    ReactInstanceMap.remove(inst);\n\n    // Some existing components rely on inst.props even after they've been\n    // destroyed (in event handlers).\n    // TODO: inst.props = null;\n    // TODO: inst.state = null;\n    // TODO: inst.context = null;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _maskContext: function (context) {\n    var Component = this._currentElement.type;\n    var contextTypes = Component.contextTypes;\n    if (!contextTypes) {\n      return emptyObject;\n    }\n    var maskedContext = {};\n    for (var contextName in contextTypes) {\n      maskedContext[contextName] = context[contextName];\n    }\n    return maskedContext;\n  },\n\n  /**\n   * Filters the context object to only contain keys specified in\n   * `contextTypes`, and asserts that they are valid.\n   *\n   * @param {object} context\n   * @return {?object}\n   * @private\n   */\n  _processContext: function (context) {\n    var maskedContext = this._maskContext(context);\n    if (\"development\" !== 'production') {\n      var Component = this._currentElement.type;\n      if (Component.contextTypes) {\n        this._checkContextTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);\n      }\n    }\n    return maskedContext;\n  },\n\n  /**\n   * @param {object} currentContext\n   * @return {object}\n   * @private\n   */\n  _processChildContext: function (currentContext) {\n    var Component = this._currentElement.type;\n    var inst = this._instance;\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onBeginProcessingChildContext();\n    }\n    var childContext = inst.getChildContext && inst.getChildContext();\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onEndProcessingChildContext();\n    }\n    if (childContext) {\n      !(typeof Component.childContextTypes === 'object') ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;\n      if (\"development\" !== 'production') {\n        this._checkContextTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);\n      }\n      for (var name in childContext) {\n        !(name in Component.childContextTypes) ? \"development\" !== 'production' ? invariant(false, '%s.getChildContext(): key \"%s\" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0;\n      }\n      return _assign({}, currentContext, childContext);\n    }\n    return currentContext;\n  },\n\n  /**\n   * Assert that the context types are valid\n   *\n   * @param {object} typeSpecs Map of context field to a ReactPropType\n   * @param {object} values Runtime values that need to be type-checked\n   * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n   * @private\n   */\n  _checkContextTypes: function (typeSpecs, values, location) {\n    checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);\n  },\n\n  receiveComponent: function (nextElement, transaction, nextContext) {\n    var prevElement = this._currentElement;\n    var prevContext = this._context;\n\n    this._pendingElement = null;\n\n    this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);\n  },\n\n  /**\n   * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`\n   * is set, update the component.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (transaction) {\n    if (this._pendingElement != null) {\n      ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);\n    } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {\n      this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);\n    } else {\n      this._updateBatchNumber = null;\n    }\n  },\n\n  /**\n   * Perform an update to a mounted component. The componentWillReceiveProps and\n   * shouldComponentUpdate methods are called, then (assuming the update isn't\n   * skipped) the remaining update lifecycle methods are called and the DOM\n   * representation is updated.\n   *\n   * By default, this implements React's rendering and reconciliation algorithm.\n   * Sophisticated clients may wish to override this.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevParentElement\n   * @param {ReactElement} nextParentElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {\n    var inst = this._instance;\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    var willReceive = false;\n    var nextContext;\n    var nextProps;\n\n    // Determine if the context has changed or not\n    if (this._context === nextUnmaskedContext) {\n      nextContext = inst.context;\n    } else {\n      nextContext = this._processContext(nextUnmaskedContext);\n      willReceive = true;\n    }\n\n    nextProps = nextParentElement.props;\n\n    // Not a simple state update but a props update\n    if (prevParentElement !== nextParentElement) {\n      willReceive = true;\n    }\n\n    // An update here will schedule an update but immediately set\n    // _pendingStateQueue which will ensure that any state updates gets\n    // immediately reconciled instead of waiting for the next batch.\n    if (willReceive && inst.componentWillReceiveProps) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n      inst.componentWillReceiveProps(nextProps, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps');\n        }\n      }\n    }\n\n    var nextState = this._processPendingState(nextProps, nextContext);\n    var shouldUpdate = true;\n\n    if (!this._pendingForceUpdate && inst.shouldComponentUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n      shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate');\n        }\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;\n    }\n\n    this._updateBatchNumber = null;\n    if (shouldUpdate) {\n      this._pendingForceUpdate = false;\n      // Will set `this.props`, `this.state` and `this.context`.\n      this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);\n    } else {\n      // If it's determined that a component should not update, we still want\n      // to set props and state but we shortcut the rest of the update.\n      this._currentElement = nextParentElement;\n      this._context = nextUnmaskedContext;\n      inst.props = nextProps;\n      inst.state = nextState;\n      inst.context = nextContext;\n    }\n  },\n\n  _processPendingState: function (props, context) {\n    var inst = this._instance;\n    var queue = this._pendingStateQueue;\n    var replace = this._pendingReplaceState;\n    this._pendingReplaceState = false;\n    this._pendingStateQueue = null;\n\n    if (!queue) {\n      return inst.state;\n    }\n\n    if (replace && queue.length === 1) {\n      return queue[0];\n    }\n\n    var nextState = _assign({}, replace ? queue[0] : inst.state);\n    for (var i = replace ? 1 : 0; i < queue.length; i++) {\n      var partial = queue[i];\n      _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);\n    }\n\n    return nextState;\n  },\n\n  /**\n   * Merges new props and state, notifies delegate methods of update and\n   * performs update.\n   *\n   * @param {ReactElement} nextElement Next element\n   * @param {object} nextProps Next public object to set as properties.\n   * @param {?object} nextState Next object to set as state.\n   * @param {?object} nextContext Next public object to set as context.\n   * @param {ReactReconcileTransaction} transaction\n   * @param {?object} unmaskedContext\n   * @private\n   */\n  _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {\n    var inst = this._instance;\n\n    var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);\n    var prevProps;\n    var prevState;\n    var prevContext;\n    if (hasComponentDidUpdate) {\n      prevProps = inst.props;\n      prevState = inst.state;\n      prevContext = inst.context;\n    }\n\n    if (inst.componentWillUpdate) {\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n      inst.componentWillUpdate(nextProps, nextState, nextContext);\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate');\n        }\n      }\n    }\n\n    this._currentElement = nextElement;\n    this._context = unmaskedContext;\n    inst.props = nextProps;\n    inst.state = nextState;\n    inst.context = nextContext;\n\n    this._updateRenderedComponent(transaction, unmaskedContext);\n\n    if (hasComponentDidUpdate) {\n      if (\"development\" !== 'production') {\n        transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this);\n      } else {\n        transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);\n      }\n    }\n  },\n\n  /**\n   * Call the component's `render` method and update the DOM accordingly.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  _updateRenderedComponent: function (transaction, context) {\n    var prevComponentInstance = this._renderedComponent;\n    var prevRenderedElement = prevComponentInstance._currentElement;\n    var nextRenderedElement = this._renderValidatedComponent();\n    if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {\n      ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));\n    } else {\n      var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);\n      ReactReconciler.unmountComponent(prevComponentInstance, false);\n\n      var nodeType = ReactNodeTypes.getType(nextRenderedElement);\n      this._renderedNodeType = nodeType;\n      var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */\n      );\n      this._renderedComponent = child;\n      if (\"development\" !== 'production') {\n        if (child._debugID !== 0 && this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetParent(child._debugID, this._debugID);\n        }\n      }\n\n      var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context));\n\n      if (\"development\" !== 'production') {\n        if (this._debugID !== 0) {\n          ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);\n        }\n      }\n\n      this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);\n    }\n  },\n\n  /**\n   * Overridden in shallow rendering.\n   *\n   * @protected\n   */\n  _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {\n    ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);\n  },\n\n  /**\n   * @protected\n   */\n  _renderValidatedComponentWithoutOwnerOrContext: function () {\n    var inst = this._instance;\n\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n    var renderedComponent = inst.render();\n    if (\"development\" !== 'production') {\n      if (this._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'render');\n      }\n    }\n\n    if (\"development\" !== 'production') {\n      // We allow auto-mocks to proceed as if they're returning null.\n      if (renderedComponent === undefined && inst.render._isMockFunction) {\n        // This is probably bad practice. Consider warning here and\n        // deprecating this convenience.\n        renderedComponent = null;\n      }\n    }\n\n    return renderedComponent;\n  },\n\n  /**\n   * @private\n   */\n  _renderValidatedComponent: function () {\n    var renderedComponent;\n    ReactCurrentOwner.current = this;\n    try {\n      renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();\n    } finally {\n      ReactCurrentOwner.current = null;\n    }\n    !(\n    // TODO: An `isValidNode` function would probably be more appropriate\n    renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? \"development\" !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0;\n\n    return renderedComponent;\n  },\n\n  /**\n   * Lazily allocates the refs object and stores `component` as `ref`.\n   *\n   * @param {string} ref Reference name.\n   * @param {component} component Component to store as `ref`.\n   * @final\n   * @private\n   */\n  attachRef: function (ref, component) {\n    var inst = this.getPublicInstance();\n    !(inst != null) ? \"development\" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0;\n    var publicComponentInstance = component.getPublicInstance();\n    if (\"development\" !== 'production') {\n      var componentName = component && component.getName ? component.getName() : 'a component';\n      \"development\" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref \"%s\" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;\n    }\n    var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;\n    refs[ref] = publicComponentInstance;\n  },\n\n  /**\n   * Detaches a reference name.\n   *\n   * @param {string} ref Name to dereference.\n   * @final\n   * @private\n   */\n  detachRef: function (ref) {\n    var refs = this.getPublicInstance().refs;\n    delete refs[ref];\n  },\n\n  /**\n   * Get a text description of the component that can be used to identify it\n   * in error messages.\n   * @return {string} The name or null.\n   * @internal\n   */\n  getName: function () {\n    var type = this._currentElement.type;\n    var constructor = this._instance && this._instance.constructor;\n    return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;\n  },\n\n  /**\n   * Get the publicly accessible representation of this component - i.e. what\n   * is exposed by refs and returned by render. Can be null for stateless\n   * components.\n   *\n   * @return {ReactComponent} the public component instance.\n   * @internal\n   */\n  getPublicInstance: function () {\n    var inst = this._instance;\n    if (inst instanceof StatelessComponent) {\n      return null;\n    }\n    return inst;\n  },\n\n  // Stub\n  _instantiateReactComponent: null\n\n};\n\nvar ReactCompositeComponent = {\n\n  Mixin: ReactCompositeComponentMixin\n\n};\n\nmodule.exports = ReactCompositeComponent;\n},{\"118\":118,\"139\":139,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"172\":172,\"33\":33,\"36\":36,\"62\":62,\"65\":65,\"73\":73,\"74\":74,\"80\":80,\"84\":84,\"87\":87}],36:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactCurrentOwner\n */\n\n'use strict';\n\n/**\n * Keeps track of the current owner.\n *\n * The current owner is the component who should own any components that are\n * currently being constructed.\n */\n\nvar ReactCurrentOwner = {\n\n  /**\n   * @internal\n   * @type {ReactComponent}\n   */\n  current: null\n\n};\n\nmodule.exports = ReactCurrentOwner;\n},{}],37:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOM\n */\n\n/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/\n\n'use strict';\n\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactMount = _dereq_(77);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdates = _dereq_(95);\nvar ReactVersion = _dereq_(96);\n\nvar findDOMNode = _dereq_(122);\nvar getHostComponentFromComposite = _dereq_(129);\nvar renderSubtreeIntoContainer = _dereq_(140);\nvar warning = _dereq_(171);\n\nReactDefaultInjection.inject();\n\nvar React = {\n  findDOMNode: findDOMNode,\n  render: ReactMount.render,\n  unmountComponentAtNode: ReactMount.unmountComponentAtNode,\n  version: ReactVersion,\n\n  /* eslint-disable camelcase */\n  unstable_batchedUpdates: ReactUpdates.batchedUpdates,\n  unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer\n};\n\n// Inject the runtime into a devtools global hook regardless of browser.\n// Allows for debugging when the hook is injected on the page.\n/* eslint-enable camelcase */\nif (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {\n  __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({\n    ComponentTree: {\n      getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,\n      getNodeFromInstance: function (inst) {\n        // inst is an internal instance (but could be a composite)\n        if (inst._renderedComponent) {\n          inst = getHostComponentFromComposite(inst);\n        }\n        if (inst) {\n          return ReactDOMComponentTree.getNodeFromInstance(inst);\n        } else {\n          return null;\n        }\n      }\n    },\n    Mount: ReactMount,\n    Reconciler: ReactReconciler\n  });\n}\n\nif (\"development\" !== 'production') {\n  var ExecutionEnvironment = _dereq_(147);\n  if (ExecutionEnvironment.canUseDOM && window.top === window.self) {\n\n    // First check if devtools is not installed\n    if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {\n      // If we're in Chrome or Firefox, provide a download link if not installed.\n      if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {\n        // Firefox does not have the issue with devtools loaded over file://\n        var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;\n        console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');\n      }\n    }\n\n    var testFunc = function testFn() {};\n    \"development\" !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;\n\n    // If we're in IE8, check to see if we are in compatibility mode and provide\n    // information on preventing compatibility mode\n    var ieCompatibilityMode = document.documentMode && document.documentMode < 8;\n\n    \"development\" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />') : void 0;\n\n    var expectedFeatures = [\n    // shims\n    Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim];\n\n    for (var i = 0; i < expectedFeatures.length; i++) {\n      if (!expectedFeatures[i]) {\n        \"development\" !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;\n        break;\n      }\n    }\n  }\n}\n\nmodule.exports = React;\n},{\"122\":122,\"129\":129,\"140\":140,\"147\":147,\"171\":171,\"41\":41,\"61\":61,\"77\":77,\"87\":87,\"95\":95,\"96\":96}],38:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMButton\n */\n\n'use strict';\n\nvar DisabledInputUtils = _dereq_(14);\n\n/**\n * Implements a <button> host component that does not receive mouse events\n * when `disabled` is set.\n */\nvar ReactDOMButton = {\n  getHostProps: DisabledInputUtils.getHostProps\n};\n\nmodule.exports = ReactDOMButton;\n},{\"14\":14}],39:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponent\n */\n\n/* global hasOwnProperty:true */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar AutoFocusUtils = _dereq_(1);\nvar CSSPropertyOperations = _dereq_(4);\nvar DOMLazyTree = _dereq_(8);\nvar DOMNamespaces = _dereq_(9);\nvar DOMProperty = _dereq_(10);\nvar DOMPropertyOperations = _dereq_(11);\nvar EventConstants = _dereq_(16);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMButton = _dereq_(38);\nvar ReactDOMComponentFlags = _dereq_(40);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMInput = _dereq_(48);\nvar ReactDOMOption = _dereq_(51);\nvar ReactDOMSelect = _dereq_(52);\nvar ReactDOMTextarea = _dereq_(56);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChild = _dereq_(78);\nvar ReactServerRenderingTransaction = _dereq_(91);\n\nvar emptyFunction = _dereq_(153);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar isEventSupported = _dereq_(135);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\nvar validateDOMNesting = _dereq_(145);\nvar warning = _dereq_(171);\n\nvar Flags = ReactDOMComponentFlags;\nvar deleteListener = EventPluginHub.deleteListener;\nvar getNode = ReactDOMComponentTree.getNodeFromInstance;\nvar listenTo = ReactBrowserEventEmitter.listenTo;\nvar registrationNameModules = EventPluginRegistry.registrationNameModules;\n\n// For quickly matching children type, to test if can be treated as content.\nvar CONTENT_TYPES = { 'string': true, 'number': true };\n\nvar STYLE = keyOf({ style: null });\nvar HTML = keyOf({ __html: null });\nvar RESERVED_PROPS = {\n  children: null,\n  dangerouslySetInnerHTML: null,\n  suppressContentEditableWarning: null\n};\n\n// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).\nvar DOC_FRAGMENT_TYPE = 11;\n\nfunction getDeclarationErrorAddendum(internalInstance) {\n  if (internalInstance) {\n    var owner = internalInstance._currentElement._owner || null;\n    if (owner) {\n      var name = owner.getName();\n      if (name) {\n        return ' This DOM node was rendered by `' + name + '`.';\n      }\n    }\n  }\n  return '';\n}\n\nfunction friendlyStringify(obj) {\n  if (typeof obj === 'object') {\n    if (Array.isArray(obj)) {\n      return '[' + obj.map(friendlyStringify).join(', ') + ']';\n    } else {\n      var pairs = [];\n      for (var key in obj) {\n        if (Object.prototype.hasOwnProperty.call(obj, key)) {\n          var keyEscaped = /^[a-z$_][\\w$_]*$/i.test(key) ? key : JSON.stringify(key);\n          pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key]));\n        }\n      }\n      return '{' + pairs.join(', ') + '}';\n    }\n  } else if (typeof obj === 'string') {\n    return JSON.stringify(obj);\n  } else if (typeof obj === 'function') {\n    return '[function object]';\n  }\n  // Differs from JSON.stringify in that undefined because undefined and that\n  // inf and nan don't become null\n  return String(obj);\n}\n\nvar styleMutationWarning = {};\n\nfunction checkAndWarnForMutatedStyle(style1, style2, component) {\n  if (style1 == null || style2 == null) {\n    return;\n  }\n  if (shallowEqual(style1, style2)) {\n    return;\n  }\n\n  var componentName = component._tag;\n  var owner = component._currentElement._owner;\n  var ownerName;\n  if (owner) {\n    ownerName = owner.getName();\n  }\n\n  var hash = ownerName + '|' + componentName;\n\n  if (styleMutationWarning.hasOwnProperty(hash)) {\n    return;\n  }\n\n  styleMutationWarning[hash] = true;\n\n  \"development\" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;\n}\n\n/**\n * @param {object} component\n * @param {?object} props\n */\nfunction assertValidProps(component, props) {\n  if (!props) {\n    return;\n  }\n  // Note the use of `==` which checks for null or undefined.\n  if (voidElementTags[component._tag]) {\n    !(props.children == null && props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : _prodInvariant('137', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : void 0;\n  }\n  if (props.dangerouslySetInnerHTML != null) {\n    !(props.children == null) ? \"development\" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : _prodInvariant('60') : void 0;\n    !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? \"development\" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : _prodInvariant('61') : void 0;\n  }\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;\n    \"development\" !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0;\n    \"development\" !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;\n  }\n  !(props.style == null || typeof props.style === 'object') ? \"development\" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \\'em\\'}} when using JSX.%s', getDeclarationErrorAddendum(component)) : _prodInvariant('62', getDeclarationErrorAddendum(component)) : void 0;\n}\n\nfunction enqueuePutListener(inst, registrationName, listener, transaction) {\n  if (transaction instanceof ReactServerRenderingTransaction) {\n    return;\n  }\n  if (\"development\" !== 'production') {\n    // IE8 has no API for event capturing and the `onScroll` event doesn't\n    // bubble.\n    \"development\" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\\'t support the `onScroll` event') : void 0;\n  }\n  var containerInfo = inst._hostContainerInfo;\n  var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;\n  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;\n  listenTo(registrationName, doc);\n  transaction.getReactMountReady().enqueue(putListener, {\n    inst: inst,\n    registrationName: registrationName,\n    listener: listener\n  });\n}\n\nfunction putListener() {\n  var listenerToPut = this;\n  EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);\n}\n\nfunction inputPostMount() {\n  var inst = this;\n  ReactDOMInput.postMountWrapper(inst);\n}\n\nfunction textareaPostMount() {\n  var inst = this;\n  ReactDOMTextarea.postMountWrapper(inst);\n}\n\nfunction optionPostMount() {\n  var inst = this;\n  ReactDOMOption.postMountWrapper(inst);\n}\n\nvar setContentChildForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  setContentChildForInstrumentation = function (content) {\n    var hasExistingContent = this._contentDebugID != null;\n    var debugID = this._debugID;\n    var contentDebugID = debugID + '#text';\n\n    if (content == null) {\n      if (hasExistingContent) {\n        ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);\n      }\n      this._contentDebugID = null;\n      return;\n    }\n\n    this._contentDebugID = contentDebugID;\n    var text = '' + content;\n\n    ReactInstrumentation.debugTool.onSetDisplayName(contentDebugID, '#text');\n    ReactInstrumentation.debugTool.onSetParent(contentDebugID, debugID);\n    ReactInstrumentation.debugTool.onSetText(contentDebugID, text);\n\n    if (hasExistingContent) {\n      ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);\n    } else {\n      ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content);\n      ReactInstrumentation.debugTool.onMountComponent(contentDebugID);\n      ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);\n    }\n  };\n}\n\n// There are so many media events, it makes sense to just\n// maintain a list rather than create a `trapBubbledEvent` for each\nvar mediaEvents = {\n  topAbort: 'abort',\n  topCanPlay: 'canplay',\n  topCanPlayThrough: 'canplaythrough',\n  topDurationChange: 'durationchange',\n  topEmptied: 'emptied',\n  topEncrypted: 'encrypted',\n  topEnded: 'ended',\n  topError: 'error',\n  topLoadedData: 'loadeddata',\n  topLoadedMetadata: 'loadedmetadata',\n  topLoadStart: 'loadstart',\n  topPause: 'pause',\n  topPlay: 'play',\n  topPlaying: 'playing',\n  topProgress: 'progress',\n  topRateChange: 'ratechange',\n  topSeeked: 'seeked',\n  topSeeking: 'seeking',\n  topStalled: 'stalled',\n  topSuspend: 'suspend',\n  topTimeUpdate: 'timeupdate',\n  topVolumeChange: 'volumechange',\n  topWaiting: 'waiting'\n};\n\nfunction trapBubbledEventsLocal() {\n  var inst = this;\n  // If a component renders to null or if another component fatals and causes\n  // the state of the tree to be corrupted, `node` here can be null.\n  !inst._rootNodeID ? \"development\" !== 'production' ? invariant(false, 'Must be mounted to trap events') : _prodInvariant('63') : void 0;\n  var node = getNode(inst);\n  !node ? \"development\" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : _prodInvariant('64') : void 0;\n\n  switch (inst._tag) {\n    case 'iframe':\n    case 'object':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'video':\n    case 'audio':\n\n      inst._wrapperState.listeners = [];\n      // Create listener for each media event\n      for (var event in mediaEvents) {\n        if (mediaEvents.hasOwnProperty(event)) {\n          inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));\n        }\n      }\n      break;\n    case 'source':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node)];\n      break;\n    case 'img':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];\n      break;\n    case 'form':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];\n      break;\n    case 'input':\n    case 'select':\n    case 'textarea':\n      inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topInvalid, 'invalid', node)];\n      break;\n  }\n}\n\nfunction postUpdateSelectWrapper() {\n  ReactDOMSelect.postUpdateWrapper(this);\n}\n\n// For HTML, certain tags should omit their close tag. We keep a whitelist for\n// those special-case tags.\n\nvar omittedCloseTags = {\n  'area': true,\n  'base': true,\n  'br': true,\n  'col': true,\n  'embed': true,\n  'hr': true,\n  'img': true,\n  'input': true,\n  'keygen': true,\n  'link': true,\n  'meta': true,\n  'param': true,\n  'source': true,\n  'track': true,\n  'wbr': true\n};\n\n// NOTE: menuitem's close tag should be omitted, but that causes problems.\nvar newlineEatingTags = {\n  'listing': true,\n  'pre': true,\n  'textarea': true\n};\n\n// For HTML, certain tags cannot have children. This has the same purpose as\n// `omittedCloseTags` except that `menuitem` should still have its closing tag.\n\nvar voidElementTags = _assign({\n  'menuitem': true\n}, omittedCloseTags);\n\n// We accept any tag to be rendered but since this gets injected into arbitrary\n// HTML, we want to make sure that it's a safe tag.\n// http://www.w3.org/TR/REC-xml/#NT-Name\n\nvar VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\\.\\-\\d]*$/; // Simplified subset\nvar validatedTagCache = {};\nvar hasOwnProperty = {}.hasOwnProperty;\n\nfunction validateDangerousTag(tag) {\n  if (!hasOwnProperty.call(validatedTagCache, tag)) {\n    !VALID_TAG_REGEX.test(tag) ? \"development\" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : _prodInvariant('65', tag) : void 0;\n    validatedTagCache[tag] = true;\n  }\n}\n\nfunction isCustomComponent(tagName, props) {\n  return tagName.indexOf('-') >= 0 || props.is != null;\n}\n\nvar globalIdCounter = 1;\n\n/**\n * Creates a new React class that is idempotent and capable of containing other\n * React components. It accepts event listeners and DOM properties that are\n * valid according to `DOMProperty`.\n *\n *  - Event listeners: `onClick`, `onMouseDown`, etc.\n *  - DOM properties: `className`, `name`, `title`, etc.\n *\n * The `style` property functions differently from the DOM API. It accepts an\n * object mapping of style properties to values.\n *\n * @constructor ReactDOMComponent\n * @extends ReactMultiChild\n */\nfunction ReactDOMComponent(element) {\n  var tag = element.type;\n  validateDangerousTag(tag);\n  this._currentElement = element;\n  this._tag = tag.toLowerCase();\n  this._namespaceURI = null;\n  this._renderedChildren = null;\n  this._previousStyle = null;\n  this._previousStyleCopy = null;\n  this._hostNode = null;\n  this._hostParent = null;\n  this._rootNodeID = null;\n  this._domID = null;\n  this._hostContainerInfo = null;\n  this._wrapperState = null;\n  this._topLevelWrapper = null;\n  this._flags = 0;\n  if (\"development\" !== 'production') {\n    this._ancestorInfo = null;\n    setContentChildForInstrumentation.call(this, null);\n  }\n}\n\nReactDOMComponent.displayName = 'ReactDOMComponent';\n\nReactDOMComponent.Mixin = {\n\n  /**\n   * Generates root tag markup then recurses. This method has side effects and\n   * is not idempotent.\n   *\n   * @internal\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?ReactDOMComponent} the containing DOM component instance\n   * @param {?object} info about the host container\n   * @param {object} context\n   * @return {string} The computed markup.\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    this._rootNodeID = globalIdCounter++;\n    this._domID = hostContainerInfo._idCounter++;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var props = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        this._wrapperState = {\n          listeners: null\n        };\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'button':\n        props = ReactDOMButton.getHostProps(this, props, hostParent);\n        break;\n      case 'input':\n        ReactDOMInput.mountWrapper(this, props, hostParent);\n        props = ReactDOMInput.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'option':\n        ReactDOMOption.mountWrapper(this, props, hostParent);\n        props = ReactDOMOption.getHostProps(this, props);\n        break;\n      case 'select':\n        ReactDOMSelect.mountWrapper(this, props, hostParent);\n        props = ReactDOMSelect.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.mountWrapper(this, props, hostParent);\n        props = ReactDOMTextarea.getHostProps(this, props);\n        transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);\n        break;\n    }\n\n    assertValidProps(this, props);\n\n    // We create tags in the namespace of their parent container, except HTML\n    // tags get no namespace.\n    var namespaceURI;\n    var parentTag;\n    if (hostParent != null) {\n      namespaceURI = hostParent._namespaceURI;\n      parentTag = hostParent._tag;\n    } else if (hostContainerInfo._tag) {\n      namespaceURI = hostContainerInfo._namespaceURI;\n      parentTag = hostContainerInfo._tag;\n    }\n    if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {\n      namespaceURI = DOMNamespaces.html;\n    }\n    if (namespaceURI === DOMNamespaces.html) {\n      if (this._tag === 'svg') {\n        namespaceURI = DOMNamespaces.svg;\n      } else if (this._tag === 'math') {\n        namespaceURI = DOMNamespaces.mathml;\n      }\n    }\n    this._namespaceURI = namespaceURI;\n\n    if (\"development\" !== 'production') {\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo._tag) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting(this._tag, this, parentInfo);\n      }\n      this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);\n    }\n\n    var mountImage;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var el;\n      if (namespaceURI === DOMNamespaces.html) {\n        if (this._tag === 'script') {\n          // Create the script via .innerHTML so its \"parser-inserted\" flag is\n          // set to true and it does not execute\n          var div = ownerDocument.createElement('div');\n          var type = this._currentElement.type;\n          div.innerHTML = '<' + type + '></' + type + '>';\n          el = div.removeChild(div.firstChild);\n        } else if (props.is) {\n          el = ownerDocument.createElement(this._currentElement.type, props.is);\n        } else {\n          // Separate else branch instead of using `props.is || undefined` above becuase of a Firefox bug.\n          // See discussion in https://github.com/facebook/react/pull/6896\n          // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240\n          el = ownerDocument.createElement(this._currentElement.type);\n        }\n      } else {\n        el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);\n      }\n      ReactDOMComponentTree.precacheNode(this, el);\n      this._flags |= Flags.hasCachedChildNodes;\n      if (!this._hostParent) {\n        DOMPropertyOperations.setAttributeForRoot(el);\n      }\n      this._updateDOMProperties(null, props, transaction);\n      var lazyTree = DOMLazyTree(el);\n      this._createInitialChildren(transaction, props, context, lazyTree);\n      mountImage = lazyTree;\n    } else {\n      var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);\n      var tagContent = this._createContentMarkup(transaction, props, context);\n      if (!tagContent && omittedCloseTags[this._tag]) {\n        mountImage = tagOpen + '/>';\n      } else {\n        mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';\n      }\n    }\n\n    switch (this._tag) {\n      case 'input':\n        transaction.getReactMountReady().enqueue(inputPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'textarea':\n        transaction.getReactMountReady().enqueue(textareaPostMount, this);\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'select':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'button':\n        if (props.autoFocus) {\n          transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);\n        }\n        break;\n      case 'option':\n        transaction.getReactMountReady().enqueue(optionPostMount, this);\n        break;\n    }\n\n    return mountImage;\n  },\n\n  /**\n   * Creates markup for the open tag and all attributes.\n   *\n   * This method has side effects because events get registered.\n   *\n   * Iterating over object properties is faster than iterating over arrays.\n   * @see http://jsperf.com/obj-vs-arr-iteration\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @return {string} Markup of opening tag.\n   */\n  _createOpenTagMarkupAndPutListeners: function (transaction, props) {\n    var ret = '<' + this._currentElement.type;\n\n    for (var propKey in props) {\n      if (!props.hasOwnProperty(propKey)) {\n        continue;\n      }\n      var propValue = props[propKey];\n      if (propValue == null) {\n        continue;\n      }\n      if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (propValue) {\n          enqueuePutListener(this, propKey, propValue, transaction);\n        }\n      } else {\n        if (propKey === STYLE) {\n          if (propValue) {\n            if (\"development\" !== 'production') {\n              // See `_updateDOMProperties`. style block\n              this._previousStyle = propValue;\n            }\n            propValue = this._previousStyleCopy = _assign({}, props.style);\n          }\n          propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);\n        }\n        var markup = null;\n        if (this._tag != null && isCustomComponent(this._tag, props)) {\n          if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n            markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);\n          }\n        } else {\n          markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);\n        }\n        if (markup) {\n          ret += ' ' + markup;\n        }\n      }\n    }\n\n    // For static pages, no need to put React ID and checksum. Saves lots of\n    // bytes.\n    if (transaction.renderToStaticMarkup) {\n      return ret;\n    }\n\n    if (!this._hostParent) {\n      ret += ' ' + DOMPropertyOperations.createMarkupForRoot();\n    }\n    ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);\n    return ret;\n  },\n\n  /**\n   * Creates markup for the content between the tags.\n   *\n   * @private\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} props\n   * @param {object} context\n   * @return {string} Content markup.\n   */\n  _createContentMarkup: function (transaction, props, context) {\n    var ret = '';\n\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        ret = innerHTML.__html;\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        ret = escapeTextContentForBrowser(contentToUse);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        ret = mountImages.join('');\n      }\n    }\n    if (newlineEatingTags[this._tag] && ret.charAt(0) === '\\n') {\n      // text/html ignores the first character in these tags if it's a newline\n      // Prefer to break application/xml over text/html (for now) by adding\n      // a newline specifically to get eaten by the parser. (Alternately for\n      // textareas, replacing \"^\\n\" with \"\\r\\n\" doesn't get eaten, and the first\n      // \\r is normalized out by HTMLTextAreaElement#value.)\n      // See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>\n      // See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>\n      // See: <http://www.w3.org/TR/html5/syntax.html#newlines>\n      // See: Parsing of \"textarea\" \"listing\" and \"pre\" elements\n      //  from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>\n      return '\\n' + ret;\n    } else {\n      return ret;\n    }\n  },\n\n  _createInitialChildren: function (transaction, props, context, lazyTree) {\n    // Intentional use of != to avoid catching zero/false.\n    var innerHTML = props.dangerouslySetInnerHTML;\n    if (innerHTML != null) {\n      if (innerHTML.__html != null) {\n        DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);\n      }\n    } else {\n      var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;\n      var childrenToUse = contentToUse != null ? null : props.children;\n      if (contentToUse != null) {\n        // TODO: Validate that text is allowed as a child of this node\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, contentToUse);\n        }\n        DOMLazyTree.queueText(lazyTree, contentToUse);\n      } else if (childrenToUse != null) {\n        var mountImages = this.mountChildren(childrenToUse, transaction, context);\n        for (var i = 0; i < mountImages.length; i++) {\n          DOMLazyTree.queueChild(lazyTree, mountImages[i]);\n        }\n      }\n    }\n  },\n\n  /**\n   * Receives a next element and updates the component.\n   *\n   * @internal\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {object} context\n   */\n  receiveComponent: function (nextElement, transaction, context) {\n    var prevElement = this._currentElement;\n    this._currentElement = nextElement;\n    this.updateComponent(transaction, prevElement, nextElement, context);\n  },\n\n  /**\n   * Updates a DOM component after it has already been allocated and\n   * attached to the DOM. Reconciles the root DOM node, then recurses.\n   *\n   * @param {ReactReconcileTransaction} transaction\n   * @param {ReactElement} prevElement\n   * @param {ReactElement} nextElement\n   * @internal\n   * @overridable\n   */\n  updateComponent: function (transaction, prevElement, nextElement, context) {\n    var lastProps = prevElement.props;\n    var nextProps = this._currentElement.props;\n\n    switch (this._tag) {\n      case 'button':\n        lastProps = ReactDOMButton.getHostProps(this, lastProps);\n        nextProps = ReactDOMButton.getHostProps(this, nextProps);\n        break;\n      case 'input':\n        ReactDOMInput.updateWrapper(this);\n        lastProps = ReactDOMInput.getHostProps(this, lastProps);\n        nextProps = ReactDOMInput.getHostProps(this, nextProps);\n        break;\n      case 'option':\n        lastProps = ReactDOMOption.getHostProps(this, lastProps);\n        nextProps = ReactDOMOption.getHostProps(this, nextProps);\n        break;\n      case 'select':\n        lastProps = ReactDOMSelect.getHostProps(this, lastProps);\n        nextProps = ReactDOMSelect.getHostProps(this, nextProps);\n        break;\n      case 'textarea':\n        ReactDOMTextarea.updateWrapper(this);\n        lastProps = ReactDOMTextarea.getHostProps(this, lastProps);\n        nextProps = ReactDOMTextarea.getHostProps(this, nextProps);\n        break;\n    }\n\n    assertValidProps(this, nextProps);\n    this._updateDOMProperties(lastProps, nextProps, transaction);\n    this._updateDOMChildren(lastProps, nextProps, transaction, context);\n\n    if (this._tag === 'select') {\n      // <select> value update needs to occur after <option> children\n      // reconciliation\n      transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);\n    }\n  },\n\n  /**\n   * Reconciles the properties by detecting differences in property values and\n   * updating the DOM as necessary. This function is probably the single most\n   * critical path for performance optimization.\n   *\n   * TODO: Benchmark whether checking for changed values in memory actually\n   *       improves performance (especially statically positioned elements).\n   * TODO: Benchmark the effects of putting this at the top since 99% of props\n   *       do not change for a given reconciliation.\n   * TODO: Benchmark areas that can be improved with caching.\n   *\n   * @private\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {?DOMElement} node\n   */\n  _updateDOMProperties: function (lastProps, nextProps, transaction) {\n    var propKey;\n    var styleName;\n    var styleUpdates;\n    for (propKey in lastProps) {\n      if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        var lastStyle = this._previousStyleCopy;\n        for (styleName in lastStyle) {\n          if (lastStyle.hasOwnProperty(styleName)) {\n            styleUpdates = styleUpdates || {};\n            styleUpdates[styleName] = '';\n          }\n        }\n        this._previousStyleCopy = null;\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (lastProps[propKey]) {\n          // Only call deleteListener if there was a listener previously or\n          // else willDeleteListener gets called when there wasn't actually a\n          // listener (e.g., onClick={null})\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, lastProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);\n      }\n    }\n    for (propKey in nextProps) {\n      var nextProp = nextProps[propKey];\n      var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;\n      if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {\n        continue;\n      }\n      if (propKey === STYLE) {\n        if (nextProp) {\n          if (\"development\" !== 'production') {\n            checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);\n            this._previousStyle = nextProp;\n          }\n          nextProp = this._previousStyleCopy = _assign({}, nextProp);\n        } else {\n          this._previousStyleCopy = null;\n        }\n        if (lastProp) {\n          // Unset styles on `lastProp` but not on `nextProp`.\n          for (styleName in lastProp) {\n            if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = '';\n            }\n          }\n          // Update styles that changed since `lastProp`.\n          for (styleName in nextProp) {\n            if (nextProp.hasOwnProperty(styleName) && lastProp[styleName] !== nextProp[styleName]) {\n              styleUpdates = styleUpdates || {};\n              styleUpdates[styleName] = nextProp[styleName];\n            }\n          }\n        } else {\n          // Relies on `updateStylesByID` not mutating `styleUpdates`.\n          styleUpdates = nextProp;\n        }\n      } else if (registrationNameModules.hasOwnProperty(propKey)) {\n        if (nextProp) {\n          enqueuePutListener(this, propKey, nextProp, transaction);\n        } else if (lastProp) {\n          deleteListener(this, propKey);\n        }\n      } else if (isCustomComponent(this._tag, nextProps)) {\n        if (!RESERVED_PROPS.hasOwnProperty(propKey)) {\n          DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);\n        }\n      } else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {\n        var node = getNode(this);\n        // If we're updating to null or undefined, we should remove the property\n        // from the DOM node instead of inadvertently setting to a string. This\n        // brings us in line with the same behavior we have on initial render.\n        if (nextProp != null) {\n          DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);\n        } else {\n          DOMPropertyOperations.deleteValueForProperty(node, propKey);\n        }\n      }\n    }\n    if (styleUpdates) {\n      CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);\n    }\n  },\n\n  /**\n   * Reconciles the children with the various properties that affect the\n   * children content.\n   *\n   * @param {object} lastProps\n   * @param {object} nextProps\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   */\n  _updateDOMChildren: function (lastProps, nextProps, transaction, context) {\n    var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;\n    var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;\n\n    var lastHtml = lastProps.dangerouslySetInnerHTML && lastProps.dangerouslySetInnerHTML.__html;\n    var nextHtml = nextProps.dangerouslySetInnerHTML && nextProps.dangerouslySetInnerHTML.__html;\n\n    // Note the use of `!=` which checks for null or undefined.\n    var lastChildren = lastContent != null ? null : lastProps.children;\n    var nextChildren = nextContent != null ? null : nextProps.children;\n\n    // If we're switching from children to content/html or vice versa, remove\n    // the old content\n    var lastHasContentOrHtml = lastContent != null || lastHtml != null;\n    var nextHasContentOrHtml = nextContent != null || nextHtml != null;\n    if (lastChildren != null && nextChildren == null) {\n      this.updateChildren(null, transaction, context);\n    } else if (lastHasContentOrHtml && !nextHasContentOrHtml) {\n      this.updateTextContent('');\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    }\n\n    if (nextContent != null) {\n      if (lastContent !== nextContent) {\n        this.updateTextContent('' + nextContent);\n        if (\"development\" !== 'production') {\n          setContentChildForInstrumentation.call(this, nextContent);\n        }\n      }\n    } else if (nextHtml != null) {\n      if (lastHtml !== nextHtml) {\n        this.updateMarkup('' + nextHtml);\n      }\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);\n      }\n    } else if (nextChildren != null) {\n      if (\"development\" !== 'production') {\n        setContentChildForInstrumentation.call(this, null);\n      }\n\n      this.updateChildren(nextChildren, transaction, context);\n    }\n  },\n\n  getHostNode: function () {\n    return getNode(this);\n  },\n\n  /**\n   * Destroys all event registrations for this instance. Does not remove from\n   * the DOM. That must be done by the parent.\n   *\n   * @internal\n   */\n  unmountComponent: function (safely) {\n    switch (this._tag) {\n      case 'audio':\n      case 'form':\n      case 'iframe':\n      case 'img':\n      case 'link':\n      case 'object':\n      case 'source':\n      case 'video':\n        var listeners = this._wrapperState.listeners;\n        if (listeners) {\n          for (var i = 0; i < listeners.length; i++) {\n            listeners[i].remove();\n          }\n        }\n        break;\n      case 'html':\n      case 'head':\n      case 'body':\n        /**\n         * Components like <html> <head> and <body> can't be removed or added\n         * easily in a cross-browser way, however it's valuable to be able to\n         * take advantage of React's reconciliation for styling and <title>\n         * management. So we just document it and throw in dangerous cases.\n         */\n        !false ? \"development\" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.', this._tag) : _prodInvariant('66', this._tag) : void 0;\n        break;\n    }\n\n    this.unmountChildren(safely);\n    ReactDOMComponentTree.uncacheNode(this);\n    EventPluginHub.deleteAllListeners(this);\n    ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);\n    this._rootNodeID = null;\n    this._domID = null;\n    this._wrapperState = null;\n\n    if (\"development\" !== 'production') {\n      setContentChildForInstrumentation.call(this, null);\n    }\n  },\n\n  getPublicInstance: function () {\n    return getNode(this);\n  }\n\n};\n\n_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);\n\nmodule.exports = ReactDOMComponent;\n},{\"1\":1,\"10\":10,\"11\":11,\"121\":121,\"135\":135,\"139\":139,\"145\":145,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"17\":17,\"170\":170,\"171\":171,\"172\":172,\"18\":18,\"27\":27,\"32\":32,\"38\":38,\"4\":4,\"40\":40,\"41\":41,\"48\":48,\"51\":51,\"52\":52,\"56\":56,\"74\":74,\"78\":78,\"8\":8,\"9\":9,\"91\":91}],40:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentFlags\n */\n\n'use strict';\n\nvar ReactDOMComponentFlags = {\n  hasCachedChildNodes: 1 << 0\n};\n\nmodule.exports = ReactDOMComponentFlags;\n},{}],41:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMComponentTree\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMProperty = _dereq_(10);\nvar ReactDOMComponentFlags = _dereq_(40);\n\nvar invariant = _dereq_(161);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar Flags = ReactDOMComponentFlags;\n\nvar internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);\n\n/**\n * Drill down (through composites and empty components) until we get a host or\n * host text component.\n *\n * This is pretty polymorphic but unavoidable with the current structure we have\n * for `_renderedChildren`.\n */\nfunction getRenderedHostOrTextFromComponent(component) {\n  var rendered;\n  while (rendered = component._renderedComponent) {\n    component = rendered;\n  }\n  return component;\n}\n\n/**\n * Populate `_hostNode` on the rendered host/text component with the given\n * DOM node. The passed `inst` can be a composite.\n */\nfunction precacheNode(inst, node) {\n  var hostInst = getRenderedHostOrTextFromComponent(inst);\n  hostInst._hostNode = node;\n  node[internalInstanceKey] = hostInst;\n}\n\nfunction uncacheNode(inst) {\n  var node = inst._hostNode;\n  if (node) {\n    delete node[internalInstanceKey];\n    inst._hostNode = null;\n  }\n}\n\n/**\n * Populate `_hostNode` on each child of `inst`, assuming that the children\n * match up with the DOM (element) children of `node`.\n *\n * We cache entire levels at once to avoid an n^2 problem where we access the\n * children of a node sequentially and have to walk from the start to our target\n * node every time.\n *\n * Since we update `_renderedChildren` and the actual DOM at (slightly)\n * different times, we could race here and see a newer `_renderedChildren` than\n * the DOM nodes we see. To avoid this, ReactMultiChild calls\n * `prepareToManageChildren` before we change `_renderedChildren`, at which\n * time the container's child nodes are always cached (until it unmounts).\n */\nfunction precacheChildNodes(inst, node) {\n  if (inst._flags & Flags.hasCachedChildNodes) {\n    return;\n  }\n  var children = inst._renderedChildren;\n  var childNode = node.firstChild;\n  outer: for (var name in children) {\n    if (!children.hasOwnProperty(name)) {\n      continue;\n    }\n    var childInst = children[name];\n    var childID = getRenderedHostOrTextFromComponent(childInst)._domID;\n    if (childID == null) {\n      // We're currently unmounting this child in ReactMultiChild; skip it.\n      continue;\n    }\n    // We assume the child nodes are in the same order as the child instances.\n    for (; childNode !== null; childNode = childNode.nextSibling) {\n      if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') {\n        precacheNode(childInst, childNode);\n        continue outer;\n      }\n    }\n    // We reached the end of the DOM children without finding an ID match.\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : _prodInvariant('32', childID) : void 0;\n  }\n  inst._flags |= Flags.hasCachedChildNodes;\n}\n\n/**\n * Given a DOM node, return the closest ReactDOMComponent or\n * ReactDOMTextComponent instance ancestor.\n */\nfunction getClosestInstanceFromNode(node) {\n  if (node[internalInstanceKey]) {\n    return node[internalInstanceKey];\n  }\n\n  // Walk up the tree until we find an ancestor whose instance we have cached.\n  var parents = [];\n  while (!node[internalInstanceKey]) {\n    parents.push(node);\n    if (node.parentNode) {\n      node = node.parentNode;\n    } else {\n      // Top of the tree. This node must not be part of a React tree (or is\n      // unmounted, potentially).\n      return null;\n    }\n  }\n\n  var closest;\n  var inst;\n  for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {\n    closest = inst;\n    if (parents.length) {\n      precacheChildNodes(inst, node);\n    }\n  }\n\n  return closest;\n}\n\n/**\n * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent\n * instance, or null if the node was not rendered by this React.\n */\nfunction getInstanceFromNode(node) {\n  var inst = getClosestInstanceFromNode(node);\n  if (inst != null && inst._hostNode === node) {\n    return inst;\n  } else {\n    return null;\n  }\n}\n\n/**\n * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding\n * DOM node.\n */\nfunction getNodeFromInstance(inst) {\n  // Without this first invariant, passing a non-DOM-component triggers the next\n  // invariant for a missing parent, which is super confusing.\n  !(inst._hostNode !== undefined) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  if (inst._hostNode) {\n    return inst._hostNode;\n  }\n\n  // Walk up the tree until we find an ancestor whose DOM node we have cached.\n  var parents = [];\n  while (!inst._hostNode) {\n    parents.push(inst);\n    !inst._hostParent ? \"development\" !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') : _prodInvariant('34') : void 0;\n    inst = inst._hostParent;\n  }\n\n  // Now parents contains each ancestor that does *not* have a cached native\n  // node, and `inst` is the deepest ancestor that does.\n  for (; parents.length; inst = parents.pop()) {\n    precacheChildNodes(inst, inst._hostNode);\n  }\n\n  return inst._hostNode;\n}\n\nvar ReactDOMComponentTree = {\n  getClosestInstanceFromNode: getClosestInstanceFromNode,\n  getInstanceFromNode: getInstanceFromNode,\n  getNodeFromInstance: getNodeFromInstance,\n  precacheChildNodes: precacheChildNodes,\n  precacheNode: precacheNode,\n  uncacheNode: uncacheNode\n};\n\nmodule.exports = ReactDOMComponentTree;\n},{\"10\":10,\"139\":139,\"161\":161,\"40\":40}],42:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMContainerInfo\n */\n\n'use strict';\n\nvar validateDOMNesting = _dereq_(145);\n\nvar DOC_NODE_TYPE = 9;\n\nfunction ReactDOMContainerInfo(topLevelWrapper, node) {\n  var info = {\n    _topLevelWrapper: topLevelWrapper,\n    _idCounter: 1,\n    _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null,\n    _node: node,\n    _tag: node ? node.nodeName.toLowerCase() : null,\n    _namespaceURI: node ? node.namespaceURI : null\n  };\n  if (\"development\" !== 'production') {\n    info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null;\n  }\n  return info;\n}\n\nmodule.exports = ReactDOMContainerInfo;\n},{\"145\":145}],43:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMDebugTool\n */\n\n'use strict';\n\nvar ReactDOMNullInputValuePropDevtool = _dereq_(50);\nvar ReactDOMUnknownPropertyDevtool = _dereq_(58);\nvar ReactDebugTool = _dereq_(59);\n\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar ReactDOMDebugTool = {\n  addDevtool: function (devtool) {\n    ReactDebugTool.addDevtool(devtool);\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    ReactDebugTool.removeDevtool(devtool);\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  onCreateMarkupForProperty: function (name, value) {\n    emitEvent('onCreateMarkupForProperty', name, value);\n  },\n  onSetValueForProperty: function (node, name, value) {\n    emitEvent('onSetValueForProperty', node, name, value);\n  },\n  onDeleteValueForProperty: function (node, name) {\n    emitEvent('onDeleteValueForProperty', node, name);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDOMDebugTool.addDevtool(ReactDOMUnknownPropertyDevtool);\nReactDOMDebugTool.addDevtool(ReactDOMNullInputValuePropDevtool);\n\nmodule.exports = ReactDOMDebugTool;\n},{\"171\":171,\"50\":50,\"58\":58,\"59\":59}],44:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMEmptyComponent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\n\nvar ReactDOMEmptyComponent = function (instantiate) {\n  // ReactCompositeComponent uses this:\n  this._currentElement = null;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n  this._hostContainerInfo = null;\n  this._domID = null;\n};\n_assign(ReactDOMEmptyComponent.prototype, {\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    var domID = hostContainerInfo._idCounter++;\n    this._domID = domID;\n    this._hostParent = hostParent;\n    this._hostContainerInfo = hostContainerInfo;\n\n    var nodeValue = ' react-empty: ' + this._domID + ' ';\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var node = ownerDocument.createComment(nodeValue);\n      ReactDOMComponentTree.precacheNode(this, node);\n      return DOMLazyTree(node);\n    } else {\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd insert a comment node, but since this is a situation\n        // where React won't take over (static pages), we can simply return\n        // nothing.\n        return '';\n      }\n      return '<!--' + nodeValue + '-->';\n    }\n  },\n  receiveComponent: function () {},\n  getHostNode: function () {\n    return ReactDOMComponentTree.getNodeFromInstance(this);\n  },\n  unmountComponent: function () {\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n});\n\nmodule.exports = ReactDOMEmptyComponent;\n},{\"172\":172,\"41\":41,\"8\":8}],45:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFactories\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\n\nvar mapObject = _dereq_(166);\n\n/**\n * Create a factory that creates HTML tag elements.\n *\n * @param {string} tag Tag name (e.g. `div`).\n * @private\n */\nfunction createDOMFactory(tag) {\n  if (\"development\" !== 'production') {\n    var ReactElementValidator = _dereq_(63);\n    return ReactElementValidator.createFactory(tag);\n  }\n  return ReactElement.createFactory(tag);\n}\n\n/**\n * Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.\n * This is also accessible via `React.DOM`.\n *\n * @public\n */\nvar ReactDOMFactories = mapObject({\n  a: 'a',\n  abbr: 'abbr',\n  address: 'address',\n  area: 'area',\n  article: 'article',\n  aside: 'aside',\n  audio: 'audio',\n  b: 'b',\n  base: 'base',\n  bdi: 'bdi',\n  bdo: 'bdo',\n  big: 'big',\n  blockquote: 'blockquote',\n  body: 'body',\n  br: 'br',\n  button: 'button',\n  canvas: 'canvas',\n  caption: 'caption',\n  cite: 'cite',\n  code: 'code',\n  col: 'col',\n  colgroup: 'colgroup',\n  data: 'data',\n  datalist: 'datalist',\n  dd: 'dd',\n  del: 'del',\n  details: 'details',\n  dfn: 'dfn',\n  dialog: 'dialog',\n  div: 'div',\n  dl: 'dl',\n  dt: 'dt',\n  em: 'em',\n  embed: 'embed',\n  fieldset: 'fieldset',\n  figcaption: 'figcaption',\n  figure: 'figure',\n  footer: 'footer',\n  form: 'form',\n  h1: 'h1',\n  h2: 'h2',\n  h3: 'h3',\n  h4: 'h4',\n  h5: 'h5',\n  h6: 'h6',\n  head: 'head',\n  header: 'header',\n  hgroup: 'hgroup',\n  hr: 'hr',\n  html: 'html',\n  i: 'i',\n  iframe: 'iframe',\n  img: 'img',\n  input: 'input',\n  ins: 'ins',\n  kbd: 'kbd',\n  keygen: 'keygen',\n  label: 'label',\n  legend: 'legend',\n  li: 'li',\n  link: 'link',\n  main: 'main',\n  map: 'map',\n  mark: 'mark',\n  menu: 'menu',\n  menuitem: 'menuitem',\n  meta: 'meta',\n  meter: 'meter',\n  nav: 'nav',\n  noscript: 'noscript',\n  object: 'object',\n  ol: 'ol',\n  optgroup: 'optgroup',\n  option: 'option',\n  output: 'output',\n  p: 'p',\n  param: 'param',\n  picture: 'picture',\n  pre: 'pre',\n  progress: 'progress',\n  q: 'q',\n  rp: 'rp',\n  rt: 'rt',\n  ruby: 'ruby',\n  s: 's',\n  samp: 'samp',\n  script: 'script',\n  section: 'section',\n  select: 'select',\n  small: 'small',\n  source: 'source',\n  span: 'span',\n  strong: 'strong',\n  style: 'style',\n  sub: 'sub',\n  summary: 'summary',\n  sup: 'sup',\n  table: 'table',\n  tbody: 'tbody',\n  td: 'td',\n  textarea: 'textarea',\n  tfoot: 'tfoot',\n  th: 'th',\n  thead: 'thead',\n  time: 'time',\n  title: 'title',\n  tr: 'tr',\n  track: 'track',\n  u: 'u',\n  ul: 'ul',\n  'var': 'var',\n  video: 'video',\n  wbr: 'wbr',\n\n  // SVG\n  circle: 'circle',\n  clipPath: 'clipPath',\n  defs: 'defs',\n  ellipse: 'ellipse',\n  g: 'g',\n  image: 'image',\n  line: 'line',\n  linearGradient: 'linearGradient',\n  mask: 'mask',\n  path: 'path',\n  pattern: 'pattern',\n  polygon: 'polygon',\n  polyline: 'polyline',\n  radialGradient: 'radialGradient',\n  rect: 'rect',\n  stop: 'stop',\n  svg: 'svg',\n  text: 'text',\n  tspan: 'tspan'\n\n}, createDOMFactory);\n\nmodule.exports = ReactDOMFactories;\n},{\"166\":166,\"62\":62,\"63\":63}],46:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMFeatureFlags\n */\n\n'use strict';\n\nvar ReactDOMFeatureFlags = {\n  useCreateElement: true\n};\n\nmodule.exports = ReactDOMFeatureFlags;\n},{}],47:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMIDOperations\n */\n\n'use strict';\n\nvar DOMChildrenOperations = _dereq_(7);\nvar ReactDOMComponentTree = _dereq_(41);\n\n/**\n * Operations used to process updates to DOM nodes.\n */\nvar ReactDOMIDOperations = {\n\n  /**\n   * Updates a component's children by processing a series of updates.\n   *\n   * @param {array<object>} updates List of update configurations.\n   * @internal\n   */\n  dangerouslyProcessChildrenUpdates: function (parentInst, updates) {\n    var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);\n    DOMChildrenOperations.processUpdates(node, updates);\n  }\n};\n\nmodule.exports = ReactDOMIDOperations;\n},{\"41\":41,\"7\":7}],48:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInput\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar DOMPropertyOperations = _dereq_(11);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnCheckedLink = false;\nvar didWarnValueDefaultValue = false;\nvar didWarnCheckedDefaultChecked = false;\nvar didWarnControlledToUncontrolled = false;\nvar didWarnUncontrolledToControlled = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMInput.updateWrapper(this);\n  }\n}\n\nfunction isControlled(props) {\n  var usesChecked = props.type === 'checkbox' || props.type === 'radio';\n  return usesChecked ? props.checked !== undefined : props.value !== undefined;\n}\n\n/**\n * Implements an <input> host component that allows setting these optional\n * props: `checked`, `value`, `defaultChecked`, and `defaultValue`.\n *\n * If `checked` or `value` are not supplied (or null/undefined), user actions\n * that affect the checked state or value will trigger updates to the element.\n *\n * If they are supplied (and not null/undefined), the rendered element will not\n * trigger updates to the element. Instead, the props must change in order for\n * the rendered element to be updated.\n *\n * The rendered element will be initialized as unchecked (or `defaultChecked`)\n * with an empty value (or `defaultValue`).\n *\n * @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html\n */\nvar ReactDOMInput = {\n  getHostProps: function (inst, props) {\n    var value = LinkedValueUtils.getValue(props);\n    var checked = LinkedValueUtils.getChecked(props);\n\n    var hostProps = _assign({\n      // Make sure we set .type before any other properties (setting .value\n      // before .type means .value is lost in IE11 and below)\n      type: undefined\n    }, DisabledInputUtils.getHostProps(inst, props), {\n      defaultChecked: undefined,\n      defaultValue: undefined,\n      value: value != null ? value : inst._wrapperState.initialValue,\n      checked: checked != null ? checked : inst._wrapperState.initialChecked,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);\n\n      var owner = inst._currentElement._owner;\n\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.checkedLink !== undefined && !didWarnCheckedLink) {\n        \"development\" !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnCheckedLink = true;\n      }\n      if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnCheckedDefaultChecked = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n        \"development\" !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnValueDefaultValue = true;\n      }\n    }\n\n    var defaultValue = props.defaultValue;\n    inst._wrapperState = {\n      initialChecked: props.checked != null ? props.checked : props.defaultChecked,\n      initialValue: props.value != null ? props.value : defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n\n    if (\"development\" !== 'production') {\n      inst._wrapperState.controlled = isControlled(props);\n    }\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    if (\"development\" !== 'production') {\n      var controlled = isControlled(props);\n      var owner = inst._currentElement._owner;\n\n      if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnUncontrolledToControlled = true;\n      }\n      if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {\n        \"development\" !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;\n        didWarnControlledToUncontrolled = true;\n      }\n    }\n\n    // TODO: Shouldn't this be getChecked(props)?\n    var checked = props.checked;\n    if (checked != null) {\n      DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);\n    }\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n    } else {\n      if (props.value == null && props.defaultValue != null) {\n        node.defaultValue = '' + props.defaultValue;\n      }\n      if (props.checked == null && props.defaultChecked != null) {\n        node.defaultChecked = !!props.defaultChecked;\n      }\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Detach value from defaultValue. We won't do anything if we're working on\n    // submit or reset inputs as those values & defaultValues are linked. They\n    // are not resetable nodes so this operation doesn't matter and actually\n    // removes browser-default values (eg \"Submit Query\") when no value is\n    // provided.\n    if (props.type !== 'submit' && props.type !== 'reset') {\n      node.value = node.value;\n    }\n\n    // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug\n    // this is needed to work around a chrome bug where setting defaultChecked\n    // will sometimes influence the value of checked (even after detachment).\n    // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416\n    // We need to temporarily unset name to avoid disrupting radio button groups.\n    var name = node.name;\n    if (name !== '') {\n      node.name = '';\n    }\n    node.defaultChecked = !node.defaultChecked;\n    node.defaultChecked = !node.defaultChecked;\n    if (name !== '') {\n      node.name = name;\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  // Here we use asap to wait until all updates have propagated, which\n  // is important when using controlled components within layers:\n  // https://github.com/facebook/react/issues/1698\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n\n  var name = props.name;\n  if (props.type === 'radio' && name != null) {\n    var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);\n    var queryRoot = rootNode;\n\n    while (queryRoot.parentNode) {\n      queryRoot = queryRoot.parentNode;\n    }\n\n    // If `rootNode.form` was non-null, then we could try `form.elements`,\n    // but that sometimes behaves strangely in IE8. We could also try using\n    // `form.getElementsByName`, but that will only return direct children\n    // and won't include inputs that use the HTML5 `form=` attribute. Since\n    // the input might not even be in a form, let's just use the global\n    // `querySelectorAll` to ensure we don't miss anything.\n    var group = queryRoot.querySelectorAll('input[name=' + JSON.stringify('' + name) + '][type=\"radio\"]');\n\n    for (var i = 0; i < group.length; i++) {\n      var otherNode = group[i];\n      if (otherNode === rootNode || otherNode.form !== rootNode.form) {\n        continue;\n      }\n      // This will throw if radio buttons rendered by different copies of React\n      // and the same name are rendered into the same form (same as #1939).\n      // That's probably okay; we don't support it just as we don't support\n      // mixing React radio buttons with non-React ones.\n      var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);\n      !otherInstance ? \"development\" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;\n      // If this is a controlled radio button group, forcing the input that\n      // was previously checked to update will cause it to be come re-checked\n      // as appropriate.\n      ReactUpdates.asap(forceUpdateIfMounted, otherInstance);\n    }\n  }\n\n  return returnValue;\n}\n\nmodule.exports = ReactDOMInput;\n},{\"11\":11,\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],49:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDOMDebugTool = _dereq_(43);\n  debugTool = ReactDOMDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"43\":43}],50:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMNullInputValuePropDevtool\n */\n\n'use strict';\n\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueNull = false;\n\nfunction handleElement(debugID, element) {\n  if (element == null) {\n    return;\n  }\n  if (element.type !== 'input' && element.type !== 'textarea' && element.type !== 'select') {\n    return;\n  }\n  if (element.props != null && element.props.value === null && !didWarnValueNull) {\n    \"development\" !== 'production' ? warning(false, '`value` prop on `%s` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n\n    didWarnValueNull = true;\n  }\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"171\":171,\"34\":34}],51:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMOption\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactChildren = _dereq_(29);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMSelect = _dereq_(52);\n\nvar warning = _dereq_(171);\nvar didWarnInvalidOptionChildren = false;\n\nfunction flattenChildren(children) {\n  var content = '';\n\n  // Flatten children and warn if they aren't strings or numbers;\n  // invalid types are ignored.\n  ReactChildren.forEach(children, function (child) {\n    if (child == null) {\n      return;\n    }\n    if (typeof child === 'string' || typeof child === 'number') {\n      content += child;\n    } else if (!didWarnInvalidOptionChildren) {\n      didWarnInvalidOptionChildren = true;\n      \"development\" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;\n    }\n  });\n\n  return content;\n}\n\n/**\n * Implements an <option> host component that warns when `selected` is set.\n */\nvar ReactDOMOption = {\n  mountWrapper: function (inst, props, hostParent) {\n    // TODO (yungsters): Remove support for `selected` in <option>.\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;\n    }\n\n    // Look up whether this option is 'selected'\n    var selectValue = null;\n    if (hostParent != null) {\n      var selectParent = hostParent;\n\n      if (selectParent._tag === 'optgroup') {\n        selectParent = selectParent._hostParent;\n      }\n\n      if (selectParent != null && selectParent._tag === 'select') {\n        selectValue = ReactDOMSelect.getSelectValueContext(selectParent);\n      }\n    }\n\n    // If the value is null (e.g., no specified value or after initial mount)\n    // or missing (e.g., for <datalist>), we don't change props.selected\n    var selected = null;\n    if (selectValue != null) {\n      var value;\n      if (props.value != null) {\n        value = props.value + '';\n      } else {\n        value = flattenChildren(props.children);\n      }\n      selected = false;\n      if (Array.isArray(selectValue)) {\n        // multiple\n        for (var i = 0; i < selectValue.length; i++) {\n          if ('' + selectValue[i] === value) {\n            selected = true;\n            break;\n          }\n        }\n      } else {\n        selected = '' + selectValue === value;\n      }\n    }\n\n    inst._wrapperState = { selected: selected };\n  },\n\n  postMountWrapper: function (inst) {\n    // value=\"\" should make a value attribute (#6219)\n    var props = inst._currentElement.props;\n    if (props.value != null) {\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      node.setAttribute('value', props.value);\n    }\n  },\n\n  getHostProps: function (inst, props) {\n    var hostProps = _assign({ selected: undefined, children: undefined }, props);\n\n    // Read state only from initial mount because <select> updates value\n    // manually; we need the initial state only for server rendering\n    if (inst._wrapperState.selected != null) {\n      hostProps.selected = inst._wrapperState.selected;\n    }\n\n    var content = flattenChildren(props.children);\n\n    if (content) {\n      hostProps.children = content;\n    }\n\n    return hostProps;\n  }\n\n};\n\nmodule.exports = ReactDOMOption;\n},{\"171\":171,\"172\":172,\"29\":29,\"41\":41,\"52\":52}],52:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelect\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValueDefaultValue = false;\n\nfunction updateOptionsIfPendingUpdateAndMounted() {\n  if (this._rootNodeID && this._wrapperState.pendingUpdate) {\n    this._wrapperState.pendingUpdate = false;\n\n    var props = this._currentElement.props;\n    var value = LinkedValueUtils.getValue(props);\n\n    if (value != null) {\n      updateOptions(this, Boolean(props.multiple), value);\n    }\n  }\n}\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nvar valuePropNames = ['value', 'defaultValue'];\n\n/**\n * Validation function for `value` and `defaultValue`.\n * @private\n */\nfunction checkSelectPropTypes(inst, props) {\n  var owner = inst._currentElement._owner;\n  LinkedValueUtils.checkPropTypes('select', props, owner);\n\n  if (props.valueLink !== undefined && !didWarnValueLink) {\n    \"development\" !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;\n    didWarnValueLink = true;\n  }\n\n  for (var i = 0; i < valuePropNames.length; i++) {\n    var propName = valuePropNames[i];\n    if (props[propName] == null) {\n      continue;\n    }\n    if (props.multiple) {\n      \"development\" !== 'production' ? warning(Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    } else {\n      \"development\" !== 'production' ? warning(!Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;\n    }\n  }\n}\n\n/**\n * @param {ReactDOMComponent} inst\n * @param {boolean} multiple\n * @param {*} propValue A stringable (with `multiple`, a list of stringables).\n * @private\n */\nfunction updateOptions(inst, multiple, propValue) {\n  var selectedValue, i;\n  var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;\n\n  if (multiple) {\n    selectedValue = {};\n    for (i = 0; i < propValue.length; i++) {\n      selectedValue['' + propValue[i]] = true;\n    }\n    for (i = 0; i < options.length; i++) {\n      var selected = selectedValue.hasOwnProperty(options[i].value);\n      if (options[i].selected !== selected) {\n        options[i].selected = selected;\n      }\n    }\n  } else {\n    // Do not set `select.value` as exact behavior isn't consistent across all\n    // browsers for all cases.\n    selectedValue = '' + propValue;\n    for (i = 0; i < options.length; i++) {\n      if (options[i].value === selectedValue) {\n        options[i].selected = true;\n        return;\n      }\n    }\n    if (options.length) {\n      options[0].selected = true;\n    }\n  }\n}\n\n/**\n * Implements a <select> host component that allows optionally setting the\n * props `value` and `defaultValue`. If `multiple` is false, the prop must be a\n * stringable. If `multiple` is true, the prop must be an array of stringables.\n *\n * If `value` is not supplied (or null/undefined), user actions that change the\n * selected option will trigger updates to the rendered options.\n *\n * If it is supplied (and not null/undefined), the rendered options will not\n * update in response to user actions. Instead, the `value` prop must change in\n * order for the rendered options to update.\n *\n * If `defaultValue` is provided, any options with the supplied values will be\n * selected.\n */\nvar ReactDOMSelect = {\n  getHostProps: function (inst, props) {\n    return _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      onChange: inst._wrapperState.onChange,\n      value: undefined\n    });\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      checkSelectPropTypes(inst, props);\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    inst._wrapperState = {\n      pendingUpdate: false,\n      initialValue: value != null ? value : props.defaultValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst),\n      wasMultiple: Boolean(props.multiple)\n    };\n\n    if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {\n      \"development\" !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n      didWarnValueDefaultValue = true;\n    }\n  },\n\n  getSelectValueContext: function (inst) {\n    // ReactDOMOption looks at this initial value so the initial generated\n    // markup has correct `selected` attributes\n    return inst._wrapperState.initialValue;\n  },\n\n  postUpdateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    // After the initial mount, we control selected-ness manually so don't pass\n    // this value down\n    inst._wrapperState.initialValue = undefined;\n\n    var wasMultiple = inst._wrapperState.wasMultiple;\n    inst._wrapperState.wasMultiple = Boolean(props.multiple);\n\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      inst._wrapperState.pendingUpdate = false;\n      updateOptions(inst, Boolean(props.multiple), value);\n    } else if (wasMultiple !== Boolean(props.multiple)) {\n      // For simplicity, reapply `defaultValue` if `multiple` is toggled.\n      if (props.defaultValue != null) {\n        updateOptions(inst, Boolean(props.multiple), props.defaultValue);\n      } else {\n        // Revert the select back to its default unselected state.\n        updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : '');\n      }\n    }\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n\n  if (this._rootNodeID) {\n    this._wrapperState.pendingUpdate = true;\n  }\n  ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMSelect;\n},{\"14\":14,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],53:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMSelection\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar getNodeForCharacterOffset = _dereq_(131);\nvar getTextContentAccessor = _dereq_(132);\n\n/**\n * While `isCollapsed` is available on the Selection object and `collapsed`\n * is available on the Range object, IE11 sometimes gets them wrong.\n * If the anchor/focus nodes and offsets are the same, the range is collapsed.\n */\nfunction isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {\n  return anchorNode === focusNode && anchorOffset === focusOffset;\n}\n\n/**\n * Get the appropriate anchor and focus node/offset pairs for IE.\n *\n * The catch here is that IE's selection API doesn't provide information\n * about whether the selection is forward or backward, so we have to\n * behave as though it's always forward.\n *\n * IE text differs from modern selection in that it behaves as though\n * block elements end with a new line. This means character offsets will\n * differ between the two APIs.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getIEOffsets(node) {\n  var selection = document.selection;\n  var selectedRange = selection.createRange();\n  var selectedLength = selectedRange.text.length;\n\n  // Duplicate selection so we can move range without breaking user selection.\n  var fromStart = selectedRange.duplicate();\n  fromStart.moveToElementText(node);\n  fromStart.setEndPoint('EndToStart', selectedRange);\n\n  var startOffset = fromStart.text.length;\n  var endOffset = startOffset + selectedLength;\n\n  return {\n    start: startOffset,\n    end: endOffset\n  };\n}\n\n/**\n * @param {DOMElement} node\n * @return {?object}\n */\nfunction getModernOffsets(node) {\n  var selection = window.getSelection && window.getSelection();\n\n  if (!selection || selection.rangeCount === 0) {\n    return null;\n  }\n\n  var anchorNode = selection.anchorNode;\n  var anchorOffset = selection.anchorOffset;\n  var focusNode = selection.focusNode;\n  var focusOffset = selection.focusOffset;\n\n  var currentRange = selection.getRangeAt(0);\n\n  // In Firefox, range.startContainer and range.endContainer can be \"anonymous\n  // divs\", e.g. the up/down buttons on an <input type=\"number\">. Anonymous\n  // divs do not seem to expose properties, triggering a \"Permission denied\n  // error\" if any of its properties are accessed. The only seemingly possible\n  // way to avoid erroring is to access a property that typically works for\n  // non-anonymous divs and catch any error that may otherwise arise. See\n  // https://bugzilla.mozilla.org/show_bug.cgi?id=208427\n  try {\n    /* eslint-disable no-unused-expressions */\n    currentRange.startContainer.nodeType;\n    currentRange.endContainer.nodeType;\n    /* eslint-enable no-unused-expressions */\n  } catch (e) {\n    return null;\n  }\n\n  // If the node and offset values are the same, the selection is collapsed.\n  // `Selection.isCollapsed` is available natively, but IE sometimes gets\n  // this value wrong.\n  var isSelectionCollapsed = isCollapsed(selection.anchorNode, selection.anchorOffset, selection.focusNode, selection.focusOffset);\n\n  var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;\n\n  var tempRange = currentRange.cloneRange();\n  tempRange.selectNodeContents(node);\n  tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);\n\n  var isTempRangeCollapsed = isCollapsed(tempRange.startContainer, tempRange.startOffset, tempRange.endContainer, tempRange.endOffset);\n\n  var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;\n  var end = start + rangeLength;\n\n  // Detect whether the selection is backward.\n  var detectionRange = document.createRange();\n  detectionRange.setStart(anchorNode, anchorOffset);\n  detectionRange.setEnd(focusNode, focusOffset);\n  var isBackward = detectionRange.collapsed;\n\n  return {\n    start: isBackward ? end : start,\n    end: isBackward ? start : end\n  };\n}\n\n/**\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setIEOffsets(node, offsets) {\n  var range = document.selection.createRange().duplicate();\n  var start, end;\n\n  if (offsets.end === undefined) {\n    start = offsets.start;\n    end = start;\n  } else if (offsets.start > offsets.end) {\n    start = offsets.end;\n    end = offsets.start;\n  } else {\n    start = offsets.start;\n    end = offsets.end;\n  }\n\n  range.moveToElementText(node);\n  range.moveStart('character', start);\n  range.setEndPoint('EndToStart', range);\n  range.moveEnd('character', end - start);\n  range.select();\n}\n\n/**\n * In modern non-IE browsers, we can support both forward and backward\n * selections.\n *\n * Note: IE10+ supports the Selection object, but it does not support\n * the `extend` method, which means that even in modern IE, it's not possible\n * to programmatically create a backward selection. Thus, for all IE\n * versions, we use the old IE API to create our selections.\n *\n * @param {DOMElement|DOMTextNode} node\n * @param {object} offsets\n */\nfunction setModernOffsets(node, offsets) {\n  if (!window.getSelection) {\n    return;\n  }\n\n  var selection = window.getSelection();\n  var length = node[getTextContentAccessor()].length;\n  var start = Math.min(offsets.start, length);\n  var end = offsets.end === undefined ? start : Math.min(offsets.end, length);\n\n  // IE 11 uses modern selection, but doesn't support the extend method.\n  // Flip backward selections, so we can set with a single range.\n  if (!selection.extend && start > end) {\n    var temp = end;\n    end = start;\n    start = temp;\n  }\n\n  var startMarker = getNodeForCharacterOffset(node, start);\n  var endMarker = getNodeForCharacterOffset(node, end);\n\n  if (startMarker && endMarker) {\n    var range = document.createRange();\n    range.setStart(startMarker.node, startMarker.offset);\n    selection.removeAllRanges();\n\n    if (start > end) {\n      selection.addRange(range);\n      selection.extend(endMarker.node, endMarker.offset);\n    } else {\n      range.setEnd(endMarker.node, endMarker.offset);\n      selection.addRange(range);\n    }\n  }\n}\n\nvar useIEOffsets = ExecutionEnvironment.canUseDOM && 'selection' in document && !('getSelection' in window);\n\nvar ReactDOMSelection = {\n  /**\n   * @param {DOMElement} node\n   */\n  getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,\n\n  /**\n   * @param {DOMElement|DOMTextNode} node\n   * @param {object} offsets\n   */\n  setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets\n};\n\nmodule.exports = ReactDOMSelection;\n},{\"131\":131,\"132\":132,\"147\":147}],54:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMServer\n */\n\n'use strict';\n\nvar ReactDefaultInjection = _dereq_(61);\nvar ReactServerRendering = _dereq_(90);\nvar ReactVersion = _dereq_(96);\n\nReactDefaultInjection.inject();\n\nvar ReactDOMServer = {\n  renderToString: ReactServerRendering.renderToString,\n  renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup,\n  version: ReactVersion\n};\n\nmodule.exports = ReactDOMServer;\n},{\"61\":61,\"90\":90,\"96\":96}],55:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DOMChildrenOperations = _dereq_(7);\nvar DOMLazyTree = _dereq_(8);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstrumentation = _dereq_(74);\n\nvar escapeTextContentForBrowser = _dereq_(121);\nvar invariant = _dereq_(161);\nvar validateDOMNesting = _dereq_(145);\n\n/**\n * Text nodes violate a couple assumptions that React makes about components:\n *\n *  - When mounting text into the DOM, adjacent text nodes are merged.\n *  - Text nodes cannot be assigned a React root ID.\n *\n * This component is used to wrap strings between comment nodes so that they\n * can undergo the same reconciliation that is applied to elements.\n *\n * TODO: Investigate representing React components in the DOM with text nodes.\n *\n * @class ReactDOMTextComponent\n * @extends ReactComponent\n * @internal\n */\nvar ReactDOMTextComponent = function (text) {\n  // TODO: This is really a ReactText (ReactNode), not a ReactElement\n  this._currentElement = text;\n  this._stringText = '' + text;\n  // ReactDOMComponentTree uses these:\n  this._hostNode = null;\n  this._hostParent = null;\n\n  // Properties\n  this._domID = null;\n  this._mountIndex = 0;\n  this._closingComment = null;\n  this._commentNodes = null;\n};\n\n_assign(ReactDOMTextComponent.prototype, {\n\n  /**\n   * Creates the markup for this text node. This node is not intended to have\n   * any features besides containing text content.\n   *\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @return {string} Markup for this text node.\n   * @internal\n   */\n  mountComponent: function (transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetText(this._debugID, this._stringText);\n\n      var parentInfo;\n      if (hostParent != null) {\n        parentInfo = hostParent._ancestorInfo;\n      } else if (hostContainerInfo != null) {\n        parentInfo = hostContainerInfo._ancestorInfo;\n      }\n      if (parentInfo) {\n        // parentInfo should always be present except for the top-level\n        // component when server rendering\n        validateDOMNesting('#text', this, parentInfo);\n      }\n    }\n\n    var domID = hostContainerInfo._idCounter++;\n    var openingValue = ' react-text: ' + domID + ' ';\n    var closingValue = ' /react-text ';\n    this._domID = domID;\n    this._hostParent = hostParent;\n    if (transaction.useCreateElement) {\n      var ownerDocument = hostContainerInfo._ownerDocument;\n      var openingComment = ownerDocument.createComment(openingValue);\n      var closingComment = ownerDocument.createComment(closingValue);\n      var lazyTree = DOMLazyTree(ownerDocument.createDocumentFragment());\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(openingComment));\n      if (this._stringText) {\n        DOMLazyTree.queueChild(lazyTree, DOMLazyTree(ownerDocument.createTextNode(this._stringText)));\n      }\n      DOMLazyTree.queueChild(lazyTree, DOMLazyTree(closingComment));\n      ReactDOMComponentTree.precacheNode(this, openingComment);\n      this._closingComment = closingComment;\n      return lazyTree;\n    } else {\n      var escapedText = escapeTextContentForBrowser(this._stringText);\n\n      if (transaction.renderToStaticMarkup) {\n        // Normally we'd wrap this between comment nodes for the reasons stated\n        // above, but since this is a situation where React won't take over\n        // (static pages), we can simply return the text as it is.\n        return escapedText;\n      }\n\n      return '<!--' + openingValue + '-->' + escapedText + '<!--' + closingValue + '-->';\n    }\n  },\n\n  /**\n   * Updates this component by updating the text content.\n   *\n   * @param {ReactText} nextText The next text content\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  receiveComponent: function (nextText, transaction) {\n    if (nextText !== this._currentElement) {\n      this._currentElement = nextText;\n      var nextStringText = '' + nextText;\n      if (nextStringText !== this._stringText) {\n        // TODO: Save this as pending props and use performUpdateIfNecessary\n        // and/or updateComponent to do the actual update for consistency with\n        // other component types?\n        this._stringText = nextStringText;\n        var commentNodes = this.getHostNode();\n        DOMChildrenOperations.replaceDelimitedText(commentNodes[0], commentNodes[1], nextStringText);\n\n        if (\"development\" !== 'production') {\n          ReactInstrumentation.debugTool.onSetText(this._debugID, nextStringText);\n        }\n      }\n    }\n  },\n\n  getHostNode: function () {\n    var hostNode = this._commentNodes;\n    if (hostNode) {\n      return hostNode;\n    }\n    if (!this._closingComment) {\n      var openingComment = ReactDOMComponentTree.getNodeFromInstance(this);\n      var node = openingComment.nextSibling;\n      while (true) {\n        !(node != null) ? \"development\" !== 'production' ? invariant(false, 'Missing closing comment for text component %s', this._domID) : _prodInvariant('67', this._domID) : void 0;\n        if (node.nodeType === 8 && node.nodeValue === ' /react-text ') {\n          this._closingComment = node;\n          break;\n        }\n        node = node.nextSibling;\n      }\n    }\n    hostNode = [this._hostNode, this._closingComment];\n    this._commentNodes = hostNode;\n    return hostNode;\n  },\n\n  unmountComponent: function () {\n    this._closingComment = null;\n    this._commentNodes = null;\n    ReactDOMComponentTree.uncacheNode(this);\n  }\n\n});\n\nmodule.exports = ReactDOMTextComponent;\n},{\"121\":121,\"139\":139,\"145\":145,\"161\":161,\"172\":172,\"41\":41,\"7\":7,\"74\":74,\"8\":8}],56:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTextarea\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar DisabledInputUtils = _dereq_(14);\nvar LinkedValueUtils = _dereq_(24);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar didWarnValueLink = false;\nvar didWarnValDefaultVal = false;\n\nfunction forceUpdateIfMounted() {\n  if (this._rootNodeID) {\n    // DOM component is still mounted; update\n    ReactDOMTextarea.updateWrapper(this);\n  }\n}\n\n/**\n * Implements a <textarea> host component that allows setting `value`, and\n * `defaultValue`. This differs from the traditional DOM API because value is\n * usually set as PCDATA children.\n *\n * If `value` is not supplied (or null/undefined), user actions that affect the\n * value will trigger updates to the element.\n *\n * If `value` is supplied (and not null/undefined), the rendered element will\n * not trigger updates to the element. Instead, the `value` prop must change in\n * order for the rendered element to be updated.\n *\n * The rendered element will be initialized with an empty value, the prop\n * `defaultValue` if specified, or the children content (deprecated).\n */\nvar ReactDOMTextarea = {\n  getHostProps: function (inst, props) {\n    !(props.dangerouslySetInnerHTML == null) ? \"development\" !== 'production' ? invariant(false, '`dangerouslySetInnerHTML` does not make sense on <textarea>.') : _prodInvariant('91') : void 0;\n\n    // Always set children to the same thing. In IE9, the selection range will\n    // get reset if `textContent` is mutated.  We could add a check in setTextContent\n    // to only set the value if/when the value differs from the node value (which would\n    // completely solve this IE9 bug), but Sebastian+Ben seemed to like this solution.\n    // The value can be a boolean or object so that's why it's forced to be a string.\n    var hostProps = _assign({}, DisabledInputUtils.getHostProps(inst, props), {\n      value: undefined,\n      defaultValue: undefined,\n      children: '' + inst._wrapperState.initialValue,\n      onChange: inst._wrapperState.onChange\n    });\n\n    return hostProps;\n  },\n\n  mountWrapper: function (inst, props) {\n    if (\"development\" !== 'production') {\n      LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);\n      if (props.valueLink !== undefined && !didWarnValueLink) {\n        \"development\" !== 'production' ? warning(false, '`valueLink` prop on `textarea` is deprecated; set `value` and `onChange` instead.') : void 0;\n        didWarnValueLink = true;\n      }\n      if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValDefaultVal) {\n        \"development\" !== 'production' ? warning(false, 'Textarea elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled textarea ' + 'and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;\n        didWarnValDefaultVal = true;\n      }\n    }\n\n    var value = LinkedValueUtils.getValue(props);\n    var initialValue = value;\n\n    // Only bother fetching default value if we're going to use it\n    if (value == null) {\n      var defaultValue = props.defaultValue;\n      // TODO (yungsters): Remove support for children content in <textarea>.\n      var children = props.children;\n      if (children != null) {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'Use the `defaultValue` or `value` props instead of setting ' + 'children on <textarea>.') : void 0;\n        }\n        !(defaultValue == null) ? \"development\" !== 'production' ? invariant(false, 'If you supply `defaultValue` on a <textarea>, do not pass children.') : _prodInvariant('92') : void 0;\n        if (Array.isArray(children)) {\n          !(children.length <= 1) ? \"development\" !== 'production' ? invariant(false, '<textarea> can only have at most one child.') : _prodInvariant('93') : void 0;\n          children = children[0];\n        }\n\n        defaultValue = '' + children;\n      }\n      if (defaultValue == null) {\n        defaultValue = '';\n      }\n      initialValue = defaultValue;\n    }\n\n    inst._wrapperState = {\n      initialValue: '' + initialValue,\n      listeners: null,\n      onChange: _handleChange.bind(inst)\n    };\n  },\n\n  updateWrapper: function (inst) {\n    var props = inst._currentElement.props;\n\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n    var value = LinkedValueUtils.getValue(props);\n    if (value != null) {\n      // Cast `value` to a string to ensure the value is set correctly. While\n      // browsers typically do this as necessary, jsdom doesn't.\n      var newValue = '' + value;\n\n      // To avoid side effects (such as losing text selection), only set value if changed\n      if (newValue !== node.value) {\n        node.value = newValue;\n      }\n      if (props.defaultValue == null) {\n        node.defaultValue = newValue;\n      }\n    }\n    if (props.defaultValue != null) {\n      node.defaultValue = props.defaultValue;\n    }\n  },\n\n  postMountWrapper: function (inst) {\n    // This is in postMount because we need access to the DOM node, which is not\n    // available until after the component has mounted.\n    var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n\n    // Warning: node.value may be the empty string at this point (IE11) if placeholder is set.\n    node.value = node.textContent; // Detach value from defaultValue\n  }\n};\n\nfunction _handleChange(event) {\n  var props = this._currentElement.props;\n  var returnValue = LinkedValueUtils.executeOnChange(props, event);\n  ReactUpdates.asap(forceUpdateIfMounted, this);\n  return returnValue;\n}\n\nmodule.exports = ReactDOMTextarea;\n},{\"139\":139,\"14\":14,\"161\":161,\"171\":171,\"172\":172,\"24\":24,\"41\":41,\"95\":95}],57:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMTreeTraversal\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Return the lowest common ancestor of A and B, or null if they are in\n * different trees.\n */\nfunction getLowestCommonAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;\n\n  var depthA = 0;\n  for (var tempA = instA; tempA; tempA = tempA._hostParent) {\n    depthA++;\n  }\n  var depthB = 0;\n  for (var tempB = instB; tempB; tempB = tempB._hostParent) {\n    depthB++;\n  }\n\n  // If A is deeper, crawl up.\n  while (depthA - depthB > 0) {\n    instA = instA._hostParent;\n    depthA--;\n  }\n\n  // If B is deeper, crawl up.\n  while (depthB - depthA > 0) {\n    instB = instB._hostParent;\n    depthB--;\n  }\n\n  // Walk in lockstep until we find a match.\n  var depth = depthA;\n  while (depth--) {\n    if (instA === instB) {\n      return instA;\n    }\n    instA = instA._hostParent;\n    instB = instB._hostParent;\n  }\n  return null;\n}\n\n/**\n * Return if A is an ancestor of B.\n */\nfunction isAncestor(instA, instB) {\n  !('_hostNode' in instA) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n  !('_hostNode' in instB) ? \"development\" !== 'production' ? invariant(false, 'isAncestor: Invalid argument.') : _prodInvariant('35') : void 0;\n\n  while (instB) {\n    if (instB === instA) {\n      return true;\n    }\n    instB = instB._hostParent;\n  }\n  return false;\n}\n\n/**\n * Return the parent instance of the passed-in instance.\n */\nfunction getParentInstance(inst) {\n  !('_hostNode' in inst) ? \"development\" !== 'production' ? invariant(false, 'getParentInstance: Invalid argument.') : _prodInvariant('36') : void 0;\n\n  return inst._hostParent;\n}\n\n/**\n * Simulates the traversal of a two-phase, capture/bubble event dispatch.\n */\nfunction traverseTwoPhase(inst, fn, arg) {\n  var path = [];\n  while (inst) {\n    path.push(inst);\n    inst = inst._hostParent;\n  }\n  var i;\n  for (i = path.length; i-- > 0;) {\n    fn(path[i], false, arg);\n  }\n  for (i = 0; i < path.length; i++) {\n    fn(path[i], true, arg);\n  }\n}\n\n/**\n * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that\n * should would receive a `mouseEnter` or `mouseLeave` event.\n *\n * Does not invoke the callback on the nearest common ancestor because nothing\n * \"entered\" or \"left\" that element.\n */\nfunction traverseEnterLeave(from, to, fn, argFrom, argTo) {\n  var common = from && to ? getLowestCommonAncestor(from, to) : null;\n  var pathFrom = [];\n  while (from && from !== common) {\n    pathFrom.push(from);\n    from = from._hostParent;\n  }\n  var pathTo = [];\n  while (to && to !== common) {\n    pathTo.push(to);\n    to = to._hostParent;\n  }\n  var i;\n  for (i = 0; i < pathFrom.length; i++) {\n    fn(pathFrom[i], true, argFrom);\n  }\n  for (i = pathTo.length; i-- > 0;) {\n    fn(pathTo[i], false, argTo);\n  }\n}\n\nmodule.exports = {\n  isAncestor: isAncestor,\n  getLowestCommonAncestor: getLowestCommonAncestor,\n  getParentInstance: getParentInstance,\n  traverseTwoPhase: traverseTwoPhase,\n  traverseEnterLeave: traverseEnterLeave\n};\n},{\"139\":139,\"161\":161}],58:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDOMUnknownPropertyDevtool\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginRegistry = _dereq_(18);\nvar ReactComponentTreeDevtool = _dereq_(34);\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var reactProps = {\n    children: true,\n    dangerouslySetInnerHTML: true,\n    key: true,\n    ref: true,\n\n    autoFocus: true,\n    defaultValue: true,\n    valueLink: true,\n    defaultChecked: true,\n    checkedLink: true,\n    innerHTML: true,\n    suppressContentEditableWarning: true,\n    onFocusIn: true,\n    onFocusOut: true\n  };\n  var warnedProperties = {};\n\n  var validateProperty = function (tagName, name, debugID) {\n    if (DOMProperty.properties.hasOwnProperty(name) || DOMProperty.isCustomAttribute(name)) {\n      return true;\n    }\n    if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {\n      return true;\n    }\n    if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) {\n      return true;\n    }\n    warnedProperties[name] = true;\n    var lowerCasedName = name.toLowerCase();\n\n    // data-* attributes should be lowercase; suggest the lowercase version\n    var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;\n\n    var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? EventPluginRegistry.possibleRegistrationNames[lowerCasedName] : null;\n\n    if (standardName != null) {\n      \"development\" !== 'production' ? warning(standardName == null, 'Unknown DOM property %s. Did you mean %s?%s', name, standardName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else if (registrationName != null) {\n      \"development\" !== 'production' ? warning(registrationName == null, 'Unknown event handler property %s. Did you mean `%s`?%s', name, registrationName, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n      return true;\n    } else {\n      // We were unable to guess which prop the user intended.\n      // It is likely that the user was just blindly spreading/forwarding props\n      // Components should be careful to only render valid props/attributes.\n      // Warning will be invoked in warnUnknownProperties to allow grouping.\n      return false;\n    }\n  };\n}\n\nvar warnUnknownProperties = function (debugID, element) {\n  var unknownProps = [];\n  for (var key in element.props) {\n    var isValid = validateProperty(element.type, key, debugID);\n    if (!isValid) {\n      unknownProps.push(key);\n    }\n  }\n\n  var unknownPropString = unknownProps.map(function (prop) {\n    return '`' + prop + '`';\n  }).join(', ');\n\n  if (unknownProps.length === 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown prop %s on <%s> tag. Remove this prop from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  } else if (unknownProps.length > 1) {\n    \"development\" !== 'production' ? warning(false, 'Unknown props %s on <%s> tag. Remove these props from the element. ' + 'For details, see https://fb.me/react-unknown-prop%s', unknownPropString, element.type, ReactComponentTreeDevtool.getStackAddendumByID(debugID)) : void 0;\n  }\n};\n\nfunction handleElement(debugID, element) {\n  if (element == null || typeof element.type !== 'string') {\n    return;\n  }\n  if (element.type.indexOf('-') >= 0 || element.props.is) {\n    return;\n  }\n  warnUnknownProperties(debugID, element);\n}\n\nvar ReactDOMUnknownPropertyDevtool = {\n  onBeforeMountComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    handleElement(debugID, element);\n  }\n};\n\nmodule.exports = ReactDOMUnknownPropertyDevtool;\n},{\"10\":10,\"171\":171,\"18\":18,\"34\":34}],59:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDebugTool\n */\n\n'use strict';\n\nvar ReactInvalidSetStateWarningDevTool = _dereq_(75);\nvar ReactHostOperationHistoryDevtool = _dereq_(70);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performanceNow = _dereq_(169);\nvar warning = _dereq_(171);\n\nvar eventHandlers = [];\nvar handlerDoesThrowForEvent = {};\n\nfunction emitEvent(handlerFunctionName, arg1, arg2, arg3, arg4, arg5) {\n  eventHandlers.forEach(function (handler) {\n    try {\n      if (handler[handlerFunctionName]) {\n        handler[handlerFunctionName](arg1, arg2, arg3, arg4, arg5);\n      }\n    } catch (e) {\n      \"development\" !== 'production' ? warning(handlerDoesThrowForEvent[handlerFunctionName], 'exception thrown by devtool while handling %s: %s', handlerFunctionName, e + '\\n' + e.stack) : void 0;\n      handlerDoesThrowForEvent[handlerFunctionName] = true;\n    }\n  });\n}\n\nvar isProfiling = false;\nvar flushHistory = [];\nvar lifeCycleTimerStack = [];\nvar currentFlushNesting = 0;\nvar currentFlushMeasurements = null;\nvar currentFlushStartTime = null;\nvar currentTimerDebugID = null;\nvar currentTimerStartTime = null;\nvar currentTimerNestedFlushDuration = null;\nvar currentTimerType = null;\n\nfunction clearHistory() {\n  ReactComponentTreeDevtool.purgeUnmountedComponents();\n  ReactHostOperationHistoryDevtool.clearHistory();\n}\n\nfunction getTreeSnapshot(registeredIDs) {\n  return registeredIDs.reduce(function (tree, id) {\n    var ownerID = ReactComponentTreeDevtool.getOwnerID(id);\n    var parentID = ReactComponentTreeDevtool.getParentID(id);\n    tree[id] = {\n      displayName: ReactComponentTreeDevtool.getDisplayName(id),\n      text: ReactComponentTreeDevtool.getText(id),\n      updateCount: ReactComponentTreeDevtool.getUpdateCount(id),\n      childIDs: ReactComponentTreeDevtool.getChildIDs(id),\n      // Text nodes don't have owners but this is close enough.\n      ownerID: ownerID || ReactComponentTreeDevtool.getOwnerID(parentID),\n      parentID: parentID\n    };\n    return tree;\n  }, {});\n}\n\nfunction resetMeasurements() {\n  var previousStartTime = currentFlushStartTime;\n  var previousMeasurements = currentFlushMeasurements || [];\n  var previousOperations = ReactHostOperationHistoryDevtool.getHistory();\n\n  if (currentFlushNesting === 0) {\n    currentFlushStartTime = null;\n    currentFlushMeasurements = null;\n    clearHistory();\n    return;\n  }\n\n  if (previousMeasurements.length || previousOperations.length) {\n    var registeredIDs = ReactComponentTreeDevtool.getRegisteredIDs();\n    flushHistory.push({\n      duration: performanceNow() - previousStartTime,\n      measurements: previousMeasurements || [],\n      operations: previousOperations || [],\n      treeSnapshot: getTreeSnapshot(registeredIDs)\n    });\n  }\n\n  clearHistory();\n  currentFlushStartTime = performanceNow();\n  currentFlushMeasurements = [];\n}\n\nfunction checkDebugID(debugID) {\n  \"development\" !== 'production' ? warning(debugID, 'ReactDebugTool: debugID may not be empty.') : void 0;\n}\n\nfunction beginLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(!currentTimerType, 'There is an internal error in the React performance measurement code. ' + 'Did not expect %s timer to start while %s timer is still in ' + 'progress for %s instance.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  currentTimerStartTime = performanceNow();\n  currentTimerNestedFlushDuration = 0;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nfunction endLifeCycleTimer(debugID, timerType) {\n  if (currentFlushNesting === 0) {\n    return;\n  }\n  \"development\" !== 'production' ? warning(currentTimerType === timerType, 'There is an internal error in the React performance measurement code. ' + 'We did not expect %s timer to stop while %s timer is still in ' + 'progress for %s instance. Please report this as a bug in React.', timerType, currentTimerType || 'no', debugID === currentTimerDebugID ? 'the same' : 'another') : void 0;\n  if (isProfiling) {\n    currentFlushMeasurements.push({\n      timerType: timerType,\n      instanceID: debugID,\n      duration: performanceNow() - currentTimerStartTime - currentTimerNestedFlushDuration\n    });\n  }\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction pauseCurrentLifeCycleTimer() {\n  var currentTimer = {\n    startTime: currentTimerStartTime,\n    nestedFlushStartTime: performanceNow(),\n    debugID: currentTimerDebugID,\n    timerType: currentTimerType\n  };\n  lifeCycleTimerStack.push(currentTimer);\n  currentTimerStartTime = null;\n  currentTimerNestedFlushDuration = null;\n  currentTimerDebugID = null;\n  currentTimerType = null;\n}\n\nfunction resumeCurrentLifeCycleTimer() {\n  var _lifeCycleTimerStack$ = lifeCycleTimerStack.pop();\n\n  var startTime = _lifeCycleTimerStack$.startTime;\n  var nestedFlushStartTime = _lifeCycleTimerStack$.nestedFlushStartTime;\n  var debugID = _lifeCycleTimerStack$.debugID;\n  var timerType = _lifeCycleTimerStack$.timerType;\n\n  var nestedFlushDuration = performanceNow() - nestedFlushStartTime;\n  currentTimerStartTime = startTime;\n  currentTimerNestedFlushDuration += nestedFlushDuration;\n  currentTimerDebugID = debugID;\n  currentTimerType = timerType;\n}\n\nvar ReactDebugTool = {\n  addDevtool: function (devtool) {\n    eventHandlers.push(devtool);\n  },\n  removeDevtool: function (devtool) {\n    for (var i = 0; i < eventHandlers.length; i++) {\n      if (eventHandlers[i] === devtool) {\n        eventHandlers.splice(i, 1);\n        i--;\n      }\n    }\n  },\n  isProfiling: function () {\n    return isProfiling;\n  },\n  beginProfiling: function () {\n    if (isProfiling) {\n      return;\n    }\n\n    isProfiling = true;\n    flushHistory.length = 0;\n    resetMeasurements();\n    ReactDebugTool.addDevtool(ReactHostOperationHistoryDevtool);\n  },\n  endProfiling: function () {\n    if (!isProfiling) {\n      return;\n    }\n\n    isProfiling = false;\n    resetMeasurements();\n    ReactDebugTool.removeDevtool(ReactHostOperationHistoryDevtool);\n  },\n  getFlushHistory: function () {\n    return flushHistory;\n  },\n  onBeginFlush: function () {\n    currentFlushNesting++;\n    resetMeasurements();\n    pauseCurrentLifeCycleTimer();\n    emitEvent('onBeginFlush');\n  },\n  onEndFlush: function () {\n    resetMeasurements();\n    currentFlushNesting--;\n    resumeCurrentLifeCycleTimer();\n    emitEvent('onEndFlush');\n  },\n  onBeginLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginLifeCycleTimer', debugID, timerType);\n    beginLifeCycleTimer(debugID, timerType);\n  },\n  onEndLifeCycleTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    endLifeCycleTimer(debugID, timerType);\n    emitEvent('onEndLifeCycleTimer', debugID, timerType);\n  },\n  onBeginReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onBeginReconcilerTimer', debugID, timerType);\n  },\n  onEndReconcilerTimer: function (debugID, timerType) {\n    checkDebugID(debugID);\n    emitEvent('onEndReconcilerTimer', debugID, timerType);\n  },\n  onError: function (debugID) {\n    if (currentTimerDebugID != null) {\n      endLifeCycleTimer(currentTimerDebugID, currentTimerType);\n    }\n    emitEvent('onError', debugID);\n  },\n  onBeginProcessingChildContext: function () {\n    emitEvent('onBeginProcessingChildContext');\n  },\n  onEndProcessingChildContext: function () {\n    emitEvent('onEndProcessingChildContext');\n  },\n  onHostOperation: function (debugID, type, payload) {\n    checkDebugID(debugID);\n    emitEvent('onHostOperation', debugID, type, payload);\n  },\n  onSetState: function () {\n    emitEvent('onSetState');\n  },\n  onSetDisplayName: function (debugID, displayName) {\n    checkDebugID(debugID);\n    emitEvent('onSetDisplayName', debugID, displayName);\n  },\n  onSetChildren: function (debugID, childDebugIDs) {\n    checkDebugID(debugID);\n    childDebugIDs.forEach(checkDebugID);\n    emitEvent('onSetChildren', debugID, childDebugIDs);\n  },\n  onSetOwner: function (debugID, ownerDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetOwner', debugID, ownerDebugID);\n  },\n  onSetParent: function (debugID, parentDebugID) {\n    checkDebugID(debugID);\n    emitEvent('onSetParent', debugID, parentDebugID);\n  },\n  onSetText: function (debugID, text) {\n    checkDebugID(debugID);\n    emitEvent('onSetText', debugID, text);\n  },\n  onMountRootComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountRootComponent', debugID);\n  },\n  onBeforeMountComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeMountComponent', debugID, element);\n  },\n  onMountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onMountComponent', debugID);\n  },\n  onBeforeUpdateComponent: function (debugID, element) {\n    checkDebugID(debugID);\n    emitEvent('onBeforeUpdateComponent', debugID, element);\n  },\n  onUpdateComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUpdateComponent', debugID);\n  },\n  onUnmountComponent: function (debugID) {\n    checkDebugID(debugID);\n    emitEvent('onUnmountComponent', debugID);\n  },\n  onTestEvent: function () {\n    emitEvent('onTestEvent');\n  }\n};\n\nReactDebugTool.addDevtool(ReactInvalidSetStateWarningDevTool);\nReactDebugTool.addDevtool(ReactComponentTreeDevtool);\nvar url = ExecutionEnvironment.canUseDOM && window.location.href || '';\nif (/[?&]react_perf\\b/.test(url)) {\n  ReactDebugTool.beginProfiling();\n}\n\nmodule.exports = ReactDebugTool;\n},{\"147\":147,\"169\":169,\"171\":171,\"34\":34,\"70\":70,\"75\":75}],60:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultBatchingStrategy\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactUpdates = _dereq_(95);\nvar Transaction = _dereq_(113);\n\nvar emptyFunction = _dereq_(153);\n\nvar RESET_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: function () {\n    ReactDefaultBatchingStrategy.isBatchingUpdates = false;\n  }\n};\n\nvar FLUSH_BATCHED_UPDATES = {\n  initialize: emptyFunction,\n  close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)\n};\n\nvar TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];\n\nfunction ReactDefaultBatchingStrategyTransaction() {\n  this.reinitializeTransaction();\n}\n\n_assign(ReactDefaultBatchingStrategyTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  }\n});\n\nvar transaction = new ReactDefaultBatchingStrategyTransaction();\n\nvar ReactDefaultBatchingStrategy = {\n  isBatchingUpdates: false,\n\n  /**\n   * Call the provided function in a context within which calls to `setState`\n   * and friends are batched such that components aren't updated unnecessarily.\n   */\n  batchedUpdates: function (callback, a, b, c, d, e) {\n    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;\n\n    ReactDefaultBatchingStrategy.isBatchingUpdates = true;\n\n    // The code is written this way to avoid extra allocations\n    if (alreadyBatchingUpdates) {\n      callback(a, b, c, d, e);\n    } else {\n      transaction.perform(callback, null, a, b, c, d, e);\n    }\n  }\n};\n\nmodule.exports = ReactDefaultBatchingStrategy;\n},{\"113\":113,\"153\":153,\"172\":172,\"95\":95}],61:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactDefaultInjection\n */\n\n'use strict';\n\nvar BeforeInputEventPlugin = _dereq_(2);\nvar ChangeEventPlugin = _dereq_(6);\nvar DefaultEventPluginOrder = _dereq_(13);\nvar EnterLeaveEventPlugin = _dereq_(15);\nvar HTMLDOMPropertyConfig = _dereq_(22);\nvar ReactComponentBrowserEnvironment = _dereq_(32);\nvar ReactDOMComponent = _dereq_(39);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMEmptyComponent = _dereq_(44);\nvar ReactDOMTreeTraversal = _dereq_(57);\nvar ReactDOMTextComponent = _dereq_(55);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactEventListener = _dereq_(67);\nvar ReactInjection = _dereq_(71);\nvar ReactReconcileTransaction = _dereq_(86);\nvar SVGDOMPropertyConfig = _dereq_(97);\nvar SelectEventPlugin = _dereq_(98);\nvar SimpleEventPlugin = _dereq_(99);\n\nvar alreadyInjected = false;\n\nfunction inject() {\n  if (alreadyInjected) {\n    // TODO: This is currently true because these injections are shared between\n    // the client and the server package. They should be built independently\n    // and not share any injection state. Then this problem will be solved.\n    return;\n  }\n  alreadyInjected = true;\n\n  ReactInjection.EventEmitter.injectReactEventListener(ReactEventListener);\n\n  /**\n   * Inject modules for resolving DOM hierarchy and plugin ordering.\n   */\n  ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);\n  ReactInjection.EventPluginUtils.injectComponentTree(ReactDOMComponentTree);\n  ReactInjection.EventPluginUtils.injectTreeTraversal(ReactDOMTreeTraversal);\n\n  /**\n   * Some important event plugins included by default (without having to require\n   * them).\n   */\n  ReactInjection.EventPluginHub.injectEventPluginsByName({\n    SimpleEventPlugin: SimpleEventPlugin,\n    EnterLeaveEventPlugin: EnterLeaveEventPlugin,\n    ChangeEventPlugin: ChangeEventPlugin,\n    SelectEventPlugin: SelectEventPlugin,\n    BeforeInputEventPlugin: BeforeInputEventPlugin\n  });\n\n  ReactInjection.HostComponent.injectGenericComponentClass(ReactDOMComponent);\n\n  ReactInjection.HostComponent.injectTextComponentClass(ReactDOMTextComponent);\n\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);\n  ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);\n\n  ReactInjection.EmptyComponent.injectEmptyComponentFactory(function (instantiate) {\n    return new ReactDOMEmptyComponent(instantiate);\n  });\n\n  ReactInjection.Updates.injectReconcileTransaction(ReactReconcileTransaction);\n  ReactInjection.Updates.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n\n  ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);\n}\n\nmodule.exports = {\n  inject: inject\n};\n},{\"13\":13,\"15\":15,\"2\":2,\"22\":22,\"32\":32,\"39\":39,\"41\":41,\"44\":44,\"55\":55,\"57\":57,\"6\":6,\"60\":60,\"67\":67,\"71\":71,\"86\":86,\"97\":97,\"98\":98,\"99\":99}],62:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElement\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactCurrentOwner = _dereq_(36);\n\nvar warning = _dereq_(171);\nvar canDefineProperty = _dereq_(117);\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n// The Symbol used to tag the ReactElement type. If there is no native Symbol\n// nor polyfill, then a plain number is used for performance.\nvar REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;\n\nvar RESERVED_PROPS = {\n  key: true,\n  ref: true,\n  __self: true,\n  __source: true\n};\n\nvar specialPropKeyWarningShown, specialPropRefWarningShown;\n\nfunction hasValidRef(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'ref')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n  if (\"development\" !== 'production') {\n    if (hasOwnProperty.call(config, 'key')) {\n      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n      if (getter && getter.isReactWarning) {\n        return false;\n      }\n    }\n  }\n  return config.key !== undefined;\n}\n\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, no instanceof check\n * will work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} key\n * @param {string|object} ref\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @param {*} owner\n * @param {*} props\n * @internal\n */\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n  var element = {\n    // This tag allow us to uniquely identify this as a React Element\n    $$typeof: REACT_ELEMENT_TYPE,\n\n    // Built-in properties that belong on the element\n    type: type,\n    key: key,\n    ref: ref,\n    props: props,\n\n    // Record the component responsible for creating this element.\n    _owner: owner\n  };\n\n  if (\"development\" !== 'production') {\n    // The validation flag is currently mutative. We put it on\n    // an external backing store so that we can freeze the whole object.\n    // This can be replaced with a WeakMap once they are implemented in\n    // commonly used development environments.\n    element._store = {};\n\n    // To make comparing ReactElements easier for testing purposes, we make\n    // the validation flag non-enumerable (where possible, which should\n    // include every environment we run tests in), so the test framework\n    // ignores it.\n    if (canDefineProperty) {\n      Object.defineProperty(element._store, 'validated', {\n        configurable: false,\n        enumerable: false,\n        writable: true,\n        value: false\n      });\n      // self and source are DEV only properties.\n      Object.defineProperty(element, '_self', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: self\n      });\n      // Two elements created in two different places should be considered\n      // equal for testing purposes and therefore we hide it from enumeration.\n      Object.defineProperty(element, '_source', {\n        configurable: false,\n        enumerable: false,\n        writable: false,\n        value: source\n      });\n    } else {\n      element._store.validated = false;\n      element._self = self;\n      element._source = source;\n    }\n    if (Object.freeze) {\n      Object.freeze(element.props);\n      Object.freeze(element);\n    }\n  }\n\n  return element;\n};\n\n/**\n * Create and return a new ReactElement of the given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createelement\n */\nReactElement.createElement = function (type, config, children) {\n  var propName;\n\n  // Reserved names are extracted\n  var props = {};\n\n  var key = null;\n  var ref = null;\n  var self = null;\n  var source = null;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.createElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      ref = config.ref;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    self = config.__self === undefined ? null : config.__self;\n    source = config.__source === undefined ? null : config.__source;\n    // Remaining properties are added to a new props object\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        props[propName] = config[propName];\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  // Resolve default props\n  if (type && type.defaultProps) {\n    var defaultProps = type.defaultProps;\n    for (propName in defaultProps) {\n      if (props[propName] === undefined) {\n        props[propName] = defaultProps[propName];\n      }\n    }\n  }\n  if (\"development\" !== 'production') {\n    var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n    // Create dummy `key` and `ref` property to `props` to warn users against its use\n    var warnAboutAccessingKey = function () {\n      if (!specialPropKeyWarningShown) {\n        specialPropKeyWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingKey.isReactWarning = true;\n\n    var warnAboutAccessingRef = function () {\n      if (!specialPropRefWarningShown) {\n        specialPropRefWarningShown = true;\n        \"development\" !== 'production' ? warning(false, '%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://fb.me/react-special-props)', displayName) : void 0;\n      }\n      return undefined;\n    };\n    warnAboutAccessingRef.isReactWarning = true;\n\n    if (typeof props.$$typeof === 'undefined' || props.$$typeof !== REACT_ELEMENT_TYPE) {\n      if (!props.hasOwnProperty('key')) {\n        Object.defineProperty(props, 'key', {\n          get: warnAboutAccessingKey,\n          configurable: true\n        });\n      }\n      if (!props.hasOwnProperty('ref')) {\n        Object.defineProperty(props, 'ref', {\n          get: warnAboutAccessingRef,\n          configurable: true\n        });\n      }\n    }\n  }\n  return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n};\n\n/**\n * Return a function that produces ReactElements of a given type.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.createfactory\n */\nReactElement.createFactory = function (type) {\n  var factory = ReactElement.createElement.bind(null, type);\n  // Expose the type on the factory and the prototype so that it can be\n  // easily accessed on elements. E.g. `<Foo />.type === Foo`.\n  // This should not be named `constructor` since this may not be the function\n  // that created the element, and it may not even be a constructor.\n  // Legacy hook TODO: Warn if this is accessed\n  factory.type = type;\n  return factory;\n};\n\nReactElement.cloneAndReplaceKey = function (oldElement, newKey) {\n  var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);\n\n  return newElement;\n};\n\n/**\n * Clone and return a new ReactElement using element as the starting point.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement\n */\nReactElement.cloneElement = function (element, config, children) {\n  var propName;\n\n  // Original props are copied\n  var props = _assign({}, element.props);\n\n  // Reserved names are extracted\n  var key = element.key;\n  var ref = element.ref;\n  // Self is preserved since the owner is preserved.\n  var self = element._self;\n  // Source is preserved since cloneElement is unlikely to be targeted by a\n  // transpiler, and the original source is probably a better indicator of the\n  // true owner.\n  var source = element._source;\n\n  // Owner will be preserved, unless ref is overridden\n  var owner = element._owner;\n\n  if (config != null) {\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(\n      /* eslint-disable no-proto */\n      config.__proto__ == null || config.__proto__ === Object.prototype,\n      /* eslint-enable no-proto */\n      'React.cloneElement(...): Expected props argument to be a plain object. ' + 'Properties defined in its prototype chain will be ignored.') : void 0;\n    }\n\n    if (hasValidRef(config)) {\n      // Silently steal the ref from the parent.\n      ref = config.ref;\n      owner = ReactCurrentOwner.current;\n    }\n    if (hasValidKey(config)) {\n      key = '' + config.key;\n    }\n\n    // Remaining properties override existing props\n    var defaultProps;\n    if (element.type && element.type.defaultProps) {\n      defaultProps = element.type.defaultProps;\n    }\n    for (propName in config) {\n      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n        if (config[propName] === undefined && defaultProps !== undefined) {\n          // Resolve default props\n          props[propName] = defaultProps[propName];\n        } else {\n          props[propName] = config[propName];\n        }\n      }\n    }\n  }\n\n  // Children can be more than one argument, and those are transferred onto\n  // the newly allocated props object.\n  var childrenLength = arguments.length - 2;\n  if (childrenLength === 1) {\n    props.children = children;\n  } else if (childrenLength > 1) {\n    var childArray = Array(childrenLength);\n    for (var i = 0; i < childrenLength; i++) {\n      childArray[i] = arguments[i + 2];\n    }\n    props.children = childArray;\n  }\n\n  return ReactElement(element.type, key, ref, self, source, owner, props);\n};\n\n/**\n * Verifies the object is a ReactElement.\n * See https://facebook.github.io/react/docs/top-level-api.html#react.isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a valid component.\n * @final\n */\nReactElement.isValidElement = function (object) {\n  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n};\n\nReactElement.REACT_ELEMENT_TYPE = REACT_ELEMENT_TYPE;\n\nmodule.exports = ReactElement;\n},{\"117\":117,\"171\":171,\"172\":172,\"36\":36}],63:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactElementValidator\n */\n\n/**\n * ReactElementValidator provides a wrapper around a element factory\n * which validates the props passed to the element. This is intended to be\n * used only in DEV and could be replaced by a static type checker for languages\n * that support it.\n */\n\n'use strict';\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactComponentTreeDevtool = _dereq_(34);\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocations = _dereq_(84);\n\nvar checkReactTypeSpec = _dereq_(118);\n\nvar canDefineProperty = _dereq_(117);\nvar getIteratorFn = _dereq_(130);\nvar warning = _dereq_(171);\n\nfunction getDeclarationErrorAddendum() {\n  if (ReactCurrentOwner.current) {\n    var name = ReactCurrentOwner.current.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n  var info = getDeclarationErrorAddendum();\n\n  if (!info) {\n    var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n    if (parentName) {\n      info = ' Check the top-level render call using <' + parentName + '>.';\n    }\n  }\n  return info;\n}\n\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\nfunction validateExplicitKey(element, parentType) {\n  if (!element._store || element._store.validated || element.key != null) {\n    return;\n  }\n  element._store.validated = true;\n\n  var memoizer = ownerHasKeyUseWarning.uniqueKey || (ownerHasKeyUseWarning.uniqueKey = {});\n\n  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n  if (memoizer[currentComponentErrorInfo]) {\n    return;\n  }\n  memoizer[currentComponentErrorInfo] = true;\n\n  // Usually the current owner is the offender, but if it accepts children as a\n  // property, it may be the creator of the child that's responsible for\n  // assigning it a key.\n  var childOwner = '';\n  if (element && element._owner && element._owner !== ReactCurrentOwner.current) {\n    // Give the component that originally created this child.\n    childOwner = ' It was passed a child from ' + element._owner.getName() + '.';\n  }\n\n  \"development\" !== 'production' ? warning(false, 'Each child in an array or iterator should have a unique \"key\" prop.' + '%s%s See https://fb.me/react-warning-keys for more information.%s', currentComponentErrorInfo, childOwner, ReactComponentTreeDevtool.getCurrentStackAddendum(element)) : void 0;\n}\n\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\nfunction validateChildKeys(node, parentType) {\n  if (typeof node !== 'object') {\n    return;\n  }\n  if (Array.isArray(node)) {\n    for (var i = 0; i < node.length; i++) {\n      var child = node[i];\n      if (ReactElement.isValidElement(child)) {\n        validateExplicitKey(child, parentType);\n      }\n    }\n  } else if (ReactElement.isValidElement(node)) {\n    // This element was passed in a valid location.\n    if (node._store) {\n      node._store.validated = true;\n    }\n  } else if (node) {\n    var iteratorFn = getIteratorFn(node);\n    // Entry iterators provide implicit keys.\n    if (iteratorFn) {\n      if (iteratorFn !== node.entries) {\n        var iterator = iteratorFn.call(node);\n        var step;\n        while (!(step = iterator.next()).done) {\n          if (ReactElement.isValidElement(step.value)) {\n            validateExplicitKey(step.value, parentType);\n          }\n        }\n      }\n    }\n  }\n}\n\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\nfunction validatePropTypes(element) {\n  var componentClass = element.type;\n  if (typeof componentClass !== 'function') {\n    return;\n  }\n  var name = componentClass.displayName || componentClass.name;\n  if (componentClass.propTypes) {\n    checkReactTypeSpec(componentClass.propTypes, element.props, ReactPropTypeLocations.prop, name, element, null);\n  }\n  if (typeof componentClass.getDefaultProps === 'function') {\n    \"development\" !== 'production' ? warning(componentClass.getDefaultProps.isReactClassApproved, 'getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.') : void 0;\n  }\n}\n\nvar ReactElementValidator = {\n\n  createElement: function (type, props, children) {\n    var validType = typeof type === 'string' || typeof type === 'function';\n    // We warn in this case but don't throw. We expect the element creation to\n    // succeed and there will likely be errors in render.\n    \"development\" !== 'production' ? warning(validType, 'React.createElement: type should not be null, undefined, boolean, or ' + 'number. It should be a string (for DOM elements) or a ReactClass ' + '(for composite components).%s', getDeclarationErrorAddendum()) : void 0;\n\n    var element = ReactElement.createElement.apply(this, arguments);\n\n    // The result can be nullish if a mock or a custom function is used.\n    // TODO: Drop this when these are no longer allowed as the type argument.\n    if (element == null) {\n      return element;\n    }\n\n    // Skip key warning if the type isn't valid since our key validation logic\n    // doesn't expect a non-string/function type and can throw confusing errors.\n    // We don't want exception behavior to differ between dev and prod.\n    // (Rendering will throw with a helpful message and as soon as the type is\n    // fixed, the key warnings will appear.)\n    if (validType) {\n      for (var i = 2; i < arguments.length; i++) {\n        validateChildKeys(arguments[i], type);\n      }\n    }\n\n    validatePropTypes(element);\n\n    return element;\n  },\n\n  createFactory: function (type) {\n    var validatedFactory = ReactElementValidator.createElement.bind(null, type);\n    // Legacy hook TODO: Warn if this is accessed\n    validatedFactory.type = type;\n\n    if (\"development\" !== 'production') {\n      if (canDefineProperty) {\n        Object.defineProperty(validatedFactory, 'type', {\n          enumerable: false,\n          get: function () {\n            \"development\" !== 'production' ? warning(false, 'Factory.type is deprecated. Access the class directly ' + 'before passing it to createFactory.') : void 0;\n            Object.defineProperty(this, 'type', {\n              value: type\n            });\n            return type;\n          }\n        });\n      }\n    }\n\n    return validatedFactory;\n  },\n\n  cloneElement: function (element, props, children) {\n    var newElement = ReactElement.cloneElement.apply(this, arguments);\n    for (var i = 2; i < arguments.length; i++) {\n      validateChildKeys(arguments[i], newElement.type);\n    }\n    validatePropTypes(newElement);\n    return newElement;\n  }\n\n};\n\nmodule.exports = ReactElementValidator;\n},{\"117\":117,\"118\":118,\"130\":130,\"171\":171,\"34\":34,\"36\":36,\"62\":62,\"84\":84}],64:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEmptyComponent\n */\n\n'use strict';\n\nvar emptyComponentFactory;\n\nvar ReactEmptyComponentInjection = {\n  injectEmptyComponentFactory: function (factory) {\n    emptyComponentFactory = factory;\n  }\n};\n\nvar ReactEmptyComponent = {\n  create: function (instantiate) {\n    return emptyComponentFactory(instantiate);\n  }\n};\n\nReactEmptyComponent.injection = ReactEmptyComponentInjection;\n\nmodule.exports = ReactEmptyComponent;\n},{}],65:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactErrorUtils\n */\n\n'use strict';\n\nvar caughtError = null;\n\n/**\n * Call a function while guarding against errors that happens within it.\n *\n * @param {?String} name of the guard to use for logging or debugging\n * @param {Function} func The function to invoke\n * @param {*} a First argument\n * @param {*} b Second argument\n */\nfunction invokeGuardedCallback(name, func, a, b) {\n  try {\n    return func(a, b);\n  } catch (x) {\n    if (caughtError === null) {\n      caughtError = x;\n    }\n    return undefined;\n  }\n}\n\nvar ReactErrorUtils = {\n  invokeGuardedCallback: invokeGuardedCallback,\n\n  /**\n   * Invoked by ReactTestUtils.Simulate so that any errors thrown by the event\n   * handler are sure to be rethrown by rethrowCaughtError.\n   */\n  invokeGuardedCallbackWithCatch: invokeGuardedCallback,\n\n  /**\n   * During execution of guarded functions we will capture the first error which\n   * we will rethrow to be handled by the top level error handler.\n   */\n  rethrowCaughtError: function () {\n    if (caughtError) {\n      var error = caughtError;\n      caughtError = null;\n      throw error;\n    }\n  }\n};\n\nif (\"development\" !== 'production') {\n  /**\n   * To help development we can get better devtools integration by simulating a\n   * real browser event.\n   */\n  if (typeof window !== 'undefined' && typeof window.dispatchEvent === 'function' && typeof document !== 'undefined' && typeof document.createEvent === 'function') {\n    var fakeNode = document.createElement('react');\n    ReactErrorUtils.invokeGuardedCallback = function (name, func, a, b) {\n      var boundFunc = func.bind(null, a, b);\n      var evtType = 'react-' + name;\n      fakeNode.addEventListener(evtType, boundFunc, false);\n      var evt = document.createEvent('Event');\n      evt.initEvent(evtType, false, false);\n      fakeNode.dispatchEvent(evt);\n      fakeNode.removeEventListener(evtType, boundFunc, false);\n    };\n  }\n}\n\nmodule.exports = ReactErrorUtils;\n},{}],66:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventEmitterMixin\n */\n\n'use strict';\n\nvar EventPluginHub = _dereq_(17);\n\nfunction runEventQueueInBatch(events) {\n  EventPluginHub.enqueueEvents(events);\n  EventPluginHub.processEventQueue(false);\n}\n\nvar ReactEventEmitterMixin = {\n\n  /**\n   * Streams a fired top-level event to `EventPluginHub` where plugins have the\n   * opportunity to create `ReactEvent`s to be dispatched.\n   */\n  handleTopLevel: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var events = EventPluginHub.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);\n    runEventQueueInBatch(events);\n  }\n};\n\nmodule.exports = ReactEventEmitterMixin;\n},{\"17\":17}],67:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactEventListener\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar EventListener = _dereq_(146);\nvar ExecutionEnvironment = _dereq_(147);\nvar PooledClass = _dereq_(25);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactUpdates = _dereq_(95);\n\nvar getEventTarget = _dereq_(128);\nvar getUnboundedScrollPosition = _dereq_(158);\n\n/**\n * Find the deepest React component completely containing the root of the\n * passed-in instance (for use when entire React trees are nested within each\n * other). If React trees are not nested, returns null.\n */\nfunction findParent(inst) {\n  // TODO: It may be a good idea to cache this to prevent unnecessary DOM\n  // traversal, but caching is difficult to do correctly without using a\n  // mutation observer to listen for all DOM changes.\n  while (inst._hostParent) {\n    inst = inst._hostParent;\n  }\n  var rootNode = ReactDOMComponentTree.getNodeFromInstance(inst);\n  var container = rootNode.parentNode;\n  return ReactDOMComponentTree.getClosestInstanceFromNode(container);\n}\n\n// Used to store ancestor hierarchy in top level callback\nfunction TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {\n  this.topLevelType = topLevelType;\n  this.nativeEvent = nativeEvent;\n  this.ancestors = [];\n}\n_assign(TopLevelCallbackBookKeeping.prototype, {\n  destructor: function () {\n    this.topLevelType = null;\n    this.nativeEvent = null;\n    this.ancestors.length = 0;\n  }\n});\nPooledClass.addPoolingTo(TopLevelCallbackBookKeeping, PooledClass.twoArgumentPooler);\n\nfunction handleTopLevelImpl(bookKeeping) {\n  var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);\n  var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(nativeEventTarget);\n\n  // Loop through the hierarchy, in case there's any nested components.\n  // It's important that we build the array of ancestors before calling any\n  // event handlers, because event handlers can modify the DOM, leading to\n  // inconsistencies with ReactMount's node cache. See #1105.\n  var ancestor = targetInst;\n  do {\n    bookKeeping.ancestors.push(ancestor);\n    ancestor = ancestor && findParent(ancestor);\n  } while (ancestor);\n\n  for (var i = 0; i < bookKeeping.ancestors.length; i++) {\n    targetInst = bookKeeping.ancestors[i];\n    ReactEventListener._handleTopLevel(bookKeeping.topLevelType, targetInst, bookKeeping.nativeEvent, getEventTarget(bookKeeping.nativeEvent));\n  }\n}\n\nfunction scrollValueMonitor(cb) {\n  var scrollPosition = getUnboundedScrollPosition(window);\n  cb(scrollPosition);\n}\n\nvar ReactEventListener = {\n  _enabled: true,\n  _handleTopLevel: null,\n\n  WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,\n\n  setHandleTopLevel: function (handleTopLevel) {\n    ReactEventListener._handleTopLevel = handleTopLevel;\n  },\n\n  setEnabled: function (enabled) {\n    ReactEventListener._enabled = !!enabled;\n  },\n\n  isEnabled: function () {\n    return ReactEventListener._enabled;\n  },\n\n  /**\n   * Traps top-level events by using event bubbling.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapBubbledEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  /**\n   * Traps a top-level event by using event capturing.\n   *\n   * @param {string} topLevelType Record from `EventConstants`.\n   * @param {string} handlerBaseName Event name (e.g. \"click\").\n   * @param {object} handle Element on which to attach listener.\n   * @return {?object} An object with a remove function which will forcefully\n   *                  remove the listener.\n   * @internal\n   */\n  trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {\n    var element = handle;\n    if (!element) {\n      return null;\n    }\n    return EventListener.capture(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType));\n  },\n\n  monitorScrollValue: function (refresh) {\n    var callback = scrollValueMonitor.bind(null, refresh);\n    EventListener.listen(window, 'scroll', callback);\n  },\n\n  dispatchEvent: function (topLevelType, nativeEvent) {\n    if (!ReactEventListener._enabled) {\n      return;\n    }\n\n    var bookKeeping = TopLevelCallbackBookKeeping.getPooled(topLevelType, nativeEvent);\n    try {\n      // Event queue being processed in the same cycle allows\n      // `preventDefault`.\n      ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);\n    } finally {\n      TopLevelCallbackBookKeeping.release(bookKeeping);\n    }\n  }\n};\n\nmodule.exports = ReactEventListener;\n},{\"128\":128,\"146\":146,\"147\":147,\"158\":158,\"172\":172,\"25\":25,\"41\":41,\"95\":95}],68:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactFeatureFlags\n * \n */\n\n'use strict';\n\nvar ReactFeatureFlags = {\n  // When true, call console.time() before and .timeEnd() after each top-level\n  // render (both initial renders and updates). Useful when looking at prod-mode\n  // timeline profiles in Chrome, for example.\n  logTopLevelRenders: false\n};\n\nmodule.exports = ReactFeatureFlags;\n},{}],69:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar invariant = _dereq_(161);\n\nvar genericComponentClass = null;\n// This registry keeps track of wrapper classes around host tags.\nvar tagToComponentClass = {};\nvar textComponentClass = null;\n\nvar ReactHostComponentInjection = {\n  // This accepts a class that receives the tag string. This is a catch all\n  // that can render any kind of tag.\n  injectGenericComponentClass: function (componentClass) {\n    genericComponentClass = componentClass;\n  },\n  // This accepts a text component class that takes the text string to be\n  // rendered as props.\n  injectTextComponentClass: function (componentClass) {\n    textComponentClass = componentClass;\n  },\n  // This accepts a keyed object with classes as values. Each key represents a\n  // tag. That particular tag will use this class instead of the generic one.\n  injectComponentClasses: function (componentClasses) {\n    _assign(tagToComponentClass, componentClasses);\n  }\n};\n\n/**\n * Get a host internal component class for a specific tag.\n *\n * @param {ReactElement} element The element to create.\n * @return {function} The internal class constructor function.\n */\nfunction createInternalComponent(element) {\n  !genericComponentClass ? \"development\" !== 'production' ? invariant(false, 'There is no registered component for the tag %s', element.type) : _prodInvariant('111', element.type) : void 0;\n  return new genericComponentClass(element);\n}\n\n/**\n * @param {ReactText} text\n * @return {ReactComponent}\n */\nfunction createInstanceForText(text) {\n  return new textComponentClass(text);\n}\n\n/**\n * @param {ReactComponent} component\n * @return {boolean}\n */\nfunction isTextComponent(component) {\n  return component instanceof textComponentClass;\n}\n\nvar ReactHostComponent = {\n  createInternalComponent: createInternalComponent,\n  createInstanceForText: createInstanceForText,\n  isTextComponent: isTextComponent,\n  injection: ReactHostComponentInjection\n};\n\nmodule.exports = ReactHostComponent;\n},{\"139\":139,\"161\":161,\"172\":172}],70:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactHostOperationHistoryDevtool\n */\n\n'use strict';\n\nvar history = [];\n\nvar ReactHostOperationHistoryDevtool = {\n  onHostOperation: function (debugID, type, payload) {\n    history.push({\n      instanceID: debugID,\n      type: type,\n      payload: payload\n    });\n  },\n  clearHistory: function () {\n    if (ReactHostOperationHistoryDevtool._preventClearing) {\n      // Should only be used for tests.\n      return;\n    }\n\n    history = [];\n  },\n  getHistory: function () {\n    return history;\n  }\n};\n\nmodule.exports = ReactHostOperationHistoryDevtool;\n},{}],71:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInjection\n */\n\n'use strict';\n\nvar DOMProperty = _dereq_(10);\nvar EventPluginHub = _dereq_(17);\nvar EventPluginUtils = _dereq_(19);\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactClass = _dereq_(30);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactHostComponent = _dereq_(69);\nvar ReactUpdates = _dereq_(95);\n\nvar ReactInjection = {\n  Component: ReactComponentEnvironment.injection,\n  Class: ReactClass.injection,\n  DOMProperty: DOMProperty.injection,\n  EmptyComponent: ReactEmptyComponent.injection,\n  EventPluginHub: EventPluginHub.injection,\n  EventPluginUtils: EventPluginUtils.injection,\n  EventEmitter: ReactBrowserEventEmitter.injection,\n  HostComponent: ReactHostComponent.injection,\n  Updates: ReactUpdates.injection\n};\n\nmodule.exports = ReactInjection;\n},{\"10\":10,\"17\":17,\"19\":19,\"27\":27,\"30\":30,\"33\":33,\"64\":64,\"69\":69,\"95\":95}],72:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInputSelection\n */\n\n'use strict';\n\nvar ReactDOMSelection = _dereq_(53);\n\nvar containsNode = _dereq_(150);\nvar focusNode = _dereq_(155);\nvar getActiveElement = _dereq_(156);\n\nfunction isInDocument(node) {\n  return containsNode(document.documentElement, node);\n}\n\n/**\n * @ReactInputSelection: React input selection module. Based on Selection.js,\n * but modified to be suitable for react and has a couple of bug fixes (doesn't\n * assume buttons have range selections allowed).\n * Input selection module for React.\n */\nvar ReactInputSelection = {\n\n  hasSelectionCapabilities: function (elem) {\n    var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n    return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true');\n  },\n\n  getSelectionInformation: function () {\n    var focusedElem = getActiveElement();\n    return {\n      focusedElem: focusedElem,\n      selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem) ? ReactInputSelection.getSelection(focusedElem) : null\n    };\n  },\n\n  /**\n   * @restoreSelection: If any selection information was potentially lost,\n   * restore it. This is useful when performing operations that could remove dom\n   * nodes and place them back in, resulting in focus being lost.\n   */\n  restoreSelection: function (priorSelectionInformation) {\n    var curFocusedElem = getActiveElement();\n    var priorFocusedElem = priorSelectionInformation.focusedElem;\n    var priorSelectionRange = priorSelectionInformation.selectionRange;\n    if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {\n      if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {\n        ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);\n      }\n      focusNode(priorFocusedElem);\n    }\n  },\n\n  /**\n   * @getSelection: Gets the selection bounds of a focused textarea, input or\n   * contentEditable node.\n   * -@input: Look up selection bounds of this input\n   * -@return {start: selectionStart, end: selectionEnd}\n   */\n  getSelection: function (input) {\n    var selection;\n\n    if ('selectionStart' in input) {\n      // Modern browser with input or textarea.\n      selection = {\n        start: input.selectionStart,\n        end: input.selectionEnd\n      };\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      // IE8 input.\n      var range = document.selection.createRange();\n      // There can only be one selection per document in IE, so it must\n      // be in our element.\n      if (range.parentElement() === input) {\n        selection = {\n          start: -range.moveStart('character', -input.value.length),\n          end: -range.moveEnd('character', -input.value.length)\n        };\n      }\n    } else {\n      // Content editable or old IE textarea.\n      selection = ReactDOMSelection.getOffsets(input);\n    }\n\n    return selection || { start: 0, end: 0 };\n  },\n\n  /**\n   * @setSelection: Sets the selection bounds of a textarea or input and focuses\n   * the input.\n   * -@input     Set selection bounds of this input or textarea\n   * -@offsets   Object of same form that is returned from get*\n   */\n  setSelection: function (input, offsets) {\n    var start = offsets.start;\n    var end = offsets.end;\n    if (end === undefined) {\n      end = start;\n    }\n\n    if ('selectionStart' in input) {\n      input.selectionStart = start;\n      input.selectionEnd = Math.min(end, input.value.length);\n    } else if (document.selection && input.nodeName && input.nodeName.toLowerCase() === 'input') {\n      var range = input.createTextRange();\n      range.collapse(true);\n      range.moveStart('character', start);\n      range.moveEnd('character', end - start);\n      range.select();\n    } else {\n      ReactDOMSelection.setOffsets(input, offsets);\n    }\n  }\n};\n\nmodule.exports = ReactInputSelection;\n},{\"150\":150,\"155\":155,\"156\":156,\"53\":53}],73:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstanceMap\n */\n\n'use strict';\n\n/**\n * `ReactInstanceMap` maintains a mapping from a public facing stateful\n * instance (key) and the internal representation (value). This allows public\n * methods to accept the user facing instance as an argument and map them back\n * to internal methods.\n */\n\n// TODO: Replace this with ES6: var ReactInstanceMap = new Map();\n\nvar ReactInstanceMap = {\n\n  /**\n   * This API should be called `delete` but we'd have to make sure to always\n   * transform these to strings for IE support. When this transform is fully\n   * supported we can rename it.\n   */\n  remove: function (key) {\n    key._reactInternalInstance = undefined;\n  },\n\n  get: function (key) {\n    return key._reactInternalInstance;\n  },\n\n  has: function (key) {\n    return key._reactInternalInstance !== undefined;\n  },\n\n  set: function (key, value) {\n    key._reactInternalInstance = value;\n  }\n\n};\n\nmodule.exports = ReactInstanceMap;\n},{}],74:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInstrumentation\n */\n\n'use strict';\n\nvar debugTool = null;\n\nif (\"development\" !== 'production') {\n  var ReactDebugTool = _dereq_(59);\n  debugTool = ReactDebugTool;\n}\n\nmodule.exports = { debugTool: debugTool };\n},{\"59\":59}],75:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactInvalidSetStateWarningDevTool\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nif (\"development\" !== 'production') {\n  var processingChildContext = false;\n\n  var warnInvalidSetState = function () {\n    \"development\" !== 'production' ? warning(!processingChildContext, 'setState(...): Cannot call setState() inside getChildContext()') : void 0;\n  };\n}\n\nvar ReactInvalidSetStateWarningDevTool = {\n  onBeginProcessingChildContext: function () {\n    processingChildContext = true;\n  },\n  onEndProcessingChildContext: function () {\n    processingChildContext = false;\n  },\n  onSetState: function () {\n    warnInvalidSetState();\n  }\n};\n\nmodule.exports = ReactInvalidSetStateWarningDevTool;\n},{\"171\":171}],76:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMarkupChecksum\n */\n\n'use strict';\n\nvar adler32 = _dereq_(116);\n\nvar TAG_END = /\\/?>/;\nvar COMMENT_START = /^<\\!\\-\\-/;\n\nvar ReactMarkupChecksum = {\n  CHECKSUM_ATTR_NAME: 'data-react-checksum',\n\n  /**\n   * @param {string} markup Markup string\n   * @return {string} Markup string with checksum attribute attached\n   */\n  addChecksumToMarkup: function (markup) {\n    var checksum = adler32(markup);\n\n    // Add checksum (handle both parent tags, comments and self-closing tags)\n    if (COMMENT_START.test(markup)) {\n      return markup;\n    } else {\n      return markup.replace(TAG_END, ' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '=\"' + checksum + '\"$&');\n    }\n  },\n\n  /**\n   * @param {string} markup to use\n   * @param {DOMElement} element root React element\n   * @returns {boolean} whether or not the markup is the same\n   */\n  canReuseMarkup: function (markup, element) {\n    var existingChecksum = element.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n    existingChecksum = existingChecksum && parseInt(existingChecksum, 10);\n    var markupChecksum = adler32(markup);\n    return markupChecksum === existingChecksum;\n  }\n};\n\nmodule.exports = ReactMarkupChecksum;\n},{\"116\":116}],77:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMount\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar DOMLazyTree = _dereq_(8);\nvar DOMProperty = _dereq_(10);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDOMFeatureFlags = _dereq_(46);\nvar ReactElement = _dereq_(62);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactUpdateQueue = _dereq_(94);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\nvar setInnerHTML = _dereq_(141);\nvar shouldUpdateReactComponent = _dereq_(143);\nvar warning = _dereq_(171);\n\nvar ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;\nvar ROOT_ATTR_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;\n\nvar ELEMENT_NODE_TYPE = 1;\nvar DOC_NODE_TYPE = 9;\nvar DOCUMENT_FRAGMENT_NODE_TYPE = 11;\n\nvar instancesByReactRootID = {};\n\n/**\n * Finds the index of the first character\n * that's not common between the two given strings.\n *\n * @return {number} the index of the character where the strings diverge\n */\nfunction firstDifferenceIndex(string1, string2) {\n  var minLen = Math.min(string1.length, string2.length);\n  for (var i = 0; i < minLen; i++) {\n    if (string1.charAt(i) !== string2.charAt(i)) {\n      return i;\n    }\n  }\n  return string1.length === string2.length ? -1 : minLen;\n}\n\n/**\n * @param {DOMElement|DOMDocument} container DOM element that may contain\n * a React component\n * @return {?*} DOM element that may have the reactRoot ID, or null.\n */\nfunction getReactRootElementInContainer(container) {\n  if (!container) {\n    return null;\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    return container.documentElement;\n  } else {\n    return container.firstChild;\n  }\n}\n\nfunction internalGetID(node) {\n  // If node is something like a window, document, or text node, none of\n  // which support attributes or a .getAttribute method, gracefully return\n  // the empty string, as if the attribute were missing.\n  return node.getAttribute && node.getAttribute(ATTR_NAME) || '';\n}\n\n/**\n * Mounts this component and inserts it into the DOM.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {ReactReconcileTransaction} transaction\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction mountComponentIntoNode(wrapperInstance, container, transaction, shouldReuseMarkup, context) {\n  var markerName;\n  if (ReactFeatureFlags.logTopLevelRenders) {\n    var wrappedElement = wrapperInstance._currentElement.props;\n    var type = wrappedElement.type;\n    markerName = 'React mount: ' + (typeof type === 'string' ? type : type.displayName || type.name);\n    console.time(markerName);\n  }\n\n  var markup = ReactReconciler.mountComponent(wrapperInstance, transaction, null, ReactDOMContainerInfo(wrapperInstance, container), context);\n\n  if (markerName) {\n    console.timeEnd(markerName);\n  }\n\n  wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;\n  ReactMount._mountImageIntoNode(markup, container, wrapperInstance, shouldReuseMarkup, transaction);\n}\n\n/**\n * Batched mount.\n *\n * @param {ReactComponent} componentInstance The instance to mount.\n * @param {DOMElement} container DOM element to mount into.\n * @param {boolean} shouldReuseMarkup If true, do not insert markup\n */\nfunction batchedMountComponentIntoNode(componentInstance, container, shouldReuseMarkup, context) {\n  var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */\n  !shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement);\n  transaction.perform(mountComponentIntoNode, null, componentInstance, container, transaction, shouldReuseMarkup, context);\n  ReactUpdates.ReactReconcileTransaction.release(transaction);\n}\n\n/**\n * Unmounts a component and removes it from the DOM.\n *\n * @param {ReactComponent} instance React component instance.\n * @param {DOMElement} container DOM element to unmount from.\n * @final\n * @internal\n * @see {ReactMount.unmountComponentAtNode}\n */\nfunction unmountComponentFromNode(instance, container, safely) {\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onBeginFlush();\n  }\n  ReactReconciler.unmountComponent(instance, safely);\n  if (\"development\" !== 'production') {\n    ReactInstrumentation.debugTool.onEndFlush();\n  }\n\n  if (container.nodeType === DOC_NODE_TYPE) {\n    container = container.documentElement;\n  }\n\n  // http://jsperf.com/emptying-a-node\n  while (container.lastChild) {\n    container.removeChild(container.lastChild);\n  }\n}\n\n/**\n * True if the supplied DOM node has a direct React-rendered child that is\n * not a React root element. Useful for warning in `render`,\n * `unmountComponentAtNode`, etc.\n *\n * @param {?DOMElement} node The candidate DOM node.\n * @return {boolean} True if the DOM element contains a direct child that was\n * rendered by React but is not a root element.\n * @internal\n */\nfunction hasNonRootReactChild(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  if (rootEl) {\n    var inst = ReactDOMComponentTree.getInstanceFromNode(rootEl);\n    return !!(inst && inst._hostParent);\n  }\n}\n\nfunction getHostRootInstanceInContainer(container) {\n  var rootEl = getReactRootElementInContainer(container);\n  var prevHostInstance = rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);\n  return prevHostInstance && !prevHostInstance._hostParent ? prevHostInstance : null;\n}\n\nfunction getTopLevelWrapperInContainer(container) {\n  var root = getHostRootInstanceInContainer(container);\n  return root ? root._hostContainerInfo._topLevelWrapper : null;\n}\n\n/**\n * Temporary (?) hack so that we can store all top-level pending updates on\n * composites instead of having to worry about different types of components\n * here.\n */\nvar topLevelRootCounter = 1;\nvar TopLevelWrapper = function () {\n  this.rootID = topLevelRootCounter++;\n};\nTopLevelWrapper.prototype.isReactComponent = {};\nif (\"development\" !== 'production') {\n  TopLevelWrapper.displayName = 'TopLevelWrapper';\n}\nTopLevelWrapper.prototype.render = function () {\n  // this.props is actually a ReactElement\n  return this.props;\n};\n\n/**\n * Mounting is the process of initializing a React component by creating its\n * representative DOM elements and inserting them into a supplied `container`.\n * Any prior content inside `container` is destroyed in the process.\n *\n *   ReactMount.render(\n *     component,\n *     document.getElementById('container')\n *   );\n *\n *   <div id=\"container\">                   <-- Supplied `container`.\n *     <div data-reactid=\".3\">              <-- Rendered reactRoot of React\n *       // ...                                 component.\n *     </div>\n *   </div>\n *\n * Inside of `container`, the first element rendered is the \"reactRoot\".\n */\nvar ReactMount = {\n\n  TopLevelWrapper: TopLevelWrapper,\n\n  /**\n   * Used by devtools. The keys are not important.\n   */\n  _instancesByReactRootID: instancesByReactRootID,\n\n  /**\n   * This is a hook provided to support rendering React components while\n   * ensuring that the apparent scroll position of its `container` does not\n   * change.\n   *\n   * @param {DOMElement} container The `container` being rendered into.\n   * @param {function} renderCallback This must be called once to do the render.\n   */\n  scrollMonitor: function (container, renderCallback) {\n    renderCallback();\n  },\n\n  /**\n   * Take a component that's already mounted into the DOM and replace its props\n   * @param {ReactComponent} prevComponent component instance already in the DOM\n   * @param {ReactElement} nextElement component instance to render\n   * @param {DOMElement} container container to render into\n   * @param {?function} callback function triggered on completion\n   */\n  _updateRootComponent: function (prevComponent, nextElement, nextContext, container, callback) {\n    ReactMount.scrollMonitor(container, function () {\n      ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement, nextContext);\n      if (callback) {\n        ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);\n      }\n    });\n\n    return prevComponent;\n  },\n\n  /**\n   * Render a new component into the DOM. Hooked by devtools!\n   *\n   * @param {ReactElement} nextElement element to render\n   * @param {DOMElement} container container to render into\n   * @param {boolean} shouldReuseMarkup if we should skip the markup insertion\n   * @return {ReactComponent} nextComponent\n   */\n  _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case.\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '_renderNewRootComponent(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from ' + 'render is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, '_registerComponent(...): Target container is not a DOM element.') : _prodInvariant('37') : void 0;\n\n    ReactBrowserEventEmitter.ensureScrollValueMonitoring();\n    var componentInstance = instantiateReactComponent(nextElement, false);\n\n    // The initial render is synchronous but any updates that happen during\n    // rendering, in componentWillMount or componentDidMount, will be batched\n    // according to the current batching strategy.\n\n    ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);\n\n    var wrapperID = componentInstance._instance.rootID;\n    instancesByReactRootID[wrapperID] = componentInstance;\n\n    if (\"development\" !== 'production') {\n      // The instance here is TopLevelWrapper so we report mount for its child.\n      ReactInstrumentation.debugTool.onMountRootComponent(componentInstance._renderedComponent._debugID);\n    }\n\n    return componentInstance;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactComponent} parentComponent The conceptual parent of this render tree.\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    !(parentComponent != null && ReactInstanceMap.has(parentComponent)) ? \"development\" !== 'production' ? invariant(false, 'parentComponent must be a valid React Component') : _prodInvariant('38') : void 0;\n    return ReactMount._renderSubtreeIntoContainer(parentComponent, nextElement, container, callback);\n  },\n\n  _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {\n    ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');\n    !ReactElement.isValidElement(nextElement) ? \"development\" !== 'production' ? invariant(false, 'ReactDOM.render(): Invalid component element.%s', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' :\n    // Check if it quacks like an element\n    nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : _prodInvariant('39', typeof nextElement === 'string' ? ' Instead of passing a string like \\'div\\', pass ' + 'React.createElement(\\'div\\') or <div />.' : typeof nextElement === 'function' ? ' Instead of passing a class like Foo, pass ' + 'React.createElement(Foo) or <Foo />.' : nextElement != null && nextElement.props !== undefined ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '') : void 0;\n\n    \"development\" !== 'production' ? warning(!container || !container.tagName || container.tagName.toUpperCase() !== 'BODY', 'render(): Rendering components directly into document.body is ' + 'discouraged, since its children are often manipulated by third-party ' + 'scripts and browser extensions. This may lead to subtle ' + 'reconciliation issues. Try rendering into a container element created ' + 'for your app.') : void 0;\n\n    var nextWrappedElement = ReactElement(TopLevelWrapper, null, null, null, null, null, nextElement);\n\n    var nextContext;\n    if (parentComponent) {\n      var parentInst = ReactInstanceMap.get(parentComponent);\n      nextContext = parentInst._processChildContext(parentInst._context);\n    } else {\n      nextContext = emptyObject;\n    }\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n\n    if (prevComponent) {\n      var prevWrappedElement = prevComponent._currentElement;\n      var prevElement = prevWrappedElement.props;\n      if (shouldUpdateReactComponent(prevElement, nextElement)) {\n        var publicInst = prevComponent._renderedComponent.getPublicInstance();\n        var updatedCallback = callback && function () {\n          callback.call(publicInst);\n        };\n        ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);\n        return publicInst;\n      } else {\n        ReactMount.unmountComponentAtNode(container);\n      }\n    }\n\n    var reactRootElement = getReactRootElementInContainer(container);\n    var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);\n    var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n    if (\"development\" !== 'production') {\n      \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'render(...): Replacing React-rendered children with a new root ' + 'component. If you intended to update the children of this node, ' + 'you should instead have the existing children update their state ' + 'and render the new components instead of calling ReactDOM.render.') : void 0;\n\n      if (!containerHasReactMarkup || reactRootElement.nextSibling) {\n        var rootElementSibling = reactRootElement;\n        while (rootElementSibling) {\n          if (internalGetID(rootElementSibling)) {\n            \"development\" !== 'production' ? warning(false, 'render(): Target node has markup rendered by React, but there ' + 'are unrelated nodes as well. This is most commonly caused by ' + 'white-space inserted around server-rendered markup.') : void 0;\n            break;\n          }\n          rootElementSibling = rootElementSibling.nextSibling;\n        }\n      }\n    }\n\n    var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;\n    var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();\n    if (callback) {\n      callback.call(component);\n    }\n    return component;\n  },\n\n  /**\n   * Renders a React component into the DOM in the supplied `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render\n   *\n   * If the React component was previously rendered into `container`, this will\n   * perform an update on it and only mutate the DOM as necessary to reflect the\n   * latest React component.\n   *\n   * @param {ReactElement} nextElement Component element to render.\n   * @param {DOMElement} container DOM element to render into.\n   * @param {?function} callback function triggered on completion\n   * @return {ReactComponent} Component instance rendered in `container`.\n   */\n  render: function (nextElement, container, callback) {\n    return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);\n  },\n\n  /**\n   * Unmounts and destroys the React component rendered in the `container`.\n   * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.unmountcomponentatnode\n   *\n   * @param {DOMElement} container DOM element containing a React component.\n   * @return {boolean} True if a component was found in and unmounted from\n   *                   `container`\n   */\n  unmountComponentAtNode: function (container) {\n    // Various parts of our code (such as ReactCompositeComponent's\n    // _renderValidatedComponent) assume that calls to render aren't nested;\n    // verify that that's the case. (Strictly speaking, unmounting won't cause a\n    // render but we still don't expect to be in a render call here.)\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, 'unmountComponentAtNode(): Render methods should be a pure function ' + 'of props and state; triggering nested component updates from render ' + 'is not allowed. If necessary, trigger nested updates in ' + 'componentDidUpdate. Check the render method of %s.', ReactCurrentOwner.current && ReactCurrentOwner.current.getName() || 'ReactCompositeComponent') : void 0;\n\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'unmountComponentAtNode(...): Target container is not a DOM element.') : _prodInvariant('40') : void 0;\n\n    var prevComponent = getTopLevelWrapperInContainer(container);\n    if (!prevComponent) {\n      // Check if the node being unmounted was rendered by React, but isn't a\n      // root node.\n      var containerHasNonRootReactChild = hasNonRootReactChild(container);\n\n      // Check if the container itself is a React root node.\n      var isContainerReactRoot = container.nodeType === 1 && container.hasAttribute(ROOT_ATTR_NAME);\n\n      if (\"development\" !== 'production') {\n        \"development\" !== 'production' ? warning(!containerHasNonRootReactChild, 'unmountComponentAtNode(): The node you\\'re attempting to unmount ' + 'was rendered by React and is not a top-level container. %s', isContainerReactRoot ? 'You may have accidentally passed in a React root node instead ' + 'of its container.' : 'Instead, have the parent component update its state and ' + 'rerender in order to remove this component.') : void 0;\n      }\n\n      return false;\n    }\n    delete instancesByReactRootID[prevComponent._instance.rootID];\n    ReactUpdates.batchedUpdates(unmountComponentFromNode, prevComponent, container, false);\n    return true;\n  },\n\n  _mountImageIntoNode: function (markup, container, instance, shouldReuseMarkup, transaction) {\n    !(container && (container.nodeType === ELEMENT_NODE_TYPE || container.nodeType === DOC_NODE_TYPE || container.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE)) ? \"development\" !== 'production' ? invariant(false, 'mountComponentIntoNode(...): Target container is not valid.') : _prodInvariant('41') : void 0;\n\n    if (shouldReuseMarkup) {\n      var rootElement = getReactRootElementInContainer(container);\n      if (ReactMarkupChecksum.canReuseMarkup(markup, rootElement)) {\n        ReactDOMComponentTree.precacheNode(instance, rootElement);\n        return;\n      } else {\n        var checksum = rootElement.getAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n        rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);\n\n        var rootMarkup = rootElement.outerHTML;\n        rootElement.setAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME, checksum);\n\n        var normalizedMarkup = markup;\n        if (\"development\" !== 'production') {\n          // because rootMarkup is retrieved from the DOM, various normalizations\n          // will have occurred which will not be present in `markup`. Here,\n          // insert markup into a <div> or <iframe> depending on the container\n          // type to perform the same normalizations before comparing.\n          var normalizer;\n          if (container.nodeType === ELEMENT_NODE_TYPE) {\n            normalizer = document.createElement('div');\n            normalizer.innerHTML = markup;\n            normalizedMarkup = normalizer.innerHTML;\n          } else {\n            normalizer = document.createElement('iframe');\n            document.body.appendChild(normalizer);\n            normalizer.contentDocument.write(markup);\n            normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;\n            document.body.removeChild(normalizer);\n          }\n        }\n\n        var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);\n        var difference = ' (client) ' + normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) + '\\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);\n\n        !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document using server rendering but the checksum was invalid. This usually means you rendered a different component type or props on the client from the one on the server, or your render() methods are impure. React cannot handle this case due to cross-browser quirks by rendering at the document root. You should look for environment dependent code in your components and ensure the props are the same client and server side:\\n%s', difference) : _prodInvariant('42', difference) : void 0;\n\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(false, 'React attempted to reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are ' + 'using server rendering and the markup generated on the ' + 'server was not what the client was expecting. React injected ' + 'new markup to compensate which works but you have lost many ' + 'of the benefits of server rendering. Instead, figure out ' + 'why the markup being generated is different on the client ' + 'or server:\\n%s', difference) : void 0;\n        }\n      }\n    }\n\n    !(container.nodeType !== DOC_NODE_TYPE) ? \"development\" !== 'production' ? invariant(false, 'You\\'re trying to render a component to the document but you didn\\'t use server rendering. We can\\'t do this without using server rendering due to cross-browser quirks. See ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('43') : void 0;\n\n    if (transaction.useCreateElement) {\n      while (container.lastChild) {\n        container.removeChild(container.lastChild);\n      }\n      DOMLazyTree.insertTreeBefore(container, markup, null);\n    } else {\n      setInnerHTML(container, markup);\n      ReactDOMComponentTree.precacheNode(instance, container.firstChild);\n    }\n\n    if (\"development\" !== 'production') {\n      var hostNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);\n      if (hostNode._debugID !== 0) {\n        ReactInstrumentation.debugTool.onHostOperation(hostNode._debugID, 'mount', markup.toString());\n      }\n    }\n  }\n};\n\nmodule.exports = ReactMount;\n},{\"10\":10,\"134\":134,\"139\":139,\"141\":141,\"143\":143,\"154\":154,\"161\":161,\"171\":171,\"27\":27,\"36\":36,\"41\":41,\"42\":42,\"46\":46,\"62\":62,\"68\":68,\"73\":73,\"74\":74,\"76\":76,\"8\":8,\"87\":87,\"94\":94,\"95\":95}],78:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChild\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactComponentEnvironment = _dereq_(33);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMultiChildUpdateTypes = _dereq_(79);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactReconciler = _dereq_(87);\nvar ReactChildReconciler = _dereq_(28);\n\nvar emptyFunction = _dereq_(153);\nvar flattenChildren = _dereq_(123);\nvar invariant = _dereq_(161);\n\n/**\n * Make an update for markup to be rendered and inserted at a supplied index.\n *\n * @param {string} markup Markup that renders into an element.\n * @param {number} toIndex Destination index.\n * @private\n */\nfunction makeInsertMarkup(markup, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.INSERT_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for moving an existing element to another index.\n *\n * @param {number} fromIndex Source index of the existing element.\n * @param {number} toIndex Destination index of the element.\n * @private\n */\nfunction makeMove(child, afterNode, toIndex) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.MOVE_EXISTING,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: ReactReconciler.getHostNode(child),\n    toIndex: toIndex,\n    afterNode: afterNode\n  };\n}\n\n/**\n * Make an update for removing an element at an index.\n *\n * @param {number} fromIndex Index of the element to remove.\n * @private\n */\nfunction makeRemove(child, node) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.REMOVE_NODE,\n    content: null,\n    fromIndex: child._mountIndex,\n    fromNode: node,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the markup of a node.\n *\n * @param {string} markup Markup that renders into an element.\n * @private\n */\nfunction makeSetMarkup(markup) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.SET_MARKUP,\n    content: markup,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Make an update for setting the text content.\n *\n * @param {string} textContent Text content to set.\n * @private\n */\nfunction makeTextContent(textContent) {\n  // NOTE: Null values reduce hidden classes.\n  return {\n    type: ReactMultiChildUpdateTypes.TEXT_CONTENT,\n    content: textContent,\n    fromIndex: null,\n    fromNode: null,\n    toIndex: null,\n    afterNode: null\n  };\n}\n\n/**\n * Push an update, if any, onto the queue. Creates a new queue if none is\n * passed and always returns the queue. Mutative.\n */\nfunction enqueue(queue, update) {\n  if (update) {\n    queue = queue || [];\n    queue.push(update);\n  }\n  return queue;\n}\n\n/**\n * Processes any enqueued updates.\n *\n * @private\n */\nfunction processQueue(inst, updateQueue) {\n  ReactComponentEnvironment.processChildrenUpdates(inst, updateQueue);\n}\n\nvar setParentForInstrumentation = emptyFunction;\nvar setChildrenForInstrumentation = emptyFunction;\nif (\"development\" !== 'production') {\n  var getDebugID = function (inst) {\n    if (!inst._debugID) {\n      // Check for ART-like instances. TODO: This is silly/gross.\n      var internal;\n      if (internal = ReactInstanceMap.get(inst)) {\n        inst = internal;\n      }\n    }\n    return inst._debugID;\n  };\n  setParentForInstrumentation = function (child) {\n    if (child._debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetParent(child._debugID, getDebugID(this));\n    }\n  };\n  setChildrenForInstrumentation = function (children) {\n    var debugID = getDebugID(this);\n    // TODO: React Native empty components are also multichild.\n    // This means they still get into this method but don't have _debugID.\n    if (debugID !== 0) {\n      ReactInstrumentation.debugTool.onSetChildren(debugID, children ? Object.keys(children).map(function (key) {\n        return children[key]._debugID;\n      }) : []);\n    }\n  };\n}\n\n/**\n * ReactMultiChild are capable of reconciling multiple children.\n *\n * @class ReactMultiChild\n * @internal\n */\nvar ReactMultiChild = {\n\n  /**\n   * Provides common functionality for components that must reconcile multiple\n   * children. This is used by `ReactDOMComponent` to mount, update, and\n   * unmount child components.\n   *\n   * @lends {ReactMultiChild.prototype}\n   */\n  Mixin: {\n\n    _reconcilerInstantiateChildren: function (nestedChildren, transaction, context) {\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n        }\n      }\n      return ReactChildReconciler.instantiateChildren(nestedChildren, transaction, context);\n    },\n\n    _reconcilerUpdateChildren: function (prevChildren, nextNestedChildrenElements, removedNodes, transaction, context) {\n      var nextChildren;\n      if (\"development\" !== 'production') {\n        if (this._currentElement) {\n          try {\n            ReactCurrentOwner.current = this._currentElement._owner;\n            nextChildren = flattenChildren(nextNestedChildrenElements, this._debugID);\n          } finally {\n            ReactCurrentOwner.current = null;\n          }\n          ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n          return nextChildren;\n        }\n      }\n      nextChildren = flattenChildren(nextNestedChildrenElements);\n      ReactChildReconciler.updateChildren(prevChildren, nextChildren, removedNodes, transaction, context);\n      return nextChildren;\n    },\n\n    /**\n     * Generates a \"mount image\" for each of the supplied children. In the case\n     * of `ReactDOMComponent`, a mount image is a string of markup.\n     *\n     * @param {?object} nestedChildren Nested child maps.\n     * @return {array} An array of mounted representations.\n     * @internal\n     */\n    mountChildren: function (nestedChildren, transaction, context) {\n      var children = this._reconcilerInstantiateChildren(nestedChildren, transaction, context);\n      this._renderedChildren = children;\n\n      var mountImages = [];\n      var index = 0;\n      for (var name in children) {\n        if (children.hasOwnProperty(name)) {\n          var child = children[name];\n          if (\"development\" !== 'production') {\n            setParentForInstrumentation.call(this, child);\n          }\n          var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n          child._mountIndex = index++;\n          mountImages.push(mountImage);\n        }\n      }\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, children);\n      }\n\n      return mountImages;\n    },\n\n    /**\n     * Replaces any rendered children with a text content string.\n     *\n     * @param {string} nextContent String of content.\n     * @internal\n     */\n    updateTextContent: function (nextContent) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      // Set new text content.\n      var updates = [makeTextContent(nextContent)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Replaces any rendered children with a markup string.\n     *\n     * @param {string} nextMarkup String of markup.\n     * @internal\n     */\n    updateMarkup: function (nextMarkup) {\n      var prevChildren = this._renderedChildren;\n      // Remove any rendered children.\n      ReactChildReconciler.unmountChildren(prevChildren, false);\n      for (var name in prevChildren) {\n        if (prevChildren.hasOwnProperty(name)) {\n          !false ? \"development\" !== 'production' ? invariant(false, 'updateTextContent called on non-empty component.') : _prodInvariant('118') : void 0;\n        }\n      }\n      var updates = [makeSetMarkup(nextMarkup)];\n      processQueue(this, updates);\n    },\n\n    /**\n     * Updates the rendered children with new children.\n     *\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @internal\n     */\n    updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      // Hook used by React ART\n      this._updateChildren(nextNestedChildrenElements, transaction, context);\n    },\n\n    /**\n     * @param {?object} nextNestedChildrenElements Nested child element maps.\n     * @param {ReactReconcileTransaction} transaction\n     * @final\n     * @protected\n     */\n    _updateChildren: function (nextNestedChildrenElements, transaction, context) {\n      var prevChildren = this._renderedChildren;\n      var removedNodes = {};\n      var nextChildren = this._reconcilerUpdateChildren(prevChildren, nextNestedChildrenElements, removedNodes, transaction, context);\n      if (!nextChildren && !prevChildren) {\n        return;\n      }\n      var updates = null;\n      var name;\n      // `nextIndex` will increment for each child in `nextChildren`, but\n      // `lastIndex` will be the last index visited in `prevChildren`.\n      var lastIndex = 0;\n      var nextIndex = 0;\n      var lastPlacedNode = null;\n      for (name in nextChildren) {\n        if (!nextChildren.hasOwnProperty(name)) {\n          continue;\n        }\n        var prevChild = prevChildren && prevChildren[name];\n        var nextChild = nextChildren[name];\n        if (prevChild === nextChild) {\n          updates = enqueue(updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex));\n          lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n          prevChild._mountIndex = nextIndex;\n        } else {\n          if (prevChild) {\n            // Update `lastIndex` before `_mountIndex` gets unset by unmounting.\n            lastIndex = Math.max(prevChild._mountIndex, lastIndex);\n            // The `removedNodes` loop below will actually remove the child.\n          }\n          // The child must be instantiated before it's mounted.\n          updates = enqueue(updates, this._mountChildAtIndex(nextChild, lastPlacedNode, nextIndex, transaction, context));\n        }\n        nextIndex++;\n        lastPlacedNode = ReactReconciler.getHostNode(nextChild);\n      }\n      // Remove children that are no longer present.\n      for (name in removedNodes) {\n        if (removedNodes.hasOwnProperty(name)) {\n          updates = enqueue(updates, this._unmountChild(prevChildren[name], removedNodes[name]));\n        }\n      }\n      if (updates) {\n        processQueue(this, updates);\n      }\n      this._renderedChildren = nextChildren;\n\n      if (\"development\" !== 'production') {\n        setChildrenForInstrumentation.call(this, nextChildren);\n      }\n    },\n\n    /**\n     * Unmounts all rendered children. This should be used to clean up children\n     * when this component is unmounted. It does not actually perform any\n     * backend operations.\n     *\n     * @internal\n     */\n    unmountChildren: function (safely) {\n      var renderedChildren = this._renderedChildren;\n      ReactChildReconciler.unmountChildren(renderedChildren, safely);\n      this._renderedChildren = null;\n    },\n\n    /**\n     * Moves a child component to the supplied index.\n     *\n     * @param {ReactComponent} child Component to move.\n     * @param {number} toIndex Destination index of the element.\n     * @param {number} lastIndex Last index visited of the siblings of `child`.\n     * @protected\n     */\n    moveChild: function (child, afterNode, toIndex, lastIndex) {\n      // If the index of `child` is less than `lastIndex`, then it needs to\n      // be moved. Otherwise, we do not need to move it because a child will be\n      // inserted or moved before `child`.\n      if (child._mountIndex < lastIndex) {\n        return makeMove(child, afterNode, toIndex);\n      }\n    },\n\n    /**\n     * Creates a child component.\n     *\n     * @param {ReactComponent} child Component to create.\n     * @param {string} mountImage Markup to insert.\n     * @protected\n     */\n    createChild: function (child, afterNode, mountImage) {\n      return makeInsertMarkup(mountImage, afterNode, child._mountIndex);\n    },\n\n    /**\n     * Removes a child component.\n     *\n     * @param {ReactComponent} child Child to remove.\n     * @protected\n     */\n    removeChild: function (child, node) {\n      return makeRemove(child, node);\n    },\n\n    /**\n     * Mounts a child with the supplied name.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to mount.\n     * @param {string} name Name of the child.\n     * @param {number} index Index at which to insert the child.\n     * @param {ReactReconcileTransaction} transaction\n     * @private\n     */\n    _mountChildAtIndex: function (child, afterNode, index, transaction, context) {\n      var mountImage = ReactReconciler.mountComponent(child, transaction, this, this._hostContainerInfo, context);\n      child._mountIndex = index;\n      return this.createChild(child, afterNode, mountImage);\n    },\n\n    /**\n     * Unmounts a rendered child.\n     *\n     * NOTE: This is part of `updateChildren` and is here for readability.\n     *\n     * @param {ReactComponent} child Component to unmount.\n     * @private\n     */\n    _unmountChild: function (child, node) {\n      var update = this.removeChild(child, node);\n      child._mountIndex = null;\n      return update;\n    }\n\n  }\n\n};\n\nmodule.exports = ReactMultiChild;\n},{\"123\":123,\"139\":139,\"153\":153,\"161\":161,\"28\":28,\"33\":33,\"36\":36,\"73\":73,\"74\":74,\"79\":79,\"87\":87}],79:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactMultiChildUpdateTypes\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\n/**\n * When a component's children are updated, a series of update configuration\n * objects are created in order to batch and serialize the required changes.\n *\n * Enumerates all the possible types of update configurations.\n *\n * @internal\n */\nvar ReactMultiChildUpdateTypes = keyMirror({\n  INSERT_MARKUP: null,\n  MOVE_EXISTING: null,\n  REMOVE_NODE: null,\n  SET_MARKUP: null,\n  TEXT_CONTENT: null\n});\n\nmodule.exports = ReactMultiChildUpdateTypes;\n},{\"164\":164}],80:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNodeTypes\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\nvar ReactNodeTypes = {\n  HOST: 0,\n  COMPOSITE: 1,\n  EMPTY: 2,\n\n  getType: function (node) {\n    if (node === null || node === false) {\n      return ReactNodeTypes.EMPTY;\n    } else if (ReactElement.isValidElement(node)) {\n      if (typeof node.type === 'function') {\n        return ReactNodeTypes.COMPOSITE;\n      } else {\n        return ReactNodeTypes.HOST;\n      }\n    }\n    !false ? \"development\" !== 'production' ? invariant(false, 'Unexpected node: %s', node) : _prodInvariant('26', node) : void 0;\n  }\n};\n\nmodule.exports = ReactNodeTypes;\n},{\"139\":139,\"161\":161,\"62\":62}],81:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactNoopUpdateQueue\n */\n\n'use strict';\n\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the abstract API for an update queue.\n */\nvar ReactNoopUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    return false;\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback) {},\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    warnNoop(publicInstance, 'forceUpdate');\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    warnNoop(publicInstance, 'replaceState');\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    warnNoop(publicInstance, 'setState');\n  }\n};\n\nmodule.exports = ReactNoopUpdateQueue;\n},{\"171\":171}],82:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactOwner\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * ReactOwners are capable of storing references to owned components.\n *\n * All components are capable of //being// referenced by owner components, but\n * only ReactOwner components are capable of //referencing// owned components.\n * The named reference is known as a \"ref\".\n *\n * Refs are available when mounted and updated during reconciliation.\n *\n *   var MyComponent = React.createClass({\n *     render: function() {\n *       return (\n *         <div onClick={this.handleClick}>\n *           <CustomComponent ref=\"custom\" />\n *         </div>\n *       );\n *     },\n *     handleClick: function() {\n *       this.refs.custom.handleClick();\n *     },\n *     componentDidMount: function() {\n *       this.refs.custom.initialize();\n *     }\n *   });\n *\n * Refs should rarely be used. When refs are used, they should only be done to\n * control data that is not handled by React's data flow.\n *\n * @class ReactOwner\n */\nvar ReactOwner = {\n\n  /**\n   * @param {?object} object\n   * @return {boolean} True if `object` is a valid owner.\n   * @final\n   */\n  isValidOwner: function (object) {\n    return !!(object && typeof object.attachRef === 'function' && typeof object.detachRef === 'function');\n  },\n\n  /**\n   * Adds a component by ref to an owner component.\n   *\n   * @param {ReactComponent} component Component to reference.\n   * @param {string} ref Name by which to refer to the component.\n   * @param {ReactOwner} owner Component on which to record the ref.\n   * @final\n   * @internal\n   */\n  addComponentAsRefTo: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('119') : void 0;\n    owner.attachRef(ref, component);\n  },\n\n  /**\n   * Removes a component by ref from an owner component.\n   *\n   * @param {ReactComponent} component Component to dereference.\n   * @param {string} ref Name of the ref to remove.\n   * @param {ReactOwner} owner Component on which the ref is recorded.\n   * @final\n   * @internal\n   */\n  removeComponentAsRefFrom: function (component, ref, owner) {\n    !ReactOwner.isValidOwner(owner) ? \"development\" !== 'production' ? invariant(false, 'removeComponentAsRefFrom(...): Only a ReactOwner can have refs. You might be removing a ref to a component that was not created inside a component\\'s `render` method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).') : _prodInvariant('120') : void 0;\n    var ownerPublicInstance = owner.getPublicInstance();\n    // Check that `component`'s owner is still alive and that `component` is still the current ref\n    // because we do not want to detach the ref if another component stole it.\n    if (ownerPublicInstance && ownerPublicInstance.refs[ref] === component.getPublicInstance()) {\n      owner.detachRef(ref);\n    }\n  }\n\n};\n\nmodule.exports = ReactOwner;\n},{\"139\":139,\"161\":161}],83:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocationNames\n */\n\n'use strict';\n\nvar ReactPropTypeLocationNames = {};\n\nif (\"development\" !== 'production') {\n  ReactPropTypeLocationNames = {\n    prop: 'prop',\n    context: 'context',\n    childContext: 'child context'\n  };\n}\n\nmodule.exports = ReactPropTypeLocationNames;\n},{}],84:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypeLocations\n */\n\n'use strict';\n\nvar keyMirror = _dereq_(164);\n\nvar ReactPropTypeLocations = keyMirror({\n  prop: null,\n  context: null,\n  childContext: null\n});\n\nmodule.exports = ReactPropTypeLocations;\n},{\"164\":164}],85:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactPropTypes\n */\n\n'use strict';\n\nvar ReactElement = _dereq_(62);\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar emptyFunction = _dereq_(153);\nvar getIteratorFn = _dereq_(130);\n\n/**\n * Collection of methods that allow declaration and validation of props that are\n * supplied to React components. Example usage:\n *\n *   var Props = require('ReactPropTypes');\n *   var MyArticle = React.createClass({\n *     propTypes: {\n *       // An optional string prop named \"description\".\n *       description: Props.string,\n *\n *       // A required enum prop named \"category\".\n *       category: Props.oneOf(['News','Photos']).isRequired,\n *\n *       // A prop named \"dialog\" that requires an instance of Dialog.\n *       dialog: Props.instanceOf(Dialog).isRequired\n *     },\n *     render: function() { ... }\n *   });\n *\n * A more formal specification of how these methods are used:\n *\n *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)\n *   decl := ReactPropTypes.{type}(.isRequired)?\n *\n * Each and every declaration produces a function with the same signature. This\n * allows the creation of custom validation functions. For example:\n *\n *  var MyLink = React.createClass({\n *    propTypes: {\n *      // An optional string or URI prop named \"href\".\n *      href: function(props, propName, componentName) {\n *        var propValue = props[propName];\n *        if (propValue != null && typeof propValue !== 'string' &&\n *            !(propValue instanceof URI)) {\n *          return new Error(\n *            'Expected a string or an URI for ' + propName + ' in ' +\n *            componentName\n *          );\n *        }\n *      }\n *    },\n *    render: function() {...}\n *  });\n *\n * @internal\n */\n\nvar ANONYMOUS = '<<anonymous>>';\n\nvar ReactPropTypes = {\n  array: createPrimitiveTypeChecker('array'),\n  bool: createPrimitiveTypeChecker('boolean'),\n  func: createPrimitiveTypeChecker('function'),\n  number: createPrimitiveTypeChecker('number'),\n  object: createPrimitiveTypeChecker('object'),\n  string: createPrimitiveTypeChecker('string'),\n  symbol: createPrimitiveTypeChecker('symbol'),\n\n  any: createAnyTypeChecker(),\n  arrayOf: createArrayOfTypeChecker,\n  element: createElementTypeChecker(),\n  instanceOf: createInstanceTypeChecker,\n  node: createNodeChecker(),\n  objectOf: createObjectOfTypeChecker,\n  oneOf: createEnumTypeChecker,\n  oneOfType: createUnionTypeChecker,\n  shape: createShapeTypeChecker\n};\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\n/*eslint-disable no-self-compare*/\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n/*eslint-enable no-self-compare*/\n\nfunction createChainableTypeChecker(validate) {\n  function checkType(isRequired, props, propName, componentName, location, propFullName) {\n    componentName = componentName || ANONYMOUS;\n    propFullName = propFullName || propName;\n    if (props[propName] == null) {\n      var locationName = ReactPropTypeLocationNames[location];\n      if (isRequired) {\n        return new Error('Required ' + locationName + ' `' + propFullName + '` was not specified in ' + ('`' + componentName + '`.'));\n      }\n      return null;\n    } else {\n      return validate(props, propName, componentName, location, propFullName);\n    }\n  }\n\n  var chainedCheckType = checkType.bind(null, false);\n  chainedCheckType.isRequired = checkType.bind(null, true);\n\n  return chainedCheckType;\n}\n\nfunction createPrimitiveTypeChecker(expectedType) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== expectedType) {\n      var locationName = ReactPropTypeLocationNames[location];\n      // `propValue` being instance of, say, date/regexp, pass the 'object'\n      // check, but we can offer a more precise error message here rather than\n      // 'of type `object`'.\n      var preciseType = getPreciseType(propValue);\n\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createAnyTypeChecker() {\n  return createChainableTypeChecker(emptyFunction.thatReturns(null));\n}\n\nfunction createArrayOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');\n    }\n    var propValue = props[propName];\n    if (!Array.isArray(propValue)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var propType = getPropType(propValue);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));\n    }\n    for (var i = 0; i < propValue.length; i++) {\n      var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']');\n      if (error instanceof Error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createElementTypeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!ReactElement.isValidElement(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a single ReactElement.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createInstanceTypeChecker(expectedClass) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!(props[propName] instanceof expectedClass)) {\n      var locationName = ReactPropTypeLocationNames[location];\n      var expectedClassName = expectedClass.name || ANONYMOUS;\n      var actualClassName = getClassName(props[propName]);\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createEnumTypeChecker(expectedValues) {\n  if (!Array.isArray(expectedValues)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOf, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    for (var i = 0; i < expectedValues.length; i++) {\n      if (is(propValue, expectedValues[i])) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    var valuesString = JSON.stringify(expectedValues);\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` of value `' + propValue + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createObjectOfTypeChecker(typeChecker) {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (typeof typeChecker !== 'function') {\n      return new Error('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');\n    }\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));\n    }\n    for (var key in propValue) {\n      if (propValue.hasOwnProperty(key)) {\n        var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key);\n        if (error instanceof Error) {\n          return error;\n        }\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createUnionTypeChecker(arrayOfTypeCheckers) {\n  if (!Array.isArray(arrayOfTypeCheckers)) {\n    return createChainableTypeChecker(function () {\n      return new Error('Invalid argument supplied to oneOfType, expected an instance of array.');\n    });\n  }\n\n  function validate(props, propName, componentName, location, propFullName) {\n    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {\n      var checker = arrayOfTypeCheckers[i];\n      if (checker(props, propName, componentName, location, propFullName) == null) {\n        return null;\n      }\n    }\n\n    var locationName = ReactPropTypeLocationNames[location];\n    return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createNodeChecker() {\n  function validate(props, propName, componentName, location, propFullName) {\n    if (!isNode(props[propName])) {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction createShapeTypeChecker(shapeTypes) {\n  function validate(props, propName, componentName, location, propFullName) {\n    var propValue = props[propName];\n    var propType = getPropType(propValue);\n    if (propType !== 'object') {\n      var locationName = ReactPropTypeLocationNames[location];\n      return new Error('Invalid ' + locationName + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));\n    }\n    for (var key in shapeTypes) {\n      var checker = shapeTypes[key];\n      if (!checker) {\n        continue;\n      }\n      var error = checker(propValue, key, componentName, location, propFullName + '.' + key);\n      if (error) {\n        return error;\n      }\n    }\n    return null;\n  }\n  return createChainableTypeChecker(validate);\n}\n\nfunction isNode(propValue) {\n  switch (typeof propValue) {\n    case 'number':\n    case 'string':\n    case 'undefined':\n      return true;\n    case 'boolean':\n      return !propValue;\n    case 'object':\n      if (Array.isArray(propValue)) {\n        return propValue.every(isNode);\n      }\n      if (propValue === null || ReactElement.isValidElement(propValue)) {\n        return true;\n      }\n\n      var iteratorFn = getIteratorFn(propValue);\n      if (iteratorFn) {\n        var iterator = iteratorFn.call(propValue);\n        var step;\n        if (iteratorFn !== propValue.entries) {\n          while (!(step = iterator.next()).done) {\n            if (!isNode(step.value)) {\n              return false;\n            }\n          }\n        } else {\n          // Iterator will provide entry [k,v] tuples rather than values.\n          while (!(step = iterator.next()).done) {\n            var entry = step.value;\n            if (entry) {\n              if (!isNode(entry[1])) {\n                return false;\n              }\n            }\n          }\n        }\n      } else {\n        return false;\n      }\n\n      return true;\n    default:\n      return false;\n  }\n}\n\nfunction isSymbol(propType, propValue) {\n  // Native Symbol.\n  if (propType === 'symbol') {\n    return true;\n  }\n\n  // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'\n  if (propValue['@@toStringTag'] === 'Symbol') {\n    return true;\n  }\n\n  // Fallback for non-spec compliant Symbols which are polyfilled.\n  if (typeof Symbol === 'function' && propValue instanceof Symbol) {\n    return true;\n  }\n\n  return false;\n}\n\n// Equivalent of `typeof` but with special handling for array and regexp.\nfunction getPropType(propValue) {\n  var propType = typeof propValue;\n  if (Array.isArray(propValue)) {\n    return 'array';\n  }\n  if (propValue instanceof RegExp) {\n    // Old webkits (at least until Android 4.0) return 'function' rather than\n    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/\n    // passes PropTypes.object.\n    return 'object';\n  }\n  if (isSymbol(propType, propValue)) {\n    return 'symbol';\n  }\n  return propType;\n}\n\n// This handles more types than `getPropType`. Only used for error messages.\n// See `createPrimitiveTypeChecker`.\nfunction getPreciseType(propValue) {\n  var propType = getPropType(propValue);\n  if (propType === 'object') {\n    if (propValue instanceof Date) {\n      return 'date';\n    } else if (propValue instanceof RegExp) {\n      return 'regexp';\n    }\n  }\n  return propType;\n}\n\n// Returns class name of the object, if any.\nfunction getClassName(propValue) {\n  if (!propValue.constructor || !propValue.constructor.name) {\n    return ANONYMOUS;\n  }\n  return propValue.constructor.name;\n}\n\nmodule.exports = ReactPropTypes;\n},{\"130\":130,\"153\":153,\"62\":62,\"83\":83}],86:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconcileTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactBrowserEventEmitter = _dereq_(27);\nvar ReactInputSelection = _dereq_(72);\nvar ReactInstrumentation = _dereq_(74);\nvar Transaction = _dereq_(113);\nvar ReactUpdateQueue = _dereq_(94);\n\n/**\n * Ensures that, when possible, the selection range (currently selected text\n * input) is not disturbed by performing the transaction.\n */\nvar SELECTION_RESTORATION = {\n  /**\n   * @return {Selection} Selection information.\n   */\n  initialize: ReactInputSelection.getSelectionInformation,\n  /**\n   * @param {Selection} sel Selection information returned from `initialize`.\n   */\n  close: ReactInputSelection.restoreSelection\n};\n\n/**\n * Suppresses events (blur/focus) that could be inadvertently dispatched due to\n * high level DOM manipulations (like temporarily removing a text input from the\n * DOM).\n */\nvar EVENT_SUPPRESSION = {\n  /**\n   * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before\n   * the reconciliation.\n   */\n  initialize: function () {\n    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();\n    ReactBrowserEventEmitter.setEnabled(false);\n    return currentlyEnabled;\n  },\n\n  /**\n   * @param {boolean} previouslyEnabled Enabled status of\n   *   `ReactBrowserEventEmitter` before the reconciliation occurred. `close`\n   *   restores the previous value.\n   */\n  close: function (previouslyEnabled) {\n    ReactBrowserEventEmitter.setEnabled(previouslyEnabled);\n  }\n};\n\n/**\n * Provides a queue for collecting `componentDidMount` and\n * `componentDidUpdate` callbacks during the transaction.\n */\nvar ON_DOM_READY_QUEUEING = {\n  /**\n   * Initializes the internal `onDOMReady` queue.\n   */\n  initialize: function () {\n    this.reactMountReady.reset();\n  },\n\n  /**\n   * After DOM is flushed, invoke all registered `onDOMReady` callbacks.\n   */\n  close: function () {\n    this.reactMountReady.notifyAll();\n  }\n};\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\n/**\n * Currently:\n * - The order that these are listed in the transaction is critical:\n * - Suppresses events.\n * - Restores selection range.\n *\n * Future:\n * - Restore document/overflow scroll positions that were unintentionally\n *   modified via DOM insertions above the top viewport boundary.\n * - Implement/integrate with customized constraint based layout system and keep\n *   track of which dimensions must be remeasured.\n *\n * @class ReactReconcileTransaction\n */\nfunction ReactReconcileTransaction(useCreateElement) {\n  this.reinitializeTransaction();\n  // Only server-side rendering really needs this option (see\n  // `ReactServerRendering`), but server-side uses\n  // `ReactServerRenderingTransaction` instead. This option is here so that it's\n  // accessible and defaults to false when `ReactDOMComponent` and\n  // `ReactDOMTextComponent` checks it in `mountComponent`.`\n  this.renderToStaticMarkup = false;\n  this.reactMountReady = CallbackQueue.getPooled(null);\n  this.useCreateElement = useCreateElement;\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array<object>} List of operation wrap procedures.\n   *   TODO: convert to array<TransactionWrapper>\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return this.reactMountReady;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return ReactUpdateQueue;\n  },\n\n  /**\n   * Save current transaction state -- if the return value from this method is\n   * passed to `rollback`, the transaction will be reset to that state.\n   */\n  checkpoint: function () {\n    // reactMountReady is the our only stateful wrapper\n    return this.reactMountReady.checkpoint();\n  },\n\n  rollback: function (checkpoint) {\n    this.reactMountReady.rollback(checkpoint);\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {\n    CallbackQueue.release(this.reactMountReady);\n    this.reactMountReady = null;\n  }\n};\n\n_assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactReconcileTransaction);\n\nmodule.exports = ReactReconcileTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"27\":27,\"5\":5,\"72\":72,\"74\":74,\"94\":94}],87:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactReconciler\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactRef = _dereq_(88);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\n\n/**\n * Helper to call ReactRef.attachRefs with this composite component, split out\n * to avoid allocations in the transaction mount-ready queue.\n */\nfunction attachRefs() {\n  ReactRef.attachRefs(this, this._currentElement);\n}\n\nvar ReactReconciler = {\n\n  /**\n   * Initializes the component, renders markup, and registers event listeners.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction\n   * @param {?object} the containing host component instance\n   * @param {?object} info about the host container\n   * @return {?string} Rendered markup to be inserted into the DOM.\n   * @final\n   * @internal\n   */\n  mountComponent: function (internalInstance, transaction, hostParent, hostContainerInfo, context) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeMountComponent(internalInstance._debugID, internalInstance._currentElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'mountComponent');\n      }\n    }\n    var markup = internalInstance.mountComponent(transaction, hostParent, hostContainerInfo, context);\n    if (internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'mountComponent');\n        ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID);\n      }\n    }\n    return markup;\n  },\n\n  /**\n   * Returns a value that can be passed to\n   * ReactComponentEnvironment.replaceNodeWithMarkup.\n   */\n  getHostNode: function (internalInstance) {\n    return internalInstance.getHostNode();\n  },\n\n  /**\n   * Releases any resources allocated by `mountComponent`.\n   *\n   * @final\n   * @internal\n   */\n  unmountComponent: function (internalInstance, safely) {\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n      }\n    }\n    ReactRef.detachRefs(internalInstance, internalInstance._currentElement);\n    internalInstance.unmountComponent(safely);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'unmountComponent');\n        ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Update a component using a new element.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactElement} nextElement\n   * @param {ReactReconcileTransaction} transaction\n   * @param {object} context\n   * @internal\n   */\n  receiveComponent: function (internalInstance, nextElement, transaction, context) {\n    var prevElement = internalInstance._currentElement;\n\n    if (nextElement === prevElement && context === internalInstance._context) {\n      // Since elements are immutable after the owner is rendered,\n      // we can do a cheap identity compare here to determine if this is a\n      // superfluous reconcile. It's possible for state to be mutable but such\n      // change should trigger an update of the owner which would recreate\n      // the element. We explicitly check for the existence of an owner since\n      // it's possible for an element created outside a composite to be\n      // deeply mutated and reused.\n\n      // TODO: Bailing out early is just a perf optimization right?\n      // TODO: Removing the return statement should affect correctness?\n      return;\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, nextElement);\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n      }\n    }\n\n    var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement);\n\n    if (refsChanged) {\n      ReactRef.detachRefs(internalInstance, prevElement);\n    }\n\n    internalInstance.receiveComponent(nextElement, transaction, context);\n\n    if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) {\n      transaction.getReactMountReady().enqueue(attachRefs, internalInstance);\n    }\n\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'receiveComponent');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  },\n\n  /**\n   * Flush any dirty changes in a component.\n   *\n   * @param {ReactComponent} internalInstance\n   * @param {ReactReconcileTransaction} transaction\n   * @internal\n   */\n  performUpdateIfNecessary: function (internalInstance, transaction, updateBatchNumber) {\n    if (internalInstance._updateBatchNumber !== updateBatchNumber) {\n      // The component's enqueued batch number should always be the current\n      // batch or the following one.\n      !(internalInstance._updateBatchNumber == null || internalInstance._updateBatchNumber === updateBatchNumber + 1) ? \"development\" !== 'production' ? invariant(false, 'performUpdateIfNecessary: Unexpected batch number (current %s, pending %s)', updateBatchNumber, internalInstance._updateBatchNumber) : _prodInvariant('121', updateBatchNumber, internalInstance._updateBatchNumber) : void 0;\n      return;\n    }\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onBeforeUpdateComponent(internalInstance._debugID, internalInstance._currentElement);\n      }\n    }\n    internalInstance.performUpdateIfNecessary(transaction);\n    if (\"development\" !== 'production') {\n      if (internalInstance._debugID !== 0) {\n        ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary');\n        ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID);\n      }\n    }\n  }\n\n};\n\nmodule.exports = ReactReconciler;\n},{\"139\":139,\"161\":161,\"74\":74,\"88\":88}],88:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactRef\n */\n\n'use strict';\n\nvar ReactOwner = _dereq_(82);\n\nvar ReactRef = {};\n\nfunction attachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(component.getPublicInstance());\n  } else {\n    // Legacy ref\n    ReactOwner.addComponentAsRefTo(component, ref, owner);\n  }\n}\n\nfunction detachRef(ref, component, owner) {\n  if (typeof ref === 'function') {\n    ref(null);\n  } else {\n    // Legacy ref\n    ReactOwner.removeComponentAsRefFrom(component, ref, owner);\n  }\n}\n\nReactRef.attachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    attachRef(ref, instance, element._owner);\n  }\n};\n\nReactRef.shouldUpdateRefs = function (prevElement, nextElement) {\n  // If either the owner or a `ref` has changed, make sure the newest owner\n  // has stored a reference to `this`, and the previous owner (if different)\n  // has forgotten the reference to `this`. We use the element instead\n  // of the public this.props because the post processing cannot determine\n  // a ref. The ref conceptually lives on the element.\n\n  // TODO: Should this even be possible? The owner cannot change because\n  // it's forbidden by shouldUpdateReactComponent. The ref can change\n  // if you swap the keys of but not the refs. Reconsider where this check\n  // is made. It probably belongs where the key checking and\n  // instantiateReactComponent is done.\n\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n\n  return(\n    // This has a few false positives w/r/t empty components.\n    prevEmpty || nextEmpty || nextElement._owner !== prevElement._owner || nextElement.ref !== prevElement.ref\n  );\n};\n\nReactRef.detachRefs = function (instance, element) {\n  if (element === null || element === false) {\n    return;\n  }\n  var ref = element.ref;\n  if (ref != null) {\n    detachRef(ref, instance, element._owner);\n  }\n};\n\nmodule.exports = ReactRef;\n},{\"82\":82}],89:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerBatchingStrategy\n */\n\n'use strict';\n\nvar ReactServerBatchingStrategy = {\n  isBatchingUpdates: false,\n  batchedUpdates: function (callback) {\n    // Don't do anything here. During the server rendering we don't want to\n    // schedule any updates. We will simply ignore them.\n  }\n};\n\nmodule.exports = ReactServerBatchingStrategy;\n},{}],90:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRendering\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactDOMContainerInfo = _dereq_(42);\nvar ReactDefaultBatchingStrategy = _dereq_(60);\nvar ReactElement = _dereq_(62);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactMarkupChecksum = _dereq_(76);\nvar ReactReconciler = _dereq_(87);\nvar ReactServerBatchingStrategy = _dereq_(89);\nvar ReactServerRenderingTransaction = _dereq_(91);\nvar ReactUpdates = _dereq_(95);\n\nvar emptyObject = _dereq_(154);\nvar instantiateReactComponent = _dereq_(134);\nvar invariant = _dereq_(161);\n\n/**\n * @param {ReactElement} element\n * @return {string} the HTML markup\n */\nfunction renderToStringImpl(element, makeStaticMarkup) {\n  var transaction;\n  try {\n    ReactUpdates.injection.injectBatchingStrategy(ReactServerBatchingStrategy);\n\n    transaction = ReactServerRenderingTransaction.getPooled(makeStaticMarkup);\n\n    return transaction.perform(function () {\n      var componentInstance = instantiateReactComponent(element, true);\n      var markup = ReactReconciler.mountComponent(componentInstance, transaction, null, ReactDOMContainerInfo(), emptyObject);\n      if (\"development\" !== 'production') {\n        ReactInstrumentation.debugTool.onUnmountComponent(componentInstance._debugID);\n      }\n      if (!makeStaticMarkup) {\n        markup = ReactMarkupChecksum.addChecksumToMarkup(markup);\n      }\n      return markup;\n    }, null);\n  } finally {\n    ReactServerRenderingTransaction.release(transaction);\n    // Revert to the DOM batching strategy since these two renderers\n    // currently share these stateful modules.\n    ReactUpdates.injection.injectBatchingStrategy(ReactDefaultBatchingStrategy);\n  }\n}\n\n/**\n * Render a ReactElement to its initial HTML. This should only be used on the\n * server.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostring\n */\nfunction renderToString(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToString(): You must pass a valid ReactElement.') : _prodInvariant('46') : void 0;\n  return renderToStringImpl(element, false);\n}\n\n/**\n * Similar to renderToString, except this doesn't create extra DOM attributes\n * such as data-react-id that React uses internally.\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostaticmarkup\n */\nfunction renderToStaticMarkup(element) {\n  !ReactElement.isValidElement(element) ? \"development\" !== 'production' ? invariant(false, 'renderToStaticMarkup(): You must pass a valid ReactElement.') : _prodInvariant('47') : void 0;\n  return renderToStringImpl(element, true);\n}\n\nmodule.exports = {\n  renderToString: renderToString,\n  renderToStaticMarkup: renderToStaticMarkup\n};\n},{\"134\":134,\"139\":139,\"154\":154,\"161\":161,\"42\":42,\"60\":60,\"62\":62,\"74\":74,\"76\":76,\"87\":87,\"89\":89,\"91\":91,\"95\":95}],91:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerRenderingTransaction\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\nvar Transaction = _dereq_(113);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactServerUpdateQueue = _dereq_(92);\n\n/**\n * Executed within the scope of the `Transaction` instance. Consider these as\n * being member methods, but with an implied ordering while being isolated from\n * each other.\n */\nvar TRANSACTION_WRAPPERS = [];\n\nif (\"development\" !== 'production') {\n  TRANSACTION_WRAPPERS.push({\n    initialize: ReactInstrumentation.debugTool.onBeginFlush,\n    close: ReactInstrumentation.debugTool.onEndFlush\n  });\n}\n\nvar noopCallbackQueue = {\n  enqueue: function () {}\n};\n\n/**\n * @class ReactServerRenderingTransaction\n * @param {boolean} renderToStaticMarkup\n */\nfunction ReactServerRenderingTransaction(renderToStaticMarkup) {\n  this.reinitializeTransaction();\n  this.renderToStaticMarkup = renderToStaticMarkup;\n  this.useCreateElement = false;\n  this.updateQueue = new ReactServerUpdateQueue(this);\n}\n\nvar Mixin = {\n  /**\n   * @see Transaction\n   * @abstract\n   * @final\n   * @return {array} Empty list of operation wrap procedures.\n   */\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  /**\n   * @return {object} The queue to collect `onDOMReady` callbacks with.\n   */\n  getReactMountReady: function () {\n    return noopCallbackQueue;\n  },\n\n  /**\n   * @return {object} The queue to collect React async events.\n   */\n  getUpdateQueue: function () {\n    return this.updateQueue;\n  },\n\n  /**\n   * `PooledClass` looks for this, and will invoke this before allowing this\n   * instance to be reused.\n   */\n  destructor: function () {},\n\n  checkpoint: function () {},\n\n  rollback: function () {}\n};\n\n_assign(ReactServerRenderingTransaction.prototype, Transaction.Mixin, Mixin);\n\nPooledClass.addPoolingTo(ReactServerRenderingTransaction);\n\nmodule.exports = ReactServerRenderingTransaction;\n},{\"113\":113,\"172\":172,\"25\":25,\"74\":74,\"92\":92}],92:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactServerUpdateQueue\n * \n */\n\n'use strict';\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nvar ReactUpdateQueue = _dereq_(94);\nvar Transaction = _dereq_(113);\nvar warning = _dereq_(171);\n\nfunction warnNoop(publicInstance, callerName) {\n  if (\"development\" !== 'production') {\n    var constructor = publicInstance.constructor;\n    \"development\" !== 'production' ? warning(false, '%s(...): Can only update a mounting component. ' + 'This usually means you called %s() outside componentWillMount() on the server. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, constructor && (constructor.displayName || constructor.name) || 'ReactClass') : void 0;\n  }\n}\n\n/**\n * This is the update queue used for server rendering.\n * It delegates to ReactUpdateQueue while server rendering is in progress and\n * switches to ReactNoopUpdateQueue after the transaction has completed.\n * @class ReactServerUpdateQueue\n * @param {Transaction} transaction\n */\n\nvar ReactServerUpdateQueue = function () {\n  /* :: transaction: Transaction; */\n\n  function ReactServerUpdateQueue(transaction) {\n    _classCallCheck(this, ReactServerUpdateQueue);\n\n    this.transaction = transaction;\n  }\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n\n\n  ReactServerUpdateQueue.prototype.isMounted = function isMounted(publicInstance) {\n    return false;\n  };\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueCallback = function enqueueCallback(publicInstance, callback, callerName) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueCallback(publicInstance, callback, callerName);\n    }\n  };\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueForceUpdate = function enqueueForceUpdate(publicInstance) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueForceUpdate(publicInstance);\n    } else {\n      warnNoop(publicInstance, 'forceUpdate');\n    }\n  };\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} completeState Next state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueReplaceState = function enqueueReplaceState(publicInstance, completeState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueReplaceState(publicInstance, completeState);\n    } else {\n      warnNoop(publicInstance, 'replaceState');\n    }\n  };\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object|function} partialState Next partial state to be merged with state.\n   * @internal\n   */\n\n\n  ReactServerUpdateQueue.prototype.enqueueSetState = function enqueueSetState(publicInstance, partialState) {\n    if (this.transaction.isInTransaction()) {\n      ReactUpdateQueue.enqueueSetState(publicInstance, partialState);\n    } else {\n      warnNoop(publicInstance, 'setState');\n    }\n  };\n\n  return ReactServerUpdateQueue;\n}();\n\nmodule.exports = ReactServerUpdateQueue;\n},{\"113\":113,\"171\":171,\"94\":94}],93:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUMDEntry\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar ReactDOM = _dereq_(37);\nvar ReactDOMServer = _dereq_(54);\nvar React = _dereq_(26);\n\n// `version` will be added here by ReactIsomorphic.\nvar ReactUMDEntry = _assign({\n  __SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOM,\n  __SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactDOMServer\n}, React);\n\nmodule.exports = ReactUMDEntry;\n},{\"172\":172,\"26\":26,\"37\":37,\"54\":54}],94:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdateQueue\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactInstanceMap = _dereq_(73);\nvar ReactInstrumentation = _dereq_(74);\nvar ReactUpdates = _dereq_(95);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nfunction enqueueUpdate(internalInstance) {\n  ReactUpdates.enqueueUpdate(internalInstance);\n}\n\nfunction formatUnexpectedArgument(arg) {\n  var type = typeof arg;\n  if (type !== 'object') {\n    return type;\n  }\n  var displayName = arg.constructor && arg.constructor.name || type;\n  var keys = Object.keys(arg);\n  if (keys.length > 0 && keys.length < 20) {\n    return displayName + ' (keys: ' + keys.join(', ') + ')';\n  }\n  return displayName;\n}\n\nfunction getInternalInstanceReadyForUpdate(publicInstance, callerName) {\n  var internalInstance = ReactInstanceMap.get(publicInstance);\n  if (!internalInstance) {\n    if (\"development\" !== 'production') {\n      // Only warn when we have a callerName. Otherwise we should be silent.\n      // We're probably calling from enqueueCallback. We don't want to warn\n      // there because we already warned for the corresponding lifecycle method.\n      \"development\" !== 'production' ? warning(!callerName, '%s(...): Can only update a mounted or mounting component. ' + 'This usually means you called %s() on an unmounted component. ' + 'This is a no-op. Please check the code for the %s component.', callerName, callerName, publicInstance.constructor.displayName) : void 0;\n    }\n    return null;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(ReactCurrentOwner.current == null, '%s(...): Cannot update during an existing state transition (such as ' + 'within `render` or another component\\'s constructor). Render methods ' + 'should be a pure function of props and state; constructor ' + 'side-effects are an anti-pattern, but can be moved to ' + '`componentWillMount`.', callerName) : void 0;\n  }\n\n  return internalInstance;\n}\n\n/**\n * ReactUpdateQueue allows for state updates to be scheduled into a later\n * reconciliation step.\n */\nvar ReactUpdateQueue = {\n\n  /**\n   * Checks whether or not this composite component is mounted.\n   * @param {ReactClass} publicInstance The instance we want to test.\n   * @return {boolean} True if mounted, false otherwise.\n   * @protected\n   * @final\n   */\n  isMounted: function (publicInstance) {\n    if (\"development\" !== 'production') {\n      var owner = ReactCurrentOwner.current;\n      if (owner !== null) {\n        \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing isMounted inside its render() function. ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n        owner._warnedAboutRefsInRender = true;\n      }\n    }\n    var internalInstance = ReactInstanceMap.get(publicInstance);\n    if (internalInstance) {\n      // During componentWillMount and render this will still be null but after\n      // that will always render to something. At least for now. So we can use\n      // this hack.\n      return !!internalInstance._renderedComponent;\n    } else {\n      return false;\n    }\n  },\n\n  /**\n   * Enqueue a callback that will be executed after all the pending updates\n   * have processed.\n   *\n   * @param {ReactClass} publicInstance The instance to use as `this` context.\n   * @param {?function} callback Called after state is updated.\n   * @param {string} callerName Name of the calling function in the public API.\n   * @internal\n   */\n  enqueueCallback: function (publicInstance, callback, callerName) {\n    ReactUpdateQueue.validateCallback(callback, callerName);\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);\n\n    // Previously we would throw an error if we didn't have an internal\n    // instance. Since we want to make it a no-op instead, we mirror the same\n    // behavior we have in other enqueue* methods.\n    // We also need to ignore callbacks in componentWillMount. See\n    // enqueueUpdates.\n    if (!internalInstance) {\n      return null;\n    }\n\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    // TODO: The callback here is ignored when setState is called from\n    // componentWillMount. Either fix it or disallow doing so completely in\n    // favor of getInitialState. Alternatively, we can disallow\n    // componentWillMount during server-side rendering.\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueCallbackInternal: function (internalInstance, callback) {\n    if (internalInstance._pendingCallbacks) {\n      internalInstance._pendingCallbacks.push(callback);\n    } else {\n      internalInstance._pendingCallbacks = [callback];\n    }\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Forces an update. This should only be invoked when it is known with\n   * certainty that we are **not** in a DOM transaction.\n   *\n   * You may want to call this when you know that some deeper aspect of the\n   * component's state has changed but `setState` was not called.\n   *\n   * This will not invoke `shouldComponentUpdate`, but it will invoke\n   * `componentWillUpdate` and `componentDidUpdate`.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @internal\n   */\n  enqueueForceUpdate: function (publicInstance) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'forceUpdate');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingForceUpdate = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Replaces all of the state. Always use this or `setState` to mutate state.\n   * You should treat `this.state` as immutable.\n   *\n   * There is no guarantee that `this.state` will be immediately updated, so\n   * accessing `this.state` after calling this method may return the old value.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} completeState Next state.\n   * @internal\n   */\n  enqueueReplaceState: function (publicInstance, completeState) {\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'replaceState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    internalInstance._pendingStateQueue = [completeState];\n    internalInstance._pendingReplaceState = true;\n\n    enqueueUpdate(internalInstance);\n  },\n\n  /**\n   * Sets a subset of the state. This only exists because _pendingState is\n   * internal. This provides a merging strategy that is not available to deep\n   * properties which is confusing. TODO: Expose pendingState or don't use it\n   * during the merge.\n   *\n   * @param {ReactClass} publicInstance The instance that should rerender.\n   * @param {object} partialState Next partial state to be merged with state.\n   * @internal\n   */\n  enqueueSetState: function (publicInstance, partialState) {\n    if (\"development\" !== 'production') {\n      ReactInstrumentation.debugTool.onSetState();\n      \"development\" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : void 0;\n    }\n\n    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');\n\n    if (!internalInstance) {\n      return;\n    }\n\n    var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);\n    queue.push(partialState);\n\n    enqueueUpdate(internalInstance);\n  },\n\n  enqueueElementInternal: function (internalInstance, nextElement, nextContext) {\n    internalInstance._pendingElement = nextElement;\n    // TODO: introduce _pendingContext instead of setting it directly.\n    internalInstance._context = nextContext;\n    enqueueUpdate(internalInstance);\n  },\n\n  validateCallback: function (callback, callerName) {\n    !(!callback || typeof callback === 'function') ? \"development\" !== 'production' ? invariant(false, '%s(...): Expected the last optional `callback` argument to be a function. Instead received: %s.', callerName, formatUnexpectedArgument(callback)) : _prodInvariant('122', callerName, formatUnexpectedArgument(callback)) : void 0;\n  }\n\n};\n\nmodule.exports = ReactUpdateQueue;\n},{\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"73\":73,\"74\":74,\"95\":95}],95:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactUpdates\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar CallbackQueue = _dereq_(5);\nvar PooledClass = _dereq_(25);\nvar ReactFeatureFlags = _dereq_(68);\nvar ReactReconciler = _dereq_(87);\nvar Transaction = _dereq_(113);\n\nvar invariant = _dereq_(161);\n\nvar dirtyComponents = [];\nvar updateBatchNumber = 0;\nvar asapCallbackQueue = CallbackQueue.getPooled();\nvar asapEnqueued = false;\n\nvar batchingStrategy = null;\n\nfunction ensureInjected() {\n  !(ReactUpdates.ReactReconcileTransaction && batchingStrategy) ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must inject a reconcile transaction class and batching strategy') : _prodInvariant('123') : void 0;\n}\n\nvar NESTED_UPDATES = {\n  initialize: function () {\n    this.dirtyComponentsLength = dirtyComponents.length;\n  },\n  close: function () {\n    if (this.dirtyComponentsLength !== dirtyComponents.length) {\n      // Additional updates were enqueued by componentDidUpdate handlers or\n      // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run\n      // these new updates so that if A's componentDidUpdate calls setState on\n      // B, B will update before the callback A's updater provided when calling\n      // setState.\n      dirtyComponents.splice(0, this.dirtyComponentsLength);\n      flushBatchedUpdates();\n    } else {\n      dirtyComponents.length = 0;\n    }\n  }\n};\n\nvar UPDATE_QUEUEING = {\n  initialize: function () {\n    this.callbackQueue.reset();\n  },\n  close: function () {\n    this.callbackQueue.notifyAll();\n  }\n};\n\nvar TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];\n\nfunction ReactUpdatesFlushTransaction() {\n  this.reinitializeTransaction();\n  this.dirtyComponentsLength = null;\n  this.callbackQueue = CallbackQueue.getPooled();\n  this.reconcileTransaction = ReactUpdates.ReactReconcileTransaction.getPooled(\n  /* useCreateElement */true);\n}\n\n_assign(ReactUpdatesFlushTransaction.prototype, Transaction.Mixin, {\n  getTransactionWrappers: function () {\n    return TRANSACTION_WRAPPERS;\n  },\n\n  destructor: function () {\n    this.dirtyComponentsLength = null;\n    CallbackQueue.release(this.callbackQueue);\n    this.callbackQueue = null;\n    ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);\n    this.reconcileTransaction = null;\n  },\n\n  perform: function (method, scope, a) {\n    // Essentially calls `this.reconcileTransaction.perform(method, scope, a)`\n    // with this transaction's wrappers around it.\n    return Transaction.Mixin.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a);\n  }\n});\n\nPooledClass.addPoolingTo(ReactUpdatesFlushTransaction);\n\nfunction batchedUpdates(callback, a, b, c, d, e) {\n  ensureInjected();\n  batchingStrategy.batchedUpdates(callback, a, b, c, d, e);\n}\n\n/**\n * Array comparator for ReactComponents by mount ordering.\n *\n * @param {ReactComponent} c1 first component you're comparing\n * @param {ReactComponent} c2 second component you're comparing\n * @return {number} Return value usable by Array.prototype.sort().\n */\nfunction mountOrderComparator(c1, c2) {\n  return c1._mountOrder - c2._mountOrder;\n}\n\nfunction runBatchedUpdates(transaction) {\n  var len = transaction.dirtyComponentsLength;\n  !(len === dirtyComponents.length) ? \"development\" !== 'production' ? invariant(false, 'Expected flush transaction\\'s stored dirty-components length (%s) to match dirty-components array length (%s).', len, dirtyComponents.length) : _prodInvariant('124', len, dirtyComponents.length) : void 0;\n\n  // Since reconciling a component higher in the owner hierarchy usually (not\n  // always -- see shouldComponentUpdate()) will reconcile children, reconcile\n  // them before their children by sorting the array.\n  dirtyComponents.sort(mountOrderComparator);\n\n  // Any updates enqueued while reconciling must be performed after this entire\n  // batch. Otherwise, if dirtyComponents is [A, B] where A has children B and\n  // C, B could update twice in a single batch if C's render enqueues an update\n  // to B (since B would have already updated, we should skip it, and the only\n  // way we can know to do so is by checking the batch counter).\n  updateBatchNumber++;\n\n  for (var i = 0; i < len; i++) {\n    // If a component is unmounted before pending changes apply, it will still\n    // be here, but we assume that it has cleared its _pendingCallbacks and\n    // that performUpdateIfNecessary is a noop.\n    var component = dirtyComponents[i];\n\n    // If performUpdateIfNecessary happens to enqueue any new updates, we\n    // shouldn't execute the callbacks until the next render happens, so\n    // stash the callbacks first\n    var callbacks = component._pendingCallbacks;\n    component._pendingCallbacks = null;\n\n    var markerName;\n    if (ReactFeatureFlags.logTopLevelRenders) {\n      var namedComponent = component;\n      // Duck type TopLevelWrapper. This is probably always true.\n      if (component._currentElement.props === component._renderedComponent._currentElement) {\n        namedComponent = component._renderedComponent;\n      }\n      markerName = 'React update: ' + namedComponent.getName();\n      console.time(markerName);\n    }\n\n    ReactReconciler.performUpdateIfNecessary(component, transaction.reconcileTransaction, updateBatchNumber);\n\n    if (markerName) {\n      console.timeEnd(markerName);\n    }\n\n    if (callbacks) {\n      for (var j = 0; j < callbacks.length; j++) {\n        transaction.callbackQueue.enqueue(callbacks[j], component.getPublicInstance());\n      }\n    }\n  }\n}\n\nvar flushBatchedUpdates = function () {\n  // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents\n  // array and perform any updates enqueued by mount-ready handlers (i.e.,\n  // componentDidUpdate) but we need to check here too in order to catch\n  // updates enqueued by setState callbacks and asap calls.\n  while (dirtyComponents.length || asapEnqueued) {\n    if (dirtyComponents.length) {\n      var transaction = ReactUpdatesFlushTransaction.getPooled();\n      transaction.perform(runBatchedUpdates, null, transaction);\n      ReactUpdatesFlushTransaction.release(transaction);\n    }\n\n    if (asapEnqueued) {\n      asapEnqueued = false;\n      var queue = asapCallbackQueue;\n      asapCallbackQueue = CallbackQueue.getPooled();\n      queue.notifyAll();\n      CallbackQueue.release(queue);\n    }\n  }\n};\n\n/**\n * Mark a component as needing a rerender, adding an optional callback to a\n * list of functions which will be executed once the rerender occurs.\n */\nfunction enqueueUpdate(component) {\n  ensureInjected();\n\n  // Various parts of our code (such as ReactCompositeComponent's\n  // _renderValidatedComponent) assume that calls to render aren't nested;\n  // verify that that's the case. (This is called by each top-level update\n  // function, like setState, forceUpdate, etc.; creation and\n  // destruction of top-level components is guarded in ReactMount.)\n\n  if (!batchingStrategy.isBatchingUpdates) {\n    batchingStrategy.batchedUpdates(enqueueUpdate, component);\n    return;\n  }\n\n  dirtyComponents.push(component);\n  if (component._updateBatchNumber == null) {\n    component._updateBatchNumber = updateBatchNumber + 1;\n  }\n}\n\n/**\n * Enqueue a callback to be run at the end of the current batching cycle. Throws\n * if no updates are currently being performed.\n */\nfunction asap(callback, context) {\n  !batchingStrategy.isBatchingUpdates ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates.asap: Can\\'t enqueue an asap callback in a context whereupdates are not being batched.') : _prodInvariant('125') : void 0;\n  asapCallbackQueue.enqueue(callback, context);\n  asapEnqueued = true;\n}\n\nvar ReactUpdatesInjection = {\n  injectReconcileTransaction: function (ReconcileTransaction) {\n    !ReconcileTransaction ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a reconcile transaction class') : _prodInvariant('126') : void 0;\n    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;\n  },\n\n  injectBatchingStrategy: function (_batchingStrategy) {\n    !_batchingStrategy ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batching strategy') : _prodInvariant('127') : void 0;\n    !(typeof _batchingStrategy.batchedUpdates === 'function') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide a batchedUpdates() function') : _prodInvariant('128') : void 0;\n    !(typeof _batchingStrategy.isBatchingUpdates === 'boolean') ? \"development\" !== 'production' ? invariant(false, 'ReactUpdates: must provide an isBatchingUpdates boolean attribute') : _prodInvariant('129') : void 0;\n    batchingStrategy = _batchingStrategy;\n  }\n};\n\nvar ReactUpdates = {\n  /**\n   * React references `ReactReconcileTransaction` using this property in order\n   * to allow dependency injection.\n   *\n   * @internal\n   */\n  ReactReconcileTransaction: null,\n\n  batchedUpdates: batchedUpdates,\n  enqueueUpdate: enqueueUpdate,\n  flushBatchedUpdates: flushBatchedUpdates,\n  injection: ReactUpdatesInjection,\n  asap: asap\n};\n\nmodule.exports = ReactUpdates;\n},{\"113\":113,\"139\":139,\"161\":161,\"172\":172,\"25\":25,\"5\":5,\"68\":68,\"87\":87}],96:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ReactVersion\n */\n\n'use strict';\n\nmodule.exports = '15.2.1';\n},{}],97:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SVGDOMPropertyConfig\n */\n\n'use strict';\n\nvar NS = {\n  xlink: 'http://www.w3.org/1999/xlink',\n  xml: 'http://www.w3.org/XML/1998/namespace'\n};\n\n// We use attributes for everything SVG so let's avoid some duplication and run\n// code instead.\n// The following are all specified in the HTML config already so we exclude here.\n// - class (as className)\n// - color\n// - height\n// - id\n// - lang\n// - max\n// - media\n// - method\n// - min\n// - name\n// - style\n// - target\n// - type\n// - width\nvar ATTRS = {\n  accentHeight: 'accent-height',\n  accumulate: 0,\n  additive: 0,\n  alignmentBaseline: 'alignment-baseline',\n  allowReorder: 'allowReorder',\n  alphabetic: 0,\n  amplitude: 0,\n  arabicForm: 'arabic-form',\n  ascent: 0,\n  attributeName: 'attributeName',\n  attributeType: 'attributeType',\n  autoReverse: 'autoReverse',\n  azimuth: 0,\n  baseFrequency: 'baseFrequency',\n  baseProfile: 'baseProfile',\n  baselineShift: 'baseline-shift',\n  bbox: 0,\n  begin: 0,\n  bias: 0,\n  by: 0,\n  calcMode: 'calcMode',\n  capHeight: 'cap-height',\n  clip: 0,\n  clipPath: 'clip-path',\n  clipRule: 'clip-rule',\n  clipPathUnits: 'clipPathUnits',\n  colorInterpolation: 'color-interpolation',\n  colorInterpolationFilters: 'color-interpolation-filters',\n  colorProfile: 'color-profile',\n  colorRendering: 'color-rendering',\n  contentScriptType: 'contentScriptType',\n  contentStyleType: 'contentStyleType',\n  cursor: 0,\n  cx: 0,\n  cy: 0,\n  d: 0,\n  decelerate: 0,\n  descent: 0,\n  diffuseConstant: 'diffuseConstant',\n  direction: 0,\n  display: 0,\n  divisor: 0,\n  dominantBaseline: 'dominant-baseline',\n  dur: 0,\n  dx: 0,\n  dy: 0,\n  edgeMode: 'edgeMode',\n  elevation: 0,\n  enableBackground: 'enable-background',\n  end: 0,\n  exponent: 0,\n  externalResourcesRequired: 'externalResourcesRequired',\n  fill: 0,\n  fillOpacity: 'fill-opacity',\n  fillRule: 'fill-rule',\n  filter: 0,\n  filterRes: 'filterRes',\n  filterUnits: 'filterUnits',\n  floodColor: 'flood-color',\n  floodOpacity: 'flood-opacity',\n  focusable: 0,\n  fontFamily: 'font-family',\n  fontSize: 'font-size',\n  fontSizeAdjust: 'font-size-adjust',\n  fontStretch: 'font-stretch',\n  fontStyle: 'font-style',\n  fontVariant: 'font-variant',\n  fontWeight: 'font-weight',\n  format: 0,\n  from: 0,\n  fx: 0,\n  fy: 0,\n  g1: 0,\n  g2: 0,\n  glyphName: 'glyph-name',\n  glyphOrientationHorizontal: 'glyph-orientation-horizontal',\n  glyphOrientationVertical: 'glyph-orientation-vertical',\n  glyphRef: 'glyphRef',\n  gradientTransform: 'gradientTransform',\n  gradientUnits: 'gradientUnits',\n  hanging: 0,\n  horizAdvX: 'horiz-adv-x',\n  horizOriginX: 'horiz-origin-x',\n  ideographic: 0,\n  imageRendering: 'image-rendering',\n  'in': 0,\n  in2: 0,\n  intercept: 0,\n  k: 0,\n  k1: 0,\n  k2: 0,\n  k3: 0,\n  k4: 0,\n  kernelMatrix: 'kernelMatrix',\n  kernelUnitLength: 'kernelUnitLength',\n  kerning: 0,\n  keyPoints: 'keyPoints',\n  keySplines: 'keySplines',\n  keyTimes: 'keyTimes',\n  lengthAdjust: 'lengthAdjust',\n  letterSpacing: 'letter-spacing',\n  lightingColor: 'lighting-color',\n  limitingConeAngle: 'limitingConeAngle',\n  local: 0,\n  markerEnd: 'marker-end',\n  markerMid: 'marker-mid',\n  markerStart: 'marker-start',\n  markerHeight: 'markerHeight',\n  markerUnits: 'markerUnits',\n  markerWidth: 'markerWidth',\n  mask: 0,\n  maskContentUnits: 'maskContentUnits',\n  maskUnits: 'maskUnits',\n  mathematical: 0,\n  mode: 0,\n  numOctaves: 'numOctaves',\n  offset: 0,\n  opacity: 0,\n  operator: 0,\n  order: 0,\n  orient: 0,\n  orientation: 0,\n  origin: 0,\n  overflow: 0,\n  overlinePosition: 'overline-position',\n  overlineThickness: 'overline-thickness',\n  paintOrder: 'paint-order',\n  panose1: 'panose-1',\n  pathLength: 'pathLength',\n  patternContentUnits: 'patternContentUnits',\n  patternTransform: 'patternTransform',\n  patternUnits: 'patternUnits',\n  pointerEvents: 'pointer-events',\n  points: 0,\n  pointsAtX: 'pointsAtX',\n  pointsAtY: 'pointsAtY',\n  pointsAtZ: 'pointsAtZ',\n  preserveAlpha: 'preserveAlpha',\n  preserveAspectRatio: 'preserveAspectRatio',\n  primitiveUnits: 'primitiveUnits',\n  r: 0,\n  radius: 0,\n  refX: 'refX',\n  refY: 'refY',\n  renderingIntent: 'rendering-intent',\n  repeatCount: 'repeatCount',\n  repeatDur: 'repeatDur',\n  requiredExtensions: 'requiredExtensions',\n  requiredFeatures: 'requiredFeatures',\n  restart: 0,\n  result: 0,\n  rotate: 0,\n  rx: 0,\n  ry: 0,\n  scale: 0,\n  seed: 0,\n  shapeRendering: 'shape-rendering',\n  slope: 0,\n  spacing: 0,\n  specularConstant: 'specularConstant',\n  specularExponent: 'specularExponent',\n  speed: 0,\n  spreadMethod: 'spreadMethod',\n  startOffset: 'startOffset',\n  stdDeviation: 'stdDeviation',\n  stemh: 0,\n  stemv: 0,\n  stitchTiles: 'stitchTiles',\n  stopColor: 'stop-color',\n  stopOpacity: 'stop-opacity',\n  strikethroughPosition: 'strikethrough-position',\n  strikethroughThickness: 'strikethrough-thickness',\n  string: 0,\n  stroke: 0,\n  strokeDasharray: 'stroke-dasharray',\n  strokeDashoffset: 'stroke-dashoffset',\n  strokeLinecap: 'stroke-linecap',\n  strokeLinejoin: 'stroke-linejoin',\n  strokeMiterlimit: 'stroke-miterlimit',\n  strokeOpacity: 'stroke-opacity',\n  strokeWidth: 'stroke-width',\n  surfaceScale: 'surfaceScale',\n  systemLanguage: 'systemLanguage',\n  tableValues: 'tableValues',\n  targetX: 'targetX',\n  targetY: 'targetY',\n  textAnchor: 'text-anchor',\n  textDecoration: 'text-decoration',\n  textRendering: 'text-rendering',\n  textLength: 'textLength',\n  to: 0,\n  transform: 0,\n  u1: 0,\n  u2: 0,\n  underlinePosition: 'underline-position',\n  underlineThickness: 'underline-thickness',\n  unicode: 0,\n  unicodeBidi: 'unicode-bidi',\n  unicodeRange: 'unicode-range',\n  unitsPerEm: 'units-per-em',\n  vAlphabetic: 'v-alphabetic',\n  vHanging: 'v-hanging',\n  vIdeographic: 'v-ideographic',\n  vMathematical: 'v-mathematical',\n  values: 0,\n  vectorEffect: 'vector-effect',\n  version: 0,\n  vertAdvY: 'vert-adv-y',\n  vertOriginX: 'vert-origin-x',\n  vertOriginY: 'vert-origin-y',\n  viewBox: 'viewBox',\n  viewTarget: 'viewTarget',\n  visibility: 0,\n  widths: 0,\n  wordSpacing: 'word-spacing',\n  writingMode: 'writing-mode',\n  x: 0,\n  xHeight: 'x-height',\n  x1: 0,\n  x2: 0,\n  xChannelSelector: 'xChannelSelector',\n  xlinkActuate: 'xlink:actuate',\n  xlinkArcrole: 'xlink:arcrole',\n  xlinkHref: 'xlink:href',\n  xlinkRole: 'xlink:role',\n  xlinkShow: 'xlink:show',\n  xlinkTitle: 'xlink:title',\n  xlinkType: 'xlink:type',\n  xmlBase: 'xml:base',\n  xmlLang: 'xml:lang',\n  xmlSpace: 'xml:space',\n  y: 0,\n  y1: 0,\n  y2: 0,\n  yChannelSelector: 'yChannelSelector',\n  z: 0,\n  zoomAndPan: 'zoomAndPan'\n};\n\nvar SVGDOMPropertyConfig = {\n  Properties: {},\n  DOMAttributeNamespaces: {\n    xlinkActuate: NS.xlink,\n    xlinkArcrole: NS.xlink,\n    xlinkHref: NS.xlink,\n    xlinkRole: NS.xlink,\n    xlinkShow: NS.xlink,\n    xlinkTitle: NS.xlink,\n    xlinkType: NS.xlink,\n    xmlBase: NS.xml,\n    xmlLang: NS.xml,\n    xmlSpace: NS.xml\n  },\n  DOMAttributeNames: {}\n};\n\nObject.keys(ATTRS).forEach(function (key) {\n  SVGDOMPropertyConfig.Properties[key] = 0;\n  if (ATTRS[key]) {\n    SVGDOMPropertyConfig.DOMAttributeNames[key] = ATTRS[key];\n  }\n});\n\nmodule.exports = SVGDOMPropertyConfig;\n},{}],98:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SelectEventPlugin\n */\n\n'use strict';\n\nvar EventConstants = _dereq_(16);\nvar EventPropagators = _dereq_(20);\nvar ExecutionEnvironment = _dereq_(147);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInputSelection = _dereq_(72);\nvar SyntheticEvent = _dereq_(104);\n\nvar getActiveElement = _dereq_(156);\nvar isTextInputElement = _dereq_(136);\nvar keyOf = _dereq_(165);\nvar shallowEqual = _dereq_(170);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11;\n\nvar eventTypes = {\n  select: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSelect: null }),\n      captured: keyOf({ onSelectCapture: null })\n    },\n    dependencies: [topLevelTypes.topBlur, topLevelTypes.topContextMenu, topLevelTypes.topFocus, topLevelTypes.topKeyDown, topLevelTypes.topMouseDown, topLevelTypes.topMouseUp, topLevelTypes.topSelectionChange]\n  }\n};\n\nvar activeElement = null;\nvar activeElementInst = null;\nvar lastSelection = null;\nvar mouseDown = false;\n\n// Track whether a listener exists for this plugin. If none exist, we do\n// not extract events. See #3639.\nvar hasListener = false;\nvar ON_SELECT_KEY = keyOf({ onSelect: null });\n\n/**\n * Get an object which is a unique representation of the current selection.\n *\n * The return value will not be consistent across nodes or browsers, but\n * two identical selections on the same node will return identical objects.\n *\n * @param {DOMElement} node\n * @return {object}\n */\nfunction getSelection(node) {\n  if ('selectionStart' in node && ReactInputSelection.hasSelectionCapabilities(node)) {\n    return {\n      start: node.selectionStart,\n      end: node.selectionEnd\n    };\n  } else if (window.getSelection) {\n    var selection = window.getSelection();\n    return {\n      anchorNode: selection.anchorNode,\n      anchorOffset: selection.anchorOffset,\n      focusNode: selection.focusNode,\n      focusOffset: selection.focusOffset\n    };\n  } else if (document.selection) {\n    var range = document.selection.createRange();\n    return {\n      parentElement: range.parentElement(),\n      text: range.text,\n      top: range.boundingTop,\n      left: range.boundingLeft\n    };\n  }\n}\n\n/**\n * Poll selection to see whether it's changed.\n *\n * @param {object} nativeEvent\n * @return {?SyntheticEvent}\n */\nfunction constructSelectEvent(nativeEvent, nativeEventTarget) {\n  // Ensure we have the right element, and that the user is not dragging a\n  // selection (this matches native `select` event behavior). In HTML5, select\n  // fires only on input and textarea thus if there's no focused element we\n  // won't dispatch.\n  if (mouseDown || activeElement == null || activeElement !== getActiveElement()) {\n    return null;\n  }\n\n  // Only fire when selection has actually changed.\n  var currentSelection = getSelection(activeElement);\n  if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) {\n    lastSelection = currentSelection;\n\n    var syntheticEvent = SyntheticEvent.getPooled(eventTypes.select, activeElementInst, nativeEvent, nativeEventTarget);\n\n    syntheticEvent.type = 'select';\n    syntheticEvent.target = activeElement;\n\n    EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent);\n\n    return syntheticEvent;\n  }\n\n  return null;\n}\n\n/**\n * This plugin creates an `onSelect` event that normalizes select events\n * across form elements.\n *\n * Supported elements are:\n * - input (see `isTextInputElement`)\n * - textarea\n * - contentEditable\n *\n * This differs from native browser implementations in the following ways:\n * - Fires on contentEditable fields as well as inputs.\n * - Fires for collapsed selection.\n * - Fires after user input.\n */\nvar SelectEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    if (!hasListener) {\n      return null;\n    }\n\n    var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;\n\n    switch (topLevelType) {\n      // Track the input node that has focus.\n      case topLevelTypes.topFocus:\n        if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') {\n          activeElement = targetNode;\n          activeElementInst = targetInst;\n          lastSelection = null;\n        }\n        break;\n      case topLevelTypes.topBlur:\n        activeElement = null;\n        activeElementInst = null;\n        lastSelection = null;\n        break;\n\n      // Don't fire the event while the user is dragging. This matches the\n      // semantics of the native select event.\n      case topLevelTypes.topMouseDown:\n        mouseDown = true;\n        break;\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topMouseUp:\n        mouseDown = false;\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n\n      // Chrome and IE fire non-standard event when selection is changed (and\n      // sometimes when it hasn't). IE's event fires out of order with respect\n      // to key and input events on deletion, so we discard it.\n      //\n      // Firefox doesn't support selectionchange, so check selection status\n      // after each key entry. The selection changes after keydown and before\n      // keyup, but we check on keydown as well in the case of holding down a\n      // key, when multiple keydown events are fired but only one keyup is.\n      // This is also our approach for IE handling, for the reason above.\n      case topLevelTypes.topSelectionChange:\n        if (skipSelectionChangeEvent) {\n          break;\n        }\n      // falls through\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        return constructSelectEvent(nativeEvent, nativeEventTarget);\n    }\n\n    return null;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    if (registrationName === ON_SELECT_KEY) {\n      hasListener = true;\n    }\n  }\n};\n\nmodule.exports = SelectEventPlugin;\n},{\"104\":104,\"136\":136,\"147\":147,\"156\":156,\"16\":16,\"165\":165,\"170\":170,\"20\":20,\"41\":41,\"72\":72}],99:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SimpleEventPlugin\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar EventConstants = _dereq_(16);\nvar EventListener = _dereq_(146);\nvar EventPropagators = _dereq_(20);\nvar ReactDOMComponentTree = _dereq_(41);\nvar SyntheticAnimationEvent = _dereq_(100);\nvar SyntheticClipboardEvent = _dereq_(101);\nvar SyntheticEvent = _dereq_(104);\nvar SyntheticFocusEvent = _dereq_(105);\nvar SyntheticKeyboardEvent = _dereq_(107);\nvar SyntheticMouseEvent = _dereq_(108);\nvar SyntheticDragEvent = _dereq_(103);\nvar SyntheticTouchEvent = _dereq_(109);\nvar SyntheticTransitionEvent = _dereq_(110);\nvar SyntheticUIEvent = _dereq_(111);\nvar SyntheticWheelEvent = _dereq_(112);\n\nvar emptyFunction = _dereq_(153);\nvar getEventCharCode = _dereq_(125);\nvar invariant = _dereq_(161);\nvar keyOf = _dereq_(165);\n\nvar topLevelTypes = EventConstants.topLevelTypes;\n\nvar eventTypes = {\n  abort: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAbort: true }),\n      captured: keyOf({ onAbortCapture: true })\n    }\n  },\n  animationEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationEnd: true }),\n      captured: keyOf({ onAnimationEndCapture: true })\n    }\n  },\n  animationIteration: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationIteration: true }),\n      captured: keyOf({ onAnimationIterationCapture: true })\n    }\n  },\n  animationStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onAnimationStart: true }),\n      captured: keyOf({ onAnimationStartCapture: true })\n    }\n  },\n  blur: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onBlur: true }),\n      captured: keyOf({ onBlurCapture: true })\n    }\n  },\n  canPlay: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlay: true }),\n      captured: keyOf({ onCanPlayCapture: true })\n    }\n  },\n  canPlayThrough: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCanPlayThrough: true }),\n      captured: keyOf({ onCanPlayThroughCapture: true })\n    }\n  },\n  click: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onClick: true }),\n      captured: keyOf({ onClickCapture: true })\n    }\n  },\n  contextMenu: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onContextMenu: true }),\n      captured: keyOf({ onContextMenuCapture: true })\n    }\n  },\n  copy: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCopy: true }),\n      captured: keyOf({ onCopyCapture: true })\n    }\n  },\n  cut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onCut: true }),\n      captured: keyOf({ onCutCapture: true })\n    }\n  },\n  doubleClick: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDoubleClick: true }),\n      captured: keyOf({ onDoubleClickCapture: true })\n    }\n  },\n  drag: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrag: true }),\n      captured: keyOf({ onDragCapture: true })\n    }\n  },\n  dragEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnd: true }),\n      captured: keyOf({ onDragEndCapture: true })\n    }\n  },\n  dragEnter: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragEnter: true }),\n      captured: keyOf({ onDragEnterCapture: true })\n    }\n  },\n  dragExit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragExit: true }),\n      captured: keyOf({ onDragExitCapture: true })\n    }\n  },\n  dragLeave: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragLeave: true }),\n      captured: keyOf({ onDragLeaveCapture: true })\n    }\n  },\n  dragOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragOver: true }),\n      captured: keyOf({ onDragOverCapture: true })\n    }\n  },\n  dragStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDragStart: true }),\n      captured: keyOf({ onDragStartCapture: true })\n    }\n  },\n  drop: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDrop: true }),\n      captured: keyOf({ onDropCapture: true })\n    }\n  },\n  durationChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onDurationChange: true }),\n      captured: keyOf({ onDurationChangeCapture: true })\n    }\n  },\n  emptied: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEmptied: true }),\n      captured: keyOf({ onEmptiedCapture: true })\n    }\n  },\n  encrypted: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEncrypted: true }),\n      captured: keyOf({ onEncryptedCapture: true })\n    }\n  },\n  ended: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onEnded: true }),\n      captured: keyOf({ onEndedCapture: true })\n    }\n  },\n  error: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onError: true }),\n      captured: keyOf({ onErrorCapture: true })\n    }\n  },\n  focus: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onFocus: true }),\n      captured: keyOf({ onFocusCapture: true })\n    }\n  },\n  input: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInput: true }),\n      captured: keyOf({ onInputCapture: true })\n    }\n  },\n  invalid: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onInvalid: true }),\n      captured: keyOf({ onInvalidCapture: true })\n    }\n  },\n  keyDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyDown: true }),\n      captured: keyOf({ onKeyDownCapture: true })\n    }\n  },\n  keyPress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyPress: true }),\n      captured: keyOf({ onKeyPressCapture: true })\n    }\n  },\n  keyUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onKeyUp: true }),\n      captured: keyOf({ onKeyUpCapture: true })\n    }\n  },\n  load: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoad: true }),\n      captured: keyOf({ onLoadCapture: true })\n    }\n  },\n  loadedData: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedData: true }),\n      captured: keyOf({ onLoadedDataCapture: true })\n    }\n  },\n  loadedMetadata: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadedMetadata: true }),\n      captured: keyOf({ onLoadedMetadataCapture: true })\n    }\n  },\n  loadStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onLoadStart: true }),\n      captured: keyOf({ onLoadStartCapture: true })\n    }\n  },\n  // Note: We do not allow listening to mouseOver events. Instead, use the\n  // onMouseEnter/onMouseLeave created by `EnterLeaveEventPlugin`.\n  mouseDown: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseDown: true }),\n      captured: keyOf({ onMouseDownCapture: true })\n    }\n  },\n  mouseMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseMove: true }),\n      captured: keyOf({ onMouseMoveCapture: true })\n    }\n  },\n  mouseOut: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOut: true }),\n      captured: keyOf({ onMouseOutCapture: true })\n    }\n  },\n  mouseOver: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseOver: true }),\n      captured: keyOf({ onMouseOverCapture: true })\n    }\n  },\n  mouseUp: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onMouseUp: true }),\n      captured: keyOf({ onMouseUpCapture: true })\n    }\n  },\n  paste: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPaste: true }),\n      captured: keyOf({ onPasteCapture: true })\n    }\n  },\n  pause: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPause: true }),\n      captured: keyOf({ onPauseCapture: true })\n    }\n  },\n  play: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlay: true }),\n      captured: keyOf({ onPlayCapture: true })\n    }\n  },\n  playing: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onPlaying: true }),\n      captured: keyOf({ onPlayingCapture: true })\n    }\n  },\n  progress: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onProgress: true }),\n      captured: keyOf({ onProgressCapture: true })\n    }\n  },\n  rateChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onRateChange: true }),\n      captured: keyOf({ onRateChangeCapture: true })\n    }\n  },\n  reset: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onReset: true }),\n      captured: keyOf({ onResetCapture: true })\n    }\n  },\n  scroll: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onScroll: true }),\n      captured: keyOf({ onScrollCapture: true })\n    }\n  },\n  seeked: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeked: true }),\n      captured: keyOf({ onSeekedCapture: true })\n    }\n  },\n  seeking: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSeeking: true }),\n      captured: keyOf({ onSeekingCapture: true })\n    }\n  },\n  stalled: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onStalled: true }),\n      captured: keyOf({ onStalledCapture: true })\n    }\n  },\n  submit: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSubmit: true }),\n      captured: keyOf({ onSubmitCapture: true })\n    }\n  },\n  suspend: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onSuspend: true }),\n      captured: keyOf({ onSuspendCapture: true })\n    }\n  },\n  timeUpdate: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTimeUpdate: true }),\n      captured: keyOf({ onTimeUpdateCapture: true })\n    }\n  },\n  touchCancel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchCancel: true }),\n      captured: keyOf({ onTouchCancelCapture: true })\n    }\n  },\n  touchEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchEnd: true }),\n      captured: keyOf({ onTouchEndCapture: true })\n    }\n  },\n  touchMove: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchMove: true }),\n      captured: keyOf({ onTouchMoveCapture: true })\n    }\n  },\n  touchStart: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTouchStart: true }),\n      captured: keyOf({ onTouchStartCapture: true })\n    }\n  },\n  transitionEnd: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onTransitionEnd: true }),\n      captured: keyOf({ onTransitionEndCapture: true })\n    }\n  },\n  volumeChange: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onVolumeChange: true }),\n      captured: keyOf({ onVolumeChangeCapture: true })\n    }\n  },\n  waiting: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWaiting: true }),\n      captured: keyOf({ onWaitingCapture: true })\n    }\n  },\n  wheel: {\n    phasedRegistrationNames: {\n      bubbled: keyOf({ onWheel: true }),\n      captured: keyOf({ onWheelCapture: true })\n    }\n  }\n};\n\nvar topLevelEventsToDispatchConfig = {\n  topAbort: eventTypes.abort,\n  topAnimationEnd: eventTypes.animationEnd,\n  topAnimationIteration: eventTypes.animationIteration,\n  topAnimationStart: eventTypes.animationStart,\n  topBlur: eventTypes.blur,\n  topCanPlay: eventTypes.canPlay,\n  topCanPlayThrough: eventTypes.canPlayThrough,\n  topClick: eventTypes.click,\n  topContextMenu: eventTypes.contextMenu,\n  topCopy: eventTypes.copy,\n  topCut: eventTypes.cut,\n  topDoubleClick: eventTypes.doubleClick,\n  topDrag: eventTypes.drag,\n  topDragEnd: eventTypes.dragEnd,\n  topDragEnter: eventTypes.dragEnter,\n  topDragExit: eventTypes.dragExit,\n  topDragLeave: eventTypes.dragLeave,\n  topDragOver: eventTypes.dragOver,\n  topDragStart: eventTypes.dragStart,\n  topDrop: eventTypes.drop,\n  topDurationChange: eventTypes.durationChange,\n  topEmptied: eventTypes.emptied,\n  topEncrypted: eventTypes.encrypted,\n  topEnded: eventTypes.ended,\n  topError: eventTypes.error,\n  topFocus: eventTypes.focus,\n  topInput: eventTypes.input,\n  topInvalid: eventTypes.invalid,\n  topKeyDown: eventTypes.keyDown,\n  topKeyPress: eventTypes.keyPress,\n  topKeyUp: eventTypes.keyUp,\n  topLoad: eventTypes.load,\n  topLoadedData: eventTypes.loadedData,\n  topLoadedMetadata: eventTypes.loadedMetadata,\n  topLoadStart: eventTypes.loadStart,\n  topMouseDown: eventTypes.mouseDown,\n  topMouseMove: eventTypes.mouseMove,\n  topMouseOut: eventTypes.mouseOut,\n  topMouseOver: eventTypes.mouseOver,\n  topMouseUp: eventTypes.mouseUp,\n  topPaste: eventTypes.paste,\n  topPause: eventTypes.pause,\n  topPlay: eventTypes.play,\n  topPlaying: eventTypes.playing,\n  topProgress: eventTypes.progress,\n  topRateChange: eventTypes.rateChange,\n  topReset: eventTypes.reset,\n  topScroll: eventTypes.scroll,\n  topSeeked: eventTypes.seeked,\n  topSeeking: eventTypes.seeking,\n  topStalled: eventTypes.stalled,\n  topSubmit: eventTypes.submit,\n  topSuspend: eventTypes.suspend,\n  topTimeUpdate: eventTypes.timeUpdate,\n  topTouchCancel: eventTypes.touchCancel,\n  topTouchEnd: eventTypes.touchEnd,\n  topTouchMove: eventTypes.touchMove,\n  topTouchStart: eventTypes.touchStart,\n  topTransitionEnd: eventTypes.transitionEnd,\n  topVolumeChange: eventTypes.volumeChange,\n  topWaiting: eventTypes.waiting,\n  topWheel: eventTypes.wheel\n};\n\nfor (var type in topLevelEventsToDispatchConfig) {\n  topLevelEventsToDispatchConfig[type].dependencies = [type];\n}\n\nvar ON_CLICK_KEY = keyOf({ onClick: null });\nvar onClickListeners = {};\n\nvar SimpleEventPlugin = {\n\n  eventTypes: eventTypes,\n\n  extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {\n    var dispatchConfig = topLevelEventsToDispatchConfig[topLevelType];\n    if (!dispatchConfig) {\n      return null;\n    }\n    var EventConstructor;\n    switch (topLevelType) {\n      case topLevelTypes.topAbort:\n      case topLevelTypes.topCanPlay:\n      case topLevelTypes.topCanPlayThrough:\n      case topLevelTypes.topDurationChange:\n      case topLevelTypes.topEmptied:\n      case topLevelTypes.topEncrypted:\n      case topLevelTypes.topEnded:\n      case topLevelTypes.topError:\n      case topLevelTypes.topInput:\n      case topLevelTypes.topInvalid:\n      case topLevelTypes.topLoad:\n      case topLevelTypes.topLoadedData:\n      case topLevelTypes.topLoadedMetadata:\n      case topLevelTypes.topLoadStart:\n      case topLevelTypes.topPause:\n      case topLevelTypes.topPlay:\n      case topLevelTypes.topPlaying:\n      case topLevelTypes.topProgress:\n      case topLevelTypes.topRateChange:\n      case topLevelTypes.topReset:\n      case topLevelTypes.topSeeked:\n      case topLevelTypes.topSeeking:\n      case topLevelTypes.topStalled:\n      case topLevelTypes.topSubmit:\n      case topLevelTypes.topSuspend:\n      case topLevelTypes.topTimeUpdate:\n      case topLevelTypes.topVolumeChange:\n      case topLevelTypes.topWaiting:\n        // HTML Events\n        // @see http://www.w3.org/TR/html5/index.html#events-0\n        EventConstructor = SyntheticEvent;\n        break;\n      case topLevelTypes.topKeyPress:\n        // Firefox creates a keypress event for function keys too. This removes\n        // the unwanted keypress events. Enter is however both printable and\n        // non-printable. One would expect Tab to be as well (but it isn't).\n        if (getEventCharCode(nativeEvent) === 0) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topKeyDown:\n      case topLevelTypes.topKeyUp:\n        EventConstructor = SyntheticKeyboardEvent;\n        break;\n      case topLevelTypes.topBlur:\n      case topLevelTypes.topFocus:\n        EventConstructor = SyntheticFocusEvent;\n        break;\n      case topLevelTypes.topClick:\n        // Firefox creates a click event on right mouse clicks. This removes the\n        // unwanted click events.\n        if (nativeEvent.button === 2) {\n          return null;\n        }\n      /* falls through */\n      case topLevelTypes.topContextMenu:\n      case topLevelTypes.topDoubleClick:\n      case topLevelTypes.topMouseDown:\n      case topLevelTypes.topMouseMove:\n      case topLevelTypes.topMouseOut:\n      case topLevelTypes.topMouseOver:\n      case topLevelTypes.topMouseUp:\n        EventConstructor = SyntheticMouseEvent;\n        break;\n      case topLevelTypes.topDrag:\n      case topLevelTypes.topDragEnd:\n      case topLevelTypes.topDragEnter:\n      case topLevelTypes.topDragExit:\n      case topLevelTypes.topDragLeave:\n      case topLevelTypes.topDragOver:\n      case topLevelTypes.topDragStart:\n      case topLevelTypes.topDrop:\n        EventConstructor = SyntheticDragEvent;\n        break;\n      case topLevelTypes.topTouchCancel:\n      case topLevelTypes.topTouchEnd:\n      case topLevelTypes.topTouchMove:\n      case topLevelTypes.topTouchStart:\n        EventConstructor = SyntheticTouchEvent;\n        break;\n      case topLevelTypes.topAnimationEnd:\n      case topLevelTypes.topAnimationIteration:\n      case topLevelTypes.topAnimationStart:\n        EventConstructor = SyntheticAnimationEvent;\n        break;\n      case topLevelTypes.topTransitionEnd:\n        EventConstructor = SyntheticTransitionEvent;\n        break;\n      case topLevelTypes.topScroll:\n        EventConstructor = SyntheticUIEvent;\n        break;\n      case topLevelTypes.topWheel:\n        EventConstructor = SyntheticWheelEvent;\n        break;\n      case topLevelTypes.topCopy:\n      case topLevelTypes.topCut:\n      case topLevelTypes.topPaste:\n        EventConstructor = SyntheticClipboardEvent;\n        break;\n    }\n    !EventConstructor ? \"development\" !== 'production' ? invariant(false, 'SimpleEventPlugin: Unhandled event type, `%s`.', topLevelType) : _prodInvariant('86', topLevelType) : void 0;\n    var event = EventConstructor.getPooled(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);\n    EventPropagators.accumulateTwoPhaseDispatches(event);\n    return event;\n  },\n\n  didPutListener: function (inst, registrationName, listener) {\n    // Mobile Safari does not fire properly bubble click events on\n    // non-interactive elements, which means delegated click listeners do not\n    // fire. The workaround for this bug involves attaching an empty click\n    // listener on the target node.\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      var node = ReactDOMComponentTree.getNodeFromInstance(inst);\n      if (!onClickListeners[id]) {\n        onClickListeners[id] = EventListener.listen(node, 'click', emptyFunction);\n      }\n    }\n  },\n\n  willDeleteListener: function (inst, registrationName) {\n    if (registrationName === ON_CLICK_KEY) {\n      var id = inst._rootNodeID;\n      onClickListeners[id].remove();\n      delete onClickListeners[id];\n    }\n  }\n\n};\n\nmodule.exports = SimpleEventPlugin;\n},{\"100\":100,\"101\":101,\"103\":103,\"104\":104,\"105\":105,\"107\":107,\"108\":108,\"109\":109,\"110\":110,\"111\":111,\"112\":112,\"125\":125,\"139\":139,\"146\":146,\"153\":153,\"16\":16,\"161\":161,\"165\":165,\"20\":20,\"41\":41}],100:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticAnimationEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface\n * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent\n */\nvar AnimationEventInterface = {\n  animationName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticAnimationEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);\n\nmodule.exports = SyntheticAnimationEvent;\n},{\"104\":104}],101:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticClipboardEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/clipboard-apis/\n */\nvar ClipboardEventInterface = {\n  clipboardData: function (event) {\n    return 'clipboardData' in event ? event.clipboardData : window.clipboardData;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);\n\nmodule.exports = SyntheticClipboardEvent;\n},{\"104\":104}],102:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticCompositionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#events-compositionevents\n */\nvar CompositionEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticCompositionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticCompositionEvent, CompositionEventInterface);\n\nmodule.exports = SyntheticCompositionEvent;\n},{\"104\":104}],103:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticDragEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface DragEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar DragEventInterface = {\n  dataTransfer: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);\n\nmodule.exports = SyntheticDragEvent;\n},{\"108\":108}],104:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticEvent\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar PooledClass = _dereq_(25);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar didWarnForAddedNewProperty = false;\nvar isProxySupported = typeof Proxy === 'function';\n\nvar shouldBeReleasedProperties = ['dispatchConfig', '_targetInst', 'nativeEvent', 'isDefaultPrevented', 'isPropagationStopped', '_dispatchListeners', '_dispatchInstances'];\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar EventInterface = {\n  type: null,\n  target: null,\n  // currentTarget is set when dispatching; no use in copying it here\n  currentTarget: emptyFunction.thatReturnsNull,\n  eventPhase: null,\n  bubbles: null,\n  cancelable: null,\n  timeStamp: function (event) {\n    return event.timeStamp || Date.now();\n  },\n  defaultPrevented: null,\n  isTrusted: null\n};\n\n/**\n * Synthetic events are dispatched by event plugins, typically in response to a\n * top-level event delegation handler.\n *\n * These systems should generally use pooling to reduce the frequency of garbage\n * collection. The system should check `isPersistent` to determine whether the\n * event should be released into the pool after being dispatched. Users that\n * need a persisted event should invoke `persist`.\n *\n * Synthetic events (and subclasses) implement the DOM Level 3 Events API by\n * normalizing browser quirks. Subclasses do not necessarily have to implement a\n * DOM interface; custom application-specific events can also subclass this.\n *\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {*} targetInst Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @param {DOMEventTarget} nativeEventTarget Target node.\n */\nfunction SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {\n  if (\"development\" !== 'production') {\n    // these have a getter/setter for warnings\n    delete this.nativeEvent;\n    delete this.preventDefault;\n    delete this.stopPropagation;\n  }\n\n  this.dispatchConfig = dispatchConfig;\n  this._targetInst = targetInst;\n  this.nativeEvent = nativeEvent;\n\n  var Interface = this.constructor.Interface;\n  for (var propName in Interface) {\n    if (!Interface.hasOwnProperty(propName)) {\n      continue;\n    }\n    if (\"development\" !== 'production') {\n      delete this[propName]; // this has a getter/setter for warnings\n    }\n    var normalize = Interface[propName];\n    if (normalize) {\n      this[propName] = normalize(nativeEvent);\n    } else {\n      if (propName === 'target') {\n        this.target = nativeEventTarget;\n      } else {\n        this[propName] = nativeEvent[propName];\n      }\n    }\n  }\n\n  var defaultPrevented = nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false;\n  if (defaultPrevented) {\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  } else {\n    this.isDefaultPrevented = emptyFunction.thatReturnsFalse;\n  }\n  this.isPropagationStopped = emptyFunction.thatReturnsFalse;\n  return this;\n}\n\n_assign(SyntheticEvent.prototype, {\n\n  preventDefault: function () {\n    this.defaultPrevented = true;\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.preventDefault) {\n      event.preventDefault();\n    } else {\n      event.returnValue = false;\n    }\n    this.isDefaultPrevented = emptyFunction.thatReturnsTrue;\n  },\n\n  stopPropagation: function () {\n    var event = this.nativeEvent;\n    if (!event) {\n      return;\n    }\n\n    if (event.stopPropagation) {\n      event.stopPropagation();\n    } else {\n      event.cancelBubble = true;\n    }\n    this.isPropagationStopped = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * We release all dispatched `SyntheticEvent`s after each event loop, adding\n   * them back into the pool. This allows a way to hold onto a reference that\n   * won't be added back into the pool.\n   */\n  persist: function () {\n    this.isPersistent = emptyFunction.thatReturnsTrue;\n  },\n\n  /**\n   * Checks if this event should be released back into the pool.\n   *\n   * @return {boolean} True if this should not be released, false otherwise.\n   */\n  isPersistent: emptyFunction.thatReturnsFalse,\n\n  /**\n   * `PooledClass` looks for `destructor` on each instance it releases.\n   */\n  destructor: function () {\n    var Interface = this.constructor.Interface;\n    for (var propName in Interface) {\n      if (\"development\" !== 'production') {\n        Object.defineProperty(this, propName, getPooledWarningPropertyDefinition(propName, Interface[propName]));\n      } else {\n        this[propName] = null;\n      }\n    }\n    for (var i = 0; i < shouldBeReleasedProperties.length; i++) {\n      this[shouldBeReleasedProperties[i]] = null;\n    }\n    if (\"development\" !== 'production') {\n      Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));\n      Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', emptyFunction));\n      Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', emptyFunction));\n    }\n  }\n\n});\n\nSyntheticEvent.Interface = EventInterface;\n\nif (\"development\" !== 'production') {\n  if (isProxySupported) {\n    /*eslint-disable no-func-assign */\n    SyntheticEvent = new Proxy(SyntheticEvent, {\n      construct: function (target, args) {\n        return this.apply(target, Object.create(target.prototype), args);\n      },\n      apply: function (constructor, that, args) {\n        return new Proxy(constructor.apply(that, args), {\n          set: function (target, prop, value) {\n            if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {\n              \"development\" !== 'production' ? warning(didWarnForAddedNewProperty || target.isPersistent(), 'This synthetic event is reused for performance reasons. If you\\'re ' + 'seeing this, you\\'re adding a new property in the synthetic event object. ' + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;\n              didWarnForAddedNewProperty = true;\n            }\n            target[prop] = value;\n            return true;\n          }\n        });\n      }\n    });\n    /*eslint-enable no-func-assign */\n  }\n}\n/**\n * Helper to reduce boilerplate when creating subclasses.\n *\n * @param {function} Class\n * @param {?object} Interface\n */\nSyntheticEvent.augmentClass = function (Class, Interface) {\n  var Super = this;\n\n  var E = function () {};\n  E.prototype = Super.prototype;\n  var prototype = new E();\n\n  _assign(prototype, Class.prototype);\n  Class.prototype = prototype;\n  Class.prototype.constructor = Class;\n\n  Class.Interface = _assign({}, Super.Interface, Interface);\n  Class.augmentClass = Super.augmentClass;\n\n  PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler);\n};\n\nPooledClass.addPoolingTo(SyntheticEvent, PooledClass.fourArgumentPooler);\n\nmodule.exports = SyntheticEvent;\n\n/**\n  * Helper to nullify syntheticEvent instance properties when destructing\n  *\n  * @param {object} SyntheticEvent\n  * @param {String} propName\n  * @return {object} defineProperty object\n  */\nfunction getPooledWarningPropertyDefinition(propName, getVal) {\n  var isFunction = typeof getVal === 'function';\n  return {\n    configurable: true,\n    set: set,\n    get: get\n  };\n\n  function set(val) {\n    var action = isFunction ? 'setting the method' : 'setting the property';\n    warn(action, 'This is effectively a no-op');\n    return val;\n  }\n\n  function get() {\n    var action = isFunction ? 'accessing the method' : 'accessing the property';\n    var result = isFunction ? 'This is a no-op function' : 'This is set to null';\n    warn(action, result);\n    return getVal;\n  }\n\n  function warn(action, result) {\n    var warningCondition = false;\n    \"development\" !== 'production' ? warning(warningCondition, 'This synthetic event is reused for performance reasons. If you\\'re seeing this, ' + 'you\\'re %s `%s` on a released/nullified synthetic event. %s. ' + 'If you must keep the original synthetic event around, use event.persist(). ' + 'See https://fb.me/react-event-pooling for more information.', action, propName, result) : void 0;\n  }\n}\n},{\"153\":153,\"171\":171,\"172\":172,\"25\":25}],105:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticFocusEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\n/**\n * @interface FocusEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar FocusEventInterface = {\n  relatedTarget: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);\n\nmodule.exports = SyntheticFocusEvent;\n},{\"111\":111}],106:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticInputEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105\n *      /#events-inputevents\n */\nvar InputEventInterface = {\n  data: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticInputEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface);\n\nmodule.exports = SyntheticInputEvent;\n},{\"104\":104}],107:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticKeyboardEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventCharCode = _dereq_(125);\nvar getEventKey = _dereq_(126);\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface KeyboardEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar KeyboardEventInterface = {\n  key: getEventKey,\n  location: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  repeat: null,\n  locale: null,\n  getModifierState: getEventModifierState,\n  // Legacy Interface\n  charCode: function (event) {\n    // `charCode` is the result of a KeyPress event and represents the value of\n    // the actual printable character.\n\n    // KeyPress is deprecated, but its replacement is not yet final and not\n    // implemented in any major browser. Only KeyPress has charCode.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    return 0;\n  },\n  keyCode: function (event) {\n    // `keyCode` is the result of a KeyDown/Up event and represents the value of\n    // physical keyboard key.\n\n    // The actual meaning of the value depends on the users' keyboard layout\n    // which cannot be detected. Assuming that it is a US keyboard layout\n    // provides a surprisingly accurate mapping for US and European users.\n    // Due to this, it is left to the user to implement at this time.\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  },\n  which: function (event) {\n    // `which` is an alias for either `keyCode` or `charCode` depending on the\n    // type of the event.\n    if (event.type === 'keypress') {\n      return getEventCharCode(event);\n    }\n    if (event.type === 'keydown' || event.type === 'keyup') {\n      return event.keyCode;\n    }\n    return 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);\n\nmodule.exports = SyntheticKeyboardEvent;\n},{\"111\":111,\"125\":125,\"126\":126,\"127\":127}],108:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticMouseEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\nvar ViewportMetrics = _dereq_(114);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface MouseEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar MouseEventInterface = {\n  screenX: null,\n  screenY: null,\n  clientX: null,\n  clientY: null,\n  ctrlKey: null,\n  shiftKey: null,\n  altKey: null,\n  metaKey: null,\n  getModifierState: getEventModifierState,\n  button: function (event) {\n    // Webkit, Firefox, IE9+\n    // which:  1 2 3\n    // button: 0 1 2 (standard)\n    var button = event.button;\n    if ('which' in event) {\n      return button;\n    }\n    // IE<9\n    // which:  undefined\n    // button: 0 0 0\n    // button: 1 4 2 (onmouseup)\n    return button === 2 ? 2 : button === 4 ? 1 : 0;\n  },\n  buttons: null,\n  relatedTarget: function (event) {\n    return event.relatedTarget || (event.fromElement === event.srcElement ? event.toElement : event.fromElement);\n  },\n  // \"Proprietary\" Interface.\n  pageX: function (event) {\n    return 'pageX' in event ? event.pageX : event.clientX + ViewportMetrics.currentScrollLeft;\n  },\n  pageY: function (event) {\n    return 'pageY' in event ? event.pageY : event.clientY + ViewportMetrics.currentScrollTop;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);\n\nmodule.exports = SyntheticMouseEvent;\n},{\"111\":111,\"114\":114,\"127\":127}],109:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTouchEvent\n */\n\n'use strict';\n\nvar SyntheticUIEvent = _dereq_(111);\n\nvar getEventModifierState = _dereq_(127);\n\n/**\n * @interface TouchEvent\n * @see http://www.w3.org/TR/touch-events/\n */\nvar TouchEventInterface = {\n  touches: null,\n  targetTouches: null,\n  changedTouches: null,\n  altKey: null,\n  metaKey: null,\n  ctrlKey: null,\n  shiftKey: null,\n  getModifierState: getEventModifierState\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticUIEvent}\n */\nfunction SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);\n\nmodule.exports = SyntheticTouchEvent;\n},{\"111\":111,\"127\":127}],110:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticTransitionEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\n/**\n * @interface Event\n * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events-\n * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent\n */\nvar TransitionEventInterface = {\n  propertyName: null,\n  elapsedTime: null,\n  pseudoElement: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticTransitionEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);\n\nmodule.exports = SyntheticTransitionEvent;\n},{\"104\":104}],111:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticUIEvent\n */\n\n'use strict';\n\nvar SyntheticEvent = _dereq_(104);\n\nvar getEventTarget = _dereq_(128);\n\n/**\n * @interface UIEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar UIEventInterface = {\n  view: function (event) {\n    if (event.view) {\n      return event.view;\n    }\n\n    var target = getEventTarget(event);\n    if (target.window === target) {\n      // target is a window object\n      return target;\n    }\n\n    var doc = target.ownerDocument;\n    // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.\n    if (doc) {\n      return doc.defaultView || doc.parentWindow;\n    } else {\n      return window;\n    }\n  },\n  detail: function (event) {\n    return event.detail || 0;\n  }\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticEvent}\n */\nfunction SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);\n\nmodule.exports = SyntheticUIEvent;\n},{\"104\":104,\"128\":128}],112:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule SyntheticWheelEvent\n */\n\n'use strict';\n\nvar SyntheticMouseEvent = _dereq_(108);\n\n/**\n * @interface WheelEvent\n * @see http://www.w3.org/TR/DOM-Level-3-Events/\n */\nvar WheelEventInterface = {\n  deltaX: function (event) {\n    return 'deltaX' in event ? event.deltaX :\n    // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).\n    'wheelDeltaX' in event ? -event.wheelDeltaX : 0;\n  },\n  deltaY: function (event) {\n    return 'deltaY' in event ? event.deltaY :\n    // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).\n    'wheelDeltaY' in event ? -event.wheelDeltaY :\n    // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).\n    'wheelDelta' in event ? -event.wheelDelta : 0;\n  },\n  deltaZ: null,\n\n  // Browsers without \"deltaMode\" is reporting in raw wheel delta where one\n  // notch on the scroll is always +/- 120, roughly equivalent to pixels.\n  // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or\n  // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size.\n  deltaMode: null\n};\n\n/**\n * @param {object} dispatchConfig Configuration used to dispatch this event.\n * @param {string} dispatchMarker Marker identifying the event target.\n * @param {object} nativeEvent Native browser event.\n * @extends {SyntheticMouseEvent}\n */\nfunction SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {\n  return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);\n}\n\nSyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);\n\nmodule.exports = SyntheticWheelEvent;\n},{\"108\":108}],113:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule Transaction\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * `Transaction` creates a black box that is able to wrap any method such that\n * certain invariants are maintained before and after the method is invoked\n * (Even if an exception is thrown while invoking the wrapped method). Whoever\n * instantiates a transaction can provide enforcers of the invariants at\n * creation time. The `Transaction` class itself will supply one additional\n * automatic invariant for you - the invariant that any transaction instance\n * should not be run while it is already being run. You would typically create a\n * single instance of a `Transaction` for reuse multiple times, that potentially\n * is used to wrap several different methods. Wrappers are extremely simple -\n * they only require implementing two methods.\n *\n * <pre>\n *                       wrappers (injected at creation time)\n *                                      +        +\n *                                      |        |\n *                    +-----------------|--------|--------------+\n *                    |                 v        |              |\n *                    |      +---------------+   |              |\n *                    |   +--|    wrapper1   |---|----+         |\n *                    |   |  +---------------+   v    |         |\n *                    |   |          +-------------+  |         |\n *                    |   |     +----|   wrapper2  |--------+   |\n *                    |   |     |    +-------------+  |     |   |\n *                    |   |     |                     |     |   |\n *                    |   v     v                     v     v   | wrapper\n *                    | +---+ +---+   +---------+   +---+ +---+ | invariants\n * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained\n * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | |   | |   |   |         |   |   | |   | |\n *                    | +---+ +---+   +---------+   +---+ +---+ |\n *                    |  initialize                    close    |\n *                    +-----------------------------------------+\n * </pre>\n *\n * Use cases:\n * - Preserving the input selection ranges before/after reconciliation.\n *   Restoring selection even in the event of an unexpected error.\n * - Deactivating events while rearranging the DOM, preventing blurs/focuses,\n *   while guaranteeing that afterwards, the event system is reactivated.\n * - Flushing a queue of collected DOM mutations to the main UI thread after a\n *   reconciliation takes place in a worker thread.\n * - Invoking any collected `componentDidUpdate` callbacks after rendering new\n *   content.\n * - (Future use case): Wrapping particular flushes of the `ReactWorker` queue\n *   to preserve the `scrollTop` (an automatic scroll aware DOM).\n * - (Future use case): Layout calculations before and after DOM updates.\n *\n * Transactional plugin API:\n * - A module that has an `initialize` method that returns any precomputation.\n * - and a `close` method that accepts the precomputation. `close` is invoked\n *   when the wrapped process is completed, or has failed.\n *\n * @param {Array<TransactionalWrapper>} transactionWrapper Wrapper modules\n * that implement `initialize` and `close`.\n * @return {Transaction} Single transaction for reuse in thread.\n *\n * @class Transaction\n */\nvar Mixin = {\n  /**\n   * Sets up this instance so that it is prepared for collecting metrics. Does\n   * so such that this setup method may be used on an instance that is already\n   * initialized, in a way that does not consume additional memory upon reuse.\n   * That can be useful if you decide to make your subclass of this mixin a\n   * \"PooledClass\".\n   */\n  reinitializeTransaction: function () {\n    this.transactionWrappers = this.getTransactionWrappers();\n    if (this.wrapperInitData) {\n      this.wrapperInitData.length = 0;\n    } else {\n      this.wrapperInitData = [];\n    }\n    this._isInTransaction = false;\n  },\n\n  _isInTransaction: false,\n\n  /**\n   * @abstract\n   * @return {Array<TransactionWrapper>} Array of transaction wrappers.\n   */\n  getTransactionWrappers: null,\n\n  isInTransaction: function () {\n    return !!this._isInTransaction;\n  },\n\n  /**\n   * Executes the function within a safety window. Use this for the top level\n   * methods that result in large amounts of computation/mutations that would\n   * need to be safety checked. The optional arguments helps prevent the need\n   * to bind in many cases.\n   *\n   * @param {function} method Member of scope to call.\n   * @param {Object} scope Scope to invoke from.\n   * @param {Object?=} a Argument to pass to the method.\n   * @param {Object?=} b Argument to pass to the method.\n   * @param {Object?=} c Argument to pass to the method.\n   * @param {Object?=} d Argument to pass to the method.\n   * @param {Object?=} e Argument to pass to the method.\n   * @param {Object?=} f Argument to pass to the method.\n   *\n   * @return {*} Return value from `method`.\n   */\n  perform: function (method, scope, a, b, c, d, e, f) {\n    !!this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.perform(...): Cannot initialize a transaction when there is already an outstanding transaction.') : _prodInvariant('27') : void 0;\n    var errorThrown;\n    var ret;\n    try {\n      this._isInTransaction = true;\n      // Catching errors makes debugging more difficult, so we start with\n      // errorThrown set to true before setting it to false after calling\n      // close -- if it's still set to true in the finally block, it means\n      // one of these calls threw.\n      errorThrown = true;\n      this.initializeAll(0);\n      ret = method.call(scope, a, b, c, d, e, f);\n      errorThrown = false;\n    } finally {\n      try {\n        if (errorThrown) {\n          // If `method` throws, prefer to show that stack trace over any thrown\n          // by invoking `closeAll`.\n          try {\n            this.closeAll(0);\n          } catch (err) {}\n        } else {\n          // Since `method` didn't throw, we don't want to silence the exception\n          // here.\n          this.closeAll(0);\n        }\n      } finally {\n        this._isInTransaction = false;\n      }\n    }\n    return ret;\n  },\n\n  initializeAll: function (startIndex) {\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      try {\n        // Catching errors makes debugging more difficult, so we start with the\n        // OBSERVED_ERROR state before overwriting it with the real return value\n        // of initialize -- if it's still set to OBSERVED_ERROR in the finally\n        // block, it means wrapper.initialize threw.\n        this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;\n        this.wrapperInitData[i] = wrapper.initialize ? wrapper.initialize.call(this) : null;\n      } finally {\n        if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {\n          // The initializer for wrapper i threw an error; initialize the\n          // remaining wrappers but silence any exceptions from them to ensure\n          // that the first error is the one to bubble up.\n          try {\n            this.initializeAll(i + 1);\n          } catch (err) {}\n        }\n      }\n    }\n  },\n\n  /**\n   * Invokes each of `this.transactionWrappers.close[i]` functions, passing into\n   * them the respective return values of `this.transactionWrappers.init[i]`\n   * (`close`rs that correspond to initializers that failed will not be\n   * invoked).\n   */\n  closeAll: function (startIndex) {\n    !this.isInTransaction() ? \"development\" !== 'production' ? invariant(false, 'Transaction.closeAll(): Cannot close transaction when none are open.') : _prodInvariant('28') : void 0;\n    var transactionWrappers = this.transactionWrappers;\n    for (var i = startIndex; i < transactionWrappers.length; i++) {\n      var wrapper = transactionWrappers[i];\n      var initData = this.wrapperInitData[i];\n      var errorThrown;\n      try {\n        // Catching errors makes debugging more difficult, so we start with\n        // errorThrown set to true before setting it to false after calling\n        // close -- if it's still set to true in the finally block, it means\n        // wrapper.close threw.\n        errorThrown = true;\n        if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) {\n          wrapper.close.call(this, initData);\n        }\n        errorThrown = false;\n      } finally {\n        if (errorThrown) {\n          // The closer for wrapper i threw an error; close the remaining\n          // wrappers but silence any exceptions from them to ensure that the\n          // first error is the one to bubble up.\n          try {\n            this.closeAll(i + 1);\n          } catch (e) {}\n        }\n      }\n    }\n    this.wrapperInitData.length = 0;\n  }\n};\n\nvar Transaction = {\n\n  Mixin: Mixin,\n\n  /**\n   * Token to look for to determine if an error occurred.\n   */\n  OBSERVED_ERROR: {}\n\n};\n\nmodule.exports = Transaction;\n},{\"139\":139,\"161\":161}],114:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule ViewportMetrics\n */\n\n'use strict';\n\nvar ViewportMetrics = {\n\n  currentScrollLeft: 0,\n\n  currentScrollTop: 0,\n\n  refreshScrollValues: function (scrollPosition) {\n    ViewportMetrics.currentScrollLeft = scrollPosition.x;\n    ViewportMetrics.currentScrollTop = scrollPosition.y;\n  }\n\n};\n\nmodule.exports = ViewportMetrics;\n},{}],115:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule accumulateInto\n * \n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar invariant = _dereq_(161);\n\n/**\n * Accumulates items that must not be null or undefined into the first one. This\n * is used to conserve memory by avoiding array allocations, and thus sacrifices\n * API cleanness. Since `current` can be null before being passed in and not\n * null after this function, make sure to assign it back to `current`:\n *\n * `a = accumulateInto(a, b);`\n *\n * This API should be sparingly used. Try `accumulate` for something cleaner.\n *\n * @return {*|array<*>} An accumulation of items.\n */\n\nfunction accumulateInto(current, next) {\n  !(next != null) ? \"development\" !== 'production' ? invariant(false, 'accumulateInto(...): Accumulated items must not be null or undefined.') : _prodInvariant('30') : void 0;\n\n  if (current == null) {\n    return next;\n  }\n\n  // Both are not empty. Warning: Never call x.concat(y) when you are not\n  // certain that x is an Array (x could be a string with concat method).\n  if (Array.isArray(current)) {\n    if (Array.isArray(next)) {\n      current.push.apply(current, next);\n      return current;\n    }\n    current.push(next);\n    return current;\n  }\n\n  if (Array.isArray(next)) {\n    // A bit too dangerous to mutate `next`.\n    return [current].concat(next);\n  }\n\n  return [current, next];\n}\n\nmodule.exports = accumulateInto;\n},{\"139\":139,\"161\":161}],116:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule adler32\n * \n */\n\n'use strict';\n\nvar MOD = 65521;\n\n// adler32 is not cryptographically strong, and is only used to sanity check that\n// markup generated on the server matches the markup generated on the client.\n// This implementation (a modified version of the SheetJS version) has been optimized\n// for our use case, at the expense of conforming to the adler32 specification\n// for non-ascii inputs.\nfunction adler32(data) {\n  var a = 1;\n  var b = 0;\n  var i = 0;\n  var l = data.length;\n  var m = l & ~0x3;\n  while (i < m) {\n    var n = Math.min(i + 4096, m);\n    for (; i < n; i += 4) {\n      b += (a += data.charCodeAt(i)) + (a += data.charCodeAt(i + 1)) + (a += data.charCodeAt(i + 2)) + (a += data.charCodeAt(i + 3));\n    }\n    a %= MOD;\n    b %= MOD;\n  }\n  for (; i < l; i++) {\n    b += a += data.charCodeAt(i);\n  }\n  a %= MOD;\n  b %= MOD;\n  return a | b << 16;\n}\n\nmodule.exports = adler32;\n},{}],117:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule canDefineProperty\n */\n\n'use strict';\n\nvar canDefineProperty = false;\nif (\"development\" !== 'production') {\n  try {\n    Object.defineProperty({}, 'x', { get: function () {} });\n    canDefineProperty = true;\n  } catch (x) {\n    // IE will fail on defineProperty\n  }\n}\n\nmodule.exports = canDefineProperty;\n},{}],118:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule checkReactTypeSpec\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactPropTypeLocationNames = _dereq_(83);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\nvar loggedTypeFailures = {};\n\n/**\n * Assert that the values match with the type specs.\n * Error messages are memorized and will only be shown once.\n *\n * @param {object} typeSpecs Map of name to a ReactPropType\n * @param {object} values Runtime values that need to be type-checked\n * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n * @param {string} componentName Name of the component for error messages.\n * @param {?object} element The React element that is being type-checked\n * @param {?number} debugID The React component instance that is being type-checked\n * @private\n */\nfunction checkReactTypeSpec(typeSpecs, values, location, componentName, element, debugID) {\n  for (var typeSpecName in typeSpecs) {\n    if (typeSpecs.hasOwnProperty(typeSpecName)) {\n      var error;\n      // Prop type validation may throw. In case they do, we don't want to\n      // fail the render phase where it didn't fail before. So we log it.\n      // After these have been cleaned up, we'll let them throw.\n      try {\n        // This is intentionally an invariant that gets caught. It's the same\n        // behavior as without this statement except with a better message.\n        !(typeof typeSpecs[typeSpecName] === 'function') ? \"development\" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : _prodInvariant('84', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName) : void 0;\n        error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location);\n      } catch (ex) {\n        error = ex;\n      }\n      \"development\" !== 'production' ? warning(!error || error instanceof Error, '%s: type specification of %s `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', ReactPropTypeLocationNames[location], typeSpecName, typeof error) : void 0;\n      if (error instanceof Error && !(error.message in loggedTypeFailures)) {\n        // Only monitor this failure once because there tends to be a lot of the\n        // same error.\n        loggedTypeFailures[error.message] = true;\n\n        var componentStackInfo = '';\n\n        if (\"development\" !== 'production') {\n          var ReactComponentTreeDevtool = _dereq_(34);\n          if (debugID !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getStackAddendumByID(debugID);\n          } else if (element !== null) {\n            componentStackInfo = ReactComponentTreeDevtool.getCurrentStackAddendum(element);\n          }\n        }\n\n        \"development\" !== 'production' ? warning(false, 'Failed %s type: %s%s', location, error.message, componentStackInfo) : void 0;\n      }\n    }\n  }\n}\n\nmodule.exports = checkReactTypeSpec;\n},{\"139\":139,\"161\":161,\"171\":171,\"34\":34,\"83\":83}],119:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule createMicrosoftUnsafeLocalFunction\n */\n\n/* globals MSApp */\n\n'use strict';\n\n/**\n * Create a function which has 'unsafe' privileges (required by windows8 apps)\n */\n\nvar createMicrosoftUnsafeLocalFunction = function (func) {\n  if (typeof MSApp !== 'undefined' && MSApp.execUnsafeLocalFunction) {\n    return function (arg0, arg1, arg2, arg3) {\n      MSApp.execUnsafeLocalFunction(function () {\n        return func(arg0, arg1, arg2, arg3);\n      });\n    };\n  } else {\n    return func;\n  }\n};\n\nmodule.exports = createMicrosoftUnsafeLocalFunction;\n},{}],120:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule dangerousStyleValue\n */\n\n'use strict';\n\nvar CSSProperty = _dereq_(3);\nvar warning = _dereq_(171);\n\nvar isUnitlessNumber = CSSProperty.isUnitlessNumber;\nvar styleWarnings = {};\n\n/**\n * Convert a value into the proper css writable value. The style name `name`\n * should be logical (no hyphens), as specified\n * in `CSSProperty.isUnitlessNumber`.\n *\n * @param {string} name CSS property name such as `topMargin`.\n * @param {*} value CSS property value such as `10px`.\n * @param {ReactDOMComponent} component\n * @return {string} Normalized style value with dimensions applied.\n */\nfunction dangerousStyleValue(name, value, component) {\n  // Note that we've removed escapeTextForBrowser() calls here since the\n  // whole string will be escaped when the attribute is injected into\n  // the markup. If you provide unsafe user data here they can inject\n  // arbitrary CSS which may be problematic (I couldn't repro this):\n  // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet\n  // http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/\n  // This is not an XSS hole but instead a potential CSS injection issue\n  // which has lead to a greater discussion about how we're going to\n  // trust URLs moving forward. See #2115901\n\n  var isEmpty = value == null || typeof value === 'boolean' || value === '';\n  if (isEmpty) {\n    return '';\n  }\n\n  var isNonNumeric = isNaN(value);\n  if (isNonNumeric || value === 0 || isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {\n    return '' + value; // cast to string\n  }\n\n  if (typeof value === 'string') {\n    if (\"development\" !== 'production') {\n      // Allow '0' to pass through without warning. 0 is already special and\n      // doesn't require units, so we don't need to warn about it.\n      if (component && value !== '0') {\n        var owner = component._currentElement._owner;\n        var ownerName = owner ? owner.getName() : null;\n        if (ownerName && !styleWarnings[ownerName]) {\n          styleWarnings[ownerName] = {};\n        }\n        var warned = false;\n        if (ownerName) {\n          var warnings = styleWarnings[ownerName];\n          warned = warnings[name];\n          if (!warned) {\n            warnings[name] = true;\n          }\n        }\n        if (!warned) {\n          \"development\" !== 'production' ? warning(false, 'a `%s` tag (owner: `%s`) was passed a numeric string value ' + 'for CSS property `%s` (value: `%s`) which will be treated ' + 'as a unitless number in a future version of React.', component._currentElement.type, ownerName || 'unknown', name, value) : void 0;\n        }\n      }\n    }\n    value = value.trim();\n  }\n  return value + 'px';\n}\n\nmodule.exports = dangerousStyleValue;\n},{\"171\":171,\"3\":3}],121:[function(_dereq_,module,exports){\n/**\n * Copyright 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * Based on the escape-html library, which is used under the MIT License below:\n *\n * Copyright (c) 2012-2013 TJ Holowaychuk\n * Copyright (c) 2015 Andreas Lubbe\n * Copyright (c) 2015 Tiancheng \"Timothy\" Gu\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * 'Software'), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n * @providesModule escapeTextContentForBrowser\n */\n\n'use strict';\n\n// code copied and modified from escape-html\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param  {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n  var str = '' + string;\n  var match = matchHtmlRegExp.exec(str);\n\n  if (!match) {\n    return str;\n  }\n\n  var escape;\n  var html = '';\n  var index = 0;\n  var lastIndex = 0;\n\n  for (index = match.index; index < str.length; index++) {\n    switch (str.charCodeAt(index)) {\n      case 34:\n        // \"\n        escape = '&quot;';\n        break;\n      case 38:\n        // &\n        escape = '&amp;';\n        break;\n      case 39:\n        // '\n        escape = '&#x27;'; // modified from escape-html; used to be '&#39'\n        break;\n      case 60:\n        // <\n        escape = '&lt;';\n        break;\n      case 62:\n        // >\n        escape = '&gt;';\n        break;\n      default:\n        continue;\n    }\n\n    if (lastIndex !== index) {\n      html += str.substring(lastIndex, index);\n    }\n\n    lastIndex = index + 1;\n    html += escape;\n  }\n\n  return lastIndex !== index ? html + str.substring(lastIndex, index) : html;\n}\n// end code copied and modified from escape-html\n\n/**\n * Escapes text to prevent scripting attacks.\n *\n * @param {*} text Text value to escape.\n * @return {string} An escaped string.\n */\nfunction escapeTextContentForBrowser(text) {\n  if (typeof text === 'boolean' || typeof text === 'number') {\n    // this shortcircuit helps perf for types that we know will never have\n    // special characters, especially given that this function is used often\n    // for numeric dom ids.\n    return '' + text;\n  }\n  return escapeHtml(text);\n}\n\nmodule.exports = escapeTextContentForBrowser;\n},{}],122:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule findDOMNode\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactDOMComponentTree = _dereq_(41);\nvar ReactInstanceMap = _dereq_(73);\n\nvar getHostComponentFromComposite = _dereq_(129);\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n/**\n * Returns the DOM node rendered by this element.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode\n *\n * @param {ReactComponent|DOMElement} componentOrElement\n * @return {?DOMElement} The root node of this element.\n */\nfunction findDOMNode(componentOrElement) {\n  if (\"development\" !== 'production') {\n    var owner = ReactCurrentOwner.current;\n    if (owner !== null) {\n      \"development\" !== 'production' ? warning(owner._warnedAboutRefsInRender, '%s is accessing findDOMNode inside its render(). ' + 'render() should be a pure function of props and state. It should ' + 'never access something that requires stale data from the previous ' + 'render, such as refs. Move this logic to componentDidMount and ' + 'componentDidUpdate instead.', owner.getName() || 'A component') : void 0;\n      owner._warnedAboutRefsInRender = true;\n    }\n  }\n  if (componentOrElement == null) {\n    return null;\n  }\n  if (componentOrElement.nodeType === 1) {\n    return componentOrElement;\n  }\n\n  var inst = ReactInstanceMap.get(componentOrElement);\n  if (inst) {\n    inst = getHostComponentFromComposite(inst);\n    return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null;\n  }\n\n  if (typeof componentOrElement.render === 'function') {\n    !false ? \"development\" !== 'production' ? invariant(false, 'findDOMNode was called on an unmounted component.') : _prodInvariant('44') : void 0;\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Element appears to be neither ReactComponent nor DOMNode (keys: %s)', Object.keys(componentOrElement)) : _prodInvariant('45', Object.keys(componentOrElement)) : void 0;\n  }\n}\n\nmodule.exports = findDOMNode;\n},{\"129\":129,\"139\":139,\"161\":161,\"171\":171,\"36\":36,\"41\":41,\"73\":73}],123:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule flattenChildren\n * \n */\n\n'use strict';\n\nvar KeyEscapeUtils = _dereq_(23);\nvar traverseAllChildren = _dereq_(144);\nvar warning = _dereq_(171);\n\n/**\n * @param {function} traverseContext Context passed through traversal.\n * @param {?ReactComponent} child React child component.\n * @param {!string} name String name of key path to child.\n * @param {number=} selfDebugID Optional debugID of the current internal instance.\n */\nfunction flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID) {\n  // We found a component instance.\n  if (traverseContext && typeof traverseContext === 'object') {\n    var result = traverseContext;\n    var keyUnique = result[name] === undefined;\n    if (\"development\" !== 'production') {\n      var ReactComponentTreeDevtool = _dereq_(34);\n      \"development\" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeDevtool.getStackAddendumByID(selfDebugID)) : void 0;\n    }\n    if (keyUnique && child != null) {\n      result[name] = child;\n    }\n  }\n}\n\n/**\n * Flattens children that are typically specified as `props.children`. Any null\n * children will not be included in the resulting object.\n * @return {!object} flattened children keyed by name.\n */\nfunction flattenChildren(children, selfDebugID) {\n  if (children == null) {\n    return children;\n  }\n  var result = {};\n\n  if (\"development\" !== 'production') {\n    traverseAllChildren(children, function (traverseContext, child, name) {\n      return flattenSingleChildIntoContext(traverseContext, child, name, selfDebugID);\n    }, result);\n  } else {\n    traverseAllChildren(children, flattenSingleChildIntoContext, result);\n  }\n  return result;\n}\n\nmodule.exports = flattenChildren;\n},{\"144\":144,\"171\":171,\"23\":23,\"34\":34}],124:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule forEachAccumulated\n * \n */\n\n'use strict';\n\n/**\n * @param {array} arr an \"accumulation\" of items which is either an Array or\n * a single item. Useful when paired with the `accumulate` module. This is a\n * simple utility that allows us to reason about a collection of items, but\n * handling the case when there is exactly one item (and we do not need to\n * allocate an array).\n */\n\nfunction forEachAccumulated(arr, cb, scope) {\n  if (Array.isArray(arr)) {\n    arr.forEach(cb, scope);\n  } else if (arr) {\n    cb.call(scope, arr);\n  }\n}\n\nmodule.exports = forEachAccumulated;\n},{}],125:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventCharCode\n */\n\n'use strict';\n\n/**\n * `charCode` represents the actual \"character code\" and is safe to use with\n * `String.fromCharCode`. As such, only keys that correspond to printable\n * characters produce a valid `charCode`, the only exception to this is Enter.\n * The Tab-key is considered non-printable and does not have a `charCode`,\n * presumably because it does not produce a tab-character in browsers.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {number} Normalized `charCode` property.\n */\n\nfunction getEventCharCode(nativeEvent) {\n  var charCode;\n  var keyCode = nativeEvent.keyCode;\n\n  if ('charCode' in nativeEvent) {\n    charCode = nativeEvent.charCode;\n\n    // FF does not set `charCode` for the Enter-key, check against `keyCode`.\n    if (charCode === 0 && keyCode === 13) {\n      charCode = 13;\n    }\n  } else {\n    // IE8 does not implement `charCode`, but `keyCode` has the correct value.\n    charCode = keyCode;\n  }\n\n  // Some non-printable keys are reported in `charCode`/`keyCode`, discard them.\n  // Must not discard the (non-)printable Enter-key.\n  if (charCode >= 32 || charCode === 13) {\n    return charCode;\n  }\n\n  return 0;\n}\n\nmodule.exports = getEventCharCode;\n},{}],126:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventKey\n */\n\n'use strict';\n\nvar getEventCharCode = _dereq_(125);\n\n/**\n * Normalization of deprecated HTML5 `key` values\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar normalizeKey = {\n  'Esc': 'Escape',\n  'Spacebar': ' ',\n  'Left': 'ArrowLeft',\n  'Up': 'ArrowUp',\n  'Right': 'ArrowRight',\n  'Down': 'ArrowDown',\n  'Del': 'Delete',\n  'Win': 'OS',\n  'Menu': 'ContextMenu',\n  'Apps': 'ContextMenu',\n  'Scroll': 'ScrollLock',\n  'MozPrintableKey': 'Unidentified'\n};\n\n/**\n * Translation from legacy `keyCode` to HTML5 `key`\n * Only special keys supported, all others depend on keyboard layout or browser\n * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names\n */\nvar translateToKey = {\n  8: 'Backspace',\n  9: 'Tab',\n  12: 'Clear',\n  13: 'Enter',\n  16: 'Shift',\n  17: 'Control',\n  18: 'Alt',\n  19: 'Pause',\n  20: 'CapsLock',\n  27: 'Escape',\n  32: ' ',\n  33: 'PageUp',\n  34: 'PageDown',\n  35: 'End',\n  36: 'Home',\n  37: 'ArrowLeft',\n  38: 'ArrowUp',\n  39: 'ArrowRight',\n  40: 'ArrowDown',\n  45: 'Insert',\n  46: 'Delete',\n  112: 'F1', 113: 'F2', 114: 'F3', 115: 'F4', 116: 'F5', 117: 'F6',\n  118: 'F7', 119: 'F8', 120: 'F9', 121: 'F10', 122: 'F11', 123: 'F12',\n  144: 'NumLock',\n  145: 'ScrollLock',\n  224: 'Meta'\n};\n\n/**\n * @param {object} nativeEvent Native browser event.\n * @return {string} Normalized `key` property.\n */\nfunction getEventKey(nativeEvent) {\n  if (nativeEvent.key) {\n    // Normalize inconsistent values reported by browsers due to\n    // implementations of a working draft specification.\n\n    // FireFox implements `key` but returns `MozPrintableKey` for all\n    // printable characters (normalized to `Unidentified`), ignore it.\n    var key = normalizeKey[nativeEvent.key] || nativeEvent.key;\n    if (key !== 'Unidentified') {\n      return key;\n    }\n  }\n\n  // Browser does not implement `key`, polyfill as much of it as we can.\n  if (nativeEvent.type === 'keypress') {\n    var charCode = getEventCharCode(nativeEvent);\n\n    // The enter-key is technically both printable and non-printable and can\n    // thus be captured by `keypress`, no other non-printable key should.\n    return charCode === 13 ? 'Enter' : String.fromCharCode(charCode);\n  }\n  if (nativeEvent.type === 'keydown' || nativeEvent.type === 'keyup') {\n    // While user keyboard layout determines the actual meaning of each\n    // `keyCode` value, almost all function keys have a universal value.\n    return translateToKey[nativeEvent.keyCode] || 'Unidentified';\n  }\n  return '';\n}\n\nmodule.exports = getEventKey;\n},{\"125\":125}],127:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventModifierState\n */\n\n'use strict';\n\n/**\n * Translation from modifier key to the associated property in the event.\n * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers\n */\n\nvar modifierKeyToProp = {\n  'Alt': 'altKey',\n  'Control': 'ctrlKey',\n  'Meta': 'metaKey',\n  'Shift': 'shiftKey'\n};\n\n// IE8 does not implement getModifierState so we simply map it to the only\n// modifier keys exposed by the event itself, does not support Lock-keys.\n// Currently, all major browsers except Chrome seems to support Lock-keys.\nfunction modifierStateGetter(keyArg) {\n  var syntheticEvent = this;\n  var nativeEvent = syntheticEvent.nativeEvent;\n  if (nativeEvent.getModifierState) {\n    return nativeEvent.getModifierState(keyArg);\n  }\n  var keyProp = modifierKeyToProp[keyArg];\n  return keyProp ? !!nativeEvent[keyProp] : false;\n}\n\nfunction getEventModifierState(nativeEvent) {\n  return modifierStateGetter;\n}\n\nmodule.exports = getEventModifierState;\n},{}],128:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getEventTarget\n */\n\n'use strict';\n\n/**\n * Gets the target node from a native browser event by accounting for\n * inconsistencies in browser DOM APIs.\n *\n * @param {object} nativeEvent Native browser event.\n * @return {DOMEventTarget} Target node.\n */\n\nfunction getEventTarget(nativeEvent) {\n  var target = nativeEvent.target || nativeEvent.srcElement || window;\n\n  // Normalize SVG <use> element events #4963\n  if (target.correspondingUseElement) {\n    target = target.correspondingUseElement;\n  }\n\n  // Safari may fire events on text nodes (Node.TEXT_NODE is 3).\n  // @see http://www.quirksmode.org/js/events_properties.html\n  return target.nodeType === 3 ? target.parentNode : target;\n}\n\nmodule.exports = getEventTarget;\n},{}],129:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getHostComponentFromComposite\n */\n\n'use strict';\n\nvar ReactNodeTypes = _dereq_(80);\n\nfunction getHostComponentFromComposite(inst) {\n  var type;\n\n  while ((type = inst._renderedNodeType) === ReactNodeTypes.COMPOSITE) {\n    inst = inst._renderedComponent;\n  }\n\n  if (type === ReactNodeTypes.HOST) {\n    return inst._renderedComponent;\n  } else if (type === ReactNodeTypes.EMPTY) {\n    return null;\n  }\n}\n\nmodule.exports = getHostComponentFromComposite;\n},{\"80\":80}],130:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getIteratorFn\n * \n */\n\n'use strict';\n\n/* global Symbol */\n\nvar ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.\n\n/**\n * Returns the iterator method function contained on the iterable object.\n *\n * Be sure to invoke the function with the iterable as context:\n *\n *     var iteratorFn = getIteratorFn(myIterable);\n *     if (iteratorFn) {\n *       var iterator = iteratorFn.call(myIterable);\n *       ...\n *     }\n *\n * @param {?object} maybeIterable\n * @return {?function}\n */\nfunction getIteratorFn(maybeIterable) {\n  var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);\n  if (typeof iteratorFn === 'function') {\n    return iteratorFn;\n  }\n}\n\nmodule.exports = getIteratorFn;\n},{}],131:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getNodeForCharacterOffset\n */\n\n'use strict';\n\n/**\n * Given any node return the first leaf node without children.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {DOMElement|DOMTextNode}\n */\n\nfunction getLeafNode(node) {\n  while (node && node.firstChild) {\n    node = node.firstChild;\n  }\n  return node;\n}\n\n/**\n * Get the next sibling within a container. This will walk up the\n * DOM if a node's siblings have been exhausted.\n *\n * @param {DOMElement|DOMTextNode} node\n * @return {?DOMElement|DOMTextNode}\n */\nfunction getSiblingNode(node) {\n  while (node) {\n    if (node.nextSibling) {\n      return node.nextSibling;\n    }\n    node = node.parentNode;\n  }\n}\n\n/**\n * Get object describing the nodes which contain characters at offset.\n *\n * @param {DOMElement|DOMTextNode} root\n * @param {number} offset\n * @return {?object}\n */\nfunction getNodeForCharacterOffset(root, offset) {\n  var node = getLeafNode(root);\n  var nodeStart = 0;\n  var nodeEnd = 0;\n\n  while (node) {\n    if (node.nodeType === 3) {\n      nodeEnd = nodeStart + node.textContent.length;\n\n      if (nodeStart <= offset && nodeEnd >= offset) {\n        return {\n          node: node,\n          offset: offset - nodeStart\n        };\n      }\n\n      nodeStart = nodeEnd;\n    }\n\n    node = getLeafNode(getSiblingNode(node));\n  }\n}\n\nmodule.exports = getNodeForCharacterOffset;\n},{}],132:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getTextContentAccessor\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar contentKey = null;\n\n/**\n * Gets the key used to access text content on a DOM node.\n *\n * @return {?string} Key used to access text content.\n * @internal\n */\nfunction getTextContentAccessor() {\n  if (!contentKey && ExecutionEnvironment.canUseDOM) {\n    // Prefer textContent to innerText because many browsers support both but\n    // SVG <text> elements don't support innerText even when <div> does.\n    contentKey = 'textContent' in document.documentElement ? 'textContent' : 'innerText';\n  }\n  return contentKey;\n}\n\nmodule.exports = getTextContentAccessor;\n},{\"147\":147}],133:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule getVendorPrefixedEventName\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\n/**\n * Generate a mapping of standard vendor prefixes using the defined style property and event name.\n *\n * @param {string} styleProp\n * @param {string} eventName\n * @returns {object}\n */\nfunction makePrefixMap(styleProp, eventName) {\n  var prefixes = {};\n\n  prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();\n  prefixes['Webkit' + styleProp] = 'webkit' + eventName;\n  prefixes['Moz' + styleProp] = 'moz' + eventName;\n  prefixes['ms' + styleProp] = 'MS' + eventName;\n  prefixes['O' + styleProp] = 'o' + eventName.toLowerCase();\n\n  return prefixes;\n}\n\n/**\n * A list of event names to a configurable list of vendor prefixes.\n */\nvar vendorPrefixes = {\n  animationend: makePrefixMap('Animation', 'AnimationEnd'),\n  animationiteration: makePrefixMap('Animation', 'AnimationIteration'),\n  animationstart: makePrefixMap('Animation', 'AnimationStart'),\n  transitionend: makePrefixMap('Transition', 'TransitionEnd')\n};\n\n/**\n * Event names that have already been detected and prefixed (if applicable).\n */\nvar prefixedEventNames = {};\n\n/**\n * Element to check for prefixes on.\n */\nvar style = {};\n\n/**\n * Bootstrap if a DOM exists.\n */\nif (ExecutionEnvironment.canUseDOM) {\n  style = document.createElement('div').style;\n\n  // On some platforms, in particular some releases of Android 4.x,\n  // the un-prefixed \"animation\" and \"transition\" properties are defined on the\n  // style object but the events that fire will still be prefixed, so we need\n  // to check if the un-prefixed events are usable, and if not remove them from the map.\n  if (!('AnimationEvent' in window)) {\n    delete vendorPrefixes.animationend.animation;\n    delete vendorPrefixes.animationiteration.animation;\n    delete vendorPrefixes.animationstart.animation;\n  }\n\n  // Same as above\n  if (!('TransitionEvent' in window)) {\n    delete vendorPrefixes.transitionend.transition;\n  }\n}\n\n/**\n * Attempts to determine the correct vendor prefixed event name.\n *\n * @param {string} eventName\n * @returns {string}\n */\nfunction getVendorPrefixedEventName(eventName) {\n  if (prefixedEventNames[eventName]) {\n    return prefixedEventNames[eventName];\n  } else if (!vendorPrefixes[eventName]) {\n    return eventName;\n  }\n\n  var prefixMap = vendorPrefixes[eventName];\n\n  for (var styleProp in prefixMap) {\n    if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) {\n      return prefixedEventNames[eventName] = prefixMap[styleProp];\n    }\n  }\n\n  return '';\n}\n\nmodule.exports = getVendorPrefixedEventName;\n},{\"147\":147}],134:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule instantiateReactComponent\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139),\n    _assign = _dereq_(172);\n\nvar ReactCompositeComponent = _dereq_(35);\nvar ReactEmptyComponent = _dereq_(64);\nvar ReactHostComponent = _dereq_(69);\nvar ReactInstrumentation = _dereq_(74);\n\nvar invariant = _dereq_(161);\nvar warning = _dereq_(171);\n\n// To avoid a cyclic dependency, we create the final class in this module\nvar ReactCompositeComponentWrapper = function (element) {\n  this.construct(element);\n};\n_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent.Mixin, {\n  _instantiateReactComponent: instantiateReactComponent\n});\n\nfunction getDeclarationErrorAddendum(owner) {\n  if (owner) {\n    var name = owner.getName();\n    if (name) {\n      return ' Check the render method of `' + name + '`.';\n    }\n  }\n  return '';\n}\n\nfunction getDisplayName(instance) {\n  var element = instance._currentElement;\n  if (element == null) {\n    return '#empty';\n  } else if (typeof element === 'string' || typeof element === 'number') {\n    return '#text';\n  } else if (typeof element.type === 'string') {\n    return element.type;\n  } else if (instance.getName) {\n    return instance.getName() || 'Unknown';\n  } else {\n    return element.type.displayName || element.type.name || 'Unknown';\n  }\n}\n\n/**\n * Check if the type reference is a known internal type. I.e. not a user\n * provided composite type.\n *\n * @param {function} type\n * @return {boolean} Returns true if this is a valid internal type.\n */\nfunction isInternalComponentType(type) {\n  return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';\n}\n\nvar nextDebugID = 1;\n\n/**\n * Given a ReactNode, create an instance that will actually be mounted.\n *\n * @param {ReactNode} node\n * @param {boolean} shouldHaveDebugID\n * @return {object} A new instance of the element's constructor.\n * @protected\n */\nfunction instantiateReactComponent(node, shouldHaveDebugID) {\n  var instance;\n\n  if (node === null || node === false) {\n    instance = ReactEmptyComponent.create(instantiateReactComponent);\n  } else if (typeof node === 'object') {\n    var element = node;\n    !(element && (typeof element.type === 'function' || typeof element.type === 'string')) ? \"development\" !== 'production' ? invariant(false, 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : _prodInvariant('130', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : void 0;\n\n    // Special case string values\n    if (typeof element.type === 'string') {\n      instance = ReactHostComponent.createInternalComponent(element);\n    } else if (isInternalComponentType(element.type)) {\n      // This is temporarily available for custom components that are not string\n      // representations. I.e. ART. Once those are updated to use the string\n      // representation, we can drop this code path.\n      instance = new element.type(element);\n\n      // We renamed this. Allow the old name for compat. :(\n      if (!instance.getHostNode) {\n        instance.getHostNode = instance.getNativeNode;\n      }\n    } else {\n      instance = new ReactCompositeComponentWrapper(element);\n    }\n  } else if (typeof node === 'string' || typeof node === 'number') {\n    instance = ReactHostComponent.createInstanceForText(node);\n  } else {\n    !false ? \"development\" !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : _prodInvariant('131', typeof node) : void 0;\n  }\n\n  if (\"development\" !== 'production') {\n    \"development\" !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getHostNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;\n  }\n\n  // These two fields are used by the DOM and ART diffing algorithms\n  // respectively. Instead of using expandos on components, we should be\n  // storing the state needed by the diffing algorithms elsewhere.\n  instance._mountIndex = 0;\n  instance._mountImage = null;\n\n  if (\"development\" !== 'production') {\n    if (shouldHaveDebugID) {\n      var debugID = nextDebugID++;\n      instance._debugID = debugID;\n      var displayName = getDisplayName(instance);\n      ReactInstrumentation.debugTool.onSetDisplayName(debugID, displayName);\n      var owner = node && node._owner;\n      if (owner) {\n        ReactInstrumentation.debugTool.onSetOwner(debugID, owner._debugID);\n      }\n    } else {\n      instance._debugID = 0;\n    }\n  }\n\n  // Internal instances should fully constructed at this point, so they should\n  // not get any new fields added to them at this point.\n  if (\"development\" !== 'production') {\n    if (Object.preventExtensions) {\n      Object.preventExtensions(instance);\n    }\n  }\n\n  return instance;\n}\n\nmodule.exports = instantiateReactComponent;\n},{\"139\":139,\"161\":161,\"171\":171,\"172\":172,\"35\":35,\"64\":64,\"69\":69,\"74\":74}],135:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isEventSupported\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar useHasFeature;\nif (ExecutionEnvironment.canUseDOM) {\n  useHasFeature = document.implementation && document.implementation.hasFeature &&\n  // always returns true in newer browsers as per the standard.\n  // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature\n  document.implementation.hasFeature('', '') !== true;\n}\n\n/**\n * Checks if an event is supported in the current execution environment.\n *\n * NOTE: This will not work correctly for non-generic events such as `change`,\n * `reset`, `load`, `error`, and `select`.\n *\n * Borrows from Modernizr.\n *\n * @param {string} eventNameSuffix Event name, e.g. \"click\".\n * @param {?boolean} capture Check if the capture phase is supported.\n * @return {boolean} True if the event is supported.\n * @internal\n * @license Modernizr 3.0.0pre (Custom Build) | MIT\n */\nfunction isEventSupported(eventNameSuffix, capture) {\n  if (!ExecutionEnvironment.canUseDOM || capture && !('addEventListener' in document)) {\n    return false;\n  }\n\n  var eventName = 'on' + eventNameSuffix;\n  var isSupported = eventName in document;\n\n  if (!isSupported) {\n    var element = document.createElement('div');\n    element.setAttribute(eventName, 'return;');\n    isSupported = typeof element[eventName] === 'function';\n  }\n\n  if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {\n    // This is the only way to test support for the `wheel` event in IE9+.\n    isSupported = document.implementation.hasFeature('Events.wheel', '3.0');\n  }\n\n  return isSupported;\n}\n\nmodule.exports = isEventSupported;\n},{\"147\":147}],136:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule isTextInputElement\n * \n */\n\n'use strict';\n\n/**\n * @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary\n */\n\nvar supportedInputTypes = {\n  'color': true,\n  'date': true,\n  'datetime': true,\n  'datetime-local': true,\n  'email': true,\n  'month': true,\n  'number': true,\n  'password': true,\n  'range': true,\n  'search': true,\n  'tel': true,\n  'text': true,\n  'time': true,\n  'url': true,\n  'week': true\n};\n\nfunction isTextInputElement(elem) {\n  var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n\n  if (nodeName === 'input') {\n    return !!supportedInputTypes[elem.type];\n  }\n\n  if (nodeName === 'textarea') {\n    return true;\n  }\n\n  return false;\n}\n\nmodule.exports = isTextInputElement;\n},{}],137:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule onlyChild\n */\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactElement = _dereq_(62);\n\nvar invariant = _dereq_(161);\n\n/**\n * Returns the first child in a collection of children and verifies that there\n * is only one child in the collection.\n *\n * See https://facebook.github.io/react/docs/top-level-api.html#react.children.only\n *\n * The current implementation of this function assumes that a single child gets\n * passed without a wrapper, but the purpose of this helper function is to\n * abstract away the particular structure of children.\n *\n * @param {?object} children Child collection structure.\n * @return {ReactElement} The first and only `ReactElement` contained in the\n * structure.\n */\nfunction onlyChild(children) {\n  !ReactElement.isValidElement(children) ? \"development\" !== 'production' ? invariant(false, 'onlyChild must be passed a children with exactly one child.') : _prodInvariant('23') : void 0;\n  return children;\n}\n\nmodule.exports = onlyChild;\n},{\"139\":139,\"161\":161,\"62\":62}],138:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule quoteAttributeValueForBrowser\n */\n\n'use strict';\n\nvar escapeTextContentForBrowser = _dereq_(121);\n\n/**\n * Escapes attribute value to prevent scripting attacks.\n *\n * @param {*} value Value to escape.\n * @return {string} An escaped string.\n */\nfunction quoteAttributeValueForBrowser(value) {\n  return '\"' + escapeTextContentForBrowser(value) + '\"';\n}\n\nmodule.exports = quoteAttributeValueForBrowser;\n},{\"121\":121}],139:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule reactProdInvariant\n * \n */\n'use strict';\n\n/**\n * WARNING: DO NOT manually require this module.\n * This is a replacement for `invariant(...)` used by the error code system\n * and will _only_ be required by the corresponding babel pass.\n * It always throws.\n */\n\nfunction reactProdInvariant(code) {\n  var argCount = arguments.length - 1;\n\n  var message = 'Minified React error #' + code + '; visit ' + 'http://facebook.github.io/react/docs/error-decoder.html?invariant=' + code;\n\n  for (var argIdx = 0; argIdx < argCount; argIdx++) {\n    message += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);\n  }\n\n  message += ' for the full message or use the non-minified dev environment' + ' for full errors and additional helpful warnings.';\n\n  var error = new Error(message);\n  error.name = 'Invariant Violation';\n  error.framesToPop = 1; // we don't care about reactProdInvariant's own frame\n\n  throw error;\n}\n\nmodule.exports = reactProdInvariant;\n},{}],140:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n* @providesModule renderSubtreeIntoContainer\n*/\n\n'use strict';\n\nvar ReactMount = _dereq_(77);\n\nmodule.exports = ReactMount.renderSubtreeIntoContainer;\n},{\"77\":77}],141:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setInnerHTML\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar DOMNamespaces = _dereq_(9);\n\nvar WHITESPACE_TEST = /^[ \\r\\n\\t\\f]/;\nvar NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \\r\\n\\t\\f\\/>]/;\n\nvar createMicrosoftUnsafeLocalFunction = _dereq_(119);\n\n// SVG temp container for IE lacking innerHTML\nvar reusableSVGContainer;\n\n/**\n * Set the innerHTML property of a node, ensuring that whitespace is preserved\n * even in IE8.\n *\n * @param {DOMElement} node\n * @param {string} html\n * @internal\n */\nvar setInnerHTML = createMicrosoftUnsafeLocalFunction(function (node, html) {\n  // IE does not have innerHTML for SVG nodes, so instead we inject the\n  // new markup in a temp node and then move the child nodes across into\n  // the target node\n  if (node.namespaceURI === DOMNamespaces.svg && !('innerHTML' in node)) {\n    reusableSVGContainer = reusableSVGContainer || document.createElement('div');\n    reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>';\n    var newNodes = reusableSVGContainer.firstChild.childNodes;\n    for (var i = 0; i < newNodes.length; i++) {\n      node.appendChild(newNodes[i]);\n    }\n  } else {\n    node.innerHTML = html;\n  }\n});\n\nif (ExecutionEnvironment.canUseDOM) {\n  // IE8: When updating a just created node with innerHTML only leading\n  // whitespace is removed. When updating an existing node with innerHTML\n  // whitespace in root TextNodes is also collapsed.\n  // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html\n\n  // Feature detection; only IE8 is known to behave improperly like this.\n  var testElement = document.createElement('div');\n  testElement.innerHTML = ' ';\n  if (testElement.innerHTML === '') {\n    setInnerHTML = function (node, html) {\n      // Magic theory: IE8 supposedly differentiates between added and updated\n      // nodes when processing innerHTML, innerHTML on updated nodes suffers\n      // from worse whitespace behavior. Re-adding a node like this triggers\n      // the initial and more favorable whitespace behavior.\n      // TODO: What to do on a detached node?\n      if (node.parentNode) {\n        node.parentNode.replaceChild(node, node);\n      }\n\n      // We also implement a workaround for non-visible tags disappearing into\n      // thin air on IE8, this only happens if there is no visible text\n      // in-front of the non-visible tags. Piggyback on the whitespace fix\n      // and simply check if any non-visible tags appear in the source.\n      if (WHITESPACE_TEST.test(html) || html[0] === '<' && NONVISIBLE_TEST.test(html)) {\n        // Recover leading whitespace by temporarily prepending any character.\n        // \\uFEFF has the potential advantage of being zero-width/invisible.\n        // UglifyJS drops U+FEFF chars when parsing, so use String.fromCharCode\n        // in hopes that this is preserved even if \"\\uFEFF\" is transformed to\n        // the actual Unicode character (by Babel, for example).\n        // https://github.com/mishoo/UglifyJS2/blob/v2.4.20/lib/parse.js#L216\n        node.innerHTML = String.fromCharCode(0xFEFF) + html;\n\n        // deleteData leaves an empty `TextNode` which offsets the index of all\n        // children. Definitely want to avoid this.\n        var textNode = node.firstChild;\n        if (textNode.data.length === 1) {\n          node.removeChild(textNode);\n        } else {\n          textNode.deleteData(0, 1);\n        }\n      } else {\n        node.innerHTML = html;\n      }\n    };\n  }\n  testElement = null;\n}\n\nmodule.exports = setInnerHTML;\n},{\"119\":119,\"147\":147,\"9\":9}],142:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule setTextContent\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\nvar escapeTextContentForBrowser = _dereq_(121);\nvar setInnerHTML = _dereq_(141);\n\n/**\n * Set the textContent property of a node, ensuring that whitespace is preserved\n * even in IE8. innerText is a poor substitute for textContent and, among many\n * issues, inserts <br> instead of the literal newline chars. innerHTML behaves\n * as it should.\n *\n * @param {DOMElement} node\n * @param {string} text\n * @internal\n */\nvar setTextContent = function (node, text) {\n  if (text) {\n    var firstChild = node.firstChild;\n\n    if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) {\n      firstChild.nodeValue = text;\n      return;\n    }\n  }\n  node.textContent = text;\n};\n\nif (ExecutionEnvironment.canUseDOM) {\n  if (!('textContent' in document.documentElement)) {\n    setTextContent = function (node, text) {\n      setInnerHTML(node, escapeTextContentForBrowser(text));\n    };\n  }\n}\n\nmodule.exports = setTextContent;\n},{\"121\":121,\"141\":141,\"147\":147}],143:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule shouldUpdateReactComponent\n */\n\n'use strict';\n\n/**\n * Given a `prevElement` and `nextElement`, determines if the existing\n * instance should be updated as opposed to being destroyed or replaced by a new\n * instance. Both arguments are elements. This ensures that this logic can\n * operate on stateless trees without any backing instance.\n *\n * @param {?object} prevElement\n * @param {?object} nextElement\n * @return {boolean} True if the existing instance should be updated.\n * @protected\n */\n\nfunction shouldUpdateReactComponent(prevElement, nextElement) {\n  var prevEmpty = prevElement === null || prevElement === false;\n  var nextEmpty = nextElement === null || nextElement === false;\n  if (prevEmpty || nextEmpty) {\n    return prevEmpty === nextEmpty;\n  }\n\n  var prevType = typeof prevElement;\n  var nextType = typeof nextElement;\n  if (prevType === 'string' || prevType === 'number') {\n    return nextType === 'string' || nextType === 'number';\n  } else {\n    return nextType === 'object' && prevElement.type === nextElement.type && prevElement.key === nextElement.key;\n  }\n}\n\nmodule.exports = shouldUpdateReactComponent;\n},{}],144:[function(_dereq_,module,exports){\n/**\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule traverseAllChildren\n */\n\n'use strict';\n\nvar _prodInvariant = _dereq_(139);\n\nvar ReactCurrentOwner = _dereq_(36);\nvar ReactElement = _dereq_(62);\n\nvar getIteratorFn = _dereq_(130);\nvar invariant = _dereq_(161);\nvar KeyEscapeUtils = _dereq_(23);\nvar warning = _dereq_(171);\n\nvar SEPARATOR = '.';\nvar SUBSEPARATOR = ':';\n\n/**\n * TODO: Test that a single child and an array with one item have the same key\n * pattern.\n */\n\nvar didWarnAboutMaps = false;\n\n/**\n * Generate a key string that identifies a component within a set.\n *\n * @param {*} component A component that could contain a manual key.\n * @param {number} index Index that is used if a manual key is not provided.\n * @return {string}\n */\nfunction getComponentKey(component, index) {\n  // Do some typechecking here since we call this blindly. We want to ensure\n  // that we don't block potential future ES APIs.\n  if (component && typeof component === 'object' && component.key != null) {\n    // Explicit key\n    return KeyEscapeUtils.escape(component.key);\n  }\n  // Implicit key determined by the index in the set\n  return index.toString(36);\n}\n\n/**\n * @param {?*} children Children tree container.\n * @param {!string} nameSoFar Name of the key path so far.\n * @param {!function} callback Callback to invoke with each child found.\n * @param {?*} traverseContext Used to pass information throughout the traversal\n * process.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildrenImpl(children, nameSoFar, callback, traverseContext) {\n  var type = typeof children;\n\n  if (type === 'undefined' || type === 'boolean') {\n    // All of the above are perceived as null.\n    children = null;\n  }\n\n  if (children === null || type === 'string' || type === 'number' || ReactElement.isValidElement(children)) {\n    callback(traverseContext, children,\n    // If it's the only child, treat the name as if it was wrapped in an array\n    // so that it's consistent if the number of children grows.\n    nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar);\n    return 1;\n  }\n\n  var child;\n  var nextName;\n  var subtreeCount = 0; // Count of children found in the current subtree.\n  var nextNamePrefix = nameSoFar === '' ? SEPARATOR : nameSoFar + SUBSEPARATOR;\n\n  if (Array.isArray(children)) {\n    for (var i = 0; i < children.length; i++) {\n      child = children[i];\n      nextName = nextNamePrefix + getComponentKey(child, i);\n      subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n    }\n  } else {\n    var iteratorFn = getIteratorFn(children);\n    if (iteratorFn) {\n      var iterator = iteratorFn.call(children);\n      var step;\n      if (iteratorFn !== children.entries) {\n        var ii = 0;\n        while (!(step = iterator.next()).done) {\n          child = step.value;\n          nextName = nextNamePrefix + getComponentKey(child, ii++);\n          subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n        }\n      } else {\n        if (\"development\" !== 'production') {\n          \"development\" !== 'production' ? warning(didWarnAboutMaps, 'Using Maps as children is not yet fully supported. It is an ' + 'experimental feature that might be removed. Convert it to a ' + 'sequence / iterable of keyed ReactElements instead.') : void 0;\n          didWarnAboutMaps = true;\n        }\n        // Iterator will provide entry [k,v] tuples rather than values.\n        while (!(step = iterator.next()).done) {\n          var entry = step.value;\n          if (entry) {\n            child = entry[1];\n            nextName = nextNamePrefix + KeyEscapeUtils.escape(entry[0]) + SUBSEPARATOR + getComponentKey(child, 0);\n            subtreeCount += traverseAllChildrenImpl(child, nextName, callback, traverseContext);\n          }\n        }\n      }\n    } else if (type === 'object') {\n      var addendum = '';\n      if (\"development\" !== 'production') {\n        addendum = ' If you meant to render a collection of children, use an array ' + 'instead or wrap the object using createFragment(object) from the ' + 'React add-ons.';\n        if (children._isReactElement) {\n          addendum = ' It looks like you\\'re using an element created by a different ' + 'version of React. Make sure to use only one copy of React.';\n        }\n        if (ReactCurrentOwner.current) {\n          var name = ReactCurrentOwner.current.getName();\n          if (name) {\n            addendum += ' Check the render method of `' + name + '`.';\n          }\n        }\n      }\n      var childrenString = String(children);\n      !false ? \"development\" !== 'production' ? invariant(false, 'Objects are not valid as a React child (found: %s).%s', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : _prodInvariant('31', childrenString === '[object Object]' ? 'object with keys {' + Object.keys(children).join(', ') + '}' : childrenString, addendum) : void 0;\n    }\n  }\n\n  return subtreeCount;\n}\n\n/**\n * Traverses children that are typically specified as `props.children`, but\n * might also be specified through attributes:\n *\n * - `traverseAllChildren(this.props.children, ...)`\n * - `traverseAllChildren(this.props.leftPanelChildren, ...)`\n *\n * The `traverseContext` is an optional argument that is passed through the\n * entire traversal. It can be used to store accumulations or anything else that\n * the callback might find relevant.\n *\n * @param {?*} children Children tree object.\n * @param {!function} callback To invoke upon traversing each child.\n * @param {?*} traverseContext Context for traversal.\n * @return {!number} The number of children in this subtree.\n */\nfunction traverseAllChildren(children, callback, traverseContext) {\n  if (children == null) {\n    return 0;\n  }\n\n  return traverseAllChildrenImpl(children, '', callback, traverseContext);\n}\n\nmodule.exports = traverseAllChildren;\n},{\"130\":130,\"139\":139,\"161\":161,\"171\":171,\"23\":23,\"36\":36,\"62\":62}],145:[function(_dereq_,module,exports){\n/**\n * Copyright 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @providesModule validateDOMNesting\n */\n\n'use strict';\n\nvar _assign = _dereq_(172);\n\nvar emptyFunction = _dereq_(153);\nvar warning = _dereq_(171);\n\nvar validateDOMNesting = emptyFunction;\n\nif (\"development\" !== 'production') {\n  // This validation code was written based on the HTML5 parsing spec:\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  //\n  // Note: this does not catch all invalid nesting, nor does it try to (as it's\n  // not clear what practical benefit doing so provides); instead, we warn only\n  // for cases where the parser will give a parse tree differing from what React\n  // intended. For example, <b><div></div></b> is invalid but we don't warn\n  // because it still parses correctly; we do warn for other cases like nested\n  // <p> tags where the beginning of the second element implicitly closes the\n  // first, causing a confusing mess.\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#special\n  var specialTags = ['address', 'applet', 'area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe', 'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu', 'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-scope\n  var inScopeTags = ['applet', 'caption', 'html', 'table', 'td', 'th', 'marquee', 'object', 'template',\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#html-integration-point\n  // TODO: Distinguish by namespace here -- for <title>, including it here\n  // errs on the side of fewer warnings\n  'foreignObject', 'desc', 'title'];\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#has-an-element-in-button-scope\n  var buttonScopeTags = inScopeTags.concat(['button']);\n\n  // https://html.spec.whatwg.org/multipage/syntax.html#generate-implied-end-tags\n  var impliedEndTags = ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'];\n\n  var emptyAncestorInfo = {\n    current: null,\n\n    formTag: null,\n    aTagInScope: null,\n    buttonTagInScope: null,\n    nobrTagInScope: null,\n    pTagInButtonScope: null,\n\n    listItemTagAutoclosing: null,\n    dlItemTagAutoclosing: null\n  };\n\n  var updatedAncestorInfo = function (oldInfo, tag, instance) {\n    var ancestorInfo = _assign({}, oldInfo || emptyAncestorInfo);\n    var info = { tag: tag, instance: instance };\n\n    if (inScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.aTagInScope = null;\n      ancestorInfo.buttonTagInScope = null;\n      ancestorInfo.nobrTagInScope = null;\n    }\n    if (buttonScopeTags.indexOf(tag) !== -1) {\n      ancestorInfo.pTagInButtonScope = null;\n    }\n\n    // See rules for 'li', 'dd', 'dt' start tags in\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    if (specialTags.indexOf(tag) !== -1 && tag !== 'address' && tag !== 'div' && tag !== 'p') {\n      ancestorInfo.listItemTagAutoclosing = null;\n      ancestorInfo.dlItemTagAutoclosing = null;\n    }\n\n    ancestorInfo.current = info;\n\n    if (tag === 'form') {\n      ancestorInfo.formTag = info;\n    }\n    if (tag === 'a') {\n      ancestorInfo.aTagInScope = info;\n    }\n    if (tag === 'button') {\n      ancestorInfo.buttonTagInScope = info;\n    }\n    if (tag === 'nobr') {\n      ancestorInfo.nobrTagInScope = info;\n    }\n    if (tag === 'p') {\n      ancestorInfo.pTagInButtonScope = info;\n    }\n    if (tag === 'li') {\n      ancestorInfo.listItemTagAutoclosing = info;\n    }\n    if (tag === 'dd' || tag === 'dt') {\n      ancestorInfo.dlItemTagAutoclosing = info;\n    }\n\n    return ancestorInfo;\n  };\n\n  /**\n   * Returns whether\n   */\n  var isTagValidWithParent = function (tag, parentTag) {\n    // First, let's check if we're in an unusual parsing mode...\n    switch (parentTag) {\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect\n      case 'select':\n        return tag === 'option' || tag === 'optgroup' || tag === '#text';\n      case 'optgroup':\n        return tag === 'option' || tag === '#text';\n      // Strictly speaking, seeing an <option> doesn't mean we're in a <select>\n      // but\n      case 'option':\n        return tag === '#text';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption\n      // No special behavior since these rules fall back to \"in body\" mode for\n      // all except special table nodes which cause bad parsing behavior anyway.\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr\n      case 'tr':\n        return tag === 'th' || tag === 'td' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody\n      case 'tbody':\n      case 'thead':\n      case 'tfoot':\n        return tag === 'tr' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup\n      case 'colgroup':\n        return tag === 'col' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable\n      case 'table':\n        return tag === 'caption' || tag === 'colgroup' || tag === 'tbody' || tag === 'tfoot' || tag === 'thead' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead\n      case 'head':\n        return tag === 'base' || tag === 'basefont' || tag === 'bgsound' || tag === 'link' || tag === 'meta' || tag === 'title' || tag === 'noscript' || tag === 'noframes' || tag === 'style' || tag === 'script' || tag === 'template';\n\n      // https://html.spec.whatwg.org/multipage/semantics.html#the-html-element\n      case 'html':\n        return tag === 'head' || tag === 'body';\n      case '#document':\n        return tag === 'html';\n    }\n\n    // Probably in the \"in body\" parsing mode, so we outlaw only tag combos\n    // where the parsing rules cause implicit opens or closes to be added.\n    // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody\n    switch (tag) {\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return parentTag !== 'h1' && parentTag !== 'h2' && parentTag !== 'h3' && parentTag !== 'h4' && parentTag !== 'h5' && parentTag !== 'h6';\n\n      case 'rp':\n      case 'rt':\n        return impliedEndTags.indexOf(parentTag) === -1;\n\n      case 'body':\n      case 'caption':\n      case 'col':\n      case 'colgroup':\n      case 'frame':\n      case 'head':\n      case 'html':\n      case 'tbody':\n      case 'td':\n      case 'tfoot':\n      case 'th':\n      case 'thead':\n      case 'tr':\n        // These tags are only valid with a few parents that have special child\n        // parsing rules -- if we're down here, then none of those matched and\n        // so we allow it only if we don't know what the parent is, as all other\n        // cases are invalid.\n        return parentTag == null;\n    }\n\n    return true;\n  };\n\n  /**\n   * Returns whether\n   */\n  var findInvalidAncestorForTag = function (tag, ancestorInfo) {\n    switch (tag) {\n      case 'address':\n      case 'article':\n      case 'aside':\n      case 'blockquote':\n      case 'center':\n      case 'details':\n      case 'dialog':\n      case 'dir':\n      case 'div':\n      case 'dl':\n      case 'fieldset':\n      case 'figcaption':\n      case 'figure':\n      case 'footer':\n      case 'header':\n      case 'hgroup':\n      case 'main':\n      case 'menu':\n      case 'nav':\n      case 'ol':\n      case 'p':\n      case 'section':\n      case 'summary':\n      case 'ul':\n\n      case 'pre':\n      case 'listing':\n\n      case 'table':\n\n      case 'hr':\n\n      case 'xmp':\n\n      case 'h1':\n      case 'h2':\n      case 'h3':\n      case 'h4':\n      case 'h5':\n      case 'h6':\n        return ancestorInfo.pTagInButtonScope;\n\n      case 'form':\n        return ancestorInfo.formTag || ancestorInfo.pTagInButtonScope;\n\n      case 'li':\n        return ancestorInfo.listItemTagAutoclosing;\n\n      case 'dd':\n      case 'dt':\n        return ancestorInfo.dlItemTagAutoclosing;\n\n      case 'button':\n        return ancestorInfo.buttonTagInScope;\n\n      case 'a':\n        // Spec says something about storing a list of markers, but it sounds\n        // equivalent to this check.\n        return ancestorInfo.aTagInScope;\n\n      case 'nobr':\n        return ancestorInfo.nobrTagInScope;\n    }\n\n    return null;\n  };\n\n  /**\n   * Given a ReactCompositeComponent instance, return a list of its recursive\n   * owners, starting at the root and ending with the instance itself.\n   */\n  var findOwnerStack = function (instance) {\n    if (!instance) {\n      return [];\n    }\n\n    var stack = [];\n    do {\n      stack.push(instance);\n    } while (instance = instance._currentElement._owner);\n    stack.reverse();\n    return stack;\n  };\n\n  var didWarn = {};\n\n  validateDOMNesting = function (childTag, childInstance, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n\n    var invalidParent = isTagValidWithParent(childTag, parentTag) ? null : parentInfo;\n    var invalidAncestor = invalidParent ? null : findInvalidAncestorForTag(childTag, ancestorInfo);\n    var problematic = invalidParent || invalidAncestor;\n\n    if (problematic) {\n      var ancestorTag = problematic.tag;\n      var ancestorInstance = problematic.instance;\n\n      var childOwner = childInstance && childInstance._currentElement._owner;\n      var ancestorOwner = ancestorInstance && ancestorInstance._currentElement._owner;\n\n      var childOwners = findOwnerStack(childOwner);\n      var ancestorOwners = findOwnerStack(ancestorOwner);\n\n      var minStackLen = Math.min(childOwners.length, ancestorOwners.length);\n      var i;\n\n      var deepestCommon = -1;\n      for (i = 0; i < minStackLen; i++) {\n        if (childOwners[i] === ancestorOwners[i]) {\n          deepestCommon = i;\n        } else {\n          break;\n        }\n      }\n\n      var UNKNOWN = '(unknown)';\n      var childOwnerNames = childOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ancestorOwnerNames = ancestorOwners.slice(deepestCommon + 1).map(function (inst) {\n        return inst.getName() || UNKNOWN;\n      });\n      var ownerInfo = [].concat(\n      // If the parent and child instances have a common owner ancestor, start\n      // with that -- otherwise we just start with the parent's owners.\n      deepestCommon !== -1 ? childOwners[deepestCommon].getName() || UNKNOWN : [], ancestorOwnerNames, ancestorTag,\n      // If we're warning about an invalid (non-parent) ancestry, add '...'\n      invalidAncestor ? ['...'] : [], childOwnerNames, childTag).join(' > ');\n\n      var warnKey = !!invalidParent + '|' + childTag + '|' + ancestorTag + '|' + ownerInfo;\n      if (didWarn[warnKey]) {\n        return;\n      }\n      didWarn[warnKey] = true;\n\n      var tagDisplayName = childTag;\n      if (childTag !== '#text') {\n        tagDisplayName = '<' + childTag + '>';\n      }\n\n      if (invalidParent) {\n        var info = '';\n        if (ancestorTag === 'table' && childTag === 'tr') {\n          info += ' Add a <tbody> to your code to match the DOM tree generated by ' + 'the browser.';\n        }\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a child of <%s>. ' + 'See %s.%s', tagDisplayName, ancestorTag, ownerInfo, info) : void 0;\n      } else {\n        \"development\" !== 'production' ? warning(false, 'validateDOMNesting(...): %s cannot appear as a descendant of ' + '<%s>. See %s.', tagDisplayName, ancestorTag, ownerInfo) : void 0;\n      }\n    }\n  };\n\n  validateDOMNesting.updatedAncestorInfo = updatedAncestorInfo;\n\n  // For testing\n  validateDOMNesting.isTagValidInContext = function (tag, ancestorInfo) {\n    ancestorInfo = ancestorInfo || emptyAncestorInfo;\n    var parentInfo = ancestorInfo.current;\n    var parentTag = parentInfo && parentInfo.tag;\n    return isTagValidWithParent(tag, parentTag) && !findInvalidAncestorForTag(tag, ancestorInfo);\n  };\n}\n\nmodule.exports = validateDOMNesting;\n},{\"153\":153,\"171\":171,\"172\":172}],146:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * @typechecks\n */\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Upstream version of event listener. Does not take into account specific\n * nature of platform.\n */\nvar EventListener = {\n  /**\n   * Listen to DOM events during the bubble phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  listen: function listen(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, false);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, false);\n        }\n      };\n    } else if (target.attachEvent) {\n      target.attachEvent('on' + eventType, callback);\n      return {\n        remove: function remove() {\n          target.detachEvent('on' + eventType, callback);\n        }\n      };\n    }\n  },\n\n  /**\n   * Listen to DOM events during the capture phase.\n   *\n   * @param {DOMEventTarget} target DOM element to register listener on.\n   * @param {string} eventType Event type, e.g. 'click' or 'mouseover'.\n   * @param {function} callback Callback function.\n   * @return {object} Object with a `remove` method.\n   */\n  capture: function capture(target, eventType, callback) {\n    if (target.addEventListener) {\n      target.addEventListener(eventType, callback, true);\n      return {\n        remove: function remove() {\n          target.removeEventListener(eventType, callback, true);\n        }\n      };\n    } else {\n      if (\"development\" !== 'production') {\n        console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.');\n      }\n      return {\n        remove: emptyFunction\n      };\n    }\n  },\n\n  registerDefault: function registerDefault() {}\n};\n\nmodule.exports = EventListener;\n},{\"153\":153}],147:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);\n\n/**\n * Simple, lightweight module assisting with the detection and context of\n * Worker. Helps avoid circular dependencies and allows code to reason about\n * whether or not they are in a Worker, even if they never include the main\n * `ReactWorker` dependency.\n */\nvar ExecutionEnvironment = {\n\n  canUseDOM: canUseDOM,\n\n  canUseWorkers: typeof Worker !== 'undefined',\n\n  canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent),\n\n  canUseViewport: canUseDOM && !!window.screen,\n\n  isInWorker: !canUseDOM // For now, this is true - might change in the future.\n\n};\n\nmodule.exports = ExecutionEnvironment;\n},{}],148:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _hyphenPattern = /-(.)/g;\n\n/**\n * Camelcases a hyphenated string, for example:\n *\n *   > camelize('background-color')\n *   < \"backgroundColor\"\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelize(string) {\n  return string.replace(_hyphenPattern, function (_, character) {\n    return character.toUpperCase();\n  });\n}\n\nmodule.exports = camelize;\n},{}],149:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar camelize = _dereq_(148);\n\nvar msPattern = /^-ms-/;\n\n/**\n * Camelcases a hyphenated CSS property name, for example:\n *\n *   > camelizeStyleName('background-color')\n *   < \"backgroundColor\"\n *   > camelizeStyleName('-moz-transition')\n *   < \"MozTransition\"\n *   > camelizeStyleName('-ms-transition')\n *   < \"msTransition\"\n *\n * As Andi Smith suggests\n * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix\n * is converted to lowercase `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction camelizeStyleName(string) {\n  return camelize(string.replace(msPattern, 'ms-'));\n}\n\nmodule.exports = camelizeStyleName;\n},{\"148\":148}],150:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nvar isTextNode = _dereq_(163);\n\n/*eslint-disable no-bitwise */\n\n/**\n * Checks if a given DOM node contains or is another DOM node.\n */\nfunction containsNode(outerNode, innerNode) {\n  if (!outerNode || !innerNode) {\n    return false;\n  } else if (outerNode === innerNode) {\n    return true;\n  } else if (isTextNode(outerNode)) {\n    return false;\n  } else if (isTextNode(innerNode)) {\n    return containsNode(outerNode, innerNode.parentNode);\n  } else if ('contains' in outerNode) {\n    return outerNode.contains(innerNode);\n  } else if (outerNode.compareDocumentPosition) {\n    return !!(outerNode.compareDocumentPosition(innerNode) & 16);\n  } else {\n    return false;\n  }\n}\n\nmodule.exports = containsNode;\n},{\"163\":163}],151:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar invariant = _dereq_(161);\n\n/**\n * Convert array-like objects to arrays.\n *\n * This API assumes the caller knows the contents of the data type. For less\n * well defined inputs use createArrayFromMixed.\n *\n * @param {object|function|filelist} obj\n * @return {array}\n */\nfunction toArray(obj) {\n  var length = obj.length;\n\n  // Some browsers builtin objects can report typeof 'function' (e.g. NodeList\n  // in old versions of Safari).\n  !(!Array.isArray(obj) && (typeof obj === 'object' || typeof obj === 'function')) ? \"development\" !== 'production' ? invariant(false, 'toArray: Array-like object expected') : invariant(false) : void 0;\n\n  !(typeof length === 'number') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object needs a length property') : invariant(false) : void 0;\n\n  !(length === 0 || length - 1 in obj) ? \"development\" !== 'production' ? invariant(false, 'toArray: Object should have keys for indices') : invariant(false) : void 0;\n\n  !(typeof obj.callee !== 'function') ? \"development\" !== 'production' ? invariant(false, 'toArray: Object can\\'t be `arguments`. Use rest params ' + '(function(...args) {}) or Array.from() instead.') : invariant(false) : void 0;\n\n  // Old IE doesn't give collections access to hasOwnProperty. Assume inputs\n  // without method will throw during the slice call and skip straight to the\n  // fallback.\n  if (obj.hasOwnProperty) {\n    try {\n      return Array.prototype.slice.call(obj);\n    } catch (e) {\n      // IE < 9 does not support Array#slice on collections objects\n    }\n  }\n\n  // Fall back to copying key by key. This assumes all keys have a value,\n  // so will not preserve sparsely populated inputs.\n  var ret = Array(length);\n  for (var ii = 0; ii < length; ii++) {\n    ret[ii] = obj[ii];\n  }\n  return ret;\n}\n\n/**\n * Perform a heuristic test to determine if an object is \"array-like\".\n *\n *   A monk asked Joshu, a Zen master, \"Has a dog Buddha nature?\"\n *   Joshu replied: \"Mu.\"\n *\n * This function determines if its argument has \"array nature\": it returns\n * true if the argument is an actual array, an `arguments' object, or an\n * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()).\n *\n * It will return false for other array-like objects like Filelist.\n *\n * @param {*} obj\n * @return {boolean}\n */\nfunction hasArrayNature(obj) {\n  return(\n    // not null/false\n    !!obj && (\n    // arrays are objects, NodeLists are functions in Safari\n    typeof obj == 'object' || typeof obj == 'function') &&\n    // quacks like an array\n    'length' in obj &&\n    // not window\n    !('setInterval' in obj) &&\n    // no DOM node should be considered an array-like\n    // a 'select' element has 'length' and 'item' properties on IE8\n    typeof obj.nodeType != 'number' && (\n    // a real array\n    Array.isArray(obj) ||\n    // arguments\n    'callee' in obj ||\n    // HTMLCollection/NodeList\n    'item' in obj)\n  );\n}\n\n/**\n * Ensure that the argument is an array by wrapping it in an array if it is not.\n * Creates a copy of the argument if it is already an array.\n *\n * This is mostly useful idiomatically:\n *\n *   var createArrayFromMixed = require('createArrayFromMixed');\n *\n *   function takesOneOrMoreThings(things) {\n *     things = createArrayFromMixed(things);\n *     ...\n *   }\n *\n * This allows you to treat `things' as an array, but accept scalars in the API.\n *\n * If you need to convert an array-like object, like `arguments`, into an array\n * use toArray instead.\n *\n * @param {*} obj\n * @return {array}\n */\nfunction createArrayFromMixed(obj) {\n  if (!hasArrayNature(obj)) {\n    return [obj];\n  } else if (Array.isArray(obj)) {\n    return obj.slice();\n  } else {\n    return toArray(obj);\n  }\n}\n\nmodule.exports = createArrayFromMixed;\n},{\"161\":161}],152:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/*eslint-disable fb-www/unsafe-html*/\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar createArrayFromMixed = _dereq_(151);\nvar getMarkupWrap = _dereq_(157);\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to render all markup.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Pattern used by `getNodeName`.\n */\nvar nodeNamePattern = /^\\s*<(\\w+)/;\n\n/**\n * Extracts the `nodeName` of the first element in a string of markup.\n *\n * @param {string} markup String of markup.\n * @return {?string} Node name of the supplied markup.\n */\nfunction getNodeName(markup) {\n  var nodeNameMatch = markup.match(nodeNamePattern);\n  return nodeNameMatch && nodeNameMatch[1].toLowerCase();\n}\n\n/**\n * Creates an array containing the nodes rendered from the supplied markup. The\n * optionally supplied `handleScript` function will be invoked once for each\n * <script> element that is rendered. If no `handleScript` function is supplied,\n * an exception is thrown if any <script> elements are rendered.\n *\n * @param {string} markup A string of valid HTML markup.\n * @param {?function} handleScript Invoked once for each rendered <script>.\n * @return {array<DOMElement|DOMTextNode>} An array of rendered nodes.\n */\nfunction createNodesFromMarkup(markup, handleScript) {\n  var node = dummyNode;\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup dummy not initialized') : invariant(false) : void 0;\n  var nodeName = getNodeName(markup);\n\n  var wrap = nodeName && getMarkupWrap(nodeName);\n  if (wrap) {\n    node.innerHTML = wrap[1] + markup + wrap[2];\n\n    var wrapDepth = wrap[0];\n    while (wrapDepth--) {\n      node = node.lastChild;\n    }\n  } else {\n    node.innerHTML = markup;\n  }\n\n  var scripts = node.getElementsByTagName('script');\n  if (scripts.length) {\n    !handleScript ? \"development\" !== 'production' ? invariant(false, 'createNodesFromMarkup(...): Unexpected <script> element rendered.') : invariant(false) : void 0;\n    createArrayFromMixed(scripts).forEach(handleScript);\n  }\n\n  var nodes = Array.from(node.childNodes);\n  while (node.lastChild) {\n    node.removeChild(node.lastChild);\n  }\n  return nodes;\n}\n\nmodule.exports = createNodesFromMarkup;\n},{\"147\":147,\"151\":151,\"157\":157,\"161\":161}],153:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n */\n\nfunction makeEmptyFunction(arg) {\n  return function () {\n    return arg;\n  };\n}\n\n/**\n * This function accepts and discards inputs; it has no side effects. This is\n * primarily useful idiomatically for overridable function endpoints which\n * always need to be callable, since JS lacks a null-call idiom ala Cocoa.\n */\nvar emptyFunction = function emptyFunction() {};\n\nemptyFunction.thatReturns = makeEmptyFunction;\nemptyFunction.thatReturnsFalse = makeEmptyFunction(false);\nemptyFunction.thatReturnsTrue = makeEmptyFunction(true);\nemptyFunction.thatReturnsNull = makeEmptyFunction(null);\nemptyFunction.thatReturnsThis = function () {\n  return this;\n};\nemptyFunction.thatReturnsArgument = function (arg) {\n  return arg;\n};\n\nmodule.exports = emptyFunction;\n},{}],154:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyObject = {};\n\nif (\"development\" !== 'production') {\n  Object.freeze(emptyObject);\n}\n\nmodule.exports = emptyObject;\n},{}],155:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * @param {DOMElement} node input/textarea to focus\n */\n\nfunction focusNode(node) {\n  // IE8 can throw \"Can't move focus to the control because it is invisible,\n  // not enabled, or of a type that does not accept the focus.\" for all kinds of\n  // reasons that are too expensive and fragile to test.\n  try {\n    node.focus();\n  } catch (e) {}\n}\n\nmodule.exports = focusNode;\n},{}],156:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/* eslint-disable fb-www/typeof-undefined */\n\n/**\n * Same as document.activeElement but wraps in a try-catch block. In IE it is\n * not safe to call document.activeElement if there is nothing focused.\n *\n * The activeElement will be null only if the document or document body is not\n * yet defined.\n */\nfunction getActiveElement() /*?DOMElement*/{\n  if (typeof document === 'undefined') {\n    return null;\n  }\n  try {\n    return document.activeElement || document.body;\n  } catch (e) {\n    return document.body;\n  }\n}\n\nmodule.exports = getActiveElement;\n},{}],157:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/*eslint-disable fb-www/unsafe-html */\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar invariant = _dereq_(161);\n\n/**\n * Dummy container used to detect which wraps are necessary.\n */\nvar dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null;\n\n/**\n * Some browsers cannot use `innerHTML` to render certain elements standalone,\n * so we wrap them, render the wrapped nodes, then extract the desired node.\n *\n * In IE8, certain elements cannot render alone, so wrap all elements ('*').\n */\n\nvar shouldWrap = {};\n\nvar selectWrap = [1, '<select multiple=\"true\">', '</select>'];\nvar tableWrap = [1, '<table>', '</table>'];\nvar trWrap = [3, '<table><tbody><tr>', '</tr></tbody></table>'];\n\nvar svgWrap = [1, '<svg xmlns=\"http://www.w3.org/2000/svg\">', '</svg>'];\n\nvar markupWrap = {\n  '*': [1, '?<div>', '</div>'],\n\n  'area': [1, '<map>', '</map>'],\n  'col': [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],\n  'legend': [1, '<fieldset>', '</fieldset>'],\n  'param': [1, '<object>', '</object>'],\n  'tr': [2, '<table><tbody>', '</tbody></table>'],\n\n  'optgroup': selectWrap,\n  'option': selectWrap,\n\n  'caption': tableWrap,\n  'colgroup': tableWrap,\n  'tbody': tableWrap,\n  'tfoot': tableWrap,\n  'thead': tableWrap,\n\n  'td': trWrap,\n  'th': trWrap\n};\n\n// Initialize the SVG elements since we know they'll always need to be wrapped\n// consistently. If they are created inside a <div> they will be initialized in\n// the wrong namespace (and will not display).\nvar svgElements = ['circle', 'clipPath', 'defs', 'ellipse', 'g', 'image', 'line', 'linearGradient', 'mask', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'text', 'tspan'];\nsvgElements.forEach(function (nodeName) {\n  markupWrap[nodeName] = svgWrap;\n  shouldWrap[nodeName] = true;\n});\n\n/**\n * Gets the markup wrap configuration for the supplied `nodeName`.\n *\n * NOTE: This lazily detects which wraps are necessary for the current browser.\n *\n * @param {string} nodeName Lowercase `nodeName`.\n * @return {?array} Markup wrap configuration, if applicable.\n */\nfunction getMarkupWrap(nodeName) {\n  !!!dummyNode ? \"development\" !== 'production' ? invariant(false, 'Markup wrapping node not initialized') : invariant(false) : void 0;\n  if (!markupWrap.hasOwnProperty(nodeName)) {\n    nodeName = '*';\n  }\n  if (!shouldWrap.hasOwnProperty(nodeName)) {\n    if (nodeName === '*') {\n      dummyNode.innerHTML = '<link />';\n    } else {\n      dummyNode.innerHTML = '<' + nodeName + '></' + nodeName + '>';\n    }\n    shouldWrap[nodeName] = !dummyNode.firstChild;\n  }\n  return shouldWrap[nodeName] ? markupWrap[nodeName] : null;\n}\n\nmodule.exports = getMarkupWrap;\n},{\"147\":147,\"161\":161}],158:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\n/**\n * Gets the scroll position of the supplied element or window.\n *\n * The return values are unbounded, unlike `getScrollPosition`. This means they\n * may be negative or exceed the element boundaries (which is possible using\n * inertial scrolling).\n *\n * @param {DOMWindow|DOMElement} scrollable\n * @return {object} Map with `x` and `y` keys.\n */\n\nfunction getUnboundedScrollPosition(scrollable) {\n  if (scrollable === window) {\n    return {\n      x: window.pageXOffset || document.documentElement.scrollLeft,\n      y: window.pageYOffset || document.documentElement.scrollTop\n    };\n  }\n  return {\n    x: scrollable.scrollLeft,\n    y: scrollable.scrollTop\n  };\n}\n\nmodule.exports = getUnboundedScrollPosition;\n},{}],159:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar _uppercasePattern = /([A-Z])/g;\n\n/**\n * Hyphenates a camelcased string, for example:\n *\n *   > hyphenate('backgroundColor')\n *   < \"background-color\"\n *\n * For CSS style names, use `hyphenateStyleName` instead which works properly\n * with all vendor prefixes, including `ms`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenate(string) {\n  return string.replace(_uppercasePattern, '-$1').toLowerCase();\n}\n\nmodule.exports = hyphenate;\n},{}],160:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar hyphenate = _dereq_(159);\n\nvar msPattern = /^ms-/;\n\n/**\n * Hyphenates a camelcased CSS property name, for example:\n *\n *   > hyphenateStyleName('backgroundColor')\n *   < \"background-color\"\n *   > hyphenateStyleName('MozTransition')\n *   < \"-moz-transition\"\n *   > hyphenateStyleName('msTransition')\n *   < \"-ms-transition\"\n *\n * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix\n * is converted to `-ms-`.\n *\n * @param {string} string\n * @return {string}\n */\nfunction hyphenateStyleName(string) {\n  return hyphenate(string).replace(msPattern, '-ms-');\n}\n\nmodule.exports = hyphenateStyleName;\n},{\"159\":159}],161:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\n/**\n * Use invariant() to assert state which your program assumes to be true.\n *\n * Provide sprintf-style format (only %s is supported) and arguments\n * to provide information about what broke and what you were\n * expecting.\n *\n * The invariant message will be stripped in production, but the invariant\n * will remain to ensure logic does not differ in production.\n */\n\nfunction invariant(condition, format, a, b, c, d, e, f) {\n  if (\"development\" !== 'production') {\n    if (format === undefined) {\n      throw new Error('invariant requires an error message argument');\n    }\n  }\n\n  if (!condition) {\n    var error;\n    if (format === undefined) {\n      error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');\n    } else {\n      var args = [a, b, c, d, e, f];\n      var argIndex = 0;\n      error = new Error(format.replace(/%s/g, function () {\n        return args[argIndex++];\n      }));\n      error.name = 'Invariant Violation';\n    }\n\n    error.framesToPop = 1; // we don't care about invariant's own frame\n    throw error;\n  }\n}\n\nmodule.exports = invariant;\n},{}],162:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM node.\n */\nfunction isNode(object) {\n  return !!(object && (typeof Node === 'function' ? object instanceof Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string'));\n}\n\nmodule.exports = isNode;\n},{}],163:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar isNode = _dereq_(162);\n\n/**\n * @param {*} object The object to check.\n * @return {boolean} Whether or not the object is a DOM text node.\n */\nfunction isTextNode(object) {\n  return isNode(object) && object.nodeType == 3;\n}\n\nmodule.exports = isTextNode;\n},{\"162\":162}],164:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks static-only\n */\n\n'use strict';\n\nvar invariant = _dereq_(161);\n\n/**\n * Constructs an enumeration with keys equal to their value.\n *\n * For example:\n *\n *   var COLORS = keyMirror({blue: null, red: null});\n *   var myColor = COLORS.blue;\n *   var isColorValid = !!COLORS[myColor];\n *\n * The last line could not be performed if the values of the generated enum were\n * not equal to their keys.\n *\n *   Input:  {key1: val1, key2: val2}\n *   Output: {key1: key1, key2: key2}\n *\n * @param {object} obj\n * @return {object}\n */\nvar keyMirror = function keyMirror(obj) {\n  var ret = {};\n  var key;\n  !(obj instanceof Object && !Array.isArray(obj)) ? \"development\" !== 'production' ? invariant(false, 'keyMirror(...): Argument must be an object.') : invariant(false) : void 0;\n  for (key in obj) {\n    if (!obj.hasOwnProperty(key)) {\n      continue;\n    }\n    ret[key] = key;\n  }\n  return ret;\n};\n\nmodule.exports = keyMirror;\n},{\"161\":161}],165:[function(_dereq_,module,exports){\n\"use strict\";\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n/**\n * Allows extraction of a minified key. Let's the build system minify keys\n * without losing the ability to dynamically use key strings as values\n * themselves. Pass in an object with a single key/val pair and it will return\n * you the string key of that single record. Suppose you want to grab the\n * value for a key 'className' inside of an object. Key/val minification may\n * have aliased that key to be 'xa12'. keyOf({className: null}) will return\n * 'xa12' in that case. Resolve keys you want to use once at startup time, then\n * reuse those resolutions.\n */\nvar keyOf = function keyOf(oneKeyObj) {\n  var key;\n  for (key in oneKeyObj) {\n    if (!oneKeyObj.hasOwnProperty(key)) {\n      continue;\n    }\n    return key;\n  }\n  return null;\n};\n\nmodule.exports = keyOf;\n},{}],166:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * Executes the provided `callback` once for each enumerable own property in the\n * object and constructs a new object from the results. The `callback` is\n * invoked with three arguments:\n *\n *  - the property value\n *  - the property name\n *  - the object being traversed\n *\n * Properties that are added after the call to `mapObject` will not be visited\n * by `callback`. If the values of existing properties are changed, the value\n * passed to `callback` will be the value at the time `mapObject` visits them.\n * Properties that are deleted before being visited are not visited.\n *\n * @grep function objectMap()\n * @grep function objMap()\n *\n * @param {?object} object\n * @param {function} callback\n * @param {*} context\n * @return {?object}\n */\nfunction mapObject(object, callback, context) {\n  if (!object) {\n    return null;\n  }\n  var result = {};\n  for (var name in object) {\n    if (hasOwnProperty.call(object, name)) {\n      result[name] = callback.call(context, object[name], name, object);\n    }\n  }\n  return result;\n}\n\nmodule.exports = mapObject;\n},{}],167:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * \n * @typechecks static-only\n */\n\n'use strict';\n\n/**\n * Memoizes the return value of a function that accepts one string argument.\n */\n\nfunction memoizeStringOnly(callback) {\n  var cache = {};\n  return function (string) {\n    if (!cache.hasOwnProperty(string)) {\n      cache[string] = callback.call(this, string);\n    }\n    return cache[string];\n  };\n}\n\nmodule.exports = memoizeStringOnly;\n},{}],168:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\n'use strict';\n\nvar ExecutionEnvironment = _dereq_(147);\n\nvar performance;\n\nif (ExecutionEnvironment.canUseDOM) {\n  performance = window.performance || window.msPerformance || window.webkitPerformance;\n}\n\nmodule.exports = performance || {};\n},{\"147\":147}],169:[function(_dereq_,module,exports){\n'use strict';\n\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n */\n\nvar performance = _dereq_(168);\n\nvar performanceNow;\n\n/**\n * Detect if we can use `window.performance.now()` and gracefully fallback to\n * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now\n * because of Facebook's testing infrastructure.\n */\nif (performance.now) {\n  performanceNow = function performanceNow() {\n    return performance.now();\n  };\n} else {\n  performanceNow = function performanceNow() {\n    return Date.now();\n  };\n}\n\nmodule.exports = performanceNow;\n},{\"168\":168}],170:[function(_dereq_,module,exports){\n/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @typechecks\n * \n */\n\n/*eslint-disable no-self-compare */\n\n'use strict';\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\nfunction is(x, y) {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    return x !== 0 || 1 / x === 1 / y;\n  } else {\n    // Step 6.a: NaN == NaN\n    return x !== x && y !== y;\n  }\n}\n\n/**\n * Performs equality by iterating through keys on an object and returning false\n * when any key has values which are not strictly equal between the arguments.\n * Returns true when the values of all keys are strictly equal.\n */\nfunction shallowEqual(objA, objB) {\n  if (is(objA, objB)) {\n    return true;\n  }\n\n  if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n    return false;\n  }\n\n  var keysA = Object.keys(objA);\n  var keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (var i = 0; i < keysA.length; i++) {\n    if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nmodule.exports = shallowEqual;\n},{}],171:[function(_dereq_,module,exports){\n/**\n * Copyright 2014-2015, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n\n'use strict';\n\nvar emptyFunction = _dereq_(153);\n\n/**\n * Similar to invariant but only logs a warning if the condition is not met.\n * This can be used to log issues in development environments in critical\n * paths. Removing the logging code for production environments will keep the\n * same logic and follow the same code paths.\n */\n\nvar warning = emptyFunction;\n\nif (\"development\" !== 'production') {\n  warning = function warning(condition, format) {\n    for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n      args[_key - 2] = arguments[_key];\n    }\n\n    if (format === undefined) {\n      throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');\n    }\n\n    if (format.indexOf('Failed Composite propType: ') === 0) {\n      return; // Ignore CompositeComponent proptype check.\n    }\n\n    if (!condition) {\n      var argIndex = 0;\n      var message = 'Warning: ' + format.replace(/%s/g, function () {\n        return args[argIndex++];\n      });\n      if (typeof console !== 'undefined') {\n        console.error(message);\n      }\n      try {\n        // --- Welcome to debugging React ---\n        // This error was thrown as a convenience so that you can use this stack\n        // to find the callsite that caused this warning to fire.\n        throw new Error(message);\n      } catch (x) {}\n    }\n  };\n}\n\nmodule.exports = warning;\n},{\"153\":153}],172:[function(_dereq_,module,exports){\n'use strict';\n/* eslint-disable no-unused-vars */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar propIsEnumerable = Object.prototype.propertyIsEnumerable;\n\nfunction toObject(val) {\n\tif (val === null || val === undefined) {\n\t\tthrow new TypeError('Object.assign cannot be called with null or undefined');\n\t}\n\n\treturn Object(val);\n}\n\nfunction shouldUseNative() {\n\ttry {\n\t\tif (!Object.assign) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Detect buggy property enumeration order in older V8 versions.\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=4118\n\t\tvar test1 = new String('abc');  // eslint-disable-line\n\t\ttest1[5] = 'de';\n\t\tif (Object.getOwnPropertyNames(test1)[0] === '5') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test2 = {};\n\t\tfor (var i = 0; i < 10; i++) {\n\t\t\ttest2['_' + String.fromCharCode(i)] = i;\n\t\t}\n\t\tvar order2 = Object.getOwnPropertyNames(test2).map(function (n) {\n\t\t\treturn test2[n];\n\t\t});\n\t\tif (order2.join('') !== '0123456789') {\n\t\t\treturn false;\n\t\t}\n\n\t\t// https://bugs.chromium.org/p/v8/issues/detail?id=3056\n\t\tvar test3 = {};\n\t\t'abcdefghijklmnopqrst'.split('').forEach(function (letter) {\n\t\t\ttest3[letter] = letter;\n\t\t});\n\t\tif (Object.keys(Object.assign({}, test3)).join('') !==\n\t\t\t\t'abcdefghijklmnopqrst') {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t} catch (e) {\n\t\t// We don't expect any of the above to throw, but better to be safe.\n\t\treturn false;\n\t}\n}\n\nmodule.exports = shouldUseNative() ? Object.assign : function (target, source) {\n\tvar from;\n\tvar to = toObject(target);\n\tvar symbols;\n\n\tfor (var s = 1; s < arguments.length; s++) {\n\t\tfrom = Object(arguments[s]);\n\n\t\tfor (var key in from) {\n\t\t\tif (hasOwnProperty.call(from, key)) {\n\t\t\t\tto[key] = from[key];\n\t\t\t}\n\t\t}\n\n\t\tif (Object.getOwnPropertySymbols) {\n\t\t\tsymbols = Object.getOwnPropertySymbols(from);\n\t\t\tfor (var i = 0; i < symbols.length; i++) {\n\t\t\t\tif (propIsEnumerable.call(from, symbols[i])) {\n\t\t\t\t\tto[symbols[i]] = from[symbols[i]];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn to;\n};\n\n},{}]},{},[93])(93)\n});"
  },
  {
    "path": "30-jstraining/demos/recharts-demo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"react-with-addons.min.js\"></script>\n    <script src=\"react-dom.js\"></script>\n    <script src=\"react-dom-server.min.js\"></script>\n    <script src=\"Recharts.min.js\"></script>\n    <script src=\"babel.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"example\" style=\"width: 1000px;height: 800px;\"></div>\n    <script type=\"text/babel\">\nconst {LineChart, Line, XAxis, YAxis, CartesianGrid} = Recharts;\nconst data = [\n      {name: 'Page A', uv: 4000, pv: 2400, amt: 2400},\n      {name: 'Page B', uv: 3000, pv: 1398, amt: 2210},\n      {name: 'Page C', uv: 2000, pv: 9800, amt: 2290},\n      {name: 'Page D', uv: 2780, pv: 3908, amt: 2000},\n      {name: 'Page E', uv: 1890, pv: 4800, amt: 2181},\n      {name: 'Page F', uv: 2390, pv: 3800, amt: 2500},\n      {name: 'Page G', uv: 3490, pv: 4300, amt: 2100},\n];\n\nconst TinyLineChart = React.createClass({\n\trender () {\n  \treturn (\n  <LineChart width={1000} height={400} data={data}>\n    <XAxis dataKey=\"name\"/>\n    <YAxis/>\n    <CartesianGrid stroke=\"#eee\" strokeDasharray=\"5 5\"/>\n    <Line type=\"monotone\" dataKey=\"uv\" stroke=\"#8884d8\" />\n    <Line type=\"monotone\" dataKey=\"pv\" stroke=\"#82ca9d\" />\n  </LineChart>\n    );\n  }\n})\n\nReactDOM.render(\n  <TinyLineChart />,\n  document.getElementById('example')\n);\n\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/recharts-demo/react-dom.js",
    "content": "/**\n * ReactDOM v15.2.1\n *\n * Copyright 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n */\n// Based off https://github.com/ForbesLindesay/umd/blob/master/template.js\n;(function(f) {\n  // CommonJS\n  if (typeof exports === \"object\" && typeof module !== \"undefined\") {\n    module.exports = f(require('react'));\n\n  // RequireJS\n  } else if (typeof define === \"function\" && define.amd) {\n    define(['react'], f);\n\n  // <script>\n  } else {\n    var g;\n    if (typeof window !== \"undefined\") {\n      g = window;\n    } else if (typeof global !== \"undefined\") {\n      g = global;\n    } else if (typeof self !== \"undefined\") {\n      g = self;\n    } else {\n      // works providing we're not in \"use strict\";\n      // needed for Java 8 Nashorn\n      // see https://github.com/facebook/react/issues/3037\n      g = this;\n    }\n    g.ReactDOM = f(g.React);\n  }\n\n})(function(React) {\n  return React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n});\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/.babelrc",
    "content": "{\n  \"presets\": [ \"es2015\", \"stage-0\", \"react\"],\n\n  /* if you want to use babel runtime, uncomment the following line */\n  // \"plugins\": [\"transform-runtime\"],\n\n  \"plugins\": [\"transform-decorators-legacy\"],\n\n  \"env\": {\n    \"build\": {\n      \"optional\": [\"optimisation\", \"minification\"]\n    }\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/.eslintignore",
    "content": "node_modules/**\n**/*.css\n**/*.html\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/.eslintrc",
    "content": "{\n  \"env\": {\n    \"node\": true\n  },\n  ecmaFeatures: {\n    jsx: true\n  },\n  \"globals\": {\n  },\n  \"plugins\": [\n  ],\n  \"extends\": \"eslint-config-airbnb\",\n  \"rules\": {\n    \"comma-dangle\": 0,\n    \"no-console\": 0,\n    \"id-length\": 0,\n    \"react/prop-types\": 0\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/.gitignore",
    "content": "node_modules\nbuild/\nnpm-debug.log\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/.jshintignore",
    "content": "node_modules\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/.jshintrc",
    "content": "{\n  \"node\": true,\n\n  \"curly\": true,\n  \"latedef\": true,\n  \"quotmark\": true,\n  \"undef\": true,\n  \"unused\": true,\n  \"trailing\": true\n}\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/app/App.js",
    "content": "import { connect } from 'react-redux';\nimport MyComponent from './myComponent';\n\n// Map Redux state to component props\nfunction mapStateToProps(state) {\n  return {\n    text: state.text,\n    name: state.name\n  };\n}\n\n// Map Redux actions to component props\nfunction mapDispatchToProps(dispatch) {\n  return {\n    onChange: (e) => dispatch({\n      type: 'change',\n      payload: e.target.value\n    })\n  }\n}\n\n// Connected Component\nconst App = connect(\n  mapStateToProps,\n  mapDispatchToProps\n)(MyComponent);\n\nexport default App;\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/app/index.html",
    "content": "<html>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"main.css\">\n  <title>React-Babel-Webpack Boileplate</title>\n  <body>\n    <script type=\"text/javascript\" src=\"bundle.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/app/main.css",
    "content": ""
  },
  {
    "path": "30-jstraining/demos/redux-demo/app/main.jsx",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { createStore } from 'redux'\nimport { Provider } from 'react-redux'\n\nimport App from './App';\nimport reducer from './reducer';\n\n// Store\nconst store = createStore(reducer);\n\nReactDOM.render(\n  <Provider store={store}>\n    <App />\n  </Provider>,\n  document.body.appendChild(document.createElement('div'))\n);\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/app/myComponent.js",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nclass MyComponent extends React.Component {\n  render() {\n    return (\n      <div className=\"index\">\n        <p>{this.props.text}</p>\n        <input defaultValue={this.props.name} onChange={this.props.onChange} />\n      </div>\n    );\n  }\n}\n\nexport default MyComponent;\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/app/reducer.js",
    "content": "function reducer(state = {\n  text: '你好，访问者',\n  name: '访问者'\n}, action) {\n  switch (action.type) {\n    case 'change':\n      return {\n        name: action.payload,\n        text: '你好，' + action.payload\n      };\n    default:\n      return state;\n  }\n}\n\nexport default reducer;\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/package.json",
    "content": "{\n  \"name\": \"redux-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app/main.jsx\",\n  \"scripts\": {\n    \"lint\": \"eslint 'app/**/*.@(js|jsx)'\",\n    \"lint:msg\": \"validate-commit-msg\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"build\": \"webpack\",\n    \"start\": \"webpack-dev-server --devtool eval --progress --hot --content-base app\",\n    \"deploy\": \"NODE_ENV=production webpack -p --config webpack.production.config.js\",\n    \"deploy-windows\": \"SET NODE_ENV=production & webpack -p --config webpack.production.config.js\",\n    \"validate\": \"npm ls\",\n    \"commit\": \"git cz\",\n    \"changelog\": \"conventional-changelog -p angular -i CHANGELOG.md -s -r 1\"\n  },\n  \"dependencies\": {\n    \"babel-plugin-transform-decorators-legacy\": \"^1.3.4\",\n    \"babel-runtime\": \"6.x\",\n    \"react\": \"15.x\",\n    \"react-dom\": \"15.x\",\n    \"react-redux\": \"^4.4.5\",\n    \"redux\": \"^3.6.0\"\n  },\n  \"devDependencies\": {\n    \"babel-core\": \"6.x\",\n    \"babel-eslint\": \"6.x\",\n    \"babel-loader\": \"6.x\",\n    \"babel-plugin-transform-runtime\": \"6.x\",\n    \"babel-preset-es2015\": \"6.x\",\n    \"babel-preset-react\": \"6.x\",\n    \"babel-preset-stage-0\": \"6.x\",\n    \"commitizen\": \"^2.5.0\",\n    \"conventional-changelog-cli\": \"1.x\",\n    \"copy-webpack-plugin\": \"latest\",\n    \"css-loader\": \"~0.23.0\",\n    \"cz-conventional-changelog\": \"^1.1.5\",\n    \"eslint\": \"latest\",\n    \"eslint-config-airbnb\": \"latest\",\n    \"eslint-plugin-import\": \"^1.9.2\",\n    \"eslint-plugin-jsx-a11y\": \"latest\",\n    \"eslint-plugin-react\": \"latest\",\n    \"ghooks\": \"^1.0.3\",\n    \"open-browser-webpack-plugin\": \"0.0.2\",\n    \"style-loader\": \"~0.13.0\",\n    \"validate-commit-msg\": \"2.x\",\n    \"webpack\": \"latest\",\n    \"webpack-dev-server\": \"latest\"\n  },\n  \"keywords\": [\n    \"es6\",\n    \"web app\",\n    \"boilerplate\"\n  ],\n  \"author\": \"Ruan Yifeng\",\n  \"license\": \"MIT\",\n  \"config\": {\n    \"ghooks\": {\n      \"pre-commit\": \"npm run lint\",\n      \"commit-msg\": \"npm run lint:msg\"\n    },\n    \"validate-commit-msg\": {\n      \"types\": [\n        \"feat\",\n        \"fix\",\n        \"docs\",\n        \"style\",\n        \"refactor\",\n        \"perf\",\n        \"test\",\n        \"chore\",\n        \"revert\"\n      ],\n      \"warnOnFail\": false,\n      \"maxSubjectLength\": 100\n    },\n    \"commitizen\": {\n      \"path\": \"node_modules/cz-conventional-changelog\"\n    }\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/webpack.config.js",
    "content": "var webpack = require('webpack');\nvar path = require('path');\nvar OpenBrowserPlugin = require('open-browser-webpack-plugin');\n\nmodule.exports = {\n  devServer: {\n    historyApiFallback: true,\n    hot: true,\n    inline: true,\n    progress: true,\n    contentBase: './app',\n    port: 8080\n  },\n  entry: [\n    'webpack/hot/dev-server',\n    'webpack-dev-server/client?http://localhost:8080',\n    path.resolve(__dirname, 'app/main.jsx')\n  ],\n  output: {\n    path: __dirname + '/build',\n    publicPath: '/',\n    filename: './bundle.js'\n  },\n  module: {\n    loaders:[\n      { test: /\\.css$/, include: path.resolve(__dirname, 'app'), loader: 'style-loader!css-loader' },\n      { test: /\\.js[x]?$/, include: path.resolve(__dirname, 'app'), exclude: /node_modules/, loader: 'babel-loader' },\n    ]\n  },\n  resolve: {\n    extensions: ['', '.js', '.jsx'],\n  },\n  plugins: [\n    new webpack.HotModuleReplacementPlugin(),\n    new OpenBrowserPlugin({ url: 'http://localhost:8080' })\n  ]\n};\n"
  },
  {
    "path": "30-jstraining/demos/redux-demo/webpack.production.config.js",
    "content": "var webpack = require('webpack');\nvar path = require('path');\nvar uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;\nvar CopyWebpackPlugin = require('copy-webpack-plugin');\n\nmodule.exports = {\n  devtool: 'cheap-source-map',\n  entry: [\n    path.resolve(__dirname, 'app/main.jsx'),\n  ],\n  output: {\n    path: __dirname + '/build',\n    publicPath: '/',\n    filename: './bundle.js'\n  },\n  module: {\n    loaders:[\n      { test: /\\.css$/, include: path.resolve(__dirname, 'app'), loader: 'style-loader!css-loader' },\n      { test: /\\.js[x]?$/, include: path.resolve(__dirname, 'app'), exclude: /node_modules/, loader: 'babel-loader' },\n    ]\n  },\n  resolve: {\n    extensions: ['', '.js', '.jsx'],\n  },\n  plugins: [\n    new webpack.optimize.DedupePlugin(),\n    new uglifyJsPlugin({\n      compress: {\n        warnings: false\n      }\n    }),\n    new CopyWebpackPlugin([\n      { from: './app/index.html', to: 'index.html' },\n      { from: './app/main.css', to: 'main.css' }\n    ]),\n  ]\n};\n"
  },
  {
    "path": "30-jstraining/demos/rest-api-demo/db.json",
    "content": "{\n  \"posts\": [\n    { \"id\": 1, \"title\": \"json-server\", \"author\": \"typicode\" }\n  ],\n  \"comments\": [\n    { \"id\": 1, \"body\": \"some comment\", \"postId\": 1 }\n  ],\n  \"profile\": { \"name\": \"typicode\" }\n}\n"
  },
  {
    "path": "30-jstraining/demos/rest-api-demo/package.json",
    "content": "{\n  \"name\": \"rest-api-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"server\": \"json-server db.json\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "30-jstraining/demos/simple-app-demo/app.js",
    "content": "const $ = require('jquery');\n$('h1').css({ color: 'red'});\n"
  },
  {
    "path": "30-jstraining/demos/simple-app-demo/bundle.js",
    "content": "/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tconst $ = __webpack_require__(1);\n\t$('h1').css({ color: 'red'});\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!\n\t * jQuery JavaScript Library v3.1.1\n\t * https://jquery.com/\n\t *\n\t * Includes Sizzle.js\n\t * https://sizzlejs.com/\n\t *\n\t * Copyright jQuery Foundation and other contributors\n\t * Released under the MIT license\n\t * https://jquery.org/license\n\t *\n\t * Date: 2016-09-22T22:30Z\n\t */\n\t( function( global, factory ) {\n\n\t\t\"use strict\";\n\n\t\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\n\t\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t\t// is present, execute the factory and get jQuery.\n\t\t\t// For environments that do not have a `window` with a `document`\n\t\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t\t// This accentuates the need for the creation of a real `window`.\n\t\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t\t// See ticket #14549 for more info.\n\t\t\tmodule.exports = global.document ?\n\t\t\t\tfactory( global, true ) :\n\t\t\t\tfunction( w ) {\n\t\t\t\t\tif ( !w.document ) {\n\t\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t\t}\n\t\t\t\t\treturn factory( w );\n\t\t\t\t};\n\t\t} else {\n\t\t\tfactory( global );\n\t\t}\n\n\t// Pass this if window is not defined yet\n\t} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n\t// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n\t// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n\t// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n\t// enough that all such attempts are guarded in a try block.\n\t\"use strict\";\n\n\tvar arr = [];\n\n\tvar document = window.document;\n\n\tvar getProto = Object.getPrototypeOf;\n\n\tvar slice = arr.slice;\n\n\tvar concat = arr.concat;\n\n\tvar push = arr.push;\n\n\tvar indexOf = arr.indexOf;\n\n\tvar class2type = {};\n\n\tvar toString = class2type.toString;\n\n\tvar hasOwn = class2type.hasOwnProperty;\n\n\tvar fnToString = hasOwn.toString;\n\n\tvar ObjectFunctionString = fnToString.call( Object );\n\n\tvar support = {};\n\n\n\n\t\tfunction DOMEval( code, doc ) {\n\t\t\tdoc = doc || document;\n\n\t\t\tvar script = doc.createElement( \"script\" );\n\n\t\t\tscript.text = code;\n\t\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t\t}\n\t/* global Symbol */\n\t// Defining this global in .eslintrc.json would create a danger of using the global\n\t// unguarded in another place, it seems safer to define global only for this module\n\n\n\n\tvar\n\t\tversion = \"3.1.1\",\n\n\t\t// Define a local copy of jQuery\n\t\tjQuery = function( selector, context ) {\n\n\t\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\t\treturn new jQuery.fn.init( selector, context );\n\t\t},\n\n\t\t// Support: Android <=4.0 only\n\t\t// Make sure we trim BOM and NBSP\n\t\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t\t// Matches dashed string for camelizing\n\t\trmsPrefix = /^-ms-/,\n\t\trdashAlpha = /-([a-z])/g,\n\n\t\t// Used by jQuery.camelCase as callback to replace()\n\t\tfcamelCase = function( all, letter ) {\n\t\t\treturn letter.toUpperCase();\n\t\t};\n\n\tjQuery.fn = jQuery.prototype = {\n\n\t\t// The current version of jQuery being used\n\t\tjquery: version,\n\n\t\tconstructor: jQuery,\n\n\t\t// The default length of a jQuery object is 0\n\t\tlength: 0,\n\n\t\ttoArray: function() {\n\t\t\treturn slice.call( this );\n\t\t},\n\n\t\t// Get the Nth element in the matched element set OR\n\t\t// Get the whole matched element set as a clean array\n\t\tget: function( num ) {\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tif ( num == null ) {\n\t\t\t\treturn slice.call( this );\n\t\t\t}\n\n\t\t\t// Return just the one element from the set\n\t\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t\t},\n\n\t\t// Take an array of elements and push it onto the stack\n\t\t// (returning the new matched element set)\n\t\tpushStack: function( elems ) {\n\n\t\t\t// Build a new jQuery matched element set\n\t\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t\t// Add the old object onto the stack (as a reference)\n\t\t\tret.prevObject = this;\n\n\t\t\t// Return the newly-formed element set\n\t\t\treturn ret;\n\t\t},\n\n\t\t// Execute a callback for every element in the matched set.\n\t\teach: function( callback ) {\n\t\t\treturn jQuery.each( this, callback );\n\t\t},\n\n\t\tmap: function( callback ) {\n\t\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\t\treturn callback.call( elem, i, elem );\n\t\t\t} ) );\n\t\t},\n\n\t\tslice: function() {\n\t\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t\t},\n\n\t\tfirst: function() {\n\t\t\treturn this.eq( 0 );\n\t\t},\n\n\t\tlast: function() {\n\t\t\treturn this.eq( -1 );\n\t\t},\n\n\t\teq: function( i ) {\n\t\t\tvar len = this.length,\n\t\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t\t},\n\n\t\tend: function() {\n\t\t\treturn this.prevObject || this.constructor();\n\t\t},\n\n\t\t// For internal use only.\n\t\t// Behaves like an Array's method, not like a jQuery method.\n\t\tpush: push,\n\t\tsort: arr.sort,\n\t\tsplice: arr.splice\n\t};\n\n\tjQuery.extend = jQuery.fn.extend = function() {\n\t\tvar options, name, src, copy, copyIsArray, clone,\n\t\t\ttarget = arguments[ 0 ] || {},\n\t\t\ti = 1,\n\t\t\tlength = arguments.length,\n\t\t\tdeep = false;\n\n\t\t// Handle a deep copy situation\n\t\tif ( typeof target === \"boolean\" ) {\n\t\t\tdeep = target;\n\n\t\t\t// Skip the boolean and the target\n\t\t\ttarget = arguments[ i ] || {};\n\t\t\ti++;\n\t\t}\n\n\t\t// Handle case when target is a string or something (possible in deep copy)\n\t\tif ( typeof target !== \"object\" && !jQuery.isFunction( target ) ) {\n\t\t\ttarget = {};\n\t\t}\n\n\t\t// Extend jQuery itself if only one argument is passed\n\t\tif ( i === length ) {\n\t\t\ttarget = this;\n\t\t\ti--;\n\t\t}\n\n\t\tfor ( ; i < length; i++ ) {\n\n\t\t\t// Only deal with non-null/undefined values\n\t\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t\t// Extend the base object\n\t\t\t\tfor ( name in options ) {\n\t\t\t\t\tsrc = target[ name ];\n\t\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t\t// Prevent never-ending loop\n\t\t\t\t\tif ( target === copy ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t\t( copyIsArray = jQuery.isArray( copy ) ) ) ) {\n\n\t\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\t\tclone = src && jQuery.isArray( src ) ? src : [];\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tclone = src && jQuery.isPlainObject( src ) ? src : {};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t\t// Don't bring in undefined values\n\t\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Return the modified object\n\t\treturn target;\n\t};\n\n\tjQuery.extend( {\n\n\t\t// Unique for each copy of jQuery on the page\n\t\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t\t// Assume jQuery is ready without the ready module\n\t\tisReady: true,\n\n\t\terror: function( msg ) {\n\t\t\tthrow new Error( msg );\n\t\t},\n\n\t\tnoop: function() {},\n\n\t\tisFunction: function( obj ) {\n\t\t\treturn jQuery.type( obj ) === \"function\";\n\t\t},\n\n\t\tisArray: Array.isArray,\n\n\t\tisWindow: function( obj ) {\n\t\t\treturn obj != null && obj === obj.window;\n\t\t},\n\n\t\tisNumeric: function( obj ) {\n\n\t\t\t// As of jQuery 3.0, isNumeric is limited to\n\t\t\t// strings and numbers (primitives or objects)\n\t\t\t// that can be coerced to finite numbers (gh-2662)\n\t\t\tvar type = jQuery.type( obj );\n\t\t\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t\t\t// subtraction forces infinities to NaN\n\t\t\t\t!isNaN( obj - parseFloat( obj ) );\n\t\t},\n\n\t\tisPlainObject: function( obj ) {\n\t\t\tvar proto, Ctor;\n\n\t\t\t// Detect obvious negatives\n\t\t\t// Use toString instead of jQuery.type to catch host objects\n\t\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tproto = getProto( obj );\n\n\t\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\t\tif ( !proto ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t\t},\n\n\t\tisEmptyObject: function( obj ) {\n\n\t\t\t/* eslint-disable no-unused-vars */\n\t\t\t// See https://github.com/eslint/eslint/issues/6125\n\t\t\tvar name;\n\n\t\t\tfor ( name in obj ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\ttype: function( obj ) {\n\t\t\tif ( obj == null ) {\n\t\t\t\treturn obj + \"\";\n\t\t\t}\n\n\t\t\t// Support: Android <=2.3 only (functionish RegExp)\n\t\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\t\t\ttypeof obj;\n\t\t},\n\n\t\t// Evaluates a script in a global context\n\t\tglobalEval: function( code ) {\n\t\t\tDOMEval( code );\n\t\t},\n\n\t\t// Convert dashed to camelCase; used by the css and data modules\n\t\t// Support: IE <=9 - 11, Edge 12 - 13\n\t\t// Microsoft forgot to hump their vendor prefix (#9572)\n\t\tcamelCase: function( string ) {\n\t\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t\t},\n\n\t\tnodeName: function( elem, name ) {\n\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t\t},\n\n\t\teach: function( obj, callback ) {\n\t\t\tvar length, i = 0;\n\n\t\t\tif ( isArrayLike( obj ) ) {\n\t\t\t\tlength = obj.length;\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn obj;\n\t\t},\n\n\t\t// Support: Android <=4.0 only\n\t\ttrim: function( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t\t},\n\n\t\t// results is for internal usage only\n\t\tmakeArray: function( arr, results ) {\n\t\t\tvar ret = results || [];\n\n\t\t\tif ( arr != null ) {\n\t\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t\t[ arr ] : arr\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tpush.call( ret, arr );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ret;\n\t\t},\n\n\t\tinArray: function( elem, arr, i ) {\n\t\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t\t},\n\n\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\tmerge: function( first, second ) {\n\t\t\tvar len = +second.length,\n\t\t\t\tj = 0,\n\t\t\t\ti = first.length;\n\n\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\n\t\t\tfirst.length = i;\n\n\t\t\treturn first;\n\t\t},\n\n\t\tgrep: function( elems, callback, invert ) {\n\t\t\tvar callbackInverse,\n\t\t\t\tmatches = [],\n\t\t\t\ti = 0,\n\t\t\t\tlength = elems.length,\n\t\t\t\tcallbackExpect = !invert;\n\n\t\t\t// Go through the array, only saving the items\n\t\t\t// that pass the validator function\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn matches;\n\t\t},\n\n\t\t// arg is for internal usage only\n\t\tmap: function( elems, callback, arg ) {\n\t\t\tvar length, value,\n\t\t\t\ti = 0,\n\t\t\t\tret = [];\n\n\t\t\t// Go through the array, translating each of the items to their new values\n\t\t\tif ( isArrayLike( elems ) ) {\n\t\t\t\tlength = elems.length;\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\t\tif ( value != null ) {\n\t\t\t\t\t\tret.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Go through every key on the object,\n\t\t\t} else {\n\t\t\t\tfor ( i in elems ) {\n\t\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\t\tif ( value != null ) {\n\t\t\t\t\t\tret.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Flatten any nested arrays\n\t\t\treturn concat.apply( [], ret );\n\t\t},\n\n\t\t// A global GUID counter for objects\n\t\tguid: 1,\n\n\t\t// Bind a function to a context, optionally partially applying any\n\t\t// arguments.\n\t\tproxy: function( fn, context ) {\n\t\t\tvar tmp, args, proxy;\n\n\t\t\tif ( typeof context === \"string\" ) {\n\t\t\t\ttmp = fn[ context ];\n\t\t\t\tcontext = fn;\n\t\t\t\tfn = tmp;\n\t\t\t}\n\n\t\t\t// Quick check to determine if target is callable, in the spec\n\t\t\t// this throws a TypeError, but we will just return undefined.\n\t\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\t// Simulated bind\n\t\t\targs = slice.call( arguments, 2 );\n\t\t\tproxy = function() {\n\t\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t\t};\n\n\t\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\t\treturn proxy;\n\t\t},\n\n\t\tnow: Date.now,\n\n\t\t// jQuery.support is not used in Core but other projects attach their\n\t\t// properties to it so it needs to exist.\n\t\tsupport: support\n\t} );\n\n\tif ( typeof Symbol === \"function\" ) {\n\t\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n\t}\n\n\t// Populate the class2type map\n\tjQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\n\tfunction( i, name ) {\n\t\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n\t} );\n\n\tfunction isArrayLike( obj ) {\n\n\t\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t\t// `in` check used to prevent JIT error (gh-2145)\n\t\t// hasOwn isn't used here due to false negatives\n\t\t// regarding Nodelist length in IE\n\t\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\t\ttype = jQuery.type( obj );\n\n\t\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn type === \"array\" || length === 0 ||\n\t\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n\t}\n\tvar Sizzle =\n\t/*!\n\t * Sizzle CSS Selector Engine v2.3.3\n\t * https://sizzlejs.com/\n\t *\n\t * Copyright jQuery Foundation and other contributors\n\t * Released under the MIT license\n\t * http://jquery.org/license\n\t *\n\t * Date: 2016-08-08\n\t */\n\t(function( window ) {\n\n\tvar i,\n\t\tsupport,\n\t\tExpr,\n\t\tgetText,\n\t\tisXML,\n\t\ttokenize,\n\t\tcompile,\n\t\tselect,\n\t\toutermostContext,\n\t\tsortInput,\n\t\thasDuplicate,\n\n\t\t// Local document vars\n\t\tsetDocument,\n\t\tdocument,\n\t\tdocElem,\n\t\tdocumentIsHTML,\n\t\trbuggyQSA,\n\t\trbuggyMatches,\n\t\tmatches,\n\t\tcontains,\n\n\t\t// Instance-specific data\n\t\texpando = \"sizzle\" + 1 * new Date(),\n\t\tpreferredDoc = window.document,\n\t\tdirruns = 0,\n\t\tdone = 0,\n\t\tclassCache = createCache(),\n\t\ttokenCache = createCache(),\n\t\tcompilerCache = createCache(),\n\t\tsortOrder = function( a, b ) {\n\t\t\tif ( a === b ) {\n\t\t\t\thasDuplicate = true;\n\t\t\t}\n\t\t\treturn 0;\n\t\t},\n\n\t\t// Instance methods\n\t\thasOwn = ({}).hasOwnProperty,\n\t\tarr = [],\n\t\tpop = arr.pop,\n\t\tpush_native = arr.push,\n\t\tpush = arr.push,\n\t\tslice = arr.slice,\n\t\t// Use a stripped-down indexOf as it's faster than native\n\t\t// https://jsperf.com/thor-indexof-vs-for/5\n\t\tindexOf = function( list, elem ) {\n\t\t\tvar i = 0,\n\t\t\t\tlen = list.length;\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tif ( list[i] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn -1;\n\t\t},\n\n\t\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t\t// Regular expressions\n\n\t\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\t\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\t\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n\n\t\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\t\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\t\t\t// Operator (capture 2)\n\t\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\t\"*\\\\]\",\n\n\t\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\t\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t\t// 2. simple (capture 6)\n\t\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t\t// 3. anything else (capture 2)\n\t\t\t\".*\" +\n\t\t\t\")\\\\)|)\",\n\n\t\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\t\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\t\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\t\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\t\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\t\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\t\trpseudo = new RegExp( pseudos ),\n\t\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\t\tmatchExpr = {\n\t\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t\t// For use in libraries implementing .is()\n\t\t\t// We use this for POS matching in `select`\n\t\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t\t},\n\n\t\trinputs = /^(?:input|select|textarea|button)$/i,\n\t\trheader = /^h\\d$/i,\n\n\t\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\t\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\t\trsibling = /[+~]/,\n\n\t\t// CSS escapes\n\t\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\t\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\t\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t\t// NaN means non-codepoint\n\t\t\t// Support: Firefox<24\n\t\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\t\treturn high !== high || escapedWhitespace ?\n\t\t\t\tescaped :\n\t\t\t\thigh < 0 ?\n\t\t\t\t\t// BMP codepoint\n\t\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t\t},\n\n\t\t// CSS string/identifier serialization\n\t\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\t\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\t\tfcssescape = function( ch, asCodePoint ) {\n\t\t\tif ( asCodePoint ) {\n\n\t\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\t\treturn \"\\uFFFD\";\n\t\t\t\t}\n\n\t\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t\t}\n\n\t\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\t\treturn \"\\\\\" + ch;\n\t\t},\n\n\t\t// Used for iframes\n\t\t// See setDocument()\n\t\t// Removing the function wrapper causes a \"Permission Denied\"\n\t\t// error in IE\n\t\tunloadHandler = function() {\n\t\t\tsetDocument();\n\t\t},\n\n\t\tdisabledAncestor = addCombinator(\n\t\t\tfunction( elem ) {\n\t\t\t\treturn elem.disabled === true && (\"form\" in elem || \"label\" in elem);\n\t\t\t},\n\t\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t\t);\n\n\t// Optimize for push.apply( _, NodeList )\n\ttry {\n\t\tpush.apply(\n\t\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\t\tpreferredDoc.childNodes\n\t\t);\n\t\t// Support: Android<4.0\n\t\t// Detect silently failing push.apply\n\t\tarr[ preferredDoc.childNodes.length ].nodeType;\n\t} catch ( e ) {\n\t\tpush = { apply: arr.length ?\n\n\t\t\t// Leverage slice if possible\n\t\t\tfunction( target, els ) {\n\t\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t\t} :\n\n\t\t\t// Support: IE<9\n\t\t\t// Otherwise append directly\n\t\t\tfunction( target, els ) {\n\t\t\t\tvar j = target.length,\n\t\t\t\t\ti = 0;\n\t\t\t\t// Can't trust NodeList.length\n\t\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\t\ttarget.length = j - 1;\n\t\t\t}\n\t\t};\n\t}\n\n\tfunction Sizzle( selector, context, results, seed ) {\n\t\tvar m, i, elem, nid, match, groups, newSelector,\n\t\t\tnewContext = context && context.ownerDocument,\n\n\t\t\t// nodeType defaults to 9, since context defaults to document\n\t\t\tnodeType = context ? context.nodeType : 9;\n\n\t\tresults = results || [];\n\n\t\t// Return early from calls with invalid selector or context\n\t\tif ( typeof selector !== \"string\" || !selector ||\n\t\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\t\treturn results;\n\t\t}\n\n\t\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\t\tif ( !seed ) {\n\n\t\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\t\tsetDocument( context );\n\t\t\t}\n\t\t\tcontext = context || document;\n\n\t\t\tif ( documentIsHTML ) {\n\n\t\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t\t// ID selector\n\t\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t\t// Document context\n\t\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Element context\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Type selector\n\t\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\t\treturn results;\n\n\t\t\t\t\t// Class selector\n\t\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Take advantage of querySelectorAll\n\t\t\t\tif ( support.qsa &&\n\t\t\t\t\t!compilerCache[ selector + \" \" ] &&\n\t\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\n\t\t\t\t\tif ( nodeType !== 1 ) {\n\t\t\t\t\t\tnewContext = context;\n\t\t\t\t\t\tnewSelector = selector;\n\n\t\t\t\t\t// qSA looks outside Element context, which is not what we want\n\t\t\t\t\t// Thanks to Andrew Dupont for this workaround technique\n\t\t\t\t\t// Support: IE <=8\n\t\t\t\t\t// Exclude object elements\n\t\t\t\t\t} else if ( context.nodeName.toLowerCase() !== \"object\" ) {\n\n\t\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\t\ti = groups.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tgroups[i] = \"#\" + nid + \" \" + toSelector( groups[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\t\tcontext;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( newSelector ) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// All others\n\t\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n\t}\n\n\t/**\n\t * Create key-value caches of limited size\n\t * @returns {function(string, object)} Returns the Object data after storing it on itself with\n\t *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n\t *\tdeleting the oldest entry\n\t */\n\tfunction createCache() {\n\t\tvar keys = [];\n\n\t\tfunction cache( key, value ) {\n\t\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t\t// Only keep the most recent entries\n\t\t\t\tdelete cache[ keys.shift() ];\n\t\t\t}\n\t\t\treturn (cache[ key + \" \" ] = value);\n\t\t}\n\t\treturn cache;\n\t}\n\n\t/**\n\t * Mark a function for special use by Sizzle\n\t * @param {Function} fn The function to mark\n\t */\n\tfunction markFunction( fn ) {\n\t\tfn[ expando ] = true;\n\t\treturn fn;\n\t}\n\n\t/**\n\t * Support testing using an element\n\t * @param {Function} fn Passed the created element and returns a boolean result\n\t */\n\tfunction assert( fn ) {\n\t\tvar el = document.createElement(\"fieldset\");\n\n\t\ttry {\n\t\t\treturn !!fn( el );\n\t\t} catch (e) {\n\t\t\treturn false;\n\t\t} finally {\n\t\t\t// Remove from its parent by default\n\t\t\tif ( el.parentNode ) {\n\t\t\t\tel.parentNode.removeChild( el );\n\t\t\t}\n\t\t\t// release memory in IE\n\t\t\tel = null;\n\t\t}\n\t}\n\n\t/**\n\t * Adds the same handler for all of the specified attrs\n\t * @param {String} attrs Pipe-separated list of attributes\n\t * @param {Function} handler The method that will be applied\n\t */\n\tfunction addHandle( attrs, handler ) {\n\t\tvar arr = attrs.split(\"|\"),\n\t\t\ti = arr.length;\n\n\t\twhile ( i-- ) {\n\t\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t\t}\n\t}\n\n\t/**\n\t * Checks document order of two siblings\n\t * @param {Element} a\n\t * @param {Element} b\n\t * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n\t */\n\tfunction siblingCheck( a, b ) {\n\t\tvar cur = b && a,\n\t\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t\t// Use IE sourceIndex if available on both nodes\n\t\tif ( diff ) {\n\t\t\treturn diff;\n\t\t}\n\n\t\t// Check if b follows a\n\t\tif ( cur ) {\n\t\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\t\tif ( cur === b ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn a ? 1 : -1;\n\t}\n\n\t/**\n\t * Returns a function to use in pseudos for input types\n\t * @param {String} type\n\t */\n\tfunction createInputPseudo( type ) {\n\t\treturn function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === type;\n\t\t};\n\t}\n\n\t/**\n\t * Returns a function to use in pseudos for buttons\n\t * @param {String} type\n\t */\n\tfunction createButtonPseudo( type ) {\n\t\treturn function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t\t};\n\t}\n\n\t/**\n\t * Returns a function to use in pseudos for :enabled/:disabled\n\t * @param {Boolean} disabled true for :disabled; false for :enabled\n\t */\n\tfunction createDisabledPseudo( disabled ) {\n\n\t\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\t\treturn function( elem ) {\n\n\t\t\t// Only certain elements can match :enabled or :disabled\n\t\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\t\tif ( \"form\" in elem ) {\n\n\t\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t\t// * option elements in a disabled optgroup\n\t\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t\t// All such elements have a \"form\" property.\n\t\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\t\t\tdisabledAncestor( elem ) === disabled;\n\t\t\t\t}\n\n\t\t\t\treturn elem.disabled === disabled;\n\n\t\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t\t// even exist on them, let alone have a boolean value.\n\t\t\t} else if ( \"label\" in elem ) {\n\t\t\t\treturn elem.disabled === disabled;\n\t\t\t}\n\n\t\t\t// Remaining elements are neither :enabled nor :disabled\n\t\t\treturn false;\n\t\t};\n\t}\n\n\t/**\n\t * Returns a function to use in pseudos for positionals\n\t * @param {Function} fn\n\t */\n\tfunction createPositionalPseudo( fn ) {\n\t\treturn markFunction(function( argument ) {\n\t\t\targument = +argument;\n\t\t\treturn markFunction(function( seed, matches ) {\n\t\t\t\tvar j,\n\t\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\t\ti = matchIndexes.length;\n\n\t\t\t\t// Match elements found at the specified indexes\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Checks a node for validity as a Sizzle context\n\t * @param {Element|Object=} context\n\t * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n\t */\n\tfunction testContext( context ) {\n\t\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n\t}\n\n\t// Expose support vars for convenience\n\tsupport = Sizzle.support = {};\n\n\t/**\n\t * Detects XML nodes\n\t * @param {Element|Object} elem An element or a document\n\t * @returns {Boolean} True iff elem is a non-HTML XML node\n\t */\n\tisXML = Sizzle.isXML = function( elem ) {\n\t\t// documentElement is verified for cases where it doesn't yet exist\n\t\t// (such as loading iframes in IE - #4833)\n\t\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\t\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n\t};\n\n\t/**\n\t * Sets document-related variables once based on the current document\n\t * @param {Element|Object} [doc] An element or document object to use to set the document\n\t * @returns {Object} Returns the current document\n\t */\n\tsetDocument = Sizzle.setDocument = function( node ) {\n\t\tvar hasCompare, subWindow,\n\t\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t\t// Return early if doc is invalid or already selected\n\t\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\t\treturn document;\n\t\t}\n\n\t\t// Update global variables\n\t\tdocument = doc;\n\t\tdocElem = document.documentElement;\n\t\tdocumentIsHTML = !isXML( document );\n\n\t\t// Support: IE 9-11, Edge\n\t\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\t\tif ( preferredDoc !== document &&\n\t\t\t(subWindow = document.defaultView) && subWindow.top !== subWindow ) {\n\n\t\t\t// Support: IE 11, Edge\n\t\t\tif ( subWindow.addEventListener ) {\n\t\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t\t// Support: IE 9 - 10 only\n\t\t\t} else if ( subWindow.attachEvent ) {\n\t\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t\t}\n\t\t}\n\n\t\t/* Attributes\n\t\t---------------------------------------------------------------------- */\n\n\t\t// Support: IE<8\n\t\t// Verify that getAttribute really returns attributes and not properties\n\t\t// (excepting IE8 booleans)\n\t\tsupport.attributes = assert(function( el ) {\n\t\t\tel.className = \"i\";\n\t\t\treturn !el.getAttribute(\"className\");\n\t\t});\n\n\t\t/* getElement(s)By*\n\t\t---------------------------------------------------------------------- */\n\n\t\t// Check if getElementsByTagName(\"*\") returns only elements\n\t\tsupport.getElementsByTagName = assert(function( el ) {\n\t\t\tel.appendChild( document.createComment(\"\") );\n\t\t\treturn !el.getElementsByTagName(\"*\").length;\n\t\t});\n\n\t\t// Support: IE<9\n\t\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t\t// Support: IE<10\n\t\t// Check if getElementById returns elements by name\n\t\t// The broken getElementById methods don't pick up programmatically-set names,\n\t\t// so use a roundabout getElementsByName test\n\t\tsupport.getById = assert(function( el ) {\n\t\t\tdocElem.appendChild( el ).id = expando;\n\t\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t\t});\n\n\t\t// ID filter and find\n\t\tif ( support.getById ) {\n\t\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t\t};\n\t\t\t};\n\t\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t\t}\n\t\t\t};\n\t\t} else {\n\t\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\t\treturn node && node.value === attrId;\n\t\t\t\t};\n\t\t\t};\n\n\t\t\t// Support: IE 6 - 7 only\n\t\t\t// getElementById is not reliable as a find shortcut\n\t\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\t\tvar node, i, elems,\n\t\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\twhile ( (elem = elems[i++]) ) {\n\t\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t// Tag\n\t\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\t\tfunction( tag, context ) {\n\t\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t\t} else if ( support.qsa ) {\n\t\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t\t}\n\t\t\t} :\n\n\t\t\tfunction( tag, context ) {\n\t\t\t\tvar elem,\n\t\t\t\t\ttmp = [],\n\t\t\t\t\ti = 0,\n\t\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t\t// Filter out possible comments\n\t\t\t\tif ( tag === \"*\" ) {\n\t\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn tmp;\n\t\t\t\t}\n\t\t\t\treturn results;\n\t\t\t};\n\n\t\t// Class\n\t\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\t\treturn context.getElementsByClassName( className );\n\t\t\t}\n\t\t};\n\n\t\t/* QSA/matchesSelector\n\t\t---------------------------------------------------------------------- */\n\n\t\t// QSA and matchesSelector support\n\n\t\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\t\trbuggyMatches = [];\n\n\t\t// qSa(:focus) reports false when true (Chrome 21)\n\t\t// We allow this because of a bug in IE8/9 that throws an error\n\t\t// whenever `document.activeElement` is accessed on an iframe\n\t\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t\t// See https://bugs.jquery.com/ticket/13378\n\t\trbuggyQSA = [];\n\n\t\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t\t// Build QSA regex\n\t\t\t// Regex strategy adopted from Diego Perini\n\t\t\tassert(function( el ) {\n\t\t\t\t// Select is set to empty string on purpose\n\t\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t\t// setting a boolean content attribute,\n\t\t\t\t// since its presence should be enough\n\t\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\t\tif ( el.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t\t}\n\n\t\t\t\t// Support: IE8\n\t\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\t\tif ( !el.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t\t}\n\n\t\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t\t}\n\n\t\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t\t// IE8 throws error here and will not see later tests\n\t\t\t\tif ( !el.querySelectorAll(\":checked\").length ) {\n\t\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t\t}\n\n\t\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tassert(function( el ) {\n\t\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t\t// Support: Windows 8 Native Apps\n\t\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\t\tvar input = document.createElement(\"input\");\n\t\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t\t// Support: IE8\n\t\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\t\tif ( el.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t\t}\n\n\t\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t\t// IE8 throws error here and will not see later tests\n\t\t\t\tif ( el.querySelectorAll(\":enabled\").length !== 2 ) {\n\t\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t\t}\n\n\t\t\t\t// Support: IE9-11+\n\t\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\t\tif ( el.querySelectorAll(\":disabled\").length !== 2 ) {\n\t\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t\t}\n\n\t\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\t\tel.querySelectorAll(\"*,:x\");\n\t\t\t\trbuggyQSA.push(\",.*:\");\n\t\t\t});\n\t\t}\n\n\t\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\t\tdocElem.webkitMatchesSelector ||\n\t\t\tdocElem.mozMatchesSelector ||\n\t\t\tdocElem.oMatchesSelector ||\n\t\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\t\tassert(function( el ) {\n\t\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t\t// on a disconnected node (IE 9)\n\t\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t\t// This should fail with an exception\n\t\t\t\t// Gecko does not error, returns false instead\n\t\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t\t});\n\t\t}\n\n\t\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\t\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t\t/* Contains\n\t\t---------------------------------------------------------------------- */\n\t\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t\t// Element contains another\n\t\t// Purposefully self-exclusive\n\t\t// As in, an element does not contain itself\n\t\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\t\tfunction( a, b ) {\n\t\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\t\tbup = b && b.parentNode;\n\t\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\t\tadown.contains ?\n\t\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t\t));\n\t\t\t} :\n\t\t\tfunction( a, b ) {\n\t\t\t\tif ( b ) {\n\t\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\n\t\t/* Sorting\n\t\t---------------------------------------------------------------------- */\n\n\t\t// Document order sorting\n\t\tsortOrder = hasCompare ?\n\t\tfunction( a, b ) {\n\n\t\t\t// Flag for duplicate removal\n\t\t\tif ( a === b ) {\n\t\t\t\thasDuplicate = true;\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\t\tif ( compare ) {\n\t\t\t\treturn compare;\n\t\t\t}\n\n\t\t\t// Calculate position if both inputs belong to the same document\n\t\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t\t// Otherwise we know they are disconnected\n\t\t\t\t1;\n\n\t\t\t// Disconnected nodes\n\t\t\tif ( compare & 1 ||\n\t\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t\t// Choose the first element that is related to our preferred document\n\t\t\t\tif ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\t// Maintain original order\n\t\t\t\treturn sortInput ?\n\t\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t\t0;\n\t\t\t}\n\n\t\t\treturn compare & 4 ? -1 : 1;\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\t// Exit early if the nodes are identical\n\t\t\tif ( a === b ) {\n\t\t\t\thasDuplicate = true;\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tvar cur,\n\t\t\t\ti = 0,\n\t\t\t\taup = a.parentNode,\n\t\t\t\tbup = b.parentNode,\n\t\t\t\tap = [ a ],\n\t\t\t\tbp = [ b ];\n\n\t\t\t// Parentless nodes are either documents or disconnected\n\t\t\tif ( !aup || !bup ) {\n\t\t\t\treturn a === document ? -1 :\n\t\t\t\t\tb === document ? 1 :\n\t\t\t\t\taup ? -1 :\n\t\t\t\t\tbup ? 1 :\n\t\t\t\t\tsortInput ?\n\t\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t\t0;\n\n\t\t\t// If the nodes are siblings, we can do a quick check\n\t\t\t} else if ( aup === bup ) {\n\t\t\t\treturn siblingCheck( a, b );\n\t\t\t}\n\n\t\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\t\tcur = a;\n\t\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\t\tap.unshift( cur );\n\t\t\t}\n\t\t\tcur = b;\n\t\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\t\tbp.unshift( cur );\n\t\t\t}\n\n\t\t\t// Walk down the tree looking for a discrepancy\n\t\t\twhile ( ap[i] === bp[i] ) {\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\treturn i ?\n\t\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t\t// Otherwise nodes in our document sort first\n\t\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t\t0;\n\t\t};\n\n\t\treturn document;\n\t};\n\n\tSizzle.matches = function( expr, elements ) {\n\t\treturn Sizzle( expr, null, null, elements );\n\t};\n\n\tSizzle.matchesSelector = function( elem, expr ) {\n\t\t// Set document vars if needed\n\t\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\t\tsetDocument( elem );\n\t\t}\n\n\t\t// Make sure that attribute selectors are quoted\n\t\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\t\tif ( support.matchesSelector && documentIsHTML &&\n\t\t\t!compilerCache[ expr + \" \" ] &&\n\t\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\t\ttry {\n\t\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t} catch (e) {}\n\t\t}\n\n\t\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n\t};\n\n\tSizzle.contains = function( context, elem ) {\n\t\t// Set document vars if needed\n\t\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\t\tsetDocument( context );\n\t\t}\n\t\treturn contains( context, elem );\n\t};\n\n\tSizzle.attr = function( elem, name ) {\n\t\t// Set document vars if needed\n\t\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\t\tsetDocument( elem );\n\t\t}\n\n\t\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\t\tundefined;\n\n\t\treturn val !== undefined ?\n\t\t\tval :\n\t\t\tsupport.attributes || !documentIsHTML ?\n\t\t\t\telem.getAttribute( name ) :\n\t\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\t\tnull;\n\t};\n\n\tSizzle.escape = function( sel ) {\n\t\treturn (sel + \"\").replace( rcssescape, fcssescape );\n\t};\n\n\tSizzle.error = function( msg ) {\n\t\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n\t};\n\n\t/**\n\t * Document sorting and removing duplicates\n\t * @param {ArrayLike} results\n\t */\n\tSizzle.uniqueSort = function( results ) {\n\t\tvar elem,\n\t\t\tduplicates = [],\n\t\t\tj = 0,\n\t\t\ti = 0;\n\n\t\t// Unless we *know* we can detect duplicates, assume their presence\n\t\thasDuplicate = !support.detectDuplicates;\n\t\tsortInput = !support.sortStable && results.slice( 0 );\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\t\tj = duplicates.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile ( j-- ) {\n\t\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t\t}\n\t\t}\n\n\t\t// Clear input after sorting to release objects\n\t\t// See https://github.com/jquery/sizzle/pull/225\n\t\tsortInput = null;\n\n\t\treturn results;\n\t};\n\n\t/**\n\t * Utility function for retrieving the text value of an array of DOM nodes\n\t * @param {Array|Element} elem\n\t */\n\tgetText = Sizzle.getText = function( elem ) {\n\t\tvar node,\n\t\t\tret = \"\",\n\t\t\ti = 0,\n\t\t\tnodeType = elem.nodeType;\n\n\t\tif ( !nodeType ) {\n\t\t\t// If no nodeType, this is expected to be an array\n\t\t\twhile ( (node = elem[i++]) ) {\n\t\t\t\t// Do not traverse comment nodes\n\t\t\t\tret += getText( node );\n\t\t\t}\n\t\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t\t// Use textContent for elements\n\t\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\t\treturn elem.textContent;\n\t\t\t} else {\n\t\t\t\t// Traverse its children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\t\tret += getText( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\t\treturn elem.nodeValue;\n\t\t}\n\t\t// Do not include comment or processing instruction nodes\n\n\t\treturn ret;\n\t};\n\n\tExpr = Sizzle.selectors = {\n\n\t\t// Can be adjusted by the user\n\t\tcacheLength: 50,\n\n\t\tcreatePseudo: markFunction,\n\n\t\tmatch: matchExpr,\n\n\t\tattrHandle: {},\n\n\t\tfind: {},\n\n\t\trelative: {\n\t\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\t\" \": { dir: \"parentNode\" },\n\t\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\t\"~\": { dir: \"previousSibling\" }\n\t\t},\n\n\t\tpreFilter: {\n\t\t\t\"ATTR\": function( match ) {\n\t\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t\t}\n\n\t\t\t\treturn match.slice( 0, 4 );\n\t\t\t},\n\n\t\t\t\"CHILD\": function( match ) {\n\t\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t\t1 type (only|nth|...)\n\t\t\t\t\t2 what (child|of-type)\n\t\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t\t5 sign of xn-component\n\t\t\t\t\t6 x of xn-component\n\t\t\t\t\t7 sign of y-component\n\t\t\t\t\t8 y of y-component\n\t\t\t\t*/\n\t\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t\t// nth-* requires argument\n\t\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t\t}\n\n\t\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t\t// other types prohibit arguments\n\t\t\t\t} else if ( match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\treturn match;\n\t\t\t},\n\n\t\t\t\"PSEUDO\": function( match ) {\n\t\t\t\tvar excess,\n\t\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t// Accept quoted arguments as-is\n\t\t\t\tif ( match[3] ) {\n\t\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t\t// excess is a negative index\n\t\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t\t}\n\n\t\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\t\treturn match.slice( 0, 3 );\n\t\t\t}\n\t\t},\n\n\t\tfilter: {\n\n\t\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\t\tfunction() { return true; } :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t\t};\n\t\t\t},\n\n\t\t\t\"CLASS\": function( className ) {\n\t\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\t\treturn pattern ||\n\t\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t\t});\n\t\t\t},\n\n\t\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\t\tif ( result == null ) {\n\t\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t\t}\n\t\t\t\t\tif ( !operator ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tresult += \"\";\n\n\t\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\t\tfalse;\n\t\t\t\t};\n\t\t\t},\n\n\t\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\t\tofType = what === \"of-type\";\n\n\t\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t\t} :\n\n\t\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\t\tif ( diff === false ) {\n\t\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t},\n\n\t\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t\t// pseudo-class names are case-insensitive\n\t\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\t\tvar args,\n\t\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t\t// The user may use createPseudo to indicate that\n\t\t\t\t// arguments are needed to create the filter function\n\t\t\t\t// just as Sizzle does\n\t\t\t\tif ( fn[ expando ] ) {\n\t\t\t\t\treturn fn( argument );\n\t\t\t\t}\n\n\t\t\t\t// But maintain support for old signatures\n\t\t\t\tif ( fn.length > 1 ) {\n\t\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}) :\n\t\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn fn;\n\t\t\t}\n\t\t},\n\n\t\tpseudos: {\n\t\t\t// Potentially complex pseudos\n\t\t\t\"not\": markFunction(function( selector ) {\n\t\t\t\t// Trim the selector passed to compile\n\t\t\t\t// to avoid treating leading and trailing\n\t\t\t\t// spaces as combinators\n\t\t\t\tvar input = [],\n\t\t\t\t\tresults = [],\n\t\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\t\treturn matcher[ expando ] ?\n\t\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\t\tvar elem,\n\t\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\t\tinput[0] = null;\n\t\t\t\t\t\treturn !results.pop();\n\t\t\t\t\t};\n\t\t\t}),\n\n\t\t\t\"has\": markFunction(function( selector ) {\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t\t};\n\t\t\t}),\n\n\t\t\t\"contains\": markFunction(function( text ) {\n\t\t\t\ttext = text.replace( runescape, funescape );\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t\t};\n\t\t\t}),\n\n\t\t\t// \"Whether an element is represented by a :lang() selector\n\t\t\t// is based solely on the element's language value\n\t\t\t// being equal to the identifier C,\n\t\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t\t// The identifier C does not have to be a valid language name.\"\n\t\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t\t// lang value must be a valid identifier\n\t\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t\t}\n\t\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\t\treturn function( elem ) {\n\t\t\t\t\tvar elemLang;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\t\treturn false;\n\t\t\t\t};\n\t\t\t}),\n\n\t\t\t// Miscellaneous\n\t\t\t\"target\": function( elem ) {\n\t\t\t\tvar hash = window.location && window.location.hash;\n\t\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t\t},\n\n\t\t\t\"root\": function( elem ) {\n\t\t\t\treturn elem === docElem;\n\t\t\t},\n\n\t\t\t\"focus\": function( elem ) {\n\t\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t\t},\n\n\t\t\t// Boolean properties\n\t\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\t\"checked\": function( elem ) {\n\t\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t\t},\n\n\t\t\t\"selected\": function( elem ) {\n\t\t\t\t// Accessing this property makes selected-by-default\n\t\t\t\t// options in Safari work properly\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t\t}\n\n\t\t\t\treturn elem.selected === true;\n\t\t\t},\n\n\t\t\t// Contents\n\t\t\t\"empty\": function( elem ) {\n\t\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t\"parent\": function( elem ) {\n\t\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t\t},\n\n\t\t\t// Element/input types\n\t\t\t\"header\": function( elem ) {\n\t\t\t\treturn rheader.test( elem.nodeName );\n\t\t\t},\n\n\t\t\t\"input\": function( elem ) {\n\t\t\t\treturn rinputs.test( elem.nodeName );\n\t\t\t},\n\n\t\t\t\"button\": function( elem ) {\n\t\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t\t},\n\n\t\t\t\"text\": function( elem ) {\n\t\t\t\tvar attr;\n\t\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t\t// Support: IE<8\n\t\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t\t},\n\n\t\t\t// Position-in-collection\n\t\t\t\"first\": createPositionalPseudo(function() {\n\t\t\t\treturn [ 0 ];\n\t\t\t}),\n\n\t\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\t\treturn [ length - 1 ];\n\t\t\t}),\n\n\t\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t\t}),\n\n\t\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\t\tvar i = 0;\n\t\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t}\n\t\t\t\treturn matchIndexes;\n\t\t\t}),\n\n\t\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\t\tvar i = 1;\n\t\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t}\n\t\t\t\treturn matchIndexes;\n\t\t\t}),\n\n\t\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t}\n\t\t\t\treturn matchIndexes;\n\t\t\t}),\n\n\t\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\t\tmatchIndexes.push( i );\n\t\t\t\t}\n\t\t\t\treturn matchIndexes;\n\t\t\t})\n\t\t}\n\t};\n\n\tExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n\t// Add button/input type pseudos\n\tfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\t\tExpr.pseudos[ i ] = createInputPseudo( i );\n\t}\n\tfor ( i in { submit: true, reset: true } ) {\n\t\tExpr.pseudos[ i ] = createButtonPseudo( i );\n\t}\n\n\t// Easy API for creating new setFilters\n\tfunction setFilters() {}\n\tsetFilters.prototype = Expr.filters = Expr.pseudos;\n\tExpr.setFilters = new setFilters();\n\n\ttokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\t\tvar matched, match, tokens, type,\n\t\t\tsoFar, groups, preFilters,\n\t\t\tcached = tokenCache[ selector + \" \" ];\n\n\t\tif ( cached ) {\n\t\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t\t}\n\n\t\tsoFar = selector;\n\t\tgroups = [];\n\t\tpreFilters = Expr.preFilter;\n\n\t\twhile ( soFar ) {\n\n\t\t\t// Comma and first run\n\t\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\t\tif ( match ) {\n\t\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t\t}\n\t\t\t\tgroups.push( (tokens = []) );\n\t\t\t}\n\n\t\t\tmatched = false;\n\n\t\t\t// Combinators\n\t\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\t// Cast descendant combinators to space\n\t\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\n\t\t\t// Filters\n\t\t\tfor ( type in Expr.filter ) {\n\t\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\t\tmatched = match.shift();\n\t\t\t\t\ttokens.push({\n\t\t\t\t\t\tvalue: matched,\n\t\t\t\t\t\ttype: type,\n\t\t\t\t\t\tmatches: match\n\t\t\t\t\t});\n\t\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !matched ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Return the length of the invalid excess\n\t\t// if we're just parsing\n\t\t// Otherwise, throw an error or return tokens\n\t\treturn parseOnly ?\n\t\t\tsoFar.length :\n\t\t\tsoFar ?\n\t\t\t\tSizzle.error( selector ) :\n\t\t\t\t// Cache the tokens\n\t\t\t\ttokenCache( selector, groups ).slice( 0 );\n\t};\n\n\tfunction toSelector( tokens ) {\n\t\tvar i = 0,\n\t\t\tlen = tokens.length,\n\t\t\tselector = \"\";\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tselector += tokens[i].value;\n\t\t}\n\t\treturn selector;\n\t}\n\n\tfunction addCombinator( matcher, combinator, base ) {\n\t\tvar dir = combinator.dir,\n\t\t\tskip = combinator.next,\n\t\t\tkey = skip || dir,\n\t\t\tcheckNonElements = base && key === \"parentNode\",\n\t\t\tdoneName = done++;\n\n\t\treturn combinator.first ?\n\t\t\t// Check against closest ancestor/preceding element\n\t\t\tfunction( elem, context, xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} :\n\n\t\t\t// Check against all ancestor/preceding elements\n\t\t\tfunction( elem, context, xml ) {\n\t\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\t\tif ( xml ) {\n\t\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t\t} else if ( (oldCache = uniqueCache[ key ]) &&\n\t\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\t}\n\n\tfunction elementMatcher( matchers ) {\n\t\treturn matchers.length > 1 ?\n\t\t\tfunction( elem, context, xml ) {\n\t\t\t\tvar i = matchers.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} :\n\t\t\tmatchers[0];\n\t}\n\n\tfunction multipleContexts( selector, contexts, results ) {\n\t\tvar i = 0,\n\t\t\tlen = contexts.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tSizzle( selector, contexts[i], results );\n\t\t}\n\t\treturn results;\n\t}\n\n\tfunction condense( unmatched, map, filter, context, xml ) {\n\t\tvar elem,\n\t\t\tnewUnmatched = [],\n\t\t\ti = 0,\n\t\t\tlen = unmatched.length,\n\t\t\tmapped = map != null;\n\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\t\tif ( mapped ) {\n\t\t\t\t\t\tmap.push( i );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn newUnmatched;\n\t}\n\n\tfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\t\tif ( postFilter && !postFilter[ expando ] ) {\n\t\t\tpostFilter = setMatcher( postFilter );\n\t\t}\n\t\tif ( postFinder && !postFinder[ expando ] ) {\n\t\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t\t}\n\t\treturn markFunction(function( seed, results, context, xml ) {\n\t\t\tvar temp, i, elem,\n\t\t\t\tpreMap = [],\n\t\t\t\tpostMap = [],\n\t\t\t\tpreexisting = results.length,\n\n\t\t\t\t// Get initial elements from seed or context\n\t\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\t\telems,\n\n\t\t\t\tmatcherOut = matcher ?\n\t\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t\t[] :\n\n\t\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\t\tresults :\n\t\t\t\t\tmatcherIn;\n\n\t\t\t// Find primary matches\n\t\t\tif ( matcher ) {\n\t\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t\t}\n\n\t\t\t// Apply postFilter\n\t\t\tif ( postFilter ) {\n\t\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\t\ti = temp.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( seed ) {\n\t\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\t\ttemp = [];\n\t\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Add elements to results, through postFinder if defined\n\t\t\t} else {\n\t\t\t\tmatcherOut = condense(\n\t\t\t\t\tmatcherOut === results ?\n\t\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\t\tmatcherOut\n\t\t\t\t);\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t\t} else {\n\t\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction matcherFromTokens( tokens ) {\n\t\tvar checkContext, matcher, j,\n\t\t\tlen = tokens.length,\n\t\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\t\ti = leadingRelative ? 1 : 0,\n\n\t\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\t\treturn elem === checkContext;\n\t\t\t}, implicitRelative, true ),\n\t\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t\t}, implicitRelative, true ),\n\t\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\t\tcheckContext = null;\n\t\t\t\treturn ret;\n\t\t\t} ];\n\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t\t} else {\n\t\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t\t// Return special upon seeing a positional matcher\n\t\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\t\tj = ++i;\n\t\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn setMatcher(\n\t\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\t\tmatcher,\n\t\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tmatchers.push( matcher );\n\t\t\t}\n\t\t}\n\n\t\treturn elementMatcher( matchers );\n\t}\n\n\tfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\t\tvar bySet = setMatchers.length > 0,\n\t\t\tbyElement = elementMatchers.length > 0,\n\t\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\t\tvar elem, j, matcher,\n\t\t\t\t\tmatchedCount = 0,\n\t\t\t\t\ti = \"0\",\n\t\t\t\t\tunmatched = seed && [],\n\t\t\t\t\tsetMatched = [],\n\t\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\t\tlen = elems.length;\n\n\t\t\t\tif ( outermost ) {\n\t\t\t\t\toutermostContext = context === document || context || outermost;\n\t\t\t\t}\n\n\t\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t\t// Support: IE<9, Safari\n\t\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t\t}\n\t\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\t\tif ( matcher( elem, context || document, xml) ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\t\tif ( bySet ) {\n\t\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t\t// makes the latter nonnegative.\n\t\t\t\tmatchedCount += i;\n\n\t\t\t\t// Apply set filters to unmatched elements\n\t\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t\t// no element matchers and no seed.\n\t\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t\t// numerically zero.\n\t\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add matches to results\n\t\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override manipulation of globals by nested matchers\n\t\t\t\tif ( outermost ) {\n\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\toutermostContext = contextBackup;\n\t\t\t\t}\n\n\t\t\t\treturn unmatched;\n\t\t\t};\n\n\t\treturn bySet ?\n\t\t\tmarkFunction( superMatcher ) :\n\t\t\tsuperMatcher;\n\t}\n\n\tcompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\t\tvar i,\n\t\t\tsetMatchers = [],\n\t\t\telementMatchers = [],\n\t\t\tcached = compilerCache[ selector + \" \" ];\n\n\t\tif ( !cached ) {\n\t\t\t// Generate a function of recursive functions that can be used to check each element\n\t\t\tif ( !match ) {\n\t\t\t\tmatch = tokenize( selector );\n\t\t\t}\n\t\t\ti = match.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\t\tif ( cached[ expando ] ) {\n\t\t\t\t\tsetMatchers.push( cached );\n\t\t\t\t} else {\n\t\t\t\t\telementMatchers.push( cached );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Cache the compiled function\n\t\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t\t// Save selector and tokenization\n\t\t\tcached.selector = selector;\n\t\t}\n\t\treturn cached;\n\t};\n\n\t/**\n\t * A low-level selection function that works with Sizzle's compiled\n\t *  selector functions\n\t * @param {String|Function} selector A selector or a pre-compiled\n\t *  selector function built with Sizzle.compile\n\t * @param {Element} context\n\t * @param {Array} [results]\n\t * @param {Array} [seed] A set of elements to match against\n\t */\n\tselect = Sizzle.select = function( selector, context, results, seed ) {\n\t\tvar i, tokens, token, type, find,\n\t\t\tcompiled = typeof selector === \"function\" && selector,\n\t\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\t\tresults = results || [];\n\n\t\t// Try to minimize operations if there is only one selector in the list and no seed\n\t\t// (the latter of which guarantees us context)\n\t\tif ( match.length === 1 ) {\n\n\t\t\t// Reduce context if the leading compound selector is an ID\n\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {\n\n\t\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\t\tif ( !context ) {\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t\t} else if ( compiled ) {\n\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t}\n\n\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t\t}\n\n\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t// Abort if we hit a combinator\n\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Compile and execute a filtering function if one is not provided\n\t\t// Provide `match` to avoid retokenization if we modified the selector above\n\t\t( compiled || compile( selector, match ) )(\n\t\t\tseed,\n\t\t\tcontext,\n\t\t\t!documentIsHTML,\n\t\t\tresults,\n\t\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t\t);\n\t\treturn results;\n\t};\n\n\t// One-time assignments\n\n\t// Sort stability\n\tsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n\t// Support: Chrome 14-35+\n\t// Always assume duplicates if they aren't passed to the comparison function\n\tsupport.detectDuplicates = !!hasDuplicate;\n\n\t// Initialize against the default document\n\tsetDocument();\n\n\t// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n\t// Detached nodes confoundingly follow *each other*\n\tsupport.sortDetached = assert(function( el ) {\n\t\t// Should return 1, but returns 4 (following)\n\t\treturn el.compareDocumentPosition( document.createElement(\"fieldset\") ) & 1;\n\t});\n\n\t// Support: IE<8\n\t// Prevent attribute/property \"interpolation\"\n\t// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\n\tif ( !assert(function( el ) {\n\t\tel.innerHTML = \"<a href='#'></a>\";\n\t\treturn el.firstChild.getAttribute(\"href\") === \"#\" ;\n\t}) ) {\n\t\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t\t}\n\t\t});\n\t}\n\n\t// Support: IE<9\n\t// Use defaultValue in place of getAttribute(\"value\")\n\tif ( !support.attributes || !assert(function( el ) {\n\t\tel.innerHTML = \"<input/>\";\n\t\tel.firstChild.setAttribute( \"value\", \"\" );\n\t\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n\t}) ) {\n\t\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\t\treturn elem.defaultValue;\n\t\t\t}\n\t\t});\n\t}\n\n\t// Support: IE<9\n\t// Use getAttributeNode to fetch booleans when getAttribute lies\n\tif ( !assert(function( el ) {\n\t\treturn el.getAttribute(\"disabled\") == null;\n\t}) ) {\n\t\taddHandle( booleans, function( elem, name, isXML ) {\n\t\t\tvar val;\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\t\tval.value :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t});\n\t}\n\n\treturn Sizzle;\n\n\t})( window );\n\n\n\n\tjQuery.find = Sizzle;\n\tjQuery.expr = Sizzle.selectors;\n\n\t// Deprecated\n\tjQuery.expr[ \":\" ] = jQuery.expr.pseudos;\n\tjQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\n\tjQuery.text = Sizzle.getText;\n\tjQuery.isXMLDoc = Sizzle.isXML;\n\tjQuery.contains = Sizzle.contains;\n\tjQuery.escapeSelector = Sizzle.escape;\n\n\n\n\n\tvar dir = function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\ttruncate = until !== undefined;\n\n\t\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t};\n\n\n\tvar siblings = function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t};\n\n\n\tvar rneedsContext = jQuery.expr.match.needsContext;\n\n\tvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\n\tvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n\t// Implement the identical functionality for filter and not\n\tfunction winnow( elements, qualifier, not ) {\n\t\tif ( jQuery.isFunction( qualifier ) ) {\n\t\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t\t} );\n\t\t}\n\n\t\t// Single element\n\t\tif ( qualifier.nodeType ) {\n\t\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\t\treturn ( elem === qualifier ) !== not;\n\t\t\t} );\n\t\t}\n\n\t\t// Arraylike of elements (jQuery, arguments, Array)\n\t\tif ( typeof qualifier !== \"string\" ) {\n\t\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t\t} );\n\t\t}\n\n\t\t// Simple selector that can be filtered directly, removing non-Elements\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\t// Complex selector, compare the two sets, removing non-Elements\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;\n\t\t} );\n\t}\n\n\tjQuery.filter = function( expr, elems, not ) {\n\t\tvar elem = elems[ 0 ];\n\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t\t}\n\n\t\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t} ) );\n\t};\n\n\tjQuery.fn.extend( {\n\t\tfind: function( selector ) {\n\t\t\tvar i, ret,\n\t\t\t\tlen = this.length,\n\t\t\t\tself = this;\n\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} ) );\n\t\t\t}\n\n\t\t\tret = this.pushStack( [] );\n\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t\t}\n\n\t\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t\t},\n\t\tfilter: function( selector ) {\n\t\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t\t},\n\t\tnot: function( selector ) {\n\t\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t\t},\n\t\tis: function( selector ) {\n\t\t\treturn !!winnow(\n\t\t\t\tthis,\n\n\t\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\t\tjQuery( selector ) :\n\t\t\t\t\tselector || [],\n\t\t\t\tfalse\n\t\t\t).length;\n\t\t}\n\t} );\n\n\n\t// Initialize a jQuery object\n\n\n\t// A central reference to the root jQuery(document)\n\tvar rootjQuery,\n\n\t\t// A simple way to check for HTML strings\n\t\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t\t// Strict HTML recognition (#11290: must start with <)\n\t\t// Shortcut simple #id case for speed\n\t\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\t\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\t\tvar match, elem;\n\n\t\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\t\tif ( !selector ) {\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\t// Method init() accepts an alternate rootjQuery\n\t\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\t\troot = root || rootjQuery;\n\n\t\t\t// Handle HTML strings\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t\t} else {\n\t\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t\t}\n\n\t\t\t\t// Match html or make sure no context is specified for #id\n\t\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t) );\n\n\t\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn this;\n\n\t\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\n\t\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t\t// HANDLE: $(expr, context)\n\t\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t\t} else {\n\t\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(DOMElement)\n\t\t\t} else if ( selector.nodeType ) {\n\t\t\t\tthis[ 0 ] = selector;\n\t\t\t\tthis.length = 1;\n\t\t\t\treturn this;\n\n\t\t\t// HANDLE: $(function)\n\t\t\t// Shortcut for document ready\n\t\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\t\treturn root.ready !== undefined ?\n\t\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\t\tselector( jQuery );\n\t\t\t}\n\n\t\t\treturn jQuery.makeArray( selector, this );\n\t\t};\n\n\t// Give the init function the jQuery prototype for later instantiation\n\tinit.prototype = jQuery.fn;\n\n\t// Initialize central reference\n\trootjQuery = jQuery( document );\n\n\n\tvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t\t// Methods guaranteed to produce a unique set when starting from a unique set\n\t\tguaranteedUnique = {\n\t\t\tchildren: true,\n\t\t\tcontents: true,\n\t\t\tnext: true,\n\t\t\tprev: true\n\t\t};\n\n\tjQuery.fn.extend( {\n\t\thas: function( target ) {\n\t\t\tvar targets = jQuery( target, this ),\n\t\t\t\tl = targets.length;\n\n\t\t\treturn this.filter( function() {\n\t\t\t\tvar i = 0;\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tclosest: function( selectors, context ) {\n\t\t\tvar cur,\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length,\n\t\t\t\tmatched = [],\n\t\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t\t// Positional selectors never match, since there's no _selection_ context\n\t\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t\t},\n\n\t\t// Determine the position of an element within the set\n\t\tindex: function( elem ) {\n\n\t\t\t// No argument, return index in parent\n\t\t\tif ( !elem ) {\n\t\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t\t}\n\n\t\t\t// Index in selector\n\t\t\tif ( typeof elem === \"string\" ) {\n\t\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t\t}\n\n\t\t\t// Locate the position of the desired element\n\t\t\treturn indexOf.call( this,\n\n\t\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t\t);\n\t\t},\n\n\t\tadd: function( selector, context ) {\n\t\t\treturn this.pushStack(\n\t\t\t\tjQuery.uniqueSort(\n\t\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t\t)\n\t\t\t);\n\t\t},\n\n\t\taddBack: function( selector ) {\n\t\t\treturn this.add( selector == null ?\n\t\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t\t);\n\t\t}\n\t} );\n\n\tfunction sibling( cur, dir ) {\n\t\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\t\treturn cur;\n\t}\n\n\tjQuery.each( {\n\t\tparent: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t\t},\n\t\tparents: function( elem ) {\n\t\t\treturn dir( elem, \"parentNode\" );\n\t\t},\n\t\tparentsUntil: function( elem, i, until ) {\n\t\t\treturn dir( elem, \"parentNode\", until );\n\t\t},\n\t\tnext: function( elem ) {\n\t\t\treturn sibling( elem, \"nextSibling\" );\n\t\t},\n\t\tprev: function( elem ) {\n\t\t\treturn sibling( elem, \"previousSibling\" );\n\t\t},\n\t\tnextAll: function( elem ) {\n\t\t\treturn dir( elem, \"nextSibling\" );\n\t\t},\n\t\tprevAll: function( elem ) {\n\t\t\treturn dir( elem, \"previousSibling\" );\n\t\t},\n\t\tnextUntil: function( elem, i, until ) {\n\t\t\treturn dir( elem, \"nextSibling\", until );\n\t\t},\n\t\tprevUntil: function( elem, i, until ) {\n\t\t\treturn dir( elem, \"previousSibling\", until );\n\t\t},\n\t\tsiblings: function( elem ) {\n\t\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t\t},\n\t\tchildren: function( elem ) {\n\t\t\treturn siblings( elem.firstChild );\n\t\t},\n\t\tcontents: function( elem ) {\n\t\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t\t}\n\t}, function( name, fn ) {\n\t\tjQuery.fn[ name ] = function( until, selector ) {\n\t\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\t\tselector = until;\n\t\t\t}\n\n\t\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t\t}\n\n\t\t\tif ( this.length > 1 ) {\n\n\t\t\t\t// Remove duplicates\n\t\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t\t}\n\n\t\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\t\tmatched.reverse();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this.pushStack( matched );\n\t\t};\n\t} );\n\tvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n\t// Convert String-formatted options into Object-formatted ones\n\tfunction createOptions( options ) {\n\t\tvar object = {};\n\t\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\t\tobject[ flag ] = true;\n\t\t} );\n\t\treturn object;\n\t}\n\n\t/*\n\t * Create a callback list using the following parameters:\n\t *\n\t *\toptions: an optional list of space-separated options that will change how\n\t *\t\t\tthe callback list behaves or a more traditional option object\n\t *\n\t * By default a callback list will act like an event callback list and can be\n\t * \"fired\" multiple times.\n\t *\n\t * Possible options:\n\t *\n\t *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n\t *\n\t *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n\t *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n\t *\t\t\t\t\tvalues (like a Deferred)\n\t *\n\t *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n\t *\n\t *\tstopOnFalse:\tinterrupt callings when a callback returns false\n\t *\n\t */\n\tjQuery.Callbacks = function( options ) {\n\n\t\t// Convert options from String-formatted to Object-formatted if needed\n\t\t// (we check in cache first)\n\t\toptions = typeof options === \"string\" ?\n\t\t\tcreateOptions( options ) :\n\t\t\tjQuery.extend( {}, options );\n\n\t\tvar // Flag to know if list is currently firing\n\t\t\tfiring,\n\n\t\t\t// Last fire value for non-forgettable lists\n\t\t\tmemory,\n\n\t\t\t// Flag to know if list was already fired\n\t\t\tfired,\n\n\t\t\t// Flag to prevent firing\n\t\t\tlocked,\n\n\t\t\t// Actual callback list\n\t\t\tlist = [],\n\n\t\t\t// Queue of execution data for repeatable lists\n\t\t\tqueue = [],\n\n\t\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\t\tfiringIndex = -1,\n\n\t\t\t// Fire callbacks\n\t\t\tfire = function() {\n\n\t\t\t\t// Enforce single-firing\n\t\t\t\tlocked = options.once;\n\n\t\t\t\t// Execute callbacks for all pending executions,\n\t\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\t\tfired = firing = true;\n\t\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\t\tmemory = queue.shift();\n\t\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Forget the data if we're done with it\n\t\t\t\tif ( !options.memory ) {\n\t\t\t\t\tmemory = false;\n\t\t\t\t}\n\n\t\t\t\tfiring = false;\n\n\t\t\t\t// Clean up if we're done firing for good\n\t\t\t\tif ( locked ) {\n\n\t\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\t\tif ( memory ) {\n\t\t\t\t\t\tlist = [];\n\n\t\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlist = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Actual Callbacks object\n\t\t\tself = {\n\n\t\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\t\tadd: function() {\n\t\t\t\t\tif ( list ) {\n\n\t\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\t\tif ( jQuery.isFunction( arg ) ) {\n\t\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if ( arg && arg.length && jQuery.type( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\t\tfire();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Remove a callback from the list\n\t\t\t\tremove: function() {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Check if a given callback is in the list.\n\t\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\t\thas: function( fn ) {\n\t\t\t\t\treturn fn ?\n\t\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\t\tlist.length > 0;\n\t\t\t\t},\n\n\t\t\t\t// Remove all callbacks from the list\n\t\t\t\tempty: function() {\n\t\t\t\t\tif ( list ) {\n\t\t\t\t\t\tlist = [];\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Disable .fire and .add\n\t\t\t\t// Abort any current/pending executions\n\t\t\t\t// Clear all callbacks and values\n\t\t\t\tdisable: function() {\n\t\t\t\t\tlocked = queue = [];\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tdisabled: function() {\n\t\t\t\t\treturn !list;\n\t\t\t\t},\n\n\t\t\t\t// Disable .fire\n\t\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t\t// Abort any pending executions\n\t\t\t\tlock: function() {\n\t\t\t\t\tlocked = queue = [];\n\t\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tlocked: function() {\n\t\t\t\t\treturn !!locked;\n\t\t\t\t},\n\n\t\t\t\t// Call all callbacks with the given context and arguments\n\t\t\t\tfireWith: function( context, args ) {\n\t\t\t\t\tif ( !locked ) {\n\t\t\t\t\t\targs = args || [];\n\t\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\t\tqueue.push( args );\n\t\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\t\tfire();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Call all the callbacks with the given arguments\n\t\t\t\tfire: function() {\n\t\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// To know if the callbacks have already been called at least once\n\t\t\t\tfired: function() {\n\t\t\t\t\treturn !!fired;\n\t\t\t\t}\n\t\t\t};\n\n\t\treturn self;\n\t};\n\n\n\tfunction Identity( v ) {\n\t\treturn v;\n\t}\n\tfunction Thrower( ex ) {\n\t\tthrow ex;\n\t}\n\n\tfunction adoptValue( value, resolve, reject ) {\n\t\tvar method;\n\n\t\ttry {\n\n\t\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\t\tif ( value && jQuery.isFunction( ( method = value.promise ) ) ) {\n\t\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t\t// Other thenables\n\t\t\t} else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {\n\t\t\t\tmethod.call( value, resolve, reject );\n\n\t\t\t// Other non-thenables\n\t\t\t} else {\n\n\t\t\t\t// Support: Android 4.0 only\n\t\t\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\t\t\tresolve.call( undefined, value );\n\t\t\t}\n\n\t\t// For Promises/A+, convert exceptions into rejections\n\t\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t\t// Deferred#then to conditionally suppress rejection.\n\t\t} catch ( value ) {\n\n\t\t\t// Support: Android 4.0 only\n\t\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\t\treject.call( undefined, value );\n\t\t}\n\t}\n\n\tjQuery.extend( {\n\n\t\tDeferred: function( func ) {\n\t\t\tvar tuples = [\n\n\t\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t\t],\n\t\t\t\tstate = \"pending\",\n\t\t\t\tpromise = {\n\t\t\t\t\tstate: function() {\n\t\t\t\t\t\treturn state;\n\t\t\t\t\t},\n\t\t\t\t\talways: function() {\n\t\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t},\n\t\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t\t},\n\n\t\t\t\t\t// Keep pipe for back-compat\n\t\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\n\t\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\tfns = null;\n\t\t\t\t\t\t} ).promise();\n\t\t\t\t\t},\n\t\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\t\tif ( jQuery.isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\twindow.setTimeout( process );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\t\tjQuery.isFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\t\tjQuery.isFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\t\tjQuery.isFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} ).promise();\n\t\t\t\t\t},\n\n\t\t\t\t\t// Get a promise for this deferred\n\t\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdeferred = {};\n\n\t\t\t// Add list-specific methods\n\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\tvar list = tuple[ 2 ],\n\t\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t\t// promise.progress = list.add\n\t\t\t\t// promise.done = list.add\n\t\t\t\t// promise.fail = list.add\n\t\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t\t// Handle state\n\t\t\t\tif ( stateString ) {\n\t\t\t\t\tlist.add(\n\t\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\t\ttuples[ 0 ][ 2 ].lock\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// progress_handlers.fire\n\t\t\t\t// fulfilled_handlers.fire\n\t\t\t\t// rejected_handlers.fire\n\t\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t};\n\n\t\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t\t} );\n\n\t\t\t// Make the deferred a promise\n\t\t\tpromise.promise( deferred );\n\n\t\t\t// Call given func if any\n\t\t\tif ( func ) {\n\t\t\t\tfunc.call( deferred, deferred );\n\t\t\t}\n\n\t\t\t// All done!\n\t\t\treturn deferred;\n\t\t},\n\n\t\t// Deferred helper\n\t\twhen: function( singleValue ) {\n\t\t\tvar\n\n\t\t\t\t// count of uncompleted subordinates\n\t\t\t\tremaining = arguments.length,\n\n\t\t\t\t// count of unprocessed arguments\n\t\t\t\ti = remaining,\n\n\t\t\t\t// subordinate fulfillment data\n\t\t\t\tresolveContexts = Array( i ),\n\t\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t\t// the master Deferred\n\t\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t\t// subordinate callback factory\n\t\t\t\tupdateFunc = function( i ) {\n\t\t\t\t\treturn function( value ) {\n\t\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\t\tif ( remaining <= 1 ) {\n\t\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject );\n\n\t\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\t\tjQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\t\treturn master.then();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\t\twhile ( i-- ) {\n\t\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t\t}\n\n\t\t\treturn master.promise();\n\t\t}\n\t} );\n\n\n\t// These usually indicate a programmer mistake during development,\n\t// warn about them ASAP rather than swallowing them by default.\n\tvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\n\tjQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t\t// Support: IE 8 - 9 only\n\t\t// Console exists when dev tools are open, which can happen at any time\n\t\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t\t}\n\t};\n\n\n\n\n\tjQuery.readyException = function( error ) {\n\t\twindow.setTimeout( function() {\n\t\t\tthrow error;\n\t\t} );\n\t};\n\n\n\n\n\t// The deferred used on DOM ready\n\tvar readyList = jQuery.Deferred();\n\n\tjQuery.fn.ready = function( fn ) {\n\n\t\treadyList\n\t\t\t.then( fn )\n\n\t\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t\t// happens at the time of error handling instead of callback\n\t\t\t// registration.\n\t\t\t.catch( function( error ) {\n\t\t\t\tjQuery.readyException( error );\n\t\t\t} );\n\n\t\treturn this;\n\t};\n\n\tjQuery.extend( {\n\n\t\t// Is the DOM ready to be used? Set to true once it occurs.\n\t\tisReady: false,\n\n\t\t// A counter to track how many items to wait for before\n\t\t// the ready event fires. See #6781\n\t\treadyWait: 1,\n\n\t\t// Hold (or release) the ready event\n\t\tholdReady: function( hold ) {\n\t\t\tif ( hold ) {\n\t\t\t\tjQuery.readyWait++;\n\t\t\t} else {\n\t\t\t\tjQuery.ready( true );\n\t\t\t}\n\t\t},\n\n\t\t// Handle when the DOM is ready\n\t\tready: function( wait ) {\n\n\t\t\t// Abort if there are pending holds or we're already ready\n\t\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Remember that the DOM is ready\n\t\t\tjQuery.isReady = true;\n\n\t\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If there are functions bound, to execute\n\t\t\treadyList.resolveWith( document, [ jQuery ] );\n\t\t}\n\t} );\n\n\tjQuery.ready.then = readyList.then;\n\n\t// The ready event handler and self cleanup method\n\tfunction completed() {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\t\twindow.removeEventListener( \"load\", completed );\n\t\tjQuery.ready();\n\t}\n\n\t// Catch cases where $(document).ready() is called\n\t// after the browser event has already occurred.\n\t// Support: IE <=9 - 10 only\n\t// Older IE sometimes signals \"interactive\" too soon\n\tif ( document.readyState === \"complete\" ||\n\t\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\twindow.setTimeout( jQuery.ready );\n\n\t} else {\n\n\t\t// Use the handy event callback\n\t\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t\t// A fallback to window.onload, that will always work\n\t\twindow.addEventListener( \"load\", completed );\n\t}\n\n\n\n\n\t// Multifunctional method to get and set values of a collection\n\t// The value/s can optionally be executed if it's a function\n\tvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\t\tvar i = 0,\n\t\t\tlen = elems.length,\n\t\t\tbulk = key == null;\n\n\t\t// Sets many values\n\t\tif ( jQuery.type( key ) === \"object\" ) {\n\t\t\tchainable = true;\n\t\t\tfor ( i in key ) {\n\t\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t\t}\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\tchainable = true;\n\n\t\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\t\traw = true;\n\t\t\t}\n\n\t\t\tif ( bulk ) {\n\n\t\t\t\t// Bulk operations run against the entire set\n\t\t\t\tif ( raw ) {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\n\t\t\t\t// ...except when executing function values\n\t\t\t\t} else {\n\t\t\t\t\tbulk = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tfn(\n\t\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\t\tvalue :\n\t\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( chainable ) {\n\t\t\treturn elems;\n\t\t}\n\n\t\t// Gets\n\t\tif ( bulk ) {\n\t\t\treturn fn.call( elems );\n\t\t}\n\n\t\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n\t};\n\tvar acceptData = function( owner ) {\n\n\t\t// Accepts only:\n\t\t//  - Node\n\t\t//    - Node.ELEMENT_NODE\n\t\t//    - Node.DOCUMENT_NODE\n\t\t//  - Object\n\t\t//    - Any\n\t\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n\t};\n\n\n\n\n\tfunction Data() {\n\t\tthis.expando = jQuery.expando + Data.uid++;\n\t}\n\n\tData.uid = 1;\n\n\tData.prototype = {\n\n\t\tcache: function( owner ) {\n\n\t\t\t// Check if the owner object already has a cache\n\t\t\tvar value = owner[ this.expando ];\n\n\t\t\t// If not, create one\n\t\t\tif ( !value ) {\n\t\t\t\tvalue = {};\n\n\t\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t\t// but we should not, see #8335.\n\t\t\t\t// Always return an empty object.\n\t\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t\t// use plain assignment\n\t\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t\t// deleted when data is removed\n\t\t\t\t\t} else {\n\t\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn value;\n\t\t},\n\t\tset: function( owner, data, value ) {\n\t\t\tvar prop,\n\t\t\t\tcache = this.cache( owner );\n\n\t\t\t// Handle: [ owner, key, value ] args\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\tif ( typeof data === \"string\" ) {\n\t\t\t\tcache[ jQuery.camelCase( data ) ] = value;\n\n\t\t\t// Handle: [ owner, { properties } ] args\n\t\t\t} else {\n\n\t\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ jQuery.camelCase( prop ) ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn cache;\n\t\t},\n\t\tget: function( owner, key ) {\n\t\t\treturn key === undefined ?\n\t\t\t\tthis.cache( owner ) :\n\n\t\t\t\t// Always use camelCase key (gh-2257)\n\t\t\t\towner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];\n\t\t},\n\t\taccess: function( owner, key, value ) {\n\n\t\t\t// In cases where either:\n\t\t\t//\n\t\t\t//   1. No key was specified\n\t\t\t//   2. A string key was specified, but no value provided\n\t\t\t//\n\t\t\t// Take the \"read\" path and allow the get method to determine\n\t\t\t// which value to return, respectively either:\n\t\t\t//\n\t\t\t//   1. The entire cache object\n\t\t\t//   2. The data stored at the key\n\t\t\t//\n\t\t\tif ( key === undefined ||\n\t\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\t\treturn this.get( owner, key );\n\t\t\t}\n\n\t\t\t// When the key is not a string, or both a key and value\n\t\t\t// are specified, set or extend (existing objects) with either:\n\t\t\t//\n\t\t\t//   1. An object of properties\n\t\t\t//   2. A key and value\n\t\t\t//\n\t\t\tthis.set( owner, key, value );\n\n\t\t\t// Since the \"set\" path can have two possible entry points\n\t\t\t// return the expected data based on which path was taken[*]\n\t\t\treturn value !== undefined ? value : key;\n\t\t},\n\t\tremove: function( owner, key ) {\n\t\t\tvar i,\n\t\t\t\tcache = owner[ this.expando ];\n\n\t\t\tif ( cache === undefined ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( key !== undefined ) {\n\n\t\t\t\t// Support array or space separated string of keys\n\t\t\t\tif ( jQuery.isArray( key ) ) {\n\n\t\t\t\t\t// If key is an array of keys...\n\t\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\t\tkey = key.map( jQuery.camelCase );\n\t\t\t\t} else {\n\t\t\t\t\tkey = jQuery.camelCase( key );\n\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tkey = key in cache ?\n\t\t\t\t\t\t[ key ] :\n\t\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t\t}\n\n\t\t\t\ti = key.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove the expando if there's no more data\n\t\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t\t// Support: Chrome <=35 - 45\n\t\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t\t} else {\n\t\t\t\t\tdelete owner[ this.expando ];\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\thasData: function( owner ) {\n\t\t\tvar cache = owner[ this.expando ];\n\t\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t\t}\n\t};\n\tvar dataPriv = new Data();\n\n\tvar dataUser = new Data();\n\n\n\n\t//\tImplementation Summary\n\t//\n\t//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n\t//\t2. Improve the module's maintainability by reducing the storage\n\t//\t\tpaths to a single mechanism.\n\t//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n\t//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n\t//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n\t//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\n\tvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\t\trmultiDash = /[A-Z]/g;\n\n\tfunction getData( data ) {\n\t\tif ( data === \"true\" ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( data === \"false\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( data === \"null\" ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Only convert to a number if it doesn't change the string\n\t\tif ( data === +data + \"\" ) {\n\t\t\treturn +data;\n\t\t}\n\n\t\tif ( rbrace.test( data ) ) {\n\t\t\treturn JSON.parse( data );\n\t\t}\n\n\t\treturn data;\n\t}\n\n\tfunction dataAttr( elem, key, data ) {\n\t\tvar name;\n\n\t\t// If nothing was found internally, try to fetch any\n\t\t// data from the HTML5 data-* attribute\n\t\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\t\tdata = elem.getAttribute( name );\n\n\t\t\tif ( typeof data === \"string\" ) {\n\t\t\t\ttry {\n\t\t\t\t\tdata = getData( data );\n\t\t\t\t} catch ( e ) {}\n\n\t\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\t\tdataUser.set( elem, key, data );\n\t\t\t} else {\n\t\t\t\tdata = undefined;\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t}\n\n\tjQuery.extend( {\n\t\thasData: function( elem ) {\n\t\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t\t},\n\n\t\tdata: function( elem, name, data ) {\n\t\t\treturn dataUser.access( elem, name, data );\n\t\t},\n\n\t\tremoveData: function( elem, name ) {\n\t\t\tdataUser.remove( elem, name );\n\t\t},\n\n\t\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t\t// with direct calls to dataPriv methods, these can be deprecated.\n\t\t_data: function( elem, name, data ) {\n\t\t\treturn dataPriv.access( elem, name, data );\n\t\t},\n\n\t\t_removeData: function( elem, name ) {\n\t\t\tdataPriv.remove( elem, name );\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tdata: function( key, value ) {\n\t\t\tvar i, name, data,\n\t\t\t\telem = this[ 0 ],\n\t\t\t\tattrs = elem && elem.attributes;\n\n\t\t\t// Gets all values\n\t\t\tif ( key === undefined ) {\n\t\t\t\tif ( this.length ) {\n\t\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\t\ti = attrs.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\t// Sets multiple values\n\t\t\tif ( typeof key === \"object\" ) {\n\t\t\t\treturn this.each( function() {\n\t\t\t\t\tdataUser.set( this, key );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn access( this, function( value ) {\n\t\t\t\tvar data;\n\n\t\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\t\treturn data;\n\t\t\t\t\t}\n\n\t\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Set the data...\n\t\t\t\tthis.each( function() {\n\n\t\t\t\t\t// We always store the camelCased key\n\t\t\t\t\tdataUser.set( this, key, value );\n\t\t\t\t} );\n\t\t\t}, null, value, arguments.length > 1, null, true );\n\t\t},\n\n\t\tremoveData: function( key ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.remove( this, key );\n\t\t\t} );\n\t\t}\n\t} );\n\n\n\tjQuery.extend( {\n\t\tqueue: function( elem, type, data ) {\n\t\t\tvar queue;\n\n\t\t\tif ( elem ) {\n\t\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tqueue.push( data );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn queue || [];\n\t\t\t}\n\t\t},\n\n\t\tdequeue: function( elem, type ) {\n\t\t\ttype = type || \"fx\";\n\n\t\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\t\tstartLength = queue.length,\n\t\t\t\tfn = queue.shift(),\n\t\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\t\tnext = function() {\n\t\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t\t};\n\n\t\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\t\tif ( fn === \"inprogress\" ) {\n\t\t\t\tfn = queue.shift();\n\t\t\t\tstartLength--;\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\n\t\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t\t// automatically dequeued\n\t\t\t\tif ( type === \"fx\" ) {\n\t\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t\t}\n\n\t\t\t\t// Clear up the last queue stop function\n\t\t\t\tdelete hooks.stop;\n\t\t\t\tfn.call( elem, next, hooks );\n\t\t\t}\n\n\t\t\tif ( !startLength && hooks ) {\n\t\t\t\thooks.empty.fire();\n\t\t\t}\n\t\t},\n\n\t\t// Not public - generate a queueHooks object, or return the current one\n\t\t_queueHooks: function( elem, type ) {\n\t\t\tvar key = type + \"queueHooks\";\n\t\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t\t} )\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tqueue: function( type, data ) {\n\t\t\tvar setter = 2;\n\n\t\t\tif ( typeof type !== \"string\" ) {\n\t\t\t\tdata = type;\n\t\t\t\ttype = \"fx\";\n\t\t\t\tsetter--;\n\t\t\t}\n\n\t\t\tif ( arguments.length < setter ) {\n\t\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t\t}\n\n\t\t\treturn data === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function() {\n\t\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t},\n\t\tdequeue: function( type ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t} );\n\t\t},\n\t\tclearQueue: function( type ) {\n\t\t\treturn this.queue( type || \"fx\", [] );\n\t\t},\n\n\t\t// Get a promise resolved when queues of a certain type\n\t\t// are emptied (fx is the type by default)\n\t\tpromise: function( type, obj ) {\n\t\t\tvar tmp,\n\t\t\t\tcount = 1,\n\t\t\t\tdefer = jQuery.Deferred(),\n\t\t\t\telements = this,\n\t\t\t\ti = this.length,\n\t\t\t\tresolve = function() {\n\t\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\tif ( typeof type !== \"string\" ) {\n\t\t\t\tobj = type;\n\t\t\t\ttype = undefined;\n\t\t\t}\n\t\t\ttype = type || \"fx\";\n\n\t\t\twhile ( i-- ) {\n\t\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\t\tcount++;\n\t\t\t\t\ttmp.empty.add( resolve );\n\t\t\t\t}\n\t\t\t}\n\t\t\tresolve();\n\t\t\treturn defer.promise( obj );\n\t\t}\n\t} );\n\tvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\n\tvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\n\tvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\n\tvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t\t// in that case, element will be second argument\n\t\t\telem = el || elem;\n\n\t\t\t// Inline style trumps all\n\t\t\treturn elem.style.display === \"none\" ||\n\t\t\t\telem.style.display === \"\" &&\n\n\t\t\t\t// Otherwise, check computed style\n\t\t\t\t// Support: Firefox <=43 - 45\n\t\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t\t// in the document.\n\t\t\t\tjQuery.contains( elem.ownerDocument, elem ) &&\n\n\t\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t\t};\n\n\tvar swap = function( elem, options, callback, args ) {\n\t\tvar ret, name,\n\t\t\told = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.apply( elem, args || [] );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t};\n\n\n\n\n\tfunction adjustCSS( elem, prop, valueParts, tween ) {\n\t\tvar adjusted,\n\t\t\tscale = 1,\n\t\t\tmaxIterations = 20,\n\t\t\tcurrentValue = tween ?\n\t\t\t\tfunction() {\n\t\t\t\t\treturn tween.cur();\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t\t},\n\t\t\tinitial = currentValue(),\n\t\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\tinitialInUnit = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\t\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t\t// Trust units reported by jQuery.css\n\t\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t\t// Make sure we update the tween properties later on\n\t\t\tvalueParts = valueParts || [];\n\n\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\tinitialInUnit = +initial || 1;\n\n\t\t\tdo {\n\n\t\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t// Adjust and apply\n\t\t\t\tinitialInUnit = initialInUnit / scale;\n\t\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t// Break the loop if scale is unchanged or perfect, or if we've just had enough.\n\t\t\t} while (\n\t\t\t\tscale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations\n\t\t\t);\n\t\t}\n\n\t\tif ( valueParts ) {\n\t\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t\t// Apply relative offset (+=/-=) if specified\n\t\t\tadjusted = valueParts[ 1 ] ?\n\t\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t\t+valueParts[ 2 ];\n\t\t\tif ( tween ) {\n\t\t\t\ttween.unit = unit;\n\t\t\t\ttween.start = initialInUnit;\n\t\t\t\ttween.end = adjusted;\n\t\t\t}\n\t\t}\n\t\treturn adjusted;\n\t}\n\n\n\tvar defaultDisplayMap = {};\n\n\tfunction getDefaultDisplay( elem ) {\n\t\tvar temp,\n\t\t\tdoc = elem.ownerDocument,\n\t\t\tnodeName = elem.nodeName,\n\t\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\t\tif ( display ) {\n\t\t\treturn display;\n\t\t}\n\n\t\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\t\tdisplay = jQuery.css( temp, \"display\" );\n\n\t\ttemp.parentNode.removeChild( temp );\n\n\t\tif ( display === \"none\" ) {\n\t\t\tdisplay = \"block\";\n\t\t}\n\t\tdefaultDisplayMap[ nodeName ] = display;\n\n\t\treturn display;\n\t}\n\n\tfunction showHide( elements, show ) {\n\t\tvar display, elem,\n\t\t\tvalues = [],\n\t\t\tindex = 0,\n\t\t\tlength = elements.length;\n\n\t\t// Determine new display value for elements that need to change\n\t\tfor ( ; index < length; index++ ) {\n\t\t\telem = elements[ index ];\n\t\t\tif ( !elem.style ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdisplay = elem.style.display;\n\t\t\tif ( show ) {\n\n\t\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t\t// inline or about-to-be-restored)\n\t\t\t\tif ( display === \"none\" ) {\n\t\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( display !== \"none\" ) {\n\t\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t\t// Remember what we're overwriting\n\t\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Set the display of the elements in a second loop to avoid constant reflow\n\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\tif ( values[ index ] != null ) {\n\t\t\t\telements[ index ].style.display = values[ index ];\n\t\t\t}\n\t\t}\n\n\t\treturn elements;\n\t}\n\n\tjQuery.fn.extend( {\n\t\tshow: function() {\n\t\t\treturn showHide( this, true );\n\t\t},\n\t\thide: function() {\n\t\t\treturn showHide( this );\n\t\t},\n\t\ttoggle: function( state ) {\n\t\t\tif ( typeof state === \"boolean\" ) {\n\t\t\t\treturn state ? this.show() : this.hide();\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\t\tjQuery( this ).show();\n\t\t\t\t} else {\n\t\t\t\t\tjQuery( this ).hide();\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t} );\n\tvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\n\tvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]+)/i );\n\n\tvar rscriptType = ( /^$|\\/(?:java|ecma)script/i );\n\n\n\n\t// We have to close these tags to support XHTML (#13200)\n\tvar wrapMap = {\n\n\t\t// Support: IE <=9 only\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\t// XHTML parsers do not magically insert elements in the\n\t\t// same way that tag soup parsers do. So we cannot shorten\n\t\t// this by omitting <tbody> or other required elements.\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n\t// Support: IE <=9 only\n\twrapMap.optgroup = wrapMap.option;\n\n\twrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\n\twrapMap.th = wrapMap.td;\n\n\n\tfunction getAll( context, tag ) {\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\t\tvar ret;\n\n\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t\t} else {\n\t\t\tret = [];\n\t\t}\n\n\t\tif ( tag === undefined || tag && jQuery.nodeName( context, tag ) ) {\n\t\t\treturn jQuery.merge( [ context ], ret );\n\t\t}\n\n\t\treturn ret;\n\t}\n\n\n\t// Mark scripts as having already been evaluated\n\tfunction setGlobalEval( elems, refElements ) {\n\t\tvar i = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tdataPriv.set(\n\t\t\t\telems[ i ],\n\t\t\t\t\"globalEval\",\n\t\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t\t);\n\t\t}\n\t}\n\n\n\tvar rhtml = /<|&#?\\w+;/;\n\n\tfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [],\n\t\t\ti = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\n\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t\t// Skip elements already in the context collection (trac-4087)\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\t\tif ( ignored ) {\n\t\t\t\t\tignored.push( elem );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t}\n\n\n\t( function() {\n\t\tvar fragment = document.createDocumentFragment(),\n\t\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\t\tinput = document.createElement( \"input\" );\n\n\t\t// Support: Android 4.0 - 4.3 only\n\t\t// Check state lost if the name is set (#11217)\n\t\t// Support: Windows Web Apps (WWA)\n\t\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\t\tinput.setAttribute( \"type\", \"radio\" );\n\t\tinput.setAttribute( \"checked\", \"checked\" );\n\t\tinput.setAttribute( \"name\", \"t\" );\n\n\t\tdiv.appendChild( input );\n\n\t\t// Support: Android <=4.1 only\n\t\t// Older WebKit doesn't clone checked state correctly in fragments\n\t\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t\t// Support: IE <=11 only\n\t\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\t\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\t\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\t} )();\n\tvar documentElement = document.documentElement;\n\n\n\n\tvar\n\t\trkeyEvent = /^key/,\n\t\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\t\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\n\tfunction returnTrue() {\n\t\treturn true;\n\t}\n\n\tfunction returnFalse() {\n\t\treturn false;\n\t}\n\n\t// Support: IE <=9 only\n\t// See #13393 for more info\n\tfunction safeActiveElement() {\n\t\ttry {\n\t\t\treturn document.activeElement;\n\t\t} catch ( err ) { }\n\t}\n\n\tfunction on( elem, types, selector, data, fn, one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn elem;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn elem;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn elem.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t} );\n\t}\n\n\t/*\n\t * Helper functions for managing events -- not part of the public interface.\n\t * Props to Dean Edwards' addEvent library for many of the ideas.\n\t */\n\tjQuery.event = {\n\n\t\tglobal: {},\n\n\t\tadd: function( elem, types, handler, data, selector ) {\n\n\t\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\t\tevents, t, handleObj,\n\t\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\t\telemData = dataPriv.get( elem );\n\n\t\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\t\tif ( !elemData ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\t\tif ( handler.handler ) {\n\t\t\t\thandleObjIn = handler;\n\t\t\t\thandler = handleObjIn.handler;\n\t\t\t\tselector = handleObjIn.selector;\n\t\t\t}\n\n\t\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\t\tif ( selector ) {\n\t\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t\t}\n\n\t\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\t\tif ( !handler.guid ) {\n\t\t\t\thandler.guid = jQuery.guid++;\n\t\t\t}\n\n\t\t\t// Init the element's event structure and main handler, if this is the first\n\t\t\tif ( !( events = elemData.events ) ) {\n\t\t\t\tevents = elemData.events = {};\n\t\t\t}\n\t\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Handle multiple events separated by a space\n\t\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\t\tt = types.length;\n\t\t\twhile ( t-- ) {\n\t\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\t\ttype = origType = tmp[ 1 ];\n\t\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\t\tif ( !type ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t\t// Update special based on newly reset type\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t\t// handleObj is passed to all event handlers\n\t\t\t\thandleObj = jQuery.extend( {\n\t\t\t\t\ttype: type,\n\t\t\t\t\torigType: origType,\n\t\t\t\t\tdata: data,\n\t\t\t\t\thandler: handler,\n\t\t\t\t\tguid: handler.guid,\n\t\t\t\t\tselector: selector,\n\t\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t\t}, handleObjIn );\n\n\t\t\t\t// Init the event handler queue if we're the first\n\t\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\t\tif ( !special.setup ||\n\t\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( special.add ) {\n\t\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Add to the element's handler list, delegates in front\n\t\t\t\tif ( selector ) {\n\t\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t\t} else {\n\t\t\t\t\thandlers.push( handleObj );\n\t\t\t\t}\n\n\t\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\t\tjQuery.event.global[ type ] = true;\n\t\t\t}\n\n\t\t},\n\n\t\t// Detach an event or set of events from an element\n\t\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\t\tvar j, origCount, tmp,\n\t\t\t\tevents, t, handleObj,\n\t\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Once for each type.namespace in types; type may be omitted\n\t\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\t\tt = types.length;\n\t\t\twhile ( t-- ) {\n\t\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\t\ttype = origType = tmp[ 1 ];\n\t\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\t\tif ( !type ) {\n\t\t\t\t\tfor ( type in events ) {\n\t\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\t\thandlers = events[ type ] || [];\n\t\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t\t// Remove matching events\n\t\t\t\torigCount = j = handlers.length;\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t\t}\n\n\t\t\t\t\tdelete events[ type ];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove data and the expando if it's no longer used\n\t\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t\t}\n\t\t},\n\n\t\tdispatch: function( nativeEvent ) {\n\n\t\t\t// Make a writable jQuery.Event from the native event object\n\t\t\tvar event = jQuery.event.fix( nativeEvent );\n\n\t\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\t\targs = new Array( arguments.length ),\n\t\t\t\thandlers = ( dataPriv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\t\targs[ 0 ] = event;\n\n\t\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\t\targs[ i ] = arguments[ i ];\n\t\t\t}\n\n\t\t\tevent.delegateTarget = this;\n\n\t\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Determine handlers\n\t\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\t\ti = 0;\n\t\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\t\tj = 0;\n\t\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\t\tif ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Call the postDispatch hook for the mapped type\n\t\t\tif ( special.postDispatch ) {\n\t\t\t\tspecial.postDispatch.call( this, event );\n\t\t\t}\n\n\t\t\treturn event.result;\n\t\t},\n\n\t\thandlers: function( event, handlers ) {\n\t\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\t\thandlerQueue = [],\n\t\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\t\tcur = event.target;\n\n\t\t\t// Find delegate handlers\n\t\t\tif ( delegateCount &&\n\n\t\t\t\t// Support: IE <=9\n\t\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\t\tcur.nodeType &&\n\n\t\t\t\t// Support: Firefox <=42\n\t\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t\t// Support: IE 11 only\n\t\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the remaining (directly-bound) handlers\n\t\t\tcur = this;\n\t\t\tif ( delegateCount < handlers.length ) {\n\t\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t\t}\n\n\t\t\treturn handlerQueue;\n\t\t},\n\n\t\taddProp: function( name, hook ) {\n\t\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\n\t\t\t\tget: jQuery.isFunction( hook ) ?\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t\t}\n\t\t\t\t\t} :\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\n\t\t\t\tset: function( value ) {\n\t\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\t\tenumerable: true,\n\t\t\t\t\t\tconfigurable: true,\n\t\t\t\t\t\twritable: true,\n\t\t\t\t\t\tvalue: value\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tfix: function( originalEvent ) {\n\t\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\t\toriginalEvent :\n\t\t\t\tnew jQuery.Event( originalEvent );\n\t\t},\n\n\t\tspecial: {\n\t\t\tload: {\n\n\t\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\t\tnoBubble: true\n\t\t\t},\n\t\t\tfocus: {\n\n\t\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\t\ttrigger: function() {\n\t\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdelegateType: \"focusin\"\n\t\t\t},\n\t\t\tblur: {\n\t\t\t\ttrigger: function() {\n\t\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\t\tthis.blur();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tdelegateType: \"focusout\"\n\t\t\t},\n\t\t\tclick: {\n\n\t\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\t\ttrigger: function() {\n\t\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\t\tthis.click();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t\t_default: function( event ) {\n\t\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tbeforeunload: {\n\t\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t\t// Support: Firefox 20+\n\t\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tjQuery.removeEvent = function( elem, type, handle ) {\n\n\t\t// This \"if\" is needed for plain objects\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle );\n\t\t}\n\t};\n\n\tjQuery.Event = function( src, props ) {\n\n\t\t// Allow instantiation without the 'new' keyword\n\t\tif ( !( this instanceof jQuery.Event ) ) {\n\t\t\treturn new jQuery.Event( src, props );\n\t\t}\n\n\t\t// Event object\n\t\tif ( src && src.type ) {\n\t\t\tthis.originalEvent = src;\n\t\t\tthis.type = src.type;\n\n\t\t\t// Events bubbling up the document may have been marked as prevented\n\t\t\t// by a handler lower down the tree; reflect the correct value.\n\t\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\t\tsrc.returnValue === false ?\n\t\t\t\treturnTrue :\n\t\t\t\treturnFalse;\n\n\t\t\t// Create target properties\n\t\t\t// Support: Safari <=6 - 7 only\n\t\t\t// Target should not be a text node (#504, #13143)\n\t\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\t\tsrc.target.parentNode :\n\t\t\t\tsrc.target;\n\n\t\t\tthis.currentTarget = src.currentTarget;\n\t\t\tthis.relatedTarget = src.relatedTarget;\n\n\t\t// Event type\n\t\t} else {\n\t\t\tthis.type = src;\n\t\t}\n\n\t\t// Put explicitly provided properties onto the event object\n\t\tif ( props ) {\n\t\t\tjQuery.extend( this, props );\n\t\t}\n\n\t\t// Create a timestamp if incoming event doesn't have one\n\t\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t\t// Mark it as fixed\n\t\tthis[ jQuery.expando ] = true;\n\t};\n\n\t// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n\t// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\n\tjQuery.Event.prototype = {\n\t\tconstructor: jQuery.Event,\n\t\tisDefaultPrevented: returnFalse,\n\t\tisPropagationStopped: returnFalse,\n\t\tisImmediatePropagationStopped: returnFalse,\n\t\tisSimulated: false,\n\n\t\tpreventDefault: function() {\n\t\t\tvar e = this.originalEvent;\n\n\t\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\t\tif ( e && !this.isSimulated ) {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t},\n\t\tstopPropagation: function() {\n\t\t\tvar e = this.originalEvent;\n\n\t\t\tthis.isPropagationStopped = returnTrue;\n\n\t\t\tif ( e && !this.isSimulated ) {\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t},\n\t\tstopImmediatePropagation: function() {\n\t\t\tvar e = this.originalEvent;\n\n\t\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\t\tif ( e && !this.isSimulated ) {\n\t\t\t\te.stopImmediatePropagation();\n\t\t\t}\n\n\t\t\tthis.stopPropagation();\n\t\t}\n\t};\n\n\t// Includes all common event props including KeyEvent and MouseEvent specific props\n\tjQuery.each( {\n\t\taltKey: true,\n\t\tbubbles: true,\n\t\tcancelable: true,\n\t\tchangedTouches: true,\n\t\tctrlKey: true,\n\t\tdetail: true,\n\t\teventPhase: true,\n\t\tmetaKey: true,\n\t\tpageX: true,\n\t\tpageY: true,\n\t\tshiftKey: true,\n\t\tview: true,\n\t\t\"char\": true,\n\t\tcharCode: true,\n\t\tkey: true,\n\t\tkeyCode: true,\n\t\tbutton: true,\n\t\tbuttons: true,\n\t\tclientX: true,\n\t\tclientY: true,\n\t\toffsetX: true,\n\t\toffsetY: true,\n\t\tpointerId: true,\n\t\tpointerType: true,\n\t\tscreenX: true,\n\t\tscreenY: true,\n\t\ttargetTouches: true,\n\t\ttoElement: true,\n\t\ttouches: true,\n\n\t\twhich: function( event ) {\n\t\t\tvar button = event.button;\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\t\tif ( button & 1 ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\n\t\t\t\tif ( button & 2 ) {\n\t\t\t\t\treturn 3;\n\t\t\t\t}\n\n\t\t\t\tif ( button & 4 ) {\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\treturn event.which;\n\t\t}\n\t}, jQuery.event.addProp );\n\n\t// Create mouseenter/leave events using mouseover/out and event-time checks\n\t// so that event delegation works in jQuery.\n\t// Do the same for pointerenter/pointerleave and pointerover/pointerout\n\t//\n\t// Support: Safari 7 only\n\t// Safari sends mouseenter too often; see:\n\t// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n\t// for the description of the bug (it existed in older Chrome versions as well).\n\tjQuery.each( {\n\t\tmouseenter: \"mouseover\",\n\t\tmouseleave: \"mouseout\",\n\t\tpointerenter: \"pointerover\",\n\t\tpointerleave: \"pointerout\"\n\t}, function( orig, fix ) {\n\t\tjQuery.event.special[ orig ] = {\n\t\t\tdelegateType: fix,\n\t\t\tbindType: fix,\n\n\t\t\thandle: function( event ) {\n\t\t\t\tvar ret,\n\t\t\t\t\ttarget = this,\n\t\t\t\t\trelated = event.relatedTarget,\n\t\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\t\tevent.type = fix;\n\t\t\t\t}\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t};\n\t} );\n\n\tjQuery.fn.extend( {\n\n\t\ton: function( types, selector, data, fn ) {\n\t\t\treturn on( this, types, selector, data, fn );\n\t\t},\n\t\tone: function( types, selector, data, fn ) {\n\t\t\treturn on( this, types, selector, data, fn, 1 );\n\t\t},\n\t\toff: function( types, selector, fn ) {\n\t\t\tvar handleObj, type;\n\t\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\t\thandleObj = types.handleObj;\n\t\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\t\thandleObj.namespace ?\n\t\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\t\thandleObj.origType,\n\t\t\t\t\thandleObj.selector,\n\t\t\t\t\thandleObj.handler\n\t\t\t\t);\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t\t// ( types-object [, selector] )\n\t\t\t\tfor ( type in types ) {\n\t\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t\t// ( types [, fn] )\n\t\t\t\tfn = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tif ( fn === false ) {\n\t\t\t\tfn = returnFalse;\n\t\t\t}\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t\t} );\n\t\t}\n\t} );\n\n\n\tvar\n\n\t\t/* eslint-disable max-len */\n\n\t\t// See https://github.com/eslint/eslint/issues/3229\n\t\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\n\t\t/* eslint-enable */\n\n\t\t// Support: IE <=10 - 11, Edge 12 - 13\n\t\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\t\trnoInnerhtml = /<script|<style|<link/i,\n\n\t\t// checked=\"checked\" or checked\n\t\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\t\trscriptTypeMasked = /^true\\/(.*)/,\n\t\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n\tfunction manipulationTarget( elem, content ) {\n\t\tif ( jQuery.nodeName( elem, \"table\" ) &&\n\t\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\t\treturn elem.getElementsByTagName( \"tbody\" )[ 0 ] || elem;\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\t// Replace/restore the type attribute of script elements for safe DOM manipulation\n\tfunction disableScript( elem ) {\n\t\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\t\treturn elem;\n\t}\n\tfunction restoreScript( elem ) {\n\t\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\t\tif ( match ) {\n\t\t\telem.type = match[ 1 ];\n\t\t} else {\n\t\t\telem.removeAttribute( \"type\" );\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\tfunction cloneCopyEvent( src, dest ) {\n\t\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\t\tif ( dest.nodeType !== 1 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// 1. Copy private data: events, handlers, etc.\n\t\tif ( dataPriv.hasData( src ) ) {\n\t\t\tpdataOld = dataPriv.access( src );\n\t\t\tpdataCur = dataPriv.set( dest, pdataOld );\n\t\t\tevents = pdataOld.events;\n\n\t\t\tif ( events ) {\n\t\t\t\tdelete pdataCur.handle;\n\t\t\t\tpdataCur.events = {};\n\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 2. Copy user data\n\t\tif ( dataUser.hasData( src ) ) {\n\t\t\tudataOld = dataUser.access( src );\n\t\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\t\tdataUser.set( dest, udataCur );\n\t\t}\n\t}\n\n\t// Fix IE bugs, see support tests\n\tfunction fixInput( src, dest ) {\n\t\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\t\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\t\tdest.checked = src.checked;\n\n\t\t// Fails to return the selected option to the default selected state when cloning options\n\t\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\t\tdest.defaultValue = src.defaultValue;\n\t\t}\n\t}\n\n\tfunction domManip( collection, args, callback, ignored ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = collection.length,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn collection.each( function( index ) {\n\t\t\t\tvar self = collection.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tdomManip( self, args, callback, ignored );\n\t\t\t} );\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\t\tif ( first || ignored ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item\n\t\t\t\t// instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), doc );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn collection;\n\t}\n\n\tfunction remove( elem, selector, keepData ) {\n\t\tvar node,\n\t\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t\t}\n\n\t\t\tif ( node.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( node.ownerDocument, node ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t\t}\n\t\t\t\tnode.parentNode.removeChild( node );\n\t\t\t}\n\t\t}\n\n\t\treturn elem;\n\t}\n\n\tjQuery.extend( {\n\t\thtmlPrefilter: function( html ) {\n\t\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t\t},\n\n\t\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\t\tvar i, l, srcElements, destElements,\n\t\t\t\tclone = elem.cloneNode( true ),\n\t\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Fix IE cloning issues\n\t\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\t\tdestElements = getAll( clone );\n\t\t\t\tsrcElements = getAll( elem );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Copy the events from the original to the clone\n\t\t\tif ( dataAndEvents ) {\n\t\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Preserve script evaluation history\n\t\t\tdestElements = getAll( clone, \"script\" );\n\t\t\tif ( destElements.length > 0 ) {\n\t\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t\t}\n\n\t\t\t// Return the cloned set\n\t\t\treturn clone;\n\t\t},\n\n\t\tcleanData: function( elems ) {\n\t\t\tvar data, elem, type,\n\t\t\t\tspecial = jQuery.event.special,\n\t\t\t\ti = 0;\n\n\t\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tdetach: function( selector ) {\n\t\t\treturn remove( this, selector, true );\n\t\t},\n\n\t\tremove: function( selector ) {\n\t\t\treturn remove( this, selector );\n\t\t},\n\n\t\ttext: function( value ) {\n\t\t\treturn access( this, function( value ) {\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\tjQuery.text( this ) :\n\t\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t}, null, value, arguments.length );\n\t\t},\n\n\t\tappend: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\t\ttarget.appendChild( elem );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tprepend: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tbefore: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.parentNode ) {\n\t\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tafter: function() {\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tif ( this.parentNode ) {\n\t\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\tempty: function() {\n\t\t\tvar elem,\n\t\t\t\ti = 0;\n\n\t\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t\t// Prevent memory leaks\n\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t\t// Remove any remaining nodes\n\t\t\t\t\telem.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\t\treturn this.map( function() {\n\t\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t\t} );\n\t\t},\n\n\t\thtml: function( value ) {\n\t\t\treturn access( this, function( value ) {\n\t\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\t\ti = 0,\n\t\t\t\t\tl = this.length;\n\n\t\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\t\treturn elem.innerHTML;\n\t\t\t\t}\n\n\t\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\telem = 0;\n\n\t\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t\t} catch ( e ) {}\n\t\t\t\t}\n\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tthis.empty().append( value );\n\t\t\t\t}\n\t\t\t}, null, value, arguments.length );\n\t\t},\n\n\t\treplaceWith: function() {\n\t\t\tvar ignored = [];\n\n\t\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\t\tvar parent = this.parentNode;\n\n\t\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\t\tif ( parent ) {\n\t\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Force callback invocation\n\t\t\t}, ignored );\n\t\t}\n\t} );\n\n\tjQuery.each( {\n\t\tappendTo: \"append\",\n\t\tprependTo: \"prepend\",\n\t\tinsertBefore: \"before\",\n\t\tinsertAfter: \"after\",\n\t\treplaceAll: \"replaceWith\"\n\t}, function( name, original ) {\n\t\tjQuery.fn[ name ] = function( selector ) {\n\t\t\tvar elems,\n\t\t\t\tret = [],\n\t\t\t\tinsert = jQuery( selector ),\n\t\t\t\tlast = insert.length - 1,\n\t\t\t\ti = 0;\n\n\t\t\tfor ( ; i <= last; i++ ) {\n\t\t\t\telems = i === last ? this : this.clone( true );\n\t\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tpush.apply( ret, elems.get() );\n\t\t\t}\n\n\t\t\treturn this.pushStack( ret );\n\t\t};\n\t} );\n\tvar rmargin = ( /^margin/ );\n\n\tvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\n\tvar getStyles = function( elem ) {\n\n\t\t\t// Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n\t\t\t// IE throws on elements created in popups\n\t\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\t\tif ( !view || !view.opener ) {\n\t\t\t\tview = window;\n\t\t\t}\n\n\t\t\treturn view.getComputedStyle( elem );\n\t\t};\n\n\n\n\t( function() {\n\n\t\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t\t// so they're executed at the same time to save the second computation.\n\t\tfunction computeStyleTests() {\n\n\t\t\t// This is a singleton, we need to execute it only once\n\t\t\tif ( !div ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdiv.style.cssText =\n\t\t\t\t\"box-sizing:border-box;\" +\n\t\t\t\t\"position:relative;display:block;\" +\n\t\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\t\"top:1%;width:50%\";\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdocumentElement.appendChild( container );\n\n\t\t\tvar divStyle = window.getComputedStyle( div );\n\t\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\t\treliableMarginLeftVal = divStyle.marginLeft === \"2px\";\n\t\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\t\t// Support: Android 4.0 - 4.3 only\n\t\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\t\tdiv.style.marginRight = \"50%\";\n\t\t\tpixelMarginRightVal = divStyle.marginRight === \"4px\";\n\n\t\t\tdocumentElement.removeChild( container );\n\n\t\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t\t// it will also be a sign that checks already performed\n\t\t\tdiv = null;\n\t\t}\n\n\t\tvar pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,\n\t\t\tcontainer = document.createElement( \"div\" ),\n\t\t\tdiv = document.createElement( \"div\" );\n\n\t\t// Finish early in limited (non-browser) environments\n\t\tif ( !div.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// Style of cloned element affects source element cloned (#8908)\n\t\tdiv.style.backgroundClip = \"content-box\";\n\t\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\t\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t\tcontainer.style.cssText = \"border:0;width:8px;height:0;top:0;left:-9999px;\" +\n\t\t\t\"padding:0;margin-top:1px;position:absolute\";\n\t\tcontainer.appendChild( div );\n\n\t\tjQuery.extend( support, {\n\t\t\tpixelPosition: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn pixelPositionVal;\n\t\t\t},\n\t\t\tboxSizingReliable: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn boxSizingReliableVal;\n\t\t\t},\n\t\t\tpixelMarginRight: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn pixelMarginRightVal;\n\t\t\t},\n\t\t\treliableMarginLeft: function() {\n\t\t\t\tcomputeStyleTests();\n\t\t\t\treturn reliableMarginLeftVal;\n\t\t\t}\n\t\t} );\n\t} )();\n\n\n\tfunction curCSS( elem, name, computed ) {\n\t\tvar width, minWidth, maxWidth, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\n\t\t// Support: IE <=9 only\n\t\t// getPropertyValue is only needed for .css('filter') (#12537)\n\t\tif ( computed ) {\n\t\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Android Browser returns percentage for some values,\n\t\t\t// but width seems to be reliably pixels.\n\t\t\t// This is against the CSSOM draft spec:\n\t\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\t\tif ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\treturn ret !== undefined ?\n\n\t\t\t// Support: IE <=9 - 11 only\n\t\t\t// IE returns zIndex value as an integer.\n\t\t\tret + \"\" :\n\t\t\tret;\n\t}\n\n\n\tfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t\t// Define the hook, we'll check on the first run if it's really needed.\n\t\treturn {\n\t\t\tget: function() {\n\t\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t\t// to missing dependency), remove it.\n\t\t\t\t\tdelete this.get;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t\t}\n\t\t};\n\t}\n\n\n\tvar\n\n\t\t// Swappable if display is none or starts with table\n\t\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\t\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\t\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\t\tcssNormalTransform = {\n\t\t\tletterSpacing: \"0\",\n\t\t\tfontWeight: \"400\"\n\t\t},\n\n\t\tcssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\t\temptyStyle = document.createElement( \"div\" ).style;\n\n\t// Return a css property mapped to a potentially vendor prefixed property\n\tfunction vendorPropName( name ) {\n\n\t\t// Shortcut for names that are not vendor prefixed\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\n\t\t// Check for vendor prefixed names\n\t\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\t\ti = cssPrefixes.length;\n\n\t\twhile ( i-- ) {\n\t\t\tname = cssPrefixes[ i ] + capName;\n\t\t\tif ( name in emptyStyle ) {\n\t\t\t\treturn name;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction setPositiveNumber( elem, value, subtract ) {\n\n\t\t// Any relative (+/-) values have already been\n\t\t// normalized at this point\n\t\tvar matches = rcssNum.exec( value );\n\t\treturn matches ?\n\n\t\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\t\tvalue;\n\t}\n\n\tfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\t\tvar i,\n\t\t\tval = 0;\n\n\t\t// If we already have the right measurement, avoid augmentation\n\t\tif ( extra === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\t\ti = 4;\n\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\t} else {\n\t\t\ti = name === \"width\" ? 1 : 0;\n\t\t}\n\n\t\tfor ( ; i < 4; i += 2 ) {\n\n\t\t\t// Both box models exclude margin, so add it if we want it\n\t\t\tif ( extra === \"margin\" ) {\n\t\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\tif ( isBorderBox ) {\n\n\t\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\t\tif ( extra === \"content\" ) {\n\t\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t\t}\n\n\t\t\t\t// At this point, extra isn't border nor margin, so remove border\n\t\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// At this point, extra isn't content, so add padding\n\t\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t\t// At this point, extra isn't content nor padding, so add border\n\t\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn val;\n\t}\n\n\tfunction getWidthOrHeight( elem, name, extra ) {\n\n\t\t// Start with offset property, which is equivalent to the border-box value\n\t\tvar val,\n\t\t\tvalueIsBorderBox = true,\n\t\t\tstyles = getStyles( elem ),\n\t\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a disconnected node\n\t\t// in IE throws an error.\n\t\tif ( elem.getClientRects().length ) {\n\t\t\tval = elem.getBoundingClientRect()[ name ];\n\t\t}\n\n\t\t// Some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\t\tif ( val <= 0 || val == null ) {\n\n\t\t\t// Fall back to computed then uncomputed css if necessary\n\t\t\tval = curCSS( elem, name, styles );\n\t\t\tif ( val < 0 || val == null ) {\n\t\t\t\tval = elem.style[ name ];\n\t\t\t}\n\n\t\t\t// Computed unit is not pixels. Stop here and return.\n\t\t\tif ( rnumnonpx.test( val ) ) {\n\t\t\t\treturn val;\n\t\t\t}\n\n\t\t\t// Check for style in case a browser which returns unreliable values\n\t\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\t\tvalueIsBorderBox = isBorderBox &&\n\t\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t\t// Normalize \"\", auto, and prepare for extra\n\t\t\tval = parseFloat( val ) || 0;\n\t\t}\n\n\t\t// Use the active box-sizing model to add/subtract irrelevant styles\n\t\treturn ( val +\n\t\t\taugmentWidthOrHeight(\n\t\t\t\telem,\n\t\t\t\tname,\n\t\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\t\tvalueIsBorderBox,\n\t\t\t\tstyles\n\t\t\t)\n\t\t) + \"px\";\n\t}\n\n\tjQuery.extend( {\n\n\t\t// Add in style property hooks for overriding the default\n\t\t// behavior of getting and setting a style property\n\t\tcssHooks: {\n\t\t\topacity: {\n\t\t\t\tget: function( elem, computed ) {\n\t\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Don't automatically add \"px\" to these possibly-unitless properties\n\t\tcssNumber: {\n\t\t\t\"animationIterationCount\": true,\n\t\t\t\"columnCount\": true,\n\t\t\t\"fillOpacity\": true,\n\t\t\t\"flexGrow\": true,\n\t\t\t\"flexShrink\": true,\n\t\t\t\"fontWeight\": true,\n\t\t\t\"lineHeight\": true,\n\t\t\t\"opacity\": true,\n\t\t\t\"order\": true,\n\t\t\t\"orphans\": true,\n\t\t\t\"widows\": true,\n\t\t\t\"zIndex\": true,\n\t\t\t\"zoom\": true\n\t\t},\n\n\t\t// Add in properties whose names you wish to fix before\n\t\t// setting or getting the value\n\t\tcssProps: {\n\t\t\t\"float\": \"cssFloat\"\n\t\t},\n\n\t\t// Get and set the style property on a DOM Node\n\t\tstyle: function( elem, name, value, extra ) {\n\n\t\t\t// Don't set styles on text and comment nodes\n\t\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Make sure that we're working with the right name\n\t\t\tvar ret, type, hooks,\n\t\t\t\torigName = jQuery.camelCase( name ),\n\t\t\t\tstyle = elem.style;\n\n\t\t\tname = jQuery.cssProps[ origName ] ||\n\t\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );\n\n\t\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t\t// Check if we're setting a value\n\t\t\tif ( value !== undefined ) {\n\t\t\t\ttype = typeof value;\n\n\t\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t\t// Fixes bug #9237\n\t\t\t\t\ttype = \"number\";\n\t\t\t\t}\n\n\t\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\t\tif ( value == null || value !== value ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\t\tif ( type === \"number\" ) {\n\t\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t\t}\n\n\t\t\t\t// background-* props affect original clone's values\n\t\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t\t}\n\n\t\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\t// Otherwise just get the value from the style object\n\t\t\t\treturn style[ name ];\n\t\t\t}\n\t\t},\n\n\t\tcss: function( elem, name, extra, styles ) {\n\t\t\tvar val, num, hooks,\n\t\t\t\torigName = jQuery.camelCase( name );\n\n\t\t\t// Make sure that we're working with the right name\n\t\t\tname = jQuery.cssProps[ origName ] ||\n\t\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );\n\n\t\t\t// Try prefixed name followed by the unprefixed name\n\t\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t\t// If a hook was provided get the computed value from there\n\t\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\t\tval = hooks.get( elem, true, extra );\n\t\t\t}\n\n\t\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\t\tif ( val === undefined ) {\n\t\t\t\tval = curCSS( elem, name, styles );\n\t\t\t}\n\n\t\t\t// Convert \"normal\" to computed value\n\t\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\t\tval = cssNormalTransform[ name ];\n\t\t\t}\n\n\t\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\t\tif ( extra === \"\" || extra ) {\n\t\t\t\tnum = parseFloat( val );\n\t\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t\t}\n\t\t\treturn val;\n\t\t}\n\t} );\n\n\tjQuery.each( [ \"height\", \"width\" ], function( i, name ) {\n\t\tjQuery.cssHooks[ name ] = {\n\t\t\tget: function( elem, computed, extra ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t\t\t} ) :\n\t\t\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tset: function( elem, value, extra ) {\n\t\t\t\tvar matches,\n\t\t\t\t\tstyles = extra && getStyles( elem ),\n\t\t\t\t\tsubtract = extra && augmentWidthOrHeight(\n\t\t\t\t\t\telem,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\textra,\n\t\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\t\tstyles\n\t\t\t\t\t);\n\n\t\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\t\telem.style[ name ] = value;\n\t\t\t\t\tvalue = jQuery.css( elem, name );\n\t\t\t\t}\n\n\t\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t\t}\n\t\t};\n\t} );\n\n\tjQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t\t} )\n\t\t\t\t\t) + \"px\";\n\t\t\t}\n\t\t}\n\t);\n\n\t// These hooks are used by animate to expand properties\n\tjQuery.each( {\n\t\tmargin: \"\",\n\t\tpadding: \"\",\n\t\tborder: \"Width\"\n\t}, function( prefix, suffix ) {\n\t\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\t\texpand: function( value ) {\n\t\t\t\tvar i = 0,\n\t\t\t\t\texpanded = {},\n\n\t\t\t\t\t// Assumes a single number if not a string\n\t\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t\t}\n\n\t\t\t\treturn expanded;\n\t\t\t}\n\t\t};\n\n\t\tif ( !rmargin.test( prefix ) ) {\n\t\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t\t}\n\t} );\n\n\tjQuery.fn.extend( {\n\t\tcss: function( name, value ) {\n\t\t\treturn access( this, function( elem, name, value ) {\n\t\t\t\tvar styles, len,\n\t\t\t\t\tmap = {},\n\t\t\t\t\ti = 0;\n\n\t\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\t\tstyles = getStyles( elem );\n\t\t\t\t\tlen = name.length;\n\n\t\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn map;\n\t\t\t\t}\n\n\t\t\t\treturn value !== undefined ?\n\t\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\t\tjQuery.css( elem, name );\n\t\t\t}, name, value, arguments.length > 1 );\n\t\t}\n\t} );\n\n\n\tfunction Tween( elem, options, prop, end, easing ) {\n\t\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n\t}\n\tjQuery.Tween = Tween;\n\n\tTween.prototype = {\n\t\tconstructor: Tween,\n\t\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\t\tthis.elem = elem;\n\t\t\tthis.prop = prop;\n\t\t\tthis.easing = easing || jQuery.easing._default;\n\t\t\tthis.options = options;\n\t\t\tthis.start = this.now = this.cur();\n\t\t\tthis.end = end;\n\t\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t\t},\n\t\tcur: function() {\n\t\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\t\treturn hooks && hooks.get ?\n\t\t\t\thooks.get( this ) :\n\t\t\t\tTween.propHooks._default.get( this );\n\t\t},\n\t\trun: function( percent ) {\n\t\t\tvar eased,\n\t\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\t\tif ( this.options.duration ) {\n\t\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthis.pos = eased = percent;\n\t\t\t}\n\t\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\t\tif ( this.options.step ) {\n\t\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t\t}\n\n\t\t\tif ( hooks && hooks.set ) {\n\t\t\t\thooks.set( this );\n\t\t\t} else {\n\t\t\t\tTween.propHooks._default.set( this );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t};\n\n\tTween.prototype.init.prototype = Tween.prototype;\n\n\tTween.propHooks = {\n\t\t_default: {\n\t\t\tget: function( tween ) {\n\t\t\t\tvar result;\n\n\t\t\t\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t\t// or when there is no matching style property that exists.\n\t\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\t\ttween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {\n\t\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t\t}\n\n\t\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\n\t\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t\t},\n\t\t\tset: function( tween ) {\n\n\t\t\t\t// Use step hook for back compat.\n\t\t\t\t// Use cssHook if its there.\n\t\t\t\t// Use .style if available and use plain properties where available.\n\t\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t\t} else if ( tween.elem.nodeType === 1 &&\n\t\t\t\t\t( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||\n\t\t\t\t\t\tjQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t\t} else {\n\t\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t// Support: IE <=9 only\n\t// Panic based approach to setting things on disconnected nodes\n\tTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\t\tset: function( tween ) {\n\t\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t};\n\n\tjQuery.easing = {\n\t\tlinear: function( p ) {\n\t\t\treturn p;\n\t\t},\n\t\tswing: function( p ) {\n\t\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t\t},\n\t\t_default: \"swing\"\n\t};\n\n\tjQuery.fx = Tween.prototype.init;\n\n\t// Back compat <1.8 extension point\n\tjQuery.fx.step = {};\n\n\n\n\n\tvar\n\t\tfxNow, timerId,\n\t\trfxtypes = /^(?:toggle|show|hide)$/,\n\t\trrun = /queueHooks$/;\n\n\tfunction raf() {\n\t\tif ( timerId ) {\n\t\t\twindow.requestAnimationFrame( raf );\n\t\t\tjQuery.fx.tick();\n\t\t}\n\t}\n\n\t// Animations created synchronously will run synchronously\n\tfunction createFxNow() {\n\t\twindow.setTimeout( function() {\n\t\t\tfxNow = undefined;\n\t\t} );\n\t\treturn ( fxNow = jQuery.now() );\n\t}\n\n\t// Generate parameters to create a standard animation\n\tfunction genFx( type, includeWidth ) {\n\t\tvar which,\n\t\t\ti = 0,\n\t\t\tattrs = { height: type };\n\n\t\t// If we include width, step value is 1 to do all cssExpand values,\n\t\t// otherwise step value is 2 to skip over Left and Right\n\t\tincludeWidth = includeWidth ? 1 : 0;\n\t\tfor ( ; i < 4; i += 2 - includeWidth ) {\n\t\t\twhich = cssExpand[ i ];\n\t\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t\t}\n\n\t\tif ( includeWidth ) {\n\t\t\tattrs.opacity = attrs.width = type;\n\t\t}\n\n\t\treturn attrs;\n\t}\n\n\tfunction createTween( value, prop, animation ) {\n\t\tvar tween,\n\t\t\tcollection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\t\tindex = 0,\n\t\t\tlength = collection.length;\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t\t// We're done with this property\n\t\t\t\treturn tween;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction defaultPrefilter( elem, props, opts ) {\n\t\tvar prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,\n\t\t\tisBox = \"width\" in props || \"height\" in props,\n\t\t\tanim = this,\n\t\t\torig = {},\n\t\t\tstyle = elem.style,\n\t\t\thidden = elem.nodeType && isHiddenWithinTree( elem ),\n\t\t\tdataShow = dataPriv.get( elem, \"fxshow\" );\n\n\t\t// Queue-skipping animations hijack the fx hooks\n\t\tif ( !opts.queue ) {\n\t\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\t\tif ( hooks.unqueued == null ) {\n\t\t\t\thooks.unqueued = 0;\n\t\t\t\toldfire = hooks.empty.fire;\n\t\t\t\thooks.empty.fire = function() {\n\t\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\t\toldfire();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t\thooks.unqueued++;\n\n\t\t\tanim.always( function() {\n\n\t\t\t\t// Ensure the complete handler is called before this completes\n\t\t\t\tanim.always( function() {\n\t\t\t\t\thooks.unqueued--;\n\t\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\t\thooks.empty.fire();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} );\n\t\t}\n\n\t\t// Detect show/hide animations\n\t\tfor ( prop in props ) {\n\t\t\tvalue = props[ prop ];\n\t\t\tif ( rfxtypes.test( value ) ) {\n\t\t\t\tdelete props[ prop ];\n\t\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t\t// Pretend to be hidden if this is a \"show\" and\n\t\t\t\t\t// there is still data from a stopped show/hide\n\t\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\t\thidden = true;\n\n\t\t\t\t\t// Ignore all other no-op show/hide data\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t\t}\n\t\t}\n\n\t\t// Bail out if this is a no-op like .hide().hide()\n\t\tpropTween = !jQuery.isEmptyObject( props );\n\t\tif ( !propTween && jQuery.isEmptyObject( orig ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Restrict \"overflow\" and \"display\" styles during box animations\n\t\tif ( isBox && elem.nodeType === 1 ) {\n\n\t\t\t// Support: IE <=9 - 11, Edge 12 - 13\n\t\t\t// Record all 3 overflow attributes because IE does not infer the shorthand\n\t\t\t// from identically-valued overflowX and overflowY\n\t\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t\t// Identify a display type, preferring old show/hide data over the CSS cascade\n\t\t\trestoreDisplay = dataShow && dataShow.display;\n\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\trestoreDisplay = dataPriv.get( elem, \"display\" );\n\t\t\t}\n\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tif ( restoreDisplay ) {\n\t\t\t\t\tdisplay = restoreDisplay;\n\t\t\t\t} else {\n\n\t\t\t\t\t// Get nonempty value(s) by temporarily forcing visibility\n\t\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\t\trestoreDisplay = elem.style.display || restoreDisplay;\n\t\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Animate inline elements as inline-block\n\t\t\tif ( display === \"inline\" || display === \"inline-block\" && restoreDisplay != null ) {\n\t\t\t\tif ( jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t\t\t// Restore the original display value at the end of pure show/hide animations\n\t\t\t\t\tif ( !propTween ) {\n\t\t\t\t\t\tanim.done( function() {\n\t\t\t\t\t\t\tstyle.display = restoreDisplay;\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\t\t\t\tdisplay = style.display;\n\t\t\t\t\t\t\trestoreDisplay = display === \"none\" ? \"\" : display;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( opts.overflow ) {\n\t\t\tstyle.overflow = \"hidden\";\n\t\t\tanim.always( function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t} );\n\t\t}\n\n\t\t// Implement show/hide animations\n\t\tpropTween = false;\n\t\tfor ( prop in orig ) {\n\n\t\t\t// General show/hide setup for this element animation\n\t\t\tif ( !propTween ) {\n\t\t\t\tif ( dataShow ) {\n\t\t\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\t\t\thidden = dataShow.hidden;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tdataShow = dataPriv.access( elem, \"fxshow\", { display: restoreDisplay } );\n\t\t\t\t}\n\n\t\t\t\t// Store hidden/visible for toggle so `.stop().toggle()` \"reverses\"\n\t\t\t\tif ( toggle ) {\n\t\t\t\t\tdataShow.hidden = !hidden;\n\t\t\t\t}\n\n\t\t\t\t// Show elements before animating them\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\t}\n\n\t\t\t\t/* eslint-disable no-loop-func */\n\n\t\t\t\tanim.done( function() {\n\n\t\t\t\t/* eslint-enable no-loop-func */\n\n\t\t\t\t\t// The final step of a \"hide\" animation is actually hiding the element\n\t\t\t\t\tif ( !hidden ) {\n\t\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.remove( elem, \"fxshow\" );\n\t\t\t\t\tfor ( prop in orig ) {\n\t\t\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Per-property setup\n\t\t\tpropTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = propTween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\tpropTween.end = propTween.start;\n\t\t\t\t\tpropTween.start = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction propFilter( props, specialEasing ) {\n\t\tvar index, name, easing, value, hooks;\n\n\t\t// camelCase, specialEasing and expand cssHook pass\n\t\tfor ( index in props ) {\n\t\t\tname = jQuery.camelCase( index );\n\t\t\teasing = specialEasing[ name ];\n\t\t\tvalue = props[ index ];\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\teasing = value[ 1 ];\n\t\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t\t}\n\n\t\t\tif ( index !== name ) {\n\t\t\t\tprops[ name ] = value;\n\t\t\t\tdelete props[ index ];\n\t\t\t}\n\n\t\t\thooks = jQuery.cssHooks[ name ];\n\t\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\t\tvalue = hooks.expand( value );\n\t\t\t\tdelete props[ name ];\n\n\t\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\t\tfor ( index in value ) {\n\t\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tspecialEasing[ name ] = easing;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction Animation( elem, properties, options ) {\n\t\tvar result,\n\t\t\tstopped,\n\t\t\tindex = 0,\n\t\t\tlength = Animation.prefilters.length,\n\t\t\tdeferred = jQuery.Deferred().always( function() {\n\n\t\t\t\t// Don't match elem in the :animated selector\n\t\t\t\tdelete tick.elem;\n\t\t\t} ),\n\t\t\ttick = function() {\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\n\t\t\t\t\t// Support: Android 2.3 only\n\t\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\t\tpercent = 1 - temp,\n\t\t\t\t\tindex = 0,\n\t\t\t\t\tlength = animation.tweens.length;\n\n\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t\t}\n\n\t\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\t\tif ( percent < 1 && length ) {\n\t\t\t\t\treturn remaining;\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tanimation = deferred.promise( {\n\t\t\t\telem: elem,\n\t\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\t\topts: jQuery.extend( true, {\n\t\t\t\t\tspecialEasing: {},\n\t\t\t\t\teasing: jQuery.easing._default\n\t\t\t\t}, options ),\n\t\t\t\toriginalProperties: properties,\n\t\t\t\toriginalOptions: options,\n\t\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\t\tduration: options.duration,\n\t\t\t\ttweens: [],\n\t\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\t\treturn tween;\n\t\t\t\t},\n\t\t\t\tstop: function( gotoEnd ) {\n\t\t\t\t\tvar index = 0,\n\n\t\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\t\tif ( stopped ) {\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\t\t\t\t\tstopped = true;\n\t\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t} ),\n\t\t\tprops = animation.props;\n\n\t\tpropFilter( props, animation.opts.specialEasing );\n\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tresult = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\t\tif ( result ) {\n\t\t\t\tif ( jQuery.isFunction( result.stop ) ) {\n\t\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\t\tjQuery.proxy( result.stop, result );\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\n\t\tjQuery.map( props, createTween, animation );\n\n\t\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\t\tanimation.opts.start.call( elem, animation );\n\t\t}\n\n\t\tjQuery.fx.timer(\n\t\t\tjQuery.extend( tick, {\n\t\t\t\telem: elem,\n\t\t\t\tanim: animation,\n\t\t\t\tqueue: animation.opts.queue\n\t\t\t} )\n\t\t);\n\n\t\t// attach callbacks from options\n\t\treturn animation.progress( animation.opts.progress )\n\t\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t\t.fail( animation.opts.fail )\n\t\t\t.always( animation.opts.always );\n\t}\n\n\tjQuery.Animation = jQuery.extend( Animation, {\n\n\t\ttweeners: {\n\t\t\t\"*\": [ function( prop, value ) {\n\t\t\t\tvar tween = this.createTween( prop, value );\n\t\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\t\treturn tween;\n\t\t\t} ]\n\t\t},\n\n\t\ttweener: function( props, callback ) {\n\t\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\t\tcallback = props;\n\t\t\t\tprops = [ \"*\" ];\n\t\t\t} else {\n\t\t\t\tprops = props.match( rnothtmlwhite );\n\t\t\t}\n\n\t\t\tvar prop,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = props.length;\n\n\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\tprop = props[ index ];\n\t\t\t\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t\t}\n\t\t},\n\n\t\tprefilters: [ defaultPrefilter ],\n\n\t\tprefilter: function( callback, prepend ) {\n\t\t\tif ( prepend ) {\n\t\t\t\tAnimation.prefilters.unshift( callback );\n\t\t\t} else {\n\t\t\t\tAnimation.prefilters.push( callback );\n\t\t\t}\n\t\t}\n\t} );\n\n\tjQuery.speed = function( speed, easing, fn ) {\n\t\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\t\tcomplete: fn || !fn && easing ||\n\t\t\t\tjQuery.isFunction( speed ) && speed,\n\t\t\tduration: speed,\n\t\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t\t};\n\n\t\t// Go to the end state if fx are off or if document is hidden\n\t\tif ( jQuery.fx.off || document.hidden ) {\n\t\t\topt.duration = 0;\n\n\t\t} else {\n\t\t\tif ( typeof opt.duration !== \"number\" ) {\n\t\t\t\tif ( opt.duration in jQuery.fx.speeds ) {\n\t\t\t\t\topt.duration = jQuery.fx.speeds[ opt.duration ];\n\n\t\t\t\t} else {\n\t\t\t\t\topt.duration = jQuery.fx.speeds._default;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\t\tif ( opt.queue == null || opt.queue === true ) {\n\t\t\topt.queue = \"fx\";\n\t\t}\n\n\t\t// Queueing\n\t\topt.old = opt.complete;\n\n\t\topt.complete = function() {\n\t\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\t\topt.old.call( this );\n\t\t\t}\n\n\t\t\tif ( opt.queue ) {\n\t\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t\t}\n\t\t};\n\n\t\treturn opt;\n\t};\n\n\tjQuery.fn.extend( {\n\t\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t\t// Show any hidden elements after setting opacity to 0\n\t\t\treturn this.filter( isHiddenWithinTree ).css( \"opacity\", 0 ).show()\n\n\t\t\t\t// Animate to the value specified\n\t\t\t\t.end().animate( { opacity: to }, speed, easing, callback );\n\t\t},\n\t\tanimate: function( prop, speed, easing, callback ) {\n\t\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\t\tdoAnimation = function() {\n\n\t\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\t\tif ( empty || dataPriv.get( this, \"finish\" ) ) {\n\t\t\t\t\t\tanim.stop( true );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tdoAnimation.finish = doAnimation;\n\n\t\t\treturn empty || optall.queue === false ?\n\t\t\t\tthis.each( doAnimation ) :\n\t\t\t\tthis.queue( optall.queue, doAnimation );\n\t\t},\n\t\tstop: function( type, clearQueue, gotoEnd ) {\n\t\t\tvar stopQueue = function( hooks ) {\n\t\t\t\tvar stop = hooks.stop;\n\t\t\t\tdelete hooks.stop;\n\t\t\t\tstop( gotoEnd );\n\t\t\t};\n\n\t\t\tif ( typeof type !== \"string\" ) {\n\t\t\t\tgotoEnd = clearQueue;\n\t\t\t\tclearQueue = type;\n\t\t\t\ttype = undefined;\n\t\t\t}\n\t\t\tif ( clearQueue && type !== false ) {\n\t\t\t\tthis.queue( type || \"fx\", [] );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tvar dequeue = true,\n\t\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\t\ttimers = jQuery.timers,\n\t\t\t\t\tdata = dataPriv.get( this );\n\n\t\t\t\tif ( index ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfor ( index in data ) {\n\t\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\t\tif ( timers[ index ].elem === this &&\n\t\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\n\t\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\t\tdequeue = false;\n\t\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\t\tfinish: function( type ) {\n\t\t\tif ( type !== false ) {\n\t\t\t\ttype = type || \"fx\";\n\t\t\t}\n\t\t\treturn this.each( function() {\n\t\t\t\tvar index,\n\t\t\t\t\tdata = dataPriv.get( this ),\n\t\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\t\ttimers = jQuery.timers,\n\t\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t\t// Enable finishing flag on private data\n\t\t\t\tdata.finish = true;\n\n\t\t\t\t// Empty the queue first\n\t\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\t\thooks.stop.call( this, true );\n\t\t\t\t}\n\n\t\t\t\t// Look for any active animations, and finish them\n\t\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Look for any animations in the old queue and finish them\n\t\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Turn off finishing flag\n\t\t\t\tdelete data.finish;\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.each( [ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\t\tvar cssFn = jQuery.fn[ name ];\n\t\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\t\tcssFn.apply( this, arguments ) :\n\t\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t\t};\n\t} );\n\n\t// Generate shortcuts for custom animations\n\tjQuery.each( {\n\t\tslideDown: genFx( \"show\" ),\n\t\tslideUp: genFx( \"hide\" ),\n\t\tslideToggle: genFx( \"toggle\" ),\n\t\tfadeIn: { opacity: \"show\" },\n\t\tfadeOut: { opacity: \"hide\" },\n\t\tfadeToggle: { opacity: \"toggle\" }\n\t}, function( name, props ) {\n\t\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\t\treturn this.animate( props, speed, easing, callback );\n\t\t};\n\t} );\n\n\tjQuery.timers = [];\n\tjQuery.fx.tick = function() {\n\t\tvar timer,\n\t\t\ti = 0,\n\t\t\ttimers = jQuery.timers;\n\n\t\tfxNow = jQuery.now();\n\n\t\tfor ( ; i < timers.length; i++ ) {\n\t\t\ttimer = timers[ i ];\n\n\t\t\t// Checks the timer has not already been removed\n\t\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\t\ttimers.splice( i--, 1 );\n\t\t\t}\n\t\t}\n\n\t\tif ( !timers.length ) {\n\t\t\tjQuery.fx.stop();\n\t\t}\n\t\tfxNow = undefined;\n\t};\n\n\tjQuery.fx.timer = function( timer ) {\n\t\tjQuery.timers.push( timer );\n\t\tif ( timer() ) {\n\t\t\tjQuery.fx.start();\n\t\t} else {\n\t\t\tjQuery.timers.pop();\n\t\t}\n\t};\n\n\tjQuery.fx.interval = 13;\n\tjQuery.fx.start = function() {\n\t\tif ( !timerId ) {\n\t\t\ttimerId = window.requestAnimationFrame ?\n\t\t\t\twindow.requestAnimationFrame( raf ) :\n\t\t\t\twindow.setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t\t}\n\t};\n\n\tjQuery.fx.stop = function() {\n\t\tif ( window.cancelAnimationFrame ) {\n\t\t\twindow.cancelAnimationFrame( timerId );\n\t\t} else {\n\t\t\twindow.clearInterval( timerId );\n\t\t}\n\n\t\ttimerId = null;\n\t};\n\n\tjQuery.fx.speeds = {\n\t\tslow: 600,\n\t\tfast: 200,\n\n\t\t// Default speed\n\t\t_default: 400\n\t};\n\n\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tjQuery.fn.delay = function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = window.setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\twindow.clearTimeout( timeout );\n\t\t\t};\n\t\t} );\n\t};\n\n\n\t( function() {\n\t\tvar input = document.createElement( \"input\" ),\n\t\t\tselect = document.createElement( \"select\" ),\n\t\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\t\tinput.type = \"checkbox\";\n\n\t\t// Support: Android <=4.3 only\n\t\t// Default value for a checkbox should be \"on\"\n\t\tsupport.checkOn = input.value !== \"\";\n\n\t\t// Support: IE <=11 only\n\t\t// Must access selectedIndex to make default options select\n\t\tsupport.optSelected = opt.selected;\n\n\t\t// Support: IE <=11 only\n\t\t// An input loses its value after becoming a radio\n\t\tinput = document.createElement( \"input\" );\n\t\tinput.value = \"t\";\n\t\tinput.type = \"radio\";\n\t\tsupport.radioValue = input.value === \"t\";\n\t} )();\n\n\n\tvar boolHook,\n\t\tattrHandle = jQuery.expr.attrHandle;\n\n\tjQuery.fn.extend( {\n\t\tattr: function( name, value ) {\n\t\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t\t},\n\n\t\tremoveAttr: function( name ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.removeAttr( this, name );\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.extend( {\n\t\tattr: function( elem, name, value ) {\n\t\t\tvar ret, hooks,\n\t\t\t\tnType = elem.nodeType;\n\n\t\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Fallback to prop when attributes are not supported\n\t\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\t\treturn jQuery.prop( elem, name, value );\n\t\t\t}\n\n\t\t\t// Attribute hooks are determined by the lowercase version\n\t\t\t// Grab necessary hook if one is defined\n\t\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t\t}\n\n\t\t\tif ( value !== undefined ) {\n\t\t\t\tif ( value === null ) {\n\t\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ? undefined : ret;\n\t\t},\n\n\t\tattrHooks: {\n\t\t\ttype: {\n\t\t\t\tset: function( elem, value ) {\n\t\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\t\tjQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tremoveAttr: function( elem, value ) {\n\t\t\tvar name,\n\t\t\t\ti = 0,\n\n\t\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\t\telem.removeAttribute( name );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} );\n\n\t// Hooks for boolean attributes\n\tboolHook = {\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( value === false ) {\n\n\t\t\t\t// Remove boolean attributes when set to false\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, name );\n\t\t\t}\n\t\t\treturn name;\n\t\t}\n\t};\n\n\tjQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\t\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\t\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\t\tvar ret, handle,\n\t\t\t\tlowercaseName = name.toLowerCase();\n\n\t\t\tif ( !isXML ) {\n\n\t\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\t\tlowercaseName :\n\t\t\t\t\tnull;\n\t\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\t} );\n\n\n\n\n\tvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\t\trclickable = /^(?:a|area)$/i;\n\n\tjQuery.fn.extend( {\n\t\tprop: function( name, value ) {\n\t\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t\t},\n\n\t\tremoveProp: function( name ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.extend( {\n\t\tprop: function( elem, name, value ) {\n\t\t\tvar ret, hooks,\n\t\t\t\tnType = elem.nodeType;\n\n\t\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t\t// Fix name and attach hooks\n\t\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\t\thooks = jQuery.propHooks[ name ];\n\t\t\t}\n\n\t\t\tif ( value !== undefined ) {\n\t\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn elem[ name ];\n\t\t},\n\n\t\tpropHooks: {\n\t\t\ttabIndex: {\n\t\t\t\tget: function( elem ) {\n\n\t\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\t\tif ( tabindex ) {\n\t\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\t\telem.href\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tpropFix: {\n\t\t\t\"for\": \"htmlFor\",\n\t\t\t\"class\": \"className\"\n\t\t}\n\t} );\n\n\t// Support: IE <=11 only\n\t// Accessing the selectedIndex property\n\t// forces the browser to respect setting selected\n\t// on the option\n\t// The getter ensures a default option is selected\n\t// when in an optgroup\n\t// eslint rule \"no-unused-expressions\" is disabled for this code\n\t// since it considers such accessions noop\n\tif ( !support.optSelected ) {\n\t\tjQuery.propHooks.selected = {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\tset: function( elem ) {\n\n\t\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tjQuery.each( [\n\t\t\"tabIndex\",\n\t\t\"readOnly\",\n\t\t\"maxLength\",\n\t\t\"cellSpacing\",\n\t\t\"cellPadding\",\n\t\t\"rowSpan\",\n\t\t\"colSpan\",\n\t\t\"useMap\",\n\t\t\"frameBorder\",\n\t\t\"contentEditable\"\n\t], function() {\n\t\tjQuery.propFix[ this.toLowerCase() ] = this;\n\t} );\n\n\n\n\n\t\t// Strip and collapse whitespace according to HTML spec\n\t\t// https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace\n\t\tfunction stripAndCollapse( value ) {\n\t\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\t\treturn tokens.join( \" \" );\n\t\t}\n\n\n\tfunction getClass( elem ) {\n\t\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n\t}\n\n\tjQuery.fn.extend( {\n\t\taddClass: function( value ) {\n\t\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each( function( j ) {\n\t\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( typeof value === \"string\" && value ) {\n\t\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\t\tcurValue = getClass( elem );\n\t\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\t\tif ( cur ) {\n\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\tremoveClass: function( value ) {\n\t\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each( function( j ) {\n\t\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( !arguments.length ) {\n\t\t\t\treturn this.attr( \"class\", \"\" );\n\t\t\t}\n\n\t\t\tif ( typeof value === \"string\" && value ) {\n\t\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\t\tif ( cur ) {\n\t\t\t\t\t\tj = 0;\n\t\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\ttoggleClass: function( value, stateVal ) {\n\t\t\tvar type = typeof value;\n\n\t\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t\t}\n\n\t\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\t\treturn this.each( function( i ) {\n\t\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\t\tstateVal\n\t\t\t\t\t);\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tvar className, i, self, classNames;\n\n\t\t\t\tif ( type === \"string\" ) {\n\n\t\t\t\t\t// Toggle individual class names\n\t\t\t\t\ti = 0;\n\t\t\t\t\tself = jQuery( this );\n\t\t\t\t\tclassNames = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Toggle whole class name\n\t\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\t\tclassName = getClass( this );\n\t\t\t\t\tif ( className ) {\n\n\t\t\t\t\t\t// Store className if set\n\t\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\thasClass: function( selector ) {\n\t\t\tvar className, elem,\n\t\t\t\ti = 0;\n\n\t\t\tclassName = \" \" + selector + \" \";\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\t} );\n\n\n\n\n\tvar rreturn = /\\r/g;\n\n\tjQuery.fn.extend( {\n\t\tval: function( value ) {\n\t\t\tvar hooks, ret, isFunction,\n\t\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !arguments.length ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\t\tif ( hooks &&\n\t\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn ret;\n\t\t\t\t\t}\n\n\t\t\t\t\tret = elem.value;\n\n\t\t\t\t\t// Handle most common string cases\n\t\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tvar val;\n\n\t\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t\t} else {\n\t\t\t\t\tval = value;\n\t\t\t\t}\n\n\t\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\t\tif ( val == null ) {\n\t\t\t\t\tval = \"\";\n\n\t\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\t\tval += \"\";\n\n\t\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\t\tthis.value = val;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t} );\n\n\tjQuery.extend( {\n\t\tvalHooks: {\n\t\t\toption: {\n\t\t\t\tget: function( elem ) {\n\n\t\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\t\treturn val != null ?\n\t\t\t\t\t\tval :\n\n\t\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t\t}\n\t\t\t},\n\t\t\tselect: {\n\t\t\t\tget: function( elem ) {\n\t\t\t\t\tvar value, option, i,\n\t\t\t\t\t\toptions = elem.options,\n\t\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\t\ti = max;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Loop through all the selected options\n\t\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t\t!option.disabled &&\n\t\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t\t!jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn values;\n\t\t\t\t},\n\n\t\t\t\tset: function( elem, value ) {\n\t\t\t\t\tvar optionSet, option,\n\t\t\t\t\t\toptions = elem.options,\n\t\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\t\ti = options.length;\n\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t\t}\n\n\t\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t\t}\n\t\t\t\t\treturn values;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} );\n\n\t// Radios and checkboxes getter/setter\n\tjQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tif ( !support.checkOn ) {\n\t\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t\t};\n\t\t}\n\t} );\n\n\n\n\n\t// Return jQuery for attributes-only inclusion\n\n\n\tvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;\n\n\tjQuery.extend( jQuery.event, {\n\n\t\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\t\teventPath = [ elem || document ],\n\t\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\t\tcur = tmp = elem = elem || document;\n\n\t\t\t// Don't do events on text and comment nodes\n\t\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\t\tnamespaces = type.split( \".\" );\n\t\t\t\ttype = namespaces.shift();\n\t\t\t\tnamespaces.sort();\n\t\t\t}\n\t\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\t\tevent = event[ jQuery.expando ] ?\n\t\t\t\tevent :\n\t\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\t\tevent.namespace = namespaces.join( \".\" );\n\t\t\tevent.rnamespace = event.namespace ?\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\t\tnull;\n\n\t\t\t// Clean up the event in case it is being reused\n\t\t\tevent.result = undefined;\n\t\t\tif ( !event.target ) {\n\t\t\t\tevent.target = elem;\n\t\t\t}\n\n\t\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\t\tdata = data == null ?\n\t\t\t\t[ event ] :\n\t\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t\t// Allow special events to draw outside the lines\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\tbubbleType = special.delegateType || type;\n\t\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\t\tcur = cur.parentNode;\n\t\t\t\t}\n\t\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\t\teventPath.push( cur );\n\t\t\t\t\ttmp = cur;\n\t\t\t\t}\n\n\t\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fire handlers on the event path\n\t\t\ti = 0;\n\t\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\n\t\t\t\tevent.type = i > 1 ?\n\t\t\t\t\tbubbleType :\n\t\t\t\t\tspecial.bindType || type;\n\n\t\t\t\t// jQuery handler\n\t\t\t\thandle = ( dataPriv.get( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\t\tif ( handle ) {\n\t\t\t\t\thandle.apply( cur, data );\n\t\t\t\t}\n\n\t\t\t\t// Native handler\n\t\t\t\thandle = ontype && cur[ ontype ];\n\t\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tevent.type = type;\n\n\t\t\t// If nobody prevented the default action, do it now\n\t\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\t\tif ( ( !special._default ||\n\t\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn event.result;\n\t\t},\n\n\t\t// Piggyback on a donor event to simulate a different one\n\t\t// Used only for `focus(in | out)` events\n\t\tsimulate: function( type, elem, event ) {\n\t\t\tvar e = jQuery.extend(\n\t\t\t\tnew jQuery.Event(),\n\t\t\t\tevent,\n\t\t\t\t{\n\t\t\t\t\ttype: type,\n\t\t\t\t\tisSimulated: true\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t}\n\n\t} );\n\n\tjQuery.fn.extend( {\n\n\t\ttrigger: function( type, data ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.event.trigger( type, data, this );\n\t\t\t} );\n\t\t},\n\t\ttriggerHandler: function( type, data ) {\n\t\t\tvar elem = this[ 0 ];\n\t\t\tif ( elem ) {\n\t\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t\t}\n\t\t}\n\t} );\n\n\n\tjQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\t\tfunction( i, name ) {\n\n\t\t// Handle event binding\n\t\tjQuery.fn[ name ] = function( data, fn ) {\n\t\t\treturn arguments.length > 0 ?\n\t\t\t\tthis.on( name, null, data, fn ) :\n\t\t\t\tthis.trigger( name );\n\t\t};\n\t} );\n\n\tjQuery.fn.extend( {\n\t\thover: function( fnOver, fnOut ) {\n\t\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t\t}\n\t} );\n\n\n\n\n\tsupport.focusin = \"onfocusin\" in window;\n\n\n\t// Support: Firefox <=44\n\t// Firefox doesn't have focus(in | out) events\n\t// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n\t//\n\t// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n\t// focus(in | out) events fire after focus & blur events,\n\t// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n\t// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\n\tif ( !support.focusin ) {\n\t\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t\t};\n\n\t\t\tjQuery.event.special[ fix ] = {\n\t\t\t\tsetup: function() {\n\t\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\t\tif ( !attaches ) {\n\t\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t\t},\n\t\t\t\tteardown: function() {\n\t\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\t\tif ( !attaches ) {\n\t\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t} );\n\t}\n\tvar location = window.location;\n\n\tvar nonce = jQuery.now();\n\n\tvar rquery = ( /\\?/ );\n\n\n\n\t// Cross-browser xml parsing\n\tjQuery.parseXML = function( data ) {\n\t\tvar xml;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Support: IE 9 - 11 only\n\t\t// IE throws on parseFromString with invalid input.\n\t\ttry {\n\t\t\txml = ( new window.DOMParser() ).parseFromString( data, \"text/xml\" );\n\t\t} catch ( e ) {\n\t\t\txml = undefined;\n\t\t}\n\n\t\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t};\n\n\n\tvar\n\t\trbracket = /\\[\\]$/,\n\t\trCRLF = /\\r?\\n/g,\n\t\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\t\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\n\tfunction buildParams( prefix, obj, traditional, add ) {\n\t\tvar name;\n\n\t\tif ( jQuery.isArray( obj ) ) {\n\n\t\t\t// Serialize array item.\n\t\t\tjQuery.each( obj, function( i, v ) {\n\t\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\t\tadd( prefix, v );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\t\tbuildParams(\n\t\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\t\tv,\n\t\t\t\t\t\ttraditional,\n\t\t\t\t\t\tadd\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\n\t\t\t// Serialize object item.\n\t\t\tfor ( name in obj ) {\n\t\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// Serialize scalar item.\n\t\t\tadd( prefix, obj );\n\t\t}\n\t}\n\n\t// Serialize an array of form elements or a set of\n\t// key/values into a query string\n\tjQuery.param = function( a, traditional ) {\n\t\tvar prefix,\n\t\t\ts = [],\n\t\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t\t// If value is a function, invoke it and use its return value\n\t\t\t\tvar value = jQuery.isFunction( valueOrFunction ) ?\n\t\t\t\t\tvalueOrFunction() :\n\t\t\t\t\tvalueOrFunction;\n\n\t\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t\t};\n\n\t\t// If an array was passed in, assume that it is an array of form elements.\n\t\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t\t// Serialize the form elements\n\t\t\tjQuery.each( a, function() {\n\t\t\t\tadd( this.name, this.value );\n\t\t\t} );\n\n\t\t} else {\n\n\t\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t\t// did it), otherwise encode params recursively.\n\t\t\tfor ( prefix in a ) {\n\t\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t\t}\n\t\t}\n\n\t\t// Return the resulting serialization\n\t\treturn s.join( \"&\" );\n\t};\n\n\tjQuery.fn.extend( {\n\t\tserialize: function() {\n\t\t\treturn jQuery.param( this.serializeArray() );\n\t\t},\n\t\tserializeArray: function() {\n\t\t\treturn this.map( function() {\n\n\t\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t\t} )\n\t\t\t.filter( function() {\n\t\t\t\tvar type = this.type;\n\n\t\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t\t} )\n\t\t\t.map( function( i, elem ) {\n\t\t\t\tvar val = jQuery( this ).val();\n\n\t\t\t\tif ( val == null ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t} ).get();\n\t\t}\n\t} );\n\n\n\tvar\n\t\tr20 = /%20/g,\n\t\trhash = /#.*$/,\n\t\trantiCache = /([?&])_=[^&]*/,\n\t\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\n\t\t// #7653, #8125, #8152: local protocol detection\n\t\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\t\trnoContent = /^(?:GET|HEAD)$/,\n\t\trprotocol = /^\\/\\//,\n\n\t\t/* Prefilters\n\t\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t\t * 2) These are called:\n\t\t *    - BEFORE asking for a transport\n\t\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t\t * 3) key is the dataType\n\t\t * 4) the catchall symbol \"*\" can be used\n\t\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t\t */\n\t\tprefilters = {},\n\n\t\t/* Transports bindings\n\t\t * 1) key is the dataType\n\t\t * 2) the catchall symbol \"*\" can be used\n\t\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t\t */\n\t\ttransports = {},\n\n\t\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\t\tallTypes = \"*/\".concat( \"*\" ),\n\n\t\t// Anchor tag for parsing the document origin\n\t\toriginAnchor = document.createElement( \"a\" );\n\t\toriginAnchor.href = location.href;\n\n\t// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\n\tfunction addToPrefiltersOrTransports( structure ) {\n\n\t\t// dataTypeExpression is optional and defaults to \"*\"\n\t\treturn function( dataTypeExpression, func ) {\n\n\t\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\t\tfunc = dataTypeExpression;\n\t\t\t\tdataTypeExpression = \"*\";\n\t\t\t}\n\n\t\t\tvar dataType,\n\t\t\t\ti = 0,\n\t\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];\n\n\t\t\tif ( jQuery.isFunction( func ) ) {\n\n\t\t\t\t// For each dataType in the dataTypeExpression\n\t\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\n\t\t\t\t\t// Prepend if requested\n\t\t\t\t\tif ( dataType[ 0 ] === \"+\" ) {\n\t\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );\n\n\t\t\t\t\t// Otherwise append\n\t\t\t\t\t} else {\n\t\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).push( func );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t// Base inspection function for prefilters and transports\n\tfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\t\tvar inspected = {},\n\t\t\tseekingTransport = ( structure === transports );\n\n\t\tfunction inspect( dataType ) {\n\t\t\tvar selected;\n\t\t\tinspected[ dataType ] = true;\n\t\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\t\tif ( typeof dataTypeOrTransport === \"string\" &&\n\t\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\n\t\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\t\treturn false;\n\t\t\t\t} else if ( seekingTransport ) {\n\t\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t\t}\n\t\t\t} );\n\t\t\treturn selected;\n\t\t}\n\n\t\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n\t}\n\n\t// A special extend for ajax options\n\t// that takes \"flat\" options (not to be deep extended)\n\t// Fixes #9887\n\tfunction ajaxExtend( target, src ) {\n\t\tvar key, deep,\n\t\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\t\tfor ( key in src ) {\n\t\t\tif ( src[ key ] !== undefined ) {\n\t\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t\t}\n\t\t}\n\t\tif ( deep ) {\n\t\t\tjQuery.extend( true, target, deep );\n\t\t}\n\n\t\treturn target;\n\t}\n\n\t/* Handles responses to an ajax request:\n\t * - finds the right dataType (mediates between content-type and expected dataType)\n\t * - returns the corresponding response\n\t */\n\tfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\t\tvar ct, type, finalDataType, firstDataType,\n\t\t\tcontents = s.contents,\n\t\t\tdataTypes = s.dataTypes;\n\n\t\t// Remove auto dataType and get content-type in the process\n\t\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\t\tdataTypes.shift();\n\t\t\tif ( ct === undefined ) {\n\t\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"Content-Type\" );\n\t\t\t}\n\t\t}\n\n\t\t// Check if we're dealing with a known content-type\n\t\tif ( ct ) {\n\t\t\tfor ( type in contents ) {\n\t\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\t\tdataTypes.unshift( type );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check to see if we have a response for the expected dataType\n\t\tif ( dataTypes[ 0 ] in responses ) {\n\t\t\tfinalDataType = dataTypes[ 0 ];\n\t\t} else {\n\n\t\t\t// Try convertible dataTypes\n\t\t\tfor ( type in responses ) {\n\t\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[ 0 ] ] ) {\n\t\t\t\t\tfinalDataType = type;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( !firstDataType ) {\n\t\t\t\t\tfirstDataType = type;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Or just use first one\n\t\t\tfinalDataType = finalDataType || firstDataType;\n\t\t}\n\n\t\t// If we found a dataType\n\t\t// We add the dataType to the list if needed\n\t\t// and return the corresponding response\n\t\tif ( finalDataType ) {\n\t\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\t\tdataTypes.unshift( finalDataType );\n\t\t\t}\n\t\t\treturn responses[ finalDataType ];\n\t\t}\n\t}\n\n\t/* Chain conversions given the request and the original response\n\t * Also sets the responseXXX fields on the jqXHR instance\n\t */\n\tfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\t\tvar conv2, current, conv, tmp, prev,\n\t\t\tconverters = {},\n\n\t\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\t\tdataTypes = s.dataTypes.slice();\n\n\t\t// Create converters map with lowercased keys\n\t\tif ( dataTypes[ 1 ] ) {\n\t\t\tfor ( conv in s.converters ) {\n\t\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t\t}\n\t\t}\n\n\t\tcurrent = dataTypes.shift();\n\n\t\t// Convert to each sequential dataType\n\t\twhile ( current ) {\n\n\t\t\tif ( s.responseFields[ current ] ) {\n\t\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t\t}\n\n\t\t\t// Apply the dataFilter if provided\n\t\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t\t}\n\n\t\t\tprev = current;\n\t\t\tcurrent = dataTypes.shift();\n\n\t\t\tif ( current ) {\n\n\t\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\t\tcurrent = prev;\n\n\t\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t\t// Seek a direct converter\n\t\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t\t// If none found, seek a pair\n\t\t\t\t\tif ( !conv ) {\n\t\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\t\tif ( conv ) {\n\n\t\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\t\tif ( conv && s.throws ) {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { state: \"success\", data: response };\n\t}\n\n\tjQuery.extend( {\n\n\t\t// Counter for holding the number of active queries\n\t\tactive: 0,\n\n\t\t// Last-Modified header cache for next request\n\t\tlastModified: {},\n\t\tetag: {},\n\n\t\tajaxSettings: {\n\t\t\turl: location.href,\n\t\t\ttype: \"GET\",\n\t\t\tisLocal: rlocalProtocol.test( location.protocol ),\n\t\t\tglobal: true,\n\t\t\tprocessData: true,\n\t\t\tasync: true,\n\t\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\n\t\t\t/*\n\t\t\ttimeout: 0,\n\t\t\tdata: null,\n\t\t\tdataType: null,\n\t\t\tusername: null,\n\t\t\tpassword: null,\n\t\t\tcache: null,\n\t\t\tthrows: false,\n\t\t\ttraditional: false,\n\t\t\theaders: {},\n\t\t\t*/\n\n\t\t\taccepts: {\n\t\t\t\t\"*\": allTypes,\n\t\t\t\ttext: \"text/plain\",\n\t\t\t\thtml: \"text/html\",\n\t\t\t\txml: \"application/xml, text/xml\",\n\t\t\t\tjson: \"application/json, text/javascript\"\n\t\t\t},\n\n\t\t\tcontents: {\n\t\t\t\txml: /\\bxml\\b/,\n\t\t\t\thtml: /\\bhtml/,\n\t\t\t\tjson: /\\bjson\\b/\n\t\t\t},\n\n\t\t\tresponseFields: {\n\t\t\t\txml: \"responseXML\",\n\t\t\t\ttext: \"responseText\",\n\t\t\t\tjson: \"responseJSON\"\n\t\t\t},\n\n\t\t\t// Data converters\n\t\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\t\tconverters: {\n\n\t\t\t\t// Convert anything to text\n\t\t\t\t\"* text\": String,\n\n\t\t\t\t// Text to html (true = no transformation)\n\t\t\t\t\"text html\": true,\n\n\t\t\t\t// Evaluate text as a json expression\n\t\t\t\t\"text json\": JSON.parse,\n\n\t\t\t\t// Parse text as xml\n\t\t\t\t\"text xml\": jQuery.parseXML\n\t\t\t},\n\n\t\t\t// For options that shouldn't be deep extended:\n\t\t\t// you can add your own custom options here if\n\t\t\t// and when you create one that shouldn't be\n\t\t\t// deep extended (see ajaxExtend)\n\t\t\tflatOptions: {\n\t\t\t\turl: true,\n\t\t\t\tcontext: true\n\t\t\t}\n\t\t},\n\n\t\t// Creates a full fledged settings object into target\n\t\t// with both ajaxSettings and settings fields.\n\t\t// If target is omitted, writes into ajaxSettings.\n\t\tajaxSetup: function( target, settings ) {\n\t\t\treturn settings ?\n\n\t\t\t\t// Building a settings object\n\t\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t\t// Extending ajaxSettings\n\t\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t\t},\n\n\t\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\t\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t\t// Main method\n\t\tajax: function( url, options ) {\n\n\t\t\t// If url is an object, simulate pre-1.5 signature\n\t\t\tif ( typeof url === \"object\" ) {\n\t\t\t\toptions = url;\n\t\t\t\turl = undefined;\n\t\t\t}\n\n\t\t\t// Force options to be an object\n\t\t\toptions = options || {};\n\n\t\t\tvar transport,\n\n\t\t\t\t// URL without anti-cache param\n\t\t\t\tcacheURL,\n\n\t\t\t\t// Response headers\n\t\t\t\tresponseHeadersString,\n\t\t\t\tresponseHeaders,\n\n\t\t\t\t// timeout handle\n\t\t\t\ttimeoutTimer,\n\n\t\t\t\t// Url cleanup var\n\t\t\t\turlAnchor,\n\n\t\t\t\t// Request state (becomes false upon send and true upon completion)\n\t\t\t\tcompleted,\n\n\t\t\t\t// To know if global events are to be dispatched\n\t\t\t\tfireGlobals,\n\n\t\t\t\t// Loop variable\n\t\t\t\ti,\n\n\t\t\t\t// uncached part of the url\n\t\t\t\tuncached,\n\n\t\t\t\t// Create the final options object\n\t\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t\t// Callbacks context\n\t\t\t\tcallbackContext = s.context || s,\n\n\t\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\t\tglobalEventContext = s.context &&\n\t\t\t\t\t( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\t\t\tjQuery.event,\n\n\t\t\t\t// Deferreds\n\t\t\t\tdeferred = jQuery.Deferred(),\n\t\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t\t// Headers (they are sent all at once)\n\t\t\t\trequestHeaders = {},\n\t\t\t\trequestHeadersNames = {},\n\n\t\t\t\t// Default abort message\n\t\t\t\tstrAbort = \"canceled\",\n\n\t\t\t\t// Fake xhr\n\t\t\t\tjqXHR = {\n\t\t\t\t\treadyState: 0,\n\n\t\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\t\tvar match;\n\t\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\t\twhile ( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\t\tresponseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Raw string\n\t\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\t\treturn completed ? responseHeadersString : null;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Caches the header\n\t\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\t\tname = requestHeadersNames[ name.toLowerCase() ] =\n\t\t\t\t\t\t\t\trequestHeadersNames[ name.toLowerCase() ] || name;\n\t\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Overrides response content-type header\n\t\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Status-dependent callbacks\n\t\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\t\tvar code;\n\t\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\t\tif ( completed ) {\n\n\t\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Lazy-add the new callbacks in a way that preserves old ones\n\t\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t},\n\n\t\t\t\t\t// Cancel the request\n\t\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t// Attach deferreds\n\t\t\tdeferred.promise( jqXHR );\n\n\t\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t\t// We also use the url parameter if available\n\t\t\ts.url = ( ( url || s.url || location.href ) + \"\" )\n\t\t\t\t.replace( rprotocol, location.protocol + \"//\" );\n\n\t\t\t// Alias method option to type as per ticket #12004\n\t\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t\t// Extract dataTypes list\n\t\t\ts.dataTypes = ( s.dataType || \"*\" ).toLowerCase().match( rnothtmlwhite ) || [ \"\" ];\n\n\t\t\t// A cross-domain request is in order when the origin doesn't match the current origin.\n\t\t\tif ( s.crossDomain == null ) {\n\t\t\t\turlAnchor = document.createElement( \"a\" );\n\n\t\t\t\t// Support: IE <=8 - 11, Edge 12 - 13\n\t\t\t\t// IE throws exception on accessing the href property if url is malformed,\n\t\t\t\t// e.g. http://example.com:80x/\n\t\t\t\ttry {\n\t\t\t\t\turlAnchor.href = s.url;\n\n\t\t\t\t\t// Support: IE <=8 - 11 only\n\t\t\t\t\t// Anchor's host property isn't correctly set when s.url is relative\n\t\t\t\t\turlAnchor.href = urlAnchor.href;\n\t\t\t\t\ts.crossDomain = originAnchor.protocol + \"//\" + originAnchor.host !==\n\t\t\t\t\t\turlAnchor.protocol + \"//\" + urlAnchor.host;\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// If there is an error parsing the URL, assume it is crossDomain,\n\t\t\t\t\t// it can be rejected by the transport if it is invalid\n\t\t\t\t\ts.crossDomain = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Convert data if not already a string\n\t\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t\t}\n\n\t\t\t// Apply prefilters\n\t\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t\t// If request was aborted inside a prefilter, stop there\n\t\t\tif ( completed ) {\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// We can fire global events as of now if asked to\n\t\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t\t// Watch for a new set of requests\n\t\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t\t}\n\n\t\t\t// Uppercase the type\n\t\t\ts.type = s.type.toUpperCase();\n\n\t\t\t// Determine if request has content\n\t\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t\t// and/or If-None-Match header later on\n\t\t\t// Remove hash to simplify url manipulation\n\t\t\tcacheURL = s.url.replace( rhash, \"\" );\n\n\t\t\t// More options handling for requests with no content\n\t\t\tif ( !s.hasContent ) {\n\n\t\t\t\t// Remember the hash so we can put it back\n\t\t\t\tuncached = s.url.slice( cacheURL.length );\n\n\t\t\t\t// If data is available, append data to url\n\t\t\t\tif ( s.data ) {\n\t\t\t\t\tcacheURL += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data;\n\n\t\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\t\tdelete s.data;\n\t\t\t\t}\n\n\t\t\t\t// Add or update anti-cache param if needed\n\t\t\t\tif ( s.cache === false ) {\n\t\t\t\t\tcacheURL = cacheURL.replace( rantiCache, \"$1\" );\n\t\t\t\t\tuncached = ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ( nonce++ ) + uncached;\n\t\t\t\t}\n\n\t\t\t\t// Put hash and anti-cache on the URL that will be requested (gh-1732)\n\t\t\t\ts.url = cacheURL + uncached;\n\n\t\t\t// Change '%20' to '+' if this is encoded form body content (gh-2658)\n\t\t\t} else if ( s.data && s.processData &&\n\t\t\t\t( s.contentType || \"\" ).indexOf( \"application/x-www-form-urlencoded\" ) === 0 ) {\n\t\t\t\ts.data = s.data.replace( r20, \"+\" );\n\t\t\t}\n\n\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\tif ( s.ifModified ) {\n\t\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t\t}\n\t\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the correct header, if data is being sent\n\t\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t\t}\n\n\t\t\t// Set the Accepts header for the server, depending on the dataType\n\t\t\tjqXHR.setRequestHeader(\n\t\t\t\t\"Accept\",\n\t\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?\n\t\t\t\t\ts.accepts[ s.dataTypes[ 0 ] ] +\n\t\t\t\t\t\t( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\t\ts.accepts[ \"*\" ]\n\t\t\t);\n\n\t\t\t// Check for headers option\n\t\t\tfor ( i in s.headers ) {\n\t\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t\t}\n\n\t\t\t// Allow custom headers/mimetypes and early abort\n\t\t\tif ( s.beforeSend &&\n\t\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {\n\n\t\t\t\t// Abort if not done already and return\n\t\t\t\treturn jqXHR.abort();\n\t\t\t}\n\n\t\t\t// Aborting is no longer a cancellation\n\t\t\tstrAbort = \"abort\";\n\n\t\t\t// Install callbacks on deferreds\n\t\t\tcompleteDeferred.add( s.complete );\n\t\t\tjqXHR.done( s.success );\n\t\t\tjqXHR.fail( s.error );\n\n\t\t\t// Get transport\n\t\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t\t// If no transport, we auto-abort\n\t\t\tif ( !transport ) {\n\t\t\t\tdone( -1, \"No Transport\" );\n\t\t\t} else {\n\t\t\t\tjqXHR.readyState = 1;\n\n\t\t\t\t// Send global event\n\t\t\t\tif ( fireGlobals ) {\n\t\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t\t}\n\n\t\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\t\tif ( completed ) {\n\t\t\t\t\treturn jqXHR;\n\t\t\t\t}\n\n\t\t\t\t// Timeout\n\t\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\t\ttimeoutTimer = window.setTimeout( function() {\n\t\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t\t}, s.timeout );\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tcompleted = false;\n\t\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// Rethrow post-completion exceptions\n\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Propagate others as results\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Callback for when everything is done\n\t\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t\t// Ignore repeat invocations\n\t\t\t\tif ( completed ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcompleted = true;\n\n\t\t\t\t// Clear timeout if it exists\n\t\t\t\tif ( timeoutTimer ) {\n\t\t\t\t\twindow.clearTimeout( timeoutTimer );\n\t\t\t\t}\n\n\t\t\t\t// Dereference transport for early garbage collection\n\t\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\t\ttransport = undefined;\n\n\t\t\t\t// Cache response headers\n\t\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t\t// Set readyState\n\t\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t\t// Determine if successful\n\t\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t\t// Get response data\n\t\t\t\tif ( responses ) {\n\t\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t\t}\n\n\t\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t\t// If successful, handle type chaining\n\t\t\t\tif ( isSuccess ) {\n\n\t\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"Last-Modified\" );\n\t\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"etag\" );\n\t\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// if no content\n\t\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t\t// if not modified\n\t\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t\t// If we have data, let's convert it\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\t\terror = response.error;\n\t\t\t\t\t\tisSuccess = !error;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\t\terror = statusText;\n\t\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Set data for the fake xhr object\n\t\t\t\tjqXHR.status = status;\n\t\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t\t// Success/Error\n\t\t\t\tif ( isSuccess ) {\n\t\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t\t}\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tjqXHR.statusCode( statusCode );\n\t\t\t\tstatusCode = undefined;\n\n\t\t\t\tif ( fireGlobals ) {\n\t\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t\t}\n\n\t\t\t\t// Complete\n\t\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\t\tif ( fireGlobals ) {\n\t\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\n\t\t\t\t\t// Handle the global AJAX counter\n\t\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn jqXHR;\n\t\t},\n\n\t\tgetJSON: function( url, data, callback ) {\n\t\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t\t},\n\n\t\tgetScript: function( url, callback ) {\n\t\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t\t}\n\t} );\n\n\tjQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\t\tjQuery[ method ] = function( url, data, callback, type ) {\n\n\t\t\t// Shift arguments if data argument was omitted\n\t\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\t\ttype = type || callback;\n\t\t\t\tcallback = data;\n\t\t\t\tdata = undefined;\n\t\t\t}\n\n\t\t\t// The url can be an options object (which then must have .url)\n\t\t\treturn jQuery.ajax( jQuery.extend( {\n\t\t\t\turl: url,\n\t\t\t\ttype: method,\n\t\t\t\tdataType: type,\n\t\t\t\tdata: data,\n\t\t\t\tsuccess: callback\n\t\t\t}, jQuery.isPlainObject( url ) && url ) );\n\t\t};\n\t} );\n\n\n\tjQuery._evalUrl = function( url ) {\n\t\treturn jQuery.ajax( {\n\t\t\turl: url,\n\n\t\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\t\ttype: \"GET\",\n\t\t\tdataType: \"script\",\n\t\t\tcache: true,\n\t\t\tasync: false,\n\t\t\tglobal: false,\n\t\t\t\"throws\": true\n\t\t} );\n\t};\n\n\n\tjQuery.fn.extend( {\n\t\twrapAll: function( html ) {\n\t\t\tvar wrap;\n\n\t\t\tif ( this[ 0 ] ) {\n\t\t\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\t// The elements to wrap the target around\n\t\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\twrap.map( function() {\n\t\t\t\t\tvar elem = this;\n\n\t\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn elem;\n\t\t\t\t} ).append( this );\n\t\t\t}\n\n\t\t\treturn this;\n\t\t},\n\n\t\twrapInner: function( html ) {\n\t\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\t\treturn this.each( function( i ) {\n\t\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\tvar self = jQuery( this ),\n\t\t\t\t\tcontents = self.contents();\n\n\t\t\t\tif ( contents.length ) {\n\t\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t\t} else {\n\t\t\t\t\tself.append( html );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\twrap: function( html ) {\n\t\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );\n\t\t\t} );\n\t\t},\n\n\t\tunwrap: function( selector ) {\n\t\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t} );\n\t\t\treturn this;\n\t\t}\n\t} );\n\n\n\tjQuery.expr.pseudos.hidden = function( elem ) {\n\t\treturn !jQuery.expr.pseudos.visible( elem );\n\t};\n\tjQuery.expr.pseudos.visible = function( elem ) {\n\t\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n\t};\n\n\n\n\n\tjQuery.ajaxSettings.xhr = function() {\n\t\ttry {\n\t\t\treturn new window.XMLHttpRequest();\n\t\t} catch ( e ) {}\n\t};\n\n\tvar xhrSuccessStatus = {\n\n\t\t\t// File protocol always yields status code 0, assume 200\n\t\t\t0: 200,\n\n\t\t\t// Support: IE <=9 only\n\t\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t\t1223: 204\n\t\t},\n\t\txhrSupported = jQuery.ajaxSettings.xhr();\n\n\tsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\n\tsupport.ajax = xhrSupported = !!xhrSupported;\n\n\tjQuery.ajaxTransport( function( options ) {\n\t\tvar callback, errorCallback;\n\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\t\t\t\t\tvar i,\n\t\t\t\t\t\txhr = options.xhr();\n\n\t\t\t\t\txhr.open(\n\t\t\t\t\t\toptions.type,\n\t\t\t\t\t\toptions.url,\n\t\t\t\t\t\toptions.async,\n\t\t\t\t\t\toptions.username,\n\t\t\t\t\t\toptions.password\n\t\t\t\t\t);\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !options.crossDomain && !headers[ \"X-Requested-With\" ] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set headers\n\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Callback\n\t\t\t\t\tcallback = function( type ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\tcallback = errorCallback = xhr.onload =\n\t\t\t\t\t\t\t\t\txhr.onerror = xhr.onabort = xhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\n\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t// On a manual native abort, IE9 throws\n\t\t\t\t\t\t\t\t\t// errors on any property access that is not readyState\n\t\t\t\t\t\t\t\t\tif ( typeof xhr.status !== \"number\" ) {\n\t\t\t\t\t\t\t\t\t\tcomplete( 0, \"error\" );\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tcomplete(\n\n\t\t\t\t\t\t\t\t\t\t\t// File: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\t\txhr.statusText,\n\n\t\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t\t// IE9 has no XHR2 but throws on binary (trac-11426)\n\t\t\t\t\t\t\t\t\t\t// For XHR2 non-text, let the caller handle it (gh-2498)\n\t\t\t\t\t\t\t\t\t\t( xhr.responseType || \"text\" ) !== \"text\"  ||\n\t\t\t\t\t\t\t\t\t\ttypeof xhr.responseText !== \"string\" ?\n\t\t\t\t\t\t\t\t\t\t\t{ binary: xhr.response } :\n\t\t\t\t\t\t\t\t\t\t\t{ text: xhr.responseText },\n\t\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\n\t\t\t\t\t// Listen to events\n\t\t\t\t\txhr.onload = callback();\n\t\t\t\t\terrorCallback = xhr.onerror = callback( \"error\" );\n\n\t\t\t\t\t// Support: IE 9 only\n\t\t\t\t\t// Use onreadystatechange to replace onabort\n\t\t\t\t\t// to handle uncaught aborts\n\t\t\t\t\tif ( xhr.onabort !== undefined ) {\n\t\t\t\t\t\txhr.onabort = errorCallback;\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.onreadystatechange = function() {\n\n\t\t\t\t\t\t\t// Check readyState before timeout as it changes\n\t\t\t\t\t\t\tif ( xhr.readyState === 4 ) {\n\n\t\t\t\t\t\t\t\t// Allow onerror to be called first,\n\t\t\t\t\t\t\t\t// but that will not handle a native abort\n\t\t\t\t\t\t\t\t// Also, save errorCallback to a variable\n\t\t\t\t\t\t\t\t// as xhr.onerror cannot be accessed\n\t\t\t\t\t\t\t\twindow.setTimeout( function() {\n\t\t\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\t\t\terrorCallback();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create the abort callback\n\t\t\t\t\tcallback = callback( \"abort\" );\n\n\t\t\t\t\ttry {\n\n\t\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tthrow e;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t} );\n\n\n\n\n\t// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)\n\tjQuery.ajaxPrefilter( function( s ) {\n\t\tif ( s.crossDomain ) {\n\t\t\ts.contents.script = false;\n\t\t}\n\t} );\n\n\t// Install script dataType\n\tjQuery.ajaxSetup( {\n\t\taccepts: {\n\t\t\tscript: \"text/javascript, application/javascript, \" +\n\t\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t\t},\n\t\tcontents: {\n\t\t\tscript: /\\b(?:java|ecma)script\\b/\n\t\t},\n\t\tconverters: {\n\t\t\t\"text script\": function( text ) {\n\t\t\t\tjQuery.globalEval( text );\n\t\t\t\treturn text;\n\t\t\t}\n\t\t}\n\t} );\n\n\t// Handle cache's special case and crossDomain\n\tjQuery.ajaxPrefilter( \"script\", function( s ) {\n\t\tif ( s.cache === undefined ) {\n\t\t\ts.cache = false;\n\t\t}\n\t\tif ( s.crossDomain ) {\n\t\t\ts.type = \"GET\";\n\t\t}\n\t} );\n\n\t// Bind script tag hack transport\n\tjQuery.ajaxTransport( \"script\", function( s ) {\n\n\t\t// This transport only deals with cross domain requests\n\t\tif ( s.crossDomain ) {\n\t\t\tvar script, callback;\n\t\t\treturn {\n\t\t\t\tsend: function( _, complete ) {\n\t\t\t\t\tscript = jQuery( \"<script>\" ).prop( {\n\t\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\t\tsrc: s.url\n\t\t\t\t\t} ).on(\n\t\t\t\t\t\t\"load error\",\n\t\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t\t},\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t} );\n\n\n\n\n\tvar oldCallbacks = [],\n\t\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n\t// Default jsonp settings\n\tjQuery.ajaxSetup( {\n\t\tjsonp: \"callback\",\n\t\tjsonpCallback: function() {\n\t\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\t\tthis[ callback ] = true;\n\t\t\treturn callback;\n\t\t}\n\t} );\n\n\t// Detect, normalize options and install callbacks for jsonp requests\n\tjQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\t\tvar callbackName, overwritten, responseContainer,\n\t\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\t\"url\" :\n\t\t\t\ttypeof s.data === \"string\" &&\n\t\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\t\trjsonp.test( s.data ) && \"data\"\n\t\t\t);\n\n\t\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\t\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t\t// Get callback name, remembering preexisting value associated with it\n\t\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\t\ts.jsonpCallback() :\n\t\t\t\ts.jsonpCallback;\n\n\t\t\t// Insert callback into url or form data\n\t\t\tif ( jsonProp ) {\n\t\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t\t} else if ( s.jsonp !== false ) {\n\t\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t\t}\n\n\t\t\t// Use data converter to retrieve json after script execution\n\t\t\ts.converters[ \"script json\" ] = function() {\n\t\t\t\tif ( !responseContainer ) {\n\t\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t\t}\n\t\t\t\treturn responseContainer[ 0 ];\n\t\t\t};\n\n\t\t\t// Force json dataType\n\t\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t\t// Install callback\n\t\t\toverwritten = window[ callbackName ];\n\t\t\twindow[ callbackName ] = function() {\n\t\t\t\tresponseContainer = arguments;\n\t\t\t};\n\n\t\t\t// Clean-up function (fires after converters)\n\t\t\tjqXHR.always( function() {\n\n\t\t\t\t// If previous value didn't exist - remove it\n\t\t\t\tif ( overwritten === undefined ) {\n\t\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t\t// Otherwise restore preexisting value\n\t\t\t\t} else {\n\t\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t\t}\n\n\t\t\t\t// Save back as free\n\t\t\t\tif ( s[ callbackName ] ) {\n\n\t\t\t\t\t// Make sure that re-using the options doesn't screw things around\n\t\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t\t// Save the callback name for future use\n\t\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t\t}\n\n\t\t\t\t// Call if it was a function and we have a response\n\t\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\tresponseContainer = overwritten = undefined;\n\t\t\t} );\n\n\t\t\t// Delegate to script\n\t\t\treturn \"script\";\n\t\t}\n\t} );\n\n\n\n\n\t// Support: Safari 8 only\n\t// In Safari 8 documents created via document.implementation.createHTMLDocument\n\t// collapse sibling forms: the second one becomes a child of the first one.\n\t// Because of that, this security measure has to be disabled in Safari 8.\n\t// https://bugs.webkit.org/show_bug.cgi?id=137337\n\tsupport.createHTMLDocument = ( function() {\n\t\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\t\tbody.innerHTML = \"<form></form><form></form>\";\n\t\treturn body.childNodes.length === 2;\n\t} )();\n\n\n\t// Argument \"data\" should be string of html\n\t// context (optional): If specified, the fragment will be created in this context,\n\t// defaults to document\n\t// keepScripts (optional): If true, will include scripts passed in the html string\n\tjQuery.parseHTML = function( data, context, keepScripts ) {\n\t\tif ( typeof data !== \"string\" ) {\n\t\t\treturn [];\n\t\t}\n\t\tif ( typeof context === \"boolean\" ) {\n\t\t\tkeepScripts = context;\n\t\t\tcontext = false;\n\t\t}\n\n\t\tvar base, parsed, scripts;\n\n\t\tif ( !context ) {\n\n\t\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t\t// by using document.implementation\n\t\t\tif ( support.createHTMLDocument ) {\n\t\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t\t// Set the base href for the created document\n\t\t\t\t// so any parsed elements with URLs\n\t\t\t\t// are based on the document's URL (gh-2965)\n\t\t\t\tbase = context.createElement( \"base\" );\n\t\t\t\tbase.href = document.location.href;\n\t\t\t\tcontext.head.appendChild( base );\n\t\t\t} else {\n\t\t\t\tcontext = document;\n\t\t\t}\n\t\t}\n\n\t\tparsed = rsingleTag.exec( data );\n\t\tscripts = !keepScripts && [];\n\n\t\t// Single tag\n\t\tif ( parsed ) {\n\t\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t\t}\n\n\t\tparsed = buildFragment( [ data ], context, scripts );\n\n\t\tif ( scripts && scripts.length ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t};\n\n\n\t/**\n\t * Load a url into a page\n\t */\n\tjQuery.fn.load = function( url, params, callback ) {\n\t\tvar selector, type, response,\n\t\t\tself = this,\n\t\t\toff = url.indexOf( \" \" );\n\n\t\tif ( off > -1 ) {\n\t\t\tselector = stripAndCollapse( url.slice( off ) );\n\t\t\turl = url.slice( 0, off );\n\t\t}\n\n\t\t// If it's a function\n\t\tif ( jQuery.isFunction( params ) ) {\n\n\t\t\t// We assume that it's the callback\n\t\t\tcallback = params;\n\t\t\tparams = undefined;\n\n\t\t// Otherwise, build a param string\n\t\t} else if ( params && typeof params === \"object\" ) {\n\t\t\ttype = \"POST\";\n\t\t}\n\n\t\t// If we have elements to modify, make the request\n\t\tif ( self.length > 0 ) {\n\t\t\tjQuery.ajax( {\n\t\t\t\turl: url,\n\n\t\t\t\t// If \"type\" variable is undefined, then \"GET\" method will be used.\n\t\t\t\t// Make value of this field explicit since\n\t\t\t\t// user can override it through ajaxSetup method\n\t\t\t\ttype: type || \"GET\",\n\t\t\t\tdataType: \"html\",\n\t\t\t\tdata: params\n\t\t\t} ).done( function( responseText ) {\n\n\t\t\t\t// Save response for use in complete callback\n\t\t\t\tresponse = arguments;\n\n\t\t\t\tself.html( selector ?\n\n\t\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\t\tjQuery( \"<div>\" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t\t// Otherwise use the full result\n\t\t\t\t\tresponseText );\n\n\t\t\t// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t\t// but they are ignored because response was set above.\n\t\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\t\tself.each( function() {\n\t\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t\t} );\n\t\t\t} );\n\t\t}\n\n\t\treturn this;\n\t};\n\n\n\n\n\t// Attach a bunch of functions for handling common AJAX events\n\tjQuery.each( [\n\t\t\"ajaxStart\",\n\t\t\"ajaxStop\",\n\t\t\"ajaxComplete\",\n\t\t\"ajaxError\",\n\t\t\"ajaxSuccess\",\n\t\t\"ajaxSend\"\n\t], function( i, type ) {\n\t\tjQuery.fn[ type ] = function( fn ) {\n\t\t\treturn this.on( type, fn );\n\t\t};\n\t} );\n\n\n\n\n\tjQuery.expr.pseudos.animated = function( elem ) {\n\t\treturn jQuery.grep( jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t} ).length;\n\t};\n\n\n\n\n\t/**\n\t * Gets a window from an element\n\t */\n\tfunction getWindow( elem ) {\n\t\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n\t}\n\n\tjQuery.offset = {\n\t\tsetOffset: function( elem, options, i ) {\n\t\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\t\tcurElem = jQuery( elem ),\n\t\t\t\tprops = {};\n\n\t\t\t// Set position first, in-case top/left are set even on static elem\n\t\t\tif ( position === \"static\" ) {\n\t\t\t\telem.style.position = \"relative\";\n\t\t\t}\n\n\t\t\tcurOffset = curElem.offset();\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t\t// Need to be able to calculate position if either\n\t\t\t// top or left is auto and position is either absolute or fixed\n\t\t\tif ( calculatePosition ) {\n\t\t\t\tcurPosition = curElem.position();\n\t\t\t\tcurTop = curPosition.top;\n\t\t\t\tcurLeft = curPosition.left;\n\n\t\t\t} else {\n\t\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t\t}\n\n\t\t\tif ( jQuery.isFunction( options ) ) {\n\n\t\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t\t}\n\n\t\t\tif ( options.top != null ) {\n\t\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t\t}\n\t\t\tif ( options.left != null ) {\n\t\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t\t}\n\n\t\t\tif ( \"using\" in options ) {\n\t\t\t\toptions.using.call( elem, props );\n\n\t\t\t} else {\n\t\t\t\tcurElem.css( props );\n\t\t\t}\n\t\t}\n\t};\n\n\tjQuery.fn.extend( {\n\t\toffset: function( options ) {\n\n\t\t\t// Preserve chaining for setter\n\t\t\tif ( arguments.length ) {\n\t\t\t\treturn options === undefined ?\n\t\t\t\t\tthis :\n\t\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t\t} );\n\t\t\t}\n\n\t\t\tvar docElem, win, rect, doc,\n\t\t\t\telem = this[ 0 ];\n\n\t\t\tif ( !elem ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Support: IE <=11 only\n\t\t\t// Running getBoundingClientRect on a\n\t\t\t// disconnected node in IE throws an error\n\t\t\tif ( !elem.getClientRects().length ) {\n\t\t\t\treturn { top: 0, left: 0 };\n\t\t\t}\n\n\t\t\trect = elem.getBoundingClientRect();\n\n\t\t\t// Make sure element is not hidden (display: none)\n\t\t\tif ( rect.width || rect.height ) {\n\t\t\t\tdoc = elem.ownerDocument;\n\t\t\t\twin = getWindow( doc );\n\t\t\t\tdocElem = doc.documentElement;\n\n\t\t\t\treturn {\n\t\t\t\t\ttop: rect.top + win.pageYOffset - docElem.clientTop,\n\t\t\t\t\tleft: rect.left + win.pageXOffset - docElem.clientLeft\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Return zeros for disconnected and hidden elements (gh-2310)\n\t\t\treturn rect;\n\t\t},\n\n\t\tposition: function() {\n\t\t\tif ( !this[ 0 ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar offsetParent, offset,\n\t\t\t\telem = this[ 0 ],\n\t\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0},\n\t\t\t// because it is its only offset parent\n\t\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t\t} else {\n\n\t\t\t\t// Get *real* offsetParent\n\t\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t\t// Get correct offsets\n\t\t\t\toffset = this.offset();\n\t\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t\t}\n\n\t\t\t\t// Add offsetParent borders\n\t\t\t\tparentOffset = {\n\t\t\t\t\ttop: parentOffset.top + jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true ),\n\t\t\t\t\tleft: parentOffset.left + jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Subtract parent offsets and element margins\n\t\t\treturn {\n\t\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t\t};\n\t\t},\n\n\t\t// This method will return documentElement in the following cases:\n\t\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t\t//    documentElement of the parent window\n\t\t// 2) For the hidden or detached element\n\t\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t\t//\n\t\t// but those exceptions were never presented as a real life use-cases\n\t\t// and might be considered as more preferable results.\n\t\t//\n\t\t// This logic, however, is not guaranteed and can change at any point in the future\n\t\toffsetParent: function() {\n\t\t\treturn this.map( function() {\n\t\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t\t}\n\n\t\t\t\treturn offsetParent || documentElement;\n\t\t\t} );\n\t\t}\n\t} );\n\n\t// Create scrollLeft and scrollTop methods\n\tjQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\t\tvar top = \"pageYOffset\" === prop;\n\n\t\tjQuery.fn[ method ] = function( val ) {\n\t\t\treturn access( this, function( elem, method, val ) {\n\t\t\t\tvar win = getWindow( elem );\n\n\t\t\t\tif ( val === undefined ) {\n\t\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t\t}\n\n\t\t\t\tif ( win ) {\n\t\t\t\t\twin.scrollTo(\n\t\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t\t);\n\n\t\t\t\t} else {\n\t\t\t\t\telem[ method ] = val;\n\t\t\t\t}\n\t\t\t}, method, val, arguments.length );\n\t\t};\n\t} );\n\n\t// Support: Safari <=7 - 9.1, Chrome <=37 - 49\n\t// Add the top/left cssHooks using jQuery.fn.position\n\t// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n\t// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n\t// getComputedStyle returns percent when specified for top/left/bottom/right;\n\t// rather than make the css module depend on the offset module, just check for it here\n\tjQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\t\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\t\tfunction( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\t\tcomputed;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t} );\n\n\n\t// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\n\tjQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\t\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\t\tfunction( defaultExtra, funcName ) {\n\n\t\t\t// Margin is only for outerHeight, outerWidth\n\t\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\t\tvar doc;\n\n\t\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Get document width or height\n\t\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t\t// whichever is greatest\n\t\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t\t};\n\t\t} );\n\t} );\n\n\n\tjQuery.fn.extend( {\n\n\t\tbind: function( types, data, fn ) {\n\t\t\treturn this.on( types, null, data, fn );\n\t\t},\n\t\tunbind: function( types, fn ) {\n\t\t\treturn this.off( types, null, fn );\n\t\t},\n\n\t\tdelegate: function( selector, types, data, fn ) {\n\t\t\treturn this.on( types, selector, data, fn );\n\t\t},\n\t\tundelegate: function( selector, types, fn ) {\n\n\t\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\t\treturn arguments.length === 1 ?\n\t\t\t\tthis.off( selector, \"**\" ) :\n\t\t\t\tthis.off( types, selector || \"**\", fn );\n\t\t}\n\t} );\n\n\tjQuery.parseJSON = JSON.parse;\n\n\n\n\n\t// Register as a named AMD module, since jQuery can be concatenated with other\n\t// files that may use define, but not via a proper concatenation script that\n\t// understands anonymous AMD modules. A named AMD is safest and most robust\n\t// way to register. Lowercase jquery is used because AMD module names are\n\t// derived from file names, and jQuery is normally delivered in a lowercase\n\t// file name. Do this after creating the global so that if an AMD module wants\n\t// to call noConflict to hide this version of jQuery, it will work.\n\n\t// Note that for maximum portability, libraries that are not jQuery should\n\t// declare themselves as anonymous modules, and avoid setting a global if an\n\t// AMD loader is present. jQuery is a special case. For more information, see\n\t// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\n\tif ( true ) {\n\t\t!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {\n\t\t\treturn jQuery;\n\t\t}.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t}\n\n\n\n\n\tvar\n\n\t\t// Map over jQuery in case of overwrite\n\t\t_jQuery = window.jQuery,\n\n\t\t// Map over the $ in case of overwrite\n\t\t_$ = window.$;\n\n\tjQuery.noConflict = function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t};\n\n\t// Expose jQuery and $ identifiers, even in AMD\n\t// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n\t// and CommonJS for browser emulators (#13566)\n\tif ( !noGlobal ) {\n\t\twindow.jQuery = window.$ = jQuery;\n\t}\n\n\n\n\n\n\treturn jQuery;\n\t} );\n\n\n/***/ }\n/******/ ]);"
  },
  {
    "path": "30-jstraining/demos/simple-app-demo/index.html",
    "content": "<html>\n  <body>\n    <h1>Hello World</h1>\n    <script src=\"bundle.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/simple-app-demo/package.json",
    "content": "{\n  \"name\": \"simple-app-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"build\": \"webpack app.js bundle.js\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"jquery\": \"^3.1.1\",\n    \"webpack\": \"^1.13.3\"\n  }\n}\n"
  },
  {
    "path": "30-jstraining/demos/vue-demo/app1.js",
    "content": "var journal = new Vue({\n  el: '#journal',\n  data: {\n    message: 'Your first entry'\n  }\n});\n"
  },
  {
    "path": "30-jstraining/demos/vue-demo/app2.js",
    "content": "var myModel = {\n  name: 'Ashley',\n  age: 24,\n  friends: [{\n    name: 'Bob',\n    age: 21\n  }, {\n    name: 'Jane',\n    age: 20\n  }, {\n    name: 'Anna',\n    age: 29\n  }],\n  search: ''\n};\n\nvar myViewModel = new Vue({\n  el: '#my_view',\n  data: myModel\n});\n"
  },
  {
    "path": "30-jstraining/demos/vue-demo/app3.js",
    "content": "new Vue({\n  el: '#app',\n  data: {\n    counter: 0\n  },\n  methods: {\n    increment() {\n      this.counter++;\n    }\n  }\n});\n"
  },
  {
    "path": "30-jstraining/demos/vue-demo/index1.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Vue Demo</title>\n  </head>\n  <body>\n    <div id=\"journal\">\n      <input type=\"text\" v-model=\"message\">\n      <div>{{message}}</div>\n    </div>\n    <script src=\"vue.min.js\"></script>\n    <script src=\"app1.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/vue-demo/index2.html",
    "content": "<!DOCTYPE html>\n<html >\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Vue Demo</title>\n  </head>\n  <body>\n    <div id=\"my_view\">\n      搜索：<input v-model=\"search\" type=\"text\" />\n    <ul>\n      <li v-for=\"friend in friends | filterBy search in 'name'\"> {{ friend.name }} </li>\n    </ul>\n    </div>\n    <script src=\"vue.min.js\"></script>\n    <script src=\"app2.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/demos/vue-demo/index3.html",
    "content": "<!DOCTYPE html>\n<html >\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>Vue Demo</title>\n  </head>\n  <body>\n    <div id=\"app\">\n      <div>{{ counter }}</div>\n      <button v-on:click=\"increment\">Increment</button>\n    </div>\n    <script src=\"vue.min.js\"></script>\n    <script src=\"app3.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "30-jstraining/docs/engineering.md",
    "content": "# 前端工程简介\n\n---\n\n## 持续集成流程\n\n前端开发转移到后端环境，意味着可以适用标准的软件工程流程。\n\n1. 本地开发（developing）\n1. 静态代码检查（linting）\n1. 单元测试（testing）\n1. 合并进入主干（merging）\n1. 自动构建（building）\n1. 自动发布（publishing）\n\n---\n\n## 持续集成的概念\n\nContinuous integration（简称 CI）：\n\n开发代码频繁地合并进主干，始终保持可发布状态的这个过程。\n\n优点\n\n- 快速发现错误\n- 防止分支大幅偏离主干\n- 让产品可以快速迭代，同时还能保持高质量\n\n---\n\n## ESLint：静态代码检查工具\n\n- 发现语法错误\n- 发现风格错误\n- 自动纠正错误\n\n![](./images/eslint.png)\n\n---\n\n## 课堂练习：ESLint 的用法\n\n进入`demos/eslint-demo`目录，按照[《操作指南》](../demos/README.md#eslint)，完成练习。\n\n---\n\n## 为什么写测试？\n\nWeb 应用越来越复杂，意味着更可能出错。测试是提高代码质量、降低错误的最好方法之一。\n\n- 测试可以确保得到预期结果。\n- 加快开发速度。\n- 方便维护。\n- 提供用法的文档。\n\n对于长期维护的项目，测试会大大加快开发速度，减轻维护难度。\n\n---\n\n## 测试的类型\n\n- 单元测试（unit testing）\n- 功能测试（feature testing）\n- 集成测试（integration testing）\n- 端对端测试 (End-to-End testing）\n\n\n---\n\n## 以测试为导向的开发模式\n\n- TDD：测试驱动的开发（Test-Driven Development）\n- BDD：行为驱动的开发（Behavior-Driven Development）\n\n---\n\n## TDD vs. BDD\n\n两者侧重点不一样\n\n- TDD：基于开发者角度，重点测试函数的输入输出\n- BDD：基于使用者角度，重点测试对用户行为的反应\n\n比如，有一个计数器函数`counter`，TDD 测试的是输入1，输出的应该是2；BDD 测试的是用户访问以后，计数器应该增加一次。\n\n---\n\n## Mocha\n\nMocha 是目前最常用的测试框架。\n\n![](./images/mocha.png)\n\n---\n\n## 课堂练习：Mocha 的用法\n\n进入`demos/mocha-demo`目录，按照[《操作指南》](../demos/README.md#mocha)，练习写单元测试。\n\n---\n\n## 功能测试\n\n功能测试指的是，站在外部用户的角度，测试软件的某项功能。\n\n与内部代码实现无关，只测试功能是否正常。\n\n很多时候，单元测试都可以通过，但是整体功能会失败。\n\n![](./images/functional-test.jpg)\n\n---\n\n## 前端的功能测试\n\n功能测试必须在真正浏览器做，现在有四种方法。\n\n- 使用本机安装的浏览器\n- 使用 Selenium Driver\n- 使用 PhantomJS\n- 使用 Electron\n\n---\n\n## Nightmare\n\n- 使用 Electron 模拟真实浏览器环境\n- 提供大量人性化、易用的 API\n- 官网：nightmarejs.org\n\n---\n\n## 示例：Nightmare\n\n打开`demos/nightmare-demo/`，按照[《操作说明》](../demos/README.md#nightmare)，完成操作。\n\n---\n\n## 移动平台的自动化测试\n\n目前，最常见的方案是使用 Appium。\n\n- 基于 WebDriver\n- 采用 客户端/服务器架构\n- 可以在模拟器运行，也可以在真机运行\n\n---\n\n## Appium 测试流程\n\n1. WebDriver 客户端发出测试请求和测试内容\n1. Appium 服务器转发到相应的测试运行器（Driver）\n1. iOS 设备是 UIAutomation，安卓设备是 UiAutomator\n1. 测试运行器将运行结果，返回给 Appium\n\n---\n\n## 持续集成服务平台\n\n代码合并进主干以后，就可以进行自动构建和发布了。\n\n网上有很多 PaaS 平台，提供持续集成服务。\n\nTravis CI 就是其中最著名的一个，它可以根据你提供的脚本，自动完成构建和发布。\n\n![](./images/travis-ci.png)\n\n---\n\n## 课堂练习：Travis CI\n\n按照[《操作说明》](../demos/README.md#travis-ci)，完成练习。\n"
  },
  {
    "path": "30-jstraining/docs/history.md",
    "content": "# 前端开发的历史和趋势\n\n---\n\n## 什么是前端\n\n- 前端：针对浏览器的开发，代码在浏览器运行\n- 后端：针对服务器的开发，代码在服务器运行\n\n![](./images/frontend.png)\n\n---\n\n## 前后端不分的时代\n\n互联网发展的早期，前后端开发是一体的，前端代码是后端代码的一部分。\n\n1. 后端收到浏览器的请求\n1. 生成静态页面\n1. 发送到浏览器\n\n---\n\n## 后端 MVC 的开发模式\n\n那时的网站开发，采用的是后端 MVC 模式。\n\n- Model（模型层）：提供/保存数据\n- Controller（控制层）：数据处理，实现业务逻辑\n- View（视图层）：展示数据，提供用户界面\n\n前端只是后端 MVC 的 V。\n\n---\n\n以 PHP 框架 Laravel 为例。\n\n![](./images/laravel-mvc.png)\n\n---\n\n## 前端工程师的角色\n\n那时的前端工程师，实际上是模板工程师，负责编写页面模板。\n\n后端代码读取模板，替换变量，渲染出页面。\n\n---\n\n## 典型的 PHP 模板\n\n```php\n<html>\n  <head><title>Car {{ $car->id }}</title></head>\n  <body>\n    <h1>Car {{ $car->id }}</h1>\n    <ul>\n      <li>Make: {{ $car->make }}</li>\n      <li>Model: {{ $car->model }}</li>\n      <li>Produced on: {{ $car->produced_on }}</li>\n    </ul>\n  </body>\n</html>\n```\n\n---\n\n## Ajax\n\nAjax 技术诞生，改变了一切。\n\n- 2004年：Gmail\n- 2005年：Google 地图\n\n前端不再是后端的模板，可以独立得到各种数据。\n\n---\n\n## Web 2.0\n\nAjax 技术促成了 Web 2.0 的诞生。\n\n![](./images/web20.gif)\n\n- Web 1.0：静态网页，纯内容展示\n- Web 2.0：动态网页，富交互，前端数据处理\n\n从那时起，前端变得复杂了，对前端工程师的要求越来越高。\n\n---\n\n## 前端 MVC 框架\n\n前端通过 Ajax 得到数据，因此也有了处理数据的需求。\n\n前端代码变得也需要保存数据、处理数据、生成视图，这导致了前端 MVC 框架的诞生。\n\n- 2010年，Backbone.js\n\n![](./images/backbone.png)\n\n---\n\n## Backbone.js\n\nBackbone 将前端代码分成两个基本部分。\n\n- Model：管理数据\n- View：数据的展现\n\n![](./images/backbone-model-view.png)\n\n---\n\n## 前端 Controller\n\nBackbone 只有 M 和 V，没有 C。因为，前端 Controller 与后端不同。\n\n- 不需要，也不应该处理业务逻辑\n- 只需要处理 UI 逻辑，响应用户的一举一动\n\n所以，前端 Controller 相对比较简单。Backbone 没有 C，只用事件来处理 UI 逻辑。\n\n```javascript\n  var AppView = Backbone.View.extend({\n    // ...\n    events: {\n      \"keypress #new-todo\":  \"createOnEnter\",\n      \"click #clear-completed\": \"clearCompleted\",\n      \"click #toggle-all\": \"toggleAllComplete\"\n    },\n  }\n```\n\n---\n\n## MVVM 模式\n\n另一些框架提出 MVVM 模式，用 View Model 代替 Controller。\n\n- Model\n- View\n- View-Model：简化的 Controller，唯一作用就是为 View 提供处理好的数据，不含其他逻辑。\n\n![](./images/mvvm.png)\n\n---\n\n## Router\n\n前端还有一种天然的方法，可以切换视图，那就是 URL。\n\n通过 URL 切换视图，这就是 Router（路由）的作用。以 Backbone 为例。\n\n![](./images/backbone-routing.png)\n\n---\n\n```javascript\nApp.Router = Backbone.Router.extend({\n  routes: {\n    '': 'index',\n    'show': 'show'\n    },\n  index: function () {\n    $(document.body).append(\"调用了 Index 路由\");\n  },\n  show: function () {\n    $(document.body).append(\"调用了 Show 路由\");\n  },\n});\n```\n---\n\n## 示例：Backbone Router\n\n打开`demos/backbone-demo/index.html`，按照[《操作说明》](../demos/README.md#backbone)，查看示例。\n\n![](./images/backbone-demo.png)\n\n---\n\n## SPA\n\n前端可以做到：\n\n> - 读写数据\n> - 切换视图\n> - 用户交互\n\n这意味着，网页其实是一个应用程序。\n\n> SPA = Single-page application\n\n2010年后，前端工程师从开发页面，变成了开发”前端应用“（跑在浏览器里面的应用程序）。\n\n---\n\n## Angular\n\nGoogle 公司推出的 Angular 是最流行的 MVC 前端框架。\n\n它的风格属于 HTML 语言的增强，核心概念是双向绑定。\n\n![](./images/angular.png)\n\n---\n\n## 示例：Angular 的双向绑定\n\n浏览器打开`demos/angular-demo/index.html`，可以看到一个输入框。\n\n![](./images/angular-demo.png)\n\n---\n\n```javascript\n<div ng-app=\"\">\n  <p>\n    姓名 :\n    <input\n      type=\"text\"\n      ng-model=\"name\"\n      placeholder=\"在这里输入您的大名\"\n    >\n  </p>\n  <h1>你好，{{name}}</h1>\n</div>\n```\n\n---\n\n## Vue\n\nVue.js 是现在很热门的一种前端 MVC 框架。\n\n它的基本思想与 Angular 类似，但是用法更简单，而且引入了响应式编程的概念。\n\n![](./images/vue-logo.png)\n\n---\n\n## 示例：Vue 的双向绑定\n\nVue 的模板与数据，是双向绑定的。\n\n打开`demos/vue-demo/index1.html`，按照[《操作说明》](../demos/README.md#vue)，查看示例。\n\n![](./images/vue-demo.png)\n\n---\n\nHTML 代码\n\n```html\n<div id=\"journal\">\n  <input type=\"text\" v-model=\"message\">\n  <div>{{message}}</div>\n</div>\n```\n\nJS 代码\n\n```javascript\nvar journal = new Vue({\n  el: '#journal',\n  data: {\n    message: 'Your first entry'\n  }\n});\n```\n\n---\n\n## 前后端分离\n\n- Ajax -> 前端应用兴起\n- 智能手机 -> 多终端支持\n\n这两个原因，导致前端开发方式发生根本的变化。\n\n前端不再是后端 MVC 中的 V，而是单独的一层。\n\n---\n\n## REST 接口\n\n前后端分离以后，它们之间通过接口通信。\n\n后端暴露出接口，前端消费后端提供的数据。\n\n后端接口一般是 REST 形式，前后端的通信协议一般是 HTTP。\n\n---\n\n## Node\n\n2009年，Node 项目诞生，它是服务器上的 JavaScript 运行环境。\n\nNode = JavaScript + 操作系统 API\n\n![](./images/node-logo.png)\n\n---\n\n## Node 的意义\n\n- JavaScript 成为服务器脚本语言，与 Python 和 Ruby 一样\n- JavaScript 成为唯一的浏览器和服务器都支持的语言\n- 前端工程师可以编写后端程序了\n\n---\n\n## 前端开发模式的根本改变\n\n- Node 环境下开发\n- 大量使用服务器端工具\n- 引入持续集成等软件工程的标准流程\n- 开发完成后，编译成浏览器可以运行的脚本，放上 CDN\n\n---\n\n## 全栈工程师\n\n前端工程师正在转变为全栈工程师\n\n- 一个人负责开发前端和后端\n- 从数据库到 UI 的所有开发\n\n---\n\n## 全栈技能\n\n怎样才能称为全栈工程师？\n\n- 传统前端技能：HTML、JavaScript、CSS\n- 一门后端语言\n- 移动端开发：iOS / Android / HTML5\n- 其他技能：数据库、HTTP 等等\n\n---\n\n## 软件行业的发展动力\n\n历史演变：前后端不分 -> 前后端分离 -> 全栈工程师\n\n动力：更加产业化、大规模地生产软件\n\n- 效率更高\n- 成本更低\n\n通用性好、能够快速产出的技术最终会赢，单个程序员的生产力要求越来越高。\n\n---\n\n## 未来软件的特点\n\n- 联网\n- 高并发\n- 分布式\n- 跨终端\n\n现在基于 Web 的前端技术，将演变为未来所有软件的通用的 GUI 解决方案。\n\n---\n\n## 未来只有两种软件工程师\n\n- 端工程师\n  - 手机端\n  - PC 端\n  - TV 端\n  - VR 端\n  - ……\n- 云工程师\n\n"
  },
  {
    "path": "30-jstraining/docs/node.md",
    "content": "# Node 应用开发\n\n---\n\n## Node 简介\n\nNode 是服务器的 JavaScript 运行环境，提供 API 与操作系统互动。\n\n主要用途：\n\n- 开发前端应用\n- 快速搭建服务\n- 架设网站\n\n---\n\n## npm\n\n安装 Node 的时候，会同时安装 npm。\n\n```bash\n$ npm -v\n```\n\n它是 Node 的模块管理器，开发 Node 项目的必备工具。\n\n---\n\n## 课堂练习：Node 的简单应用\n\n进入`demos/simple-app-demo`目录，参考[《操作指南》](../demos/README.md#simple-app)，自己动手在 Node 里面，编写并编译一个前端脚本。\n\n---\n\n## Node 开发前端脚本的好处\n\n1. 模块机制\n1. 版本管理\n1. 对外发布\n1. 持续集成的标准开发流程\n\n---\n\n## REST API\n\nREST 是浏览器与服务器通信方式的一种设计风格。\n\n它的全称是“REpresentational State Transfer”，中文意为”表现层状态转换“。\n\n- Resource：资源\n- Representation：表现层\n- State：状态\n- Transfer：转换\n\n---\n\n## REST 的核心概念\n\n1. 互联网上所有可以访问的内容，都是资源。\n1. 服务器保存资源，客户端请求资源。\n1. 同一个资源，有多种表现形式。\n1. 协议本身不带有状态，通信时客户端必须通过参数，表示请求不同状态的资源。\n1. 状态转换通过HTTP动词表示。\n\n---\n\n## URL 设计\n\nURL 是资源的唯一识别符。\n\n- /store/1\n- /store/2\n- /store/1/employee/2\n\n---\n\n## 查询字符串\n\n查询字符串表示对所请求资源的约束条件。\n\n- GET /zoos/1/animals?limit=10\n- GET /zoos/1/animals?limit=10&offset=10\n- GET /animals?zoo_id=1\n\n---\n\n## HTTP 动词\n\n|操作|SQL方法|HTTP动词|\n|----|-------|--------|\n|CREATE|INSERT|POST|\n|READ|SELECT|GET|\n|UPDATE|UPDATE|PUT/PATCH|\n|DELETE|DELETE|DELETE|\n\n```\nGET /v1/stores/1234\nPUT /v1/stores/1234\nPOST /v1/stores\nDELETE /v1/stores/1234\n```\n\n---\n\n## 课堂练习：REST API\n\n打开`demos/rest-api-demo`，按照[《操作指南》](../demos/README.md#rest-api)，熟悉 REST API 的基本用法。\n\n---\n\n## Express\n\nExpress 是最常用的 Node 框架，用来搭建 Web 应用。\n\n![](./images/express.png)\n\n---\n\n## 课堂练习：Express 搭建 Web 应用\n\n进入`demos/express-demo`目录，按照[《操作指南》](../demos/README.md#express)，学习使用 Express 搭建 Web 应用。\n\n---\n\n定义一个 Web 应用实例，并且启动它。\n\n```javascript\nvar express    = require('express');\nvar app        = express();\n\nvar port = process.env.PORT || 8080;\n\napp.listen(port);\nconsole.log('Magic happens on port ' + port);\n```\n\n---\n\n定义一个路由\n\n```javascript\nvar router = express.Router();\n\nrouter.get('/', function(req, res) {\n  res.send('<h1>Hello World</h1>');\n});\n\napp.use('/home', router);\n```\n\n---\n\n中间件：对 HTTP 请求进行加工。\n\n```javascript\nrouter.use(function(req, res, next) {\n  console.log('Thers is a requesting.');\n  next();\n});\n```\n\n"
  },
  {
    "path": "30-jstraining/docs/preparation.md",
    "content": "# 培训准备\n\n参加培训的学员，事先应该做好以下准备工作。\n\n## 知识准备\n\n- 掌握 HTML、CSS、JS 的基本用法\n- 掌握命令行的基本用法\n\n## 安装 Git\n\n请到官网 [git-scm.com](https://git-scm.com/) 或国内的下载站，下载安装包。\n\n## 安装 Node\n\n请到 Node 官网[nodejs.org](https://nodejs.org)，或者国内镜像[npm.taobao.org/mirrors/node](https://npm.taobao.org/mirrors/node)，下载安装包。推荐安装最新的稳定版，目前是v6.x。\n\n安装完成后，命令行执行下面的命令，确认是否安装成功。\n\n```bash\n$ node -v\nv6.9.1\n```\n\nNode 的模块管理器 npm 会一起安装好。由于 Node 的官方模块仓库网速太慢，模块仓库需要切换到阿里的源。\n\n```bash\n$ npm config set registry https://registry.npm.taobao.org/\n```\n\n执行下面的命令，确认是否切换成功。\n\n```bash\n$ npm config get registry\n```\n\n## 安装 Postman\n\nPostman 是一个 HTTP 通信测试工具，REST API 的练习会用到它。\n\n请到官网 [GetPostman.com](https://www.getpostman.com/) 下载独立安装包；也可以参考这篇文章[www.cnblogs.com/mafly/p/postman.html](http://www.cnblogs.com/mafly/p/postman.html)，下载 Chrome 浏览器的插件，它们的效果一样。\n\n## 安装示例库\n\n所有的讲义和练习源码，都是开源的，网址是 [github.com/ruanyf/jstraining](https://github.com/ruanyf/jstraining)。执行下面的命令，将这个库拷贝到你的硬盘上。\n\n```bash\n# Linux & Mac\n$ git clone git@github.com:ruanyf/jstraining.git\n\n# Windows\n$ git clone https://github.com/ruanyf/jstraining.git\n```\n\n如果因为种种原因，Git 命令行无法使用，也可以直接下载压缩包，地址是 https://github.com/ruanyf/jstraining/archive/master.zip 。\n\n"
  },
  {
    "path": "30-jstraining/docs/react.md",
    "content": "# React 技术栈\n\n---\n\nReact 是目前最热门的前端框架。\n\n- Facebook 公司2013年推出\n- 现在最好的社区支持和生态圈\n- 大量的第三方工具\n\n![](./images/react-logo.png)\n\n---\n\n## React 的优点\n\n- 组件模式：代码复用和团队分工\n- 虚拟 DOM：性能优势\n- 移动端支持：跨终端\n\n---\n\n## React 的缺点\n\n- 学习曲线较陡峭\n- 全新的一套概念，与其他所有框架截然不同\n- 只有采用它的整个技术栈，才能发挥最大威力\n\n总结：React 非常先进和强大，但是学习和实现成本都不低\n\n---\n\n## JSX 语法\n\nReact 使用 JSX 语法，JavaScript 代码中可以写 HTML 代码。\n\n```javascript\nlet myTitle = <h1>Hello, world!</h1>;\n```\n\n---\n\n## JSX 语法解释\n\n（1）JSX 语法的最外层，只能有一个节点。\n\n```javascript\n// 错误\nlet myTitle = <p>Hello</p><p>World</p>;\n```\n\n（2）JSX 语法中可以插入 JavaScript 代码，使用大括号。\n\n```javascript\nlet myTitle = <p>{'Hello ' + 'World'}</p>\n```\n\n---\n\n## Babel 转码器\n\nJavaScript 引擎（包括浏览器和 Node）都不认识 JSX，需要首先使用 Babel 转码，然后才能运行。\n\n```html\n<script src=\"react.js\"></script>\n<script src=\"react-dom.js\"></script>\n<script src=\"babel.min.js\"></script>\n<script type=\"text/babel\">\n  // ** Our code goes here! **\n</script>\n```\n\nReact 需要加载两个库：React 和 React-DOM，前者是 React 的核心库，后者是 React 的 DOM 适配库。\n\nBabel 用来在浏览器转换 JSX 语法，如果服务器已经转好了，浏览器就不需要加载这个库。\n\n---\n\n## 课堂练习：JSX 语法\n\n浏览器打开`demos/jsx-demo/index.html`，按照[《操作说明》](../demos/README.md#jsx)，完成练习。\n\n```javascript\nReactDOM.render(\n  <span>Hello World!</span>,\n  document.getElementById('example')\n);\n```\n\n---\n\n## 示例：React 组件\n\nReact 允许用户定义自己的组件，插入网页。\n\n浏览器打开`demos/react-component-demo/index1.html`，按照[《操作说明》](../demos/README.md#react-组件语法)，仔细查看源码。\n\n```javascript\nclass MyTitle extends React.Component {\n  render() {\n    return <h1>Hello World</h1>;\n  }\n};\n\nReactDOM.render(\n  <MyTitle/>,\n  document.getElementById('example')\n);\n```\n\n---\n\n## 课堂练习：组件的参数\n\n组件可以从外部传入参数，内部使用`this.props`获取参数。\n\n打开`demos/react-component-demo/index2.html`，按照[《操作说明》](../demos/README.md#react-组件的参数)，完成练习。\n\n```javascript\nclass MyTitle extends React.Component {\n  render() {\n    return <h1\n      style={{color: this.props.color}}\n    >Hello World</h1>;\n  }\n};\n\n<MyTitle color=\"red\" />,\n```\n\n---\n\n## 示例：组件的状态\n\n组件往往会有内部状态，使用`this.state`表示。\n\n浏览器打开`demos/react-component-demo/index3.html`，按照[《操作说明》](../demos/README.md#react-组件的状态)，仔细查看源码。\n\n![](./images/react-component-state.png)\n\n---\n\n## 课堂练习：React 组件实战\n\n浏览器打开`demos/react-component-demo/index4.html`，按照[《操作说明》](../demos/README.md#react-组件实战)，完成练习。\n\n---\n\n## 组件的生命周期\n\nReact 为组件的不同生命阶段，提供了近十个钩子方法。\n\n- `componentWillMount()`：组件加载前调用\n- `componentDidMount()`：组件加载后调用\n- `componentWillUpdate()`: 组件更新前调用\n- `componentDidUpdate()`: 组件更新后调用\n- `componentWillUnmount()`：组件卸载前调用\n\n我们可以利用这些钩子，自动完成一些操作。\n\n---\n\n## 课堂练习：组件的生命周期\n\n组件可以通过 Ajax 请求，从服务器获取数据。Ajax 请求一般在`componentDidMount`方法里面发出。\n\n```javascript\ncomponentDidMount() {\n  const url = '...';\n  $.getJSON(url)\n    .done()\n    .fail();\n}\n```\n\n打开`demos/react-lifecycle-demo/index.html`，按照[《操作说明》](../demos/README.md#react-组件的生命周期)，完成练习。\n\n---\n\n## React 组件库\n\nReact 的一大优势，就是网上有很多已经写好的组件库，可以使用。\n\nReact-Bootstrap：https://react-bootstrap.github.io/\n\n![](./images/react-bootstrap.png)\n\n---\n\n## 示例：ReCharts\n\nReCharts 是一个 React 图表组件库。http://recharts.org/\n\n浏览器打开`demos/recharts-demo/index.html`，按照[《操作说明》](../demos/README.md#recharts)，仔细查看源码。\n\n```html\n<LineChart width={1000} height={400} data={data}>\n  <XAxis dataKey=\"name\"/>\n  <YAxis/>\n  <CartesianGrid stroke=\"#eee\" strokeDasharray=\"5 5\"/>\n  <Line type=\"monotone\" dataKey=\"uv\" stroke=\"#8884d8\" />\n  <Line type=\"monotone\" dataKey=\"pv\" stroke=\"#82ca9d\" />\n</LineChart>\n```\n\n---\n\n## React 应用的架构\n\nReact 只是一个 DOM 的抽象层，并没有解决应用程序的架构问题：大型应用程序应该如何组织代码？\n\nFacebook 提出 Flux 架构的概念。\n\n![](./images/flow.png)\n\n最大特点：数据单向流动\n\n---\n\n## 目前最流行的两个 React 框架\n\n- MobX：采用观察者模式，自动响应数据变化\n- Redux：Flux 的函数式实现\n\n---\n\n## MobX 架构\n\nMobX 的核心概念，就是组件是观察者，一旦`Store`有变化，会立刻被组件观察到，从而引发重新渲染。\n\n```javascript\n@observer\nclass App extends React.Component {\n  render() {\n    // ...\n  }\n}\n```\n\n---\n\n## 示例：MobX\n\n进入`demos/mobx-demo`目录，按照[《操作说明》](../demos/README.md#mobx)，理解 MobX 框架。\n\n---\n\nUI 层是观察者，Store 是被观察者。\n\nStore 所有的属性，分成两大类：直接被观察的属性和自动计算出来的属性。\n\n```javascript\nclass Store {\n  @observable name = 'Bartek';\n  @computed get decorated() {\n    return `${this.name} is awesome!`;\n  }\n}\n```\n\nUI 会观察到 Store 的变化，自动重新渲染。\n\n---\n\n## Redux 架构\n\nRedux 的核心概念\n\n- 所有的状态存放在`Store`。组件每次重新渲染，都必须由状态变化引起。\n- 用户在 UI 上发出`action`。\n- `reducer`函数接收`action`，然后根据当前的`state`，计算出新的`state`。\n\n![](./images/redux-architecture.png)\n\n---\n\n## 示例：Redux\n\n进入`demos/redux-demo`目录，按照[《操作说明》](../demos/README.md#redux)，理解 Redux 框架。\n\n---\n\n- Redux 将组件分成 UI 组件和容器组件两类。\n- UI 组件是纯组件，需要用户自己写。\n\n```javascript\n<div className=\"index\">\n  <p>{this.props.text}</p>\n  <input\n    defaultValue={this.props.name}\n    onChange={this.props.onChange}\n  />\n</div>\n```\n\n---\n\n容器组件在用户给出配置以后，由 Redux 生成。\n\n```javascript、\n// MyComponent 是纯的 UI 组件\nconst App = connect(\n  mapStateToProps,\n  mapDispatchToProps\n)(MyComponent);\n```\n\n- mapStateToProps: 定义 UI 组件参数与 State 之间的映射\n- mapDispatchToProps：定义 UI 组件与 Action 之间的映射\n\n---\n\n`reducer`是一个纯函数，用来接收`action`，算出新的`state`。\n\n```javascript\nfunction reducer(state = {\n  text: '你好，访问者',\n  name: '访问者'\n}, action) {\n  switch (action.type) {\n    case 'change':\n      return {\n        name: action.payload,\n        text: '你好，' + action.payload\n      };\n  }\n}\n```\n\n---\n\n- `Store`由 Redux 提供的`createStore`方法生成，该方法接受`reducer`作为参数。\n- 为了把`Store`传入组件，必须使用 Redux 提供的`Provider`组件在应用的最外面，包裹一层。\n\n```javascript\nconst store = createStore(reducer);\n\nReactDOM.render(\n  <Provider store={store}>\n    <App />\n  </Provider>,\n  document.body.appendChild(document.createElement('div'))\n);\n```\n\n"
  },
  {
    "path": "31-awesome-javascript-cn/README.md",
    "content": "# JavaScript 资源大全中文版\n\n我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理。[awesome-javascript](https://github.com/sorrycc/awesome-javascript) 是 sorrycc 发起维护的 JS 资源列表，内容包括：包管理器、加载器、测试框架、运行器、QA、MVC框架和库、模板引擎、数据可视化、时间轴、编辑器等等\n\nAwesome 系列虽然挺全，但基本只对收录的资源做了极为简要的介绍，如果有更详细的中文介绍，对相应开发者的帮助会更大。这也是我们发起这个开源项目的初衷。\n\n* * *\n\n### 我们要做什么？\n\n- 基于 awesome-javascript 列表，我们将对其中的各个资源项进行编译整理。此外还将从其他来源补充好资源。\n- 整理后的内容，将收录在[伯乐在线资源频道](http://hao.jobbole.com/)。可参考已整理的内容：\n  - 《[jQWidgets：jQuery HTML5 UI组件框架](http://hao.jobbole.com/jqwidgets-jquery-html5-ui/)》\n  - 《[Bootstrap：Web前端开发框架](http://hao.jobbole.com/bootstrap/)》\n  - 《[YUI Compressor：JS/CSS压缩工具](http://hao.jobbole.com/yui-compressor/)》\n\n* * *\n\n### 如何参与本项目？\n\n从下面的目录来看，本项目的工作量小不了，所以非常期待能有更多程序员一起来参与。\n\n不过加入前，有几个小要求：\n\n* 英文还不错，能读懂英文并用自己的话复述；\n* 在用 JavaScript；\n\n如有兴趣，请加 QQ：50872495。加 Q 时请注明「JS大全」\n\n* * *\n\n### 如何为列表贡献新资源？\n\n欢迎大家为列表贡献高质量的新资源，提交PR时请参照以下要求：\n\n* 请确保推荐的资源自己使用过\n* 提交PR时请注明推荐理由\n\n资源列表管理收到PR请求后，会定期（每周）在微博转发本周提交的PR列表，并在微博上面听取使用过这些资源的意见。确认通过后，会加入资源大全。\n\n感谢您的贡献！\n\n* * *\n\n### 本项目的参与者\n\n- 维护者：\n- 贡献者：[刘健超](https://github.com/JChehe)、MissNull、一兮、Mr. Somebody、Jason Lee、[Tab_Gre](http://www.jobbole.com/members/ivanberry/)、[GavinZhang](http://www.jobbole.com/members/KeepMoving/)、[shadowkimi520](https://github.com/shadowkimi520/)、[zhoutk](http://www.jobbole.com/members/zhoutk/)、[tzstone](http://www.jobbole.com/members/tzstone)、[Erichain](http://www.jobbole.com/members/Erichain)、[chen](http://www.jobbole.com/members/atmfans)、[ElizabethMa](https://github.com/ElizabethMa)、[LeuisKen](http://www.jobbole.com/members/LeuisKen)、[linacre](http://www.jobbole.com/members/linacre)、[王涛](http://www.jobbole.com/members/wt726553124/)、[neal1991](https://github.com/neal1991)、[luoyjx](https://github.com/luoyjx)、[appleshowc](https://github.com/appleshowc)、[TAMMENY](https://github.com/TAMMENY)、[cike8899](https://github.com/cike8899)、[cnzin](https://github.com/cnzin)、[cike8899](https://github.com/cike8899)、[hustcc](https://github.com/hustcc)、[冰斌](http://www.jobbole.com/members/libing1209/)、[邢敏](https://github.com/dfghj44444)\n\n注：名单不分排名，不定期补充更新\n\n* * *\n\n### 奖励计划\n\n虽然奖励可能并不是你加入的主要原因，但还是有必要提一下：\n\n* 整理超过 20 个资源后，可在伯乐在线上开通打赏；\n* 每整理 20 个资源，有机会获得技术书籍或各种有意思的创意、极客产品；\n* [奖励详情](http://hao.jobbole.com/rewards/)\n\n* * *\n### 目录\n\n* [JavaScript资源大全中文版](#awesome-javascript-cn)\n  * [包管理器](#package-managers)\n  * [加载器](#loaders)\n  * [打包工具](#bundlers)\n  * [测试框架](#testing-frameworks)\n  * [QA 工具](#qa-tools)\n  * [MVC 框架和库](#mvc-frameworks-and-libraries)\n  * [基于 Node 的 CMS 框架](#node-powered-cms-frameworks)\n  * [模板引擎](#templating-engines)\n  * [Flux](#data-flow)\n  * [数据可视化](#data-visualization)\n    * [时间轴](#timeline)\n  * [编辑器](#editors)\n  * 工具\n    * [文件](#files)\n    * [函数式编程](#functional-programming)\n    * [响应式编程](#reactive-programming)\n    * [数据结构](#data-structure)\n    * [日期](#date)\n    * [字符串](#string)\n    * [数字](#number)\n    * [存储](#storage)\n    * [颜色](#color)\n    * [国际化和本地化](#i18n-and-l10n)\n    * [类](#class)\n    * [控制流](#control-flow)\n    * [路由](#routing)\n    * [安全性](#security)\n    * [日志](#log)\n    * [正则表达式](#regexp)\n    * [媒体](#media)\n    * [语言命令](#voice-command)\n    * [API](#api)\n    * [视觉检测](#vision-detection)\n    * [浏览器检测](#browser-detection)\n  * UI\n    * [代码高亮](#code-highlighting)\n    * [加载状态](#loading-status)\n    * [验证](#validation)\n    * [键盘封装器](#keyboard-wrappers)\n    * [浏览和引导](#tours-and-guides)\n    * [通知](#notifications)\n    * [幻灯片](#sliders)\n    * [滑块控件](#range-sliders)\n    * [表单组件](#form-widgets)\n    * [提示](#tips)\n    * [模态框和弹出框](#modals-and-popups)\n    * [滚动条](#scroll)\n    * [菜单](#menu)\n    * [表格/栅格](#table-grid)\n    * [框架](#frameworks-1)\n  * 移动\n    * [手势](#gesture)\n    * [触摸](#touch)\n  * [地图](#maps)\n  * [视频/音频](#video-audio)\n  * [动画](#animations)\n  * [图片处理](#image-processing)\n  * [ES6](#es6)\n  * [SDK](#sdk)\n  * [大杂烩](#misc)\n* [精品阅读](#worth-reading)\n- [资源](#resources)\n    - [社区](#communities)\n    - [有影响力的书](#influential-books)\n    - [微博、微信公众号](#weibo-weixin)\n    - [知名网站](#websites)\n    - [博客](blogs)\n\n* * *\n\n<h2 id=\"package-managers\">包管理器</h2>\n\n管理着 JavaScript 库，并提供读取和打包它们的工具。\n\n* npm：npm 是 JavaScript 的包管理器。[官网](https://www.npmjs.com/)\n* Bower：一个 web 应用的包管理器。[官网](https://github.com/bower/bower)\n* component：能构建更好 web 应用的客户端包管理器。[官网](https://github.com/componentjs/component)\n* spm：全新的静态包管理器。[官网](https://github.com/spmjs/spm)\n* jam：一个专注于浏览器端和兼容 RequireJS 的包管理器。[官网](https://github.com/caolan/jam)\n* jspm：流畅的浏览器包管理器。[官网](https://github.com/jspm/jspm-cli)\n* Ender：没有库文件的程序库。[官网](https://github.com/ender-js/Ender)\n* volo：以项目模板、添加依赖项与自动化生成的方式创建前端项目。[官网](https://github.com/volojs/volo) \n* Duo：一个整合 Component、Browserify 和 Go [官网](https://github.com/duojs/duo)的最佳思想，使开发者能快速方便地组织和编写前端代码的下一代包管理器。\n\n<h2 id=\"loaders\">加载器</h2>\n\nJavaScript 的模块或加载系统。\n\n* RequireJS：JavaScript 文件和模块的加载器。[官网](https://github.com/jrburke/requirejs)\n* browserify：在浏览器端以 node.js 的方式 require()。[官网](https://github.com/substack/node-browserify)\n* SeaJS：用于 Web 的模块加载器。[官网](https://github.com/seajs/seajs)\n* HeadJS：HEAD 的唯一脚本。[官网](https://github.com/headjs/headjs)\n* curl：小巧、快速且易扩展的模块加载器，它能处理 AMD、CommonJS Modules/1.1、CSS、HTML/text 和历史脚本。[官网](https://github.com/cujojs/curl)\n* lazyload：小巧且无依赖的异步 JavaScript 和 CSS 加载器。[官网](https://github.com/rgrove/lazyload/)\n* script.js：异步 JavaScript 加载器和依赖管理器。[官网](https://github.com/ded/script.js)\n* systemjs：AMD、CJS（commonJS） 和符合 ES6 规范的模块加载器。[官网](https://github.com/systemjs/systemjs)\n* LodJS：基于 AMD 的模块加载器。[官网](https://github.com/yanhaijing/lodjs)\n* ESL：浏览器端的模块加载器，支持延迟定义和 AMD。[官网](https://github.com/ecomfe/esl)\n* modulejs：轻量的 JavaScript 模块系统。[官网](https://github.com/lrsjng/modulejs)\n\n<h2 id=\"bundlers\">打包工具</h2>\n\n* browserify ：Browserify 让你能在浏览器端使用 require('modules') ，打包所有依赖。[官网](https://github.com/substack/node-browserify)\n* webpack：为浏览器打包 CommonJs/AMD 模块。[官网](https://github.com/webpack/webpack)\n* gulp：用自动化构建工具增强你的工作流程！[官网](http://gulpjs.com/)\n\n<h2 id=\"testing-frameworks\">测试框架</h2>\n\n### 框架\n\n* mocha：适用于 node.js 和浏览器、简易、灵活、有趣的 JavaScript 测试框架。[官网](https://github.com/mochajs/mocha)\n* jasmine：简单无 DOM 的 JavaScript 测试框架。[官网](https://github.com/jasmine/jasmine)\n* qunit：一个易于使用的 JavaScript 单元测试框架。[官网](https://github.com/jquery/qunit)\n* jest：简单的 JavaScript 单元测试框架。[官网](https://github.com/facebook/jest)\n* prova：基于 Tape 和 Browserify 的测试运行器，它适用于 Node &amp; 浏览器。[官网](https://github.com/azer/prova)\n* DalekJS：自动化且跨浏览器的 JavaScript 功能测试框架。[官网](https://github.com/dalekjs/dalek)\n\n### 断言\n\n* chai：适用于 node.js 和浏览器的 BDD / TDD 断言框架，并能搭配其它测试框架使用。[官网](https://github.com/chaijs/chai)\n* Sinon.JS：对 JavaScript 进行 spies、stubs 和 mock 测试。[官网](https://github.com/sinonjs/sinon)\n* expect.js：简约的、适用于 Node.js 和浏览器端的 BDD 式断言工具。[官网](https://github.com/Automattic/expect.js)\n* should.js：适用于 Node.js 的 BDD 式断言工具。[官网](https://github.com/tj/should.js)\n\n### 覆盖率\n\n* istanbul：另一个 JS 代码覆盖率检测工具。[官网](https://github.com/gotwarlost/istanbul)\n* blanket：一个简单的代码覆盖率检测库。它的设计理念是易于安装和使用，且可用于浏览器端和 node.js。[官网](https://github.com/alex-seville/blanket)\n* JSCover：JSCover 是一个检测 JavaScript 程序代码覆盖率的工具。[官网](https://github.com/tntim96/JSCover)\n\n### 运行器\n\n* phantomjs：脚本化的 Headless WebKit。[官网](https://github.com/ariya/phantomjs)\n* slimerjs：一个内核为 Gecko 的类似 PhantomJS 工具。[官网](https://github.com/laurentj/slimerjs)\n* casperjs：基于 PhantomJS 和 Slimer JS 的导航脚本和测试工具。[官网](https://github.com/n1k0/casperjs) \n* zombie：基于 node.js 、快速、全栈且无图形界面的浏览器的测试工具。[官网](https://github.com/assaf/zombie)\n* totoro：一个简单可靠且能跨浏览器运行的测试工具。[官网](https://github.com/totorojs/totoro)\n* karma：一个优秀的的 JavaScript 测试运行器。[官网](https://github.com/karma-runner/karma)\n* nightwatch：基于 node.js 和 selenium webdriver 的图形界面自动化测试框架。[官网](https://github.com/nightwatchjs/nightwatch)\n* intern：下一代 JavaScript 代码测试栈。[官网](https://github.com/theintern/intern)\n* yolpo：在浏览器逐句执行的 JavaScript 解释器。[官网](http://www.yolpo.com/)\n\n<h2 id=\"qa-tools\">QA 工具</h2>\n\n* JSHint：JSHint 是一个有助于发现 JavaScript 代码错误和潜在问题的工具。[官网](https://github.com/jshint/jshint/)\n* jscs：JavaScript 代码风格检测工具。[官网](https://github.com/jscs-dev/node-jscs)\n* jsfmt：格式化、搜索和改写 JavaScript。[官网](https://github.com/rdio/jsfmt)\n* jsinspect：检测复制粘贴和结构类似的代码。[官网](https://github.com/danielstjules/jsinspect)\n* buddy.js：发现 JavaScript 代码里的 [魔术数字](https://zh.wikipedia.org/wiki/%E9%AD%94%E8%A1%93%E6%95%B8%E5%AD%97)。[官网](https://github.com/danielstjules/buddy.js)\n* ESLint：完全插件化的工具，能在 JavaScript 中识别和记录模式。[官网](https://github.com/eslint/eslint)\n* JSLint ：高标准、严格和固执的代码质量工具，旨在只保持语言的优良部分。[官网](https://github.com/douglascrockford/JSLint)\n\n<h2 id=\"mvc-frameworks-and-libraries\">MVC 框架和库</h2>\n\n* [angular.js](http://hao.jobbole.com/angularjs/)：为网络应用增强 HTML。[官网](https://github.com/angular/angular.js)\n* aurelia：一个适用于移动设备、桌面电脑和 web 的客户端 JavaScript 框架。[官网](http://aurelia.io/)\n* backbone：给你的 JS 应用加入带有 Models、Views、Collections 和 Events 的 Backbone。[官网](https://github.com/jashkenas/backbone)\n* batman.js：最适合 Rails 开发者的 JavaScript 框架。[官网](http://batmanjs.org/)\n* ember.js：一个旨在创建非凡 web 应用的 JavaScript 框架。[官网](https://github.com/emberjs/ember.js)\n* meteor：一个超简单的、数据库无处不在的、只传输数据的纯 JavaScript web 框架。[官网](https://github.com/meteor/meteor)\n* ractive：新一代 DOM 操作。[官网](https://github.com/ractivejs/ractive)\n* vue：一个用于构建可交互界面的、直观快速和可组合的 MVVM 框架。[官网](https://github.com/vuejs/vue) \n* knockout：Knockout 用 JavaScript 让创建响应式的富 UI 更加容易。[官网](https://github.com/knockout/knockout) \n* spine：构建 JavaScript 应用的轻量 MVC 库。[官网](https://github.com/spine/spine)\n* espresso.js：一个极小的、用于制作用户界面的 JavaScript 库。[官网](https://github.com/techlayer/espresso.js)\n* canjs：让 JS 更好、更快、更简单。[官网](https://github.com/canjs/canjs)\n* react：用于建构用户界面的库。它是声明式的、高效的和极度灵活的，并使用虚拟 DOM 作为其不同的实现。[官网](https://facebook.github.io/react/)\n* react-native：一个用 React 构建原生应用的框架。[官网](https://github.com/facebook/react-native)\n* riot：类 React 库，但很轻量。[官网](https://github.com/riot/riot)\n* thorax：加强你的 Backbone。[官网](https://github.com/walmartlabs/thorax)\n* chaplin：使用 Backbone.js 库的 JavaScript 应用架构。[官网](https://github.com/chaplinjs/chaplin)\n* marionette：一个 Backbone.js 的复合应用程序库，旨在简化大型 JavaScript 应用结构。[官网](https://github.com/marionettejs/backbone.marionette)\n* ripple：一个小巧的、用于构建响应界面的基础框架。[官网](https://github.com/ripplejs/ripple)\n* rivets：轻量却拥有强大的数据绑定和模板解决方案[官网](https://github.com/mikeric/rivets)\n* derby：让编写实时和协同应用更简单的 MVC 框架，能够在 Node.js 和浏览器同时运行。[官网](https://github.com/derbyjs/derby)\n    * derby-awesome：很棒的 derby 组件集合。[官网](https://github.com/russll/awesome-derby)\n* [way.js](http://hao.jobbole.com/way-js/)：简单、轻量、持久化的双向数据绑定。[官网](https://github.com/gwendall/way.js)\n* mithril.js：Mithril 是一个客户端 MVC 框架（轻量、强大和快速）[官网](https://github.com/lhorie/mithril.js)\n* jsblocks：jsblocks 是一个更好的 MV-ish 框架。[官网](https://github.com/astoilkov/jsblocks)\n* LiquidLava：易懂的、用于构建用户界面的 MVC 框架。[官网](http://www.lava-framework.com/)\n* [Electron](http://hao.jobbole.com/electron/)：用Html、CSS和JavaScript构建跨平台的客户端应用程序。[官网](http://electron.atom.io/)、[GitHub](https://github.com/electron/electron)\n\n<h2 id=\"node-powered-cms-frameworks\">基于 Node 的 CMS 框架</h2>\n\n* KeystoneJS：强大的 CMS 和 web 应用框架。[官网](https://github.com/keystonejs/keystone)\n* Reaction Commerce：拥有实时的架构和设计的响应式（reactive） CMS。[官网](https://github.com/reactioncommerce/reaction)\n* Ghost：简单、强大的发布平台。[官网](https://github.com/tryghost/Ghost)\n* Apostrophe：提供内容编辑和基本服务的 CMS。[官网](https://github.com/punkave/apostrophe)\n* We.js：适用于实时应用、网站或博客的框架。[官网](https://github.com/wejs/we/)\n* Hatch.js：拥有社交特性的 CMS 平台。[官网](https://github.com/inventures/hatchjs)\n* TaracotJS：拥有快速、极简风格特点且基于Node.js 的 CMS。[官网](https://github.com/xtremespb/taracotjs-generator/)\n* Nodizecms：为 CoffeeScript 爱好者准备的 CMS。[官网](https://github.com/nodize/nodizecms)\n* Cody：拥有所见即所得的编辑器的 CMS。[官网](https://github.com/jcoppieters/cody)\n* PencilBlue：CMS 和博客平台。[官网](https://github.com/pencilblue/pencilblue/)\n\n<h2 id=\"templating-engines\">模板引擎</h2>\n\n模板引擎允许您执行字符串插值。\n\n* mustache.js：是 JavaScript 中带有 {{mustaches}} 的最简模板。[官网](https://github.com/janl/mustache.js)\n* handlebars.js：是 Mustache 模板语言的扩展。[官网](https://github.com/wycats/handlebars.js/)\n* hogan.js：是 Mustache 模板语言的编译器。[官网](https://github.com/twitter/hogan.js)\n* doT：最快速简洁的 JavaScript 模板引擎，适用于 nodejs 和浏览器。[官网](https://github.com/olado/doT)\n* dustjs：适用于浏览器和 node.js 的异步模板。[官网](https://github.com/linkedin/dustjs/)\n* eco：嵌入式的 CoffeeScript 模板。[官网](https://github.com/sstephenson/eco/)\n* JavaScript-Templates：轻量（小于 1KB）、快速且无依赖的强大 JavaScript 模版引擎。[官网](https://github.com/blueimp/JavaScript-Templates)\n* t.js：小巧的 JavaScript 模板框架，压缩后约为 400 字节。[官网](https://github.com/jasonmoo/t.js)\n* Jade：健壮的、优雅且功能丰富的 nodejs 模板引擎。[官网](https://github.com/pugjs/jade)\n* EJS：高效的 JavaScript 模板。[官网](https://github.com/mde/ejs)\n* xtemplate：可扩展的模板引擎，适用于 node 和浏览器。[官网](https://github.com/xtemplate/xtemplate)\n* marko：快速轻量且基于 HTML 的模板引擎，支持异步、流、自定义标签和 CommonJS 模编译后输出。适用于 Node.js [官网](https://github.com/marko-js/marko)和浏览器。\n\n<h2 id=\"data-flow\">Flux</h2>\n\nFlux是Facebook用来构建客户端Web应用的应用架构\n\n* Reflux是根据React的flux创建的单向数据流类库。[官网](https://github.com/reflux/refluxjs)\n* Redux是可预测javascript应用程序状态的容器。[官网](http://redux.js.org/)\n\n<h2 id=\"data visualization\">数据可视化</h2>\n\nWeb 数据可视化工具\n\n* d3：一个对 HTML 和 SVG 进行可视化的 JavaScript 库。[官网](https://github.com/mbostock/d3)\n* metrics-graphics：更简洁和拥有更规范的数据图表布局优化算法的库。[官网](https://github.com/mozilla/metrics-graphics)\n* pykcharts.js：经过精心设计后，去除 d3.js 复杂性的 d3.js 图表库。[官网](https://github.com/pykih/PykCharts.js)\n* [three.js](http://hao.jobbole.com/three-js/)：JavaScript 3D 库。[官网](https://github.com/mrdoob/three.js)\n* Chart.js：简单的、基于 canvas 标签的 HTML5 图表库。[官网](https://github.com/nnnick/Chart.js)\n* paper.js：是矢量图形脚本中的瑞士军刀 —— 使用 HTML5 Canvas 将 Scriptographer  移植到 JavaScript [官网](https://github.com/paperjs/paper.js)和浏览器。\n* fabric.js：JavaScript Canvas 库，SVG 与 Canvas 可以相互解析。[官网](https://github.com/kangax/fabric.js)\n* peity：进度条、线状和饼状图。[官网](https://github.com/benpickles/peity)\n* raphael：JavaScript 矢量库。[官网](https://github.com/DmitryBaranovskiy/raphael)\n* echarts：商业产品图表。[官网](https://github.com/ecomfe/echarts)\n* vis：动态的、基于浏览器的可视化库。[官网](https://github.com/almende/vis)\n* two.js：一个渲染器无关的适用于 web 的二维绘图 api 。[官网](https://github.com/jonobr1/two.js)\n* g.raphael：基于 Raphaël 图表库。[官网](https://github.com/DmitryBaranovskiy/g.raphael)\n* sigma.js：一个致力于图形绘画的 JavaScript 库。[官网](https://github.com/jacomyal/sigma.js)\n* arbor：一个使用 web workers 和 jQuery 的图形可视化库。[官网](https://github.com/samizdatco/arbor)\n* cubism：可视化时间序列的 D3 插件。[官网](https://github.com/square/cubism)\n* dc.js：与 crossfilter 无缝合作的多维图表绘制库，使用 d3.js 渲染。[官网](https://github.com/dc-js/dc.js)\n* vega：一套可视化语法。[官网](https://github.com/trifacta/vega)\n* processing.js：Processing.js 基于 Web 标准使数据可视化，而无需任何插件。[官网](http://processingjs.org/)\n* envisionjs：动态的 HTML5 可视化。[官网](https://github.com/HumbleSoftware/envisionjs)\n* rickshaw：用于构建交互式实时图表的 JavaScript 工具包。[官网](https://github.com/shutterstock/rickshaw)\n* flot：吸引人的、基于 jQuery 的 JavaScript 图表库。[官网](https://github.com/flot/flot)\n* morris.js：漂亮的时间序列线框图。[官网](https://github.com/morrisjs/morris.js)\n* nvd3：一个为 D3.js 构建可复用图表和图表组件的库。[官网](https://github.com/novus/nvd3)\n* svg.js：一个轻量的、用于操作和添加 SVG 动画的库。[官网](https://github.com/wout/svg.js)\n* heatmap.js：基于 HTML5 canvas 的热力图 JavaScript 库。[官网](https://github.com/pa7/heatmap.js)\n* jquery.sparkline：一个直接在浏览器端生成小型走势图的 jQuery 插件。[官网](https://github.com/gwatts/jquery.sparkline)\n* xCharts：一个基于 D3、用于构建自定义图表和图形的库。[官网](https://github.com/tenxer/xCharts)\n* trianglify：基于 d3.js 的低多边形（low poly）风格背景图片生成器。[官网](https://github.com/qrohlf/trianglify)\n* d3-cloud：创建词云（word cloud）效果的 JavaScript 库。[官网](https://github.com/jasondavies/d3-cloud)\n* d4：一个基于 D3 、友好、可复用的 DSL 图表库 。[官网](https://github.com/heavysixer/d4)\n* dimple.js：基于 d3 的简易商业分析图表库。[官网](http://dimplejs.org/)\n* chartist-js：简单的响应式图表。[官网](https://github.com/gionkunz/chartist-js)\n* epoch：一个通用的实时图表库。[官网](https://github.com/epochjs/epoch)\n* c3：基于 D3 的可复用图表库。[官网](https://github.com/masayuki0812/c3)\n* BabylonJS：一个运用 HTML5 和 WebGL 构建 3D 游戏的框架。[官网](https://github.com/BabylonJS/Babylon.js)\n* jquery.raty.js：一个星级评分插件。[官网](https://github.com/wbotelhos/raty)\n\n也有一些很棒的收费库，如 [amchart](https://www.amcharts.com/)、[plotly](https://plot.ly/) 和 [highchart](http://www.highcharts.com/)。\n\n<h3 id=\"timeline\">时间轴</h3>\n\n* TimelineJS： 一个用 JavaScript 编写的可叙事时间轴库。[官网](https://github.com/NUKnightLab/TimelineJS)\n* timesheet.js：用于构建简单的 HTML5 &amp; CSS3 时间表的 JavaScript 库。[官网](https://github.com/semu/timesheet.js)\n\n<h2 id=\"editors\">编辑器</h2>\n\n* ace：Ace（Ajax.org Cloud9 Editor）。[官网](https://github.com/ajaxorg/ace)\n* CodeMirror：浏览器端的代码编辑器。[官网](https://github.com/codemirror/CodeMirror)\n* esprima：用于综合分析的 ECMAScript 解析器。[官网](https://github.com/ariya/esprima)\n* [quill](http://hao.jobbole.com/quill/)：一个带有 API 的跨浏览器富文本编辑器。([官网](http://quilljs.com/))\n* medium-editor：Medium.com 所见即所得编辑器的克隆版。[官网](https://github.com/yabwe/medium-editor)\n* pen：享受在线编辑（支持 markdown）。[官网](https://github.com/sofish/pen)\n* jquery-notebook：一个易用的、简洁优雅的文本编辑器。灵感来源于 Medium 的魅力。[官网](https://github.com/raphaelcruzeiro/jquery-notebook)\n* bootstrap-wysiwyg：小巧的、兼容 bootstrap 的所见即所得的富文本编辑器。[官网](https://github.com/mindmup/bootstrap-wysiwyg)\n* ckeditor-releases：适用于每个人的 web 文本编辑器。[官网](https://github.com/ckeditor/ckeditor-releases)\n* editor：一个 markdown 编辑器，但仍在开发中。[官网](https://github.com/lepture/editor)\n* EpicEditor：一个可嵌入的 JavaScript Markdown [官网](https://github.com/OscarGodson/EpicEditor)的编辑器，拥有全屏编辑、即时预览、自动保存草稿和离线支持等功能。\n* jsoneditor：查看、编辑和格式化 JSON 的 web 工具。[官网](https://github.com/josdejong/jsoneditor)\n* vim.js： 拥有持久化 ~/.vimrc 的 Vim 编辑器的 JavaScript 移植版本。[官网](https://github.com/coolwanglu/vim.js)\n* Squire：HTML5 富文本编辑器。[官网](https://github.com/neilj/Squire)\n* TinyMCE：JavaScript 富文本编辑器。[官网](https://github.com/tinymce/tinymce)\n* trix：由 Basecamp 制作，适用于每天写作的富文本编辑器。[官网](https://github.com/basecamp/trix)\n\n<h3 id=\"files\">文件</h3>\n\n处理文件的库。\n\n* Papa Parse：一款强大的 CSV 库，支持解析 CSV 文件/字符串，也能导出 CSV。[官网](https://github.com/mholt/PapaParse)\n* jBinary：对用声明式语法描述文件类型和数据结构的二进制文件，进行高级 I/O（加载、解析、操作、序列化、存储）操作。[官网](https://github.com/jDataView/jBinary)\n\n<h3 id=\"functional-programming\">函数式编程</h3>\n\n函数式编程库扩展了 JavaScript 的能力。\n\n* [underscore](http://hao.jobbole.com/underscore/)：JavaScript 的实用工具。[官网](https://github.com/jashkenas/underscore)\n* [lodash](http://hao.jobbole.com/lodash/)：提供一致性、可定制、高性能和额外功能的实用库。[官网](https://github.com/lodash/lodash)\n* Sugar：一个扩展了原生对象功能的 JavaScript 库。[官网](https://github.com/andrewplummer/Sugar)\n* lazy.js：类似 Underscore，但性能更优越[官网](https://github.com/dtao/lazy.js)\n* ramda：一个针对 JavaScript 程序员的实用函数库。[官网](https://github.com/CrossEye/ramda)\n* mout：模块化的 JavaScript 工具库。[官网](https://github.com/mout/mout)\n* mesh：流数据同步工具。[官网](https://github.com/crcn/mesh.js)\n\n<h3 id=\"reactive-programming\">响应式编程</h3>\n\n响应式程序库扩展了 JavaScript 的能力。\n\n* RxJs：对 JavaScript 进行响应式扩展。[官网](https://github.com/Reactive-Extensions/RxJS)\n* Bacon：JavaScript 的 FPR（函数式响应式编程）库。[官网](https://github.com/baconjs/bacon.js)\n* Kefir：受 Bacon.js 和 RxJS 启发的 FRP 库，专注于高性能和低内存消耗。[官网](https://github.com/pozadi/kefir)\n* Highland：对 JavaScript 实用工具的重新思考，Highland 能轻易地管理同步和异步信息，而且仅使用标准 JavaScript 和类 Node 流。[官网](http://highlandjs.org/)\n* Most.js：高性能 FRP 库。[官网](https://github.com/cujojs/most)\n\n<h3 id=\"data-structure\">数据结构</h3>\n\n数据结构库用于构建一个更复杂的应用。\n\n* immutable-js：不可变的数据集合，包括 Sequence、Range、Repeat、Map、OrderedMap、Set 和 sparse Vector。[官网](https://github.com/facebook/immutable-js)\n* mori：使用 ClojureScript 持久化数据结构和支持原生 JavaScript API 的库。[官网](https://github.com/swannodette/mori)\n* buckets：完整的、经过充分测试和记录数据结构的 JavaScript 库。[官网](https://github.com/mauriciosantos/Buckets-JS)\n* hashmap：简单的 hashmap 实现，支持任何类型的键值。[官网](https://github.com/flesler/hashmap)\n\n<h3 id=\"date\">日期</h3>\n\n日期库。\n\n* moment：解析、验证、操作和显示日期。[官网](https://github.com/moment/moment)\n* moment-timezone：基于 moment.js 的时区库。[官网](https://github.com/moment/moment-timezone)\n* jquery-timeago：一款支持自动更新模糊时间戳的 jQuery 插件（如：\"4 分钟之前\"）。[官网](https://github.com/rmm5t/jquery-timeago)\n* timezone-js：让 JavaScript Date 对象拥有时区功能。使用 Olson zoneinfo 文件记录着时区数据。[官网](https://github.com/mde/timezone-js)\n* date：拥有人性化的 Date() 方法。[官网](https://github.com/MatthewMueller/date)\n* ms.js：小巧的毫秒转换工具。[官网](https://github.com/rauchg/ms.js)\n* timeago.js：一个非常轻量级(~1.7 Kb)的用于将时间转化成`xxx时间前`格式，例如：8分钟前。[官网](http://timeago.org)\n\n<h3 id=\"string\">字符串</h3>\n\n字符串库。\n\n* selecting：一个允许你获取用户选定文本的库。[官网](https://github.com/EvandroLG/selecting)\n* underscore.string：扩展了 Underscore.js 的字符串操作。[官网](https://github.com/epeli/underscore.string)\n* string.js：额外的 JavaScript 字符串方法。[官网](https://github.com/jprichardson/string.js)\n* he：健壮的 HTML 实体编码/解码器。[官网](https://github.com/mathiasbynens/he)\n* multiline：多行字符串。[官网](https://github.com/sindresorhus/multiline)\n* query-string：解析和字符串化 URL 查询字符串。[官网](https://github.com/sindresorhus/query-string)\n* URI.js：URL 操作库。[官网](https://github.com/medialize/URI.js/) \n* jsurl：轻量的 URL 操作库。[官网](https://github.com/Mikhus/jsurl)\n* sprintf.js：实现字符串格式化。[官网](https://github.com/alexei/sprintf.js)\n* url-pattern：让 url 和其它字符串进行比正则表达式匹配更简单。字符串和数据可相互转化。[官网](https://github.com/snd/url-pattern)\n\n<h3 id=\"number\">数字</h3>\n\n* Numeral-js：对数字进行格式化和操作的库。[官网](https://github.com/adamwdraper/Numeral-js)\n* odometer：流畅的数字过渡效果。[官网](https://github.com/HubSpot/odometer)\n* accounting.js：对数字、金钱、货币进行格式化的轻量库——完全本地化和无依赖。[官网](https://github.com/josscrowcroft/accounting.js)\n* money.js：一个小巧（1kb）的货币转换库，适用于 web 和 nodeJS。[官网](https://github.com/josscrowcroft/money.js)\n* Fraction.js：一个有理数库。[官网](https://github.com/infusion/Fraction.js)\n* Complex.js： 一个复数库。[官网](https://github.com/infusion/Complex.js)\n* Polynomial.js：一个多项式库。[官网](https://github.com/infusion/Polynomial.js)\n\n<h3 id=\"storage\">存储</h3>\n\n* store.js：为所有浏览器封装了 LocalStorage，而没有使用 cookies 和 flash。隐秘地使用 localStorage、globalStorage 和用户数据。[官网](https://github.com/marcuswestin/store.js)\n* localForage：改善后的离线存储。其封装了 IndexedDB、WebSQL 和 localStorage，拥有操作简单和强大的 API。[官网](https://github.com/mozilla/localForage)\n* jStorage：jStorage 是一个简单的键值对数据库，用于在浏览器端存储数据。[官网](https://github.com/andris9/jStorage)\n* cross-storage：获得权限后，能跨域名本地存储。[官网](https://github.com/zendesk/cross-storage)\n* basket.js：用 localStorage 加载和缓存脚本的资源加载器。[官网](https://github.com/addyosmani/basket.js)\n* bag.js：可以缓存脚本和加载资源，与 basket.js 相似，但增加了键值对接口和对 localStorage / websql / [官网](https://github.com/nodeca/bag.js)undexedDB 的支持。\n* basil.js：智能的 JavaScript 数据持久层库。[官网](https://github.com/Wisembly/basil.js)\n* jquery-cookie：轻量简单的、用于读取、编辑和删除 cookie 的 jQuery 插件。[官网](https://github.com/carhartl/jquery-cookie)\n* Cookies：客户端 Cookie 操作库。[官网](https://github.com/ScottHamper/Cookies)\n* DB.js：基于 Promise 的、封装了 IndexedDB 的库。[官网](https://github.com/aaronpowell/db.js/)\n* lawnchair.js：简单的客户端 JSON 存储。[官网](https://github.com/brianleroux/lawnchair/)\n\n<h3 id=\"color\">颜色</h3>\n\n* randomColor：JavaScript 颜色生成器。[官网](https://github.com/davidmerfield/randomColor)\n* chroma.js：拥有各种各样颜色操作的 JavaScript 库。[官网](https://github.com/gka/chroma.js)\n* color：JavaScript 颜色转换和操作库。[官网](https://github.com/MoOx/color)\n* colors：更智能的默认 web 颜色。[官网](https://github.com/mrmrs/colors)\n* PleaseJS：随机创建出赏心悦目的颜色和配色方案。[官网](https://github.com/Fooidge/PleaseJS)\n* TinyColor：快速、轻巧的颜色操作和转换库。[官网](https://github.com/bgrins/TinyColor)\n* Vibrant.js：从图像提取主要颜色。[官网](https://github.com/jariz/vibrant.js/)\n\n<h3 id=\"i18n-and-l10n\">国际化和本地化（I18n And L10n）</h3>\n\n本地化和国际化 JavaScript 库\n\n* i18next：JavaScript 最简单的国际化（i18n）方法。[官网](https://github.com/i18next/i18next)\n* polyglot：小巧的国际化助手库。[官网](https://github.com/airbnb/polyglot.js)\n* babelfish：i18n 提供友好易懂的 API ，并且内置多种支持。[官网](https://github.com/nodeca/babelfish/)\n\n<h3 id=\"class\">类</h3>\n\n* ClassManager：世界上最快、最方便的类系统之一。[官网](https://github.com/kogarashisan/ClassManager)\n* klass：用于创建极富表现力的类工具库。[官网](https://github.com/ded/klass)\n* augment：世界上最小且最快的一流 JavaScript 继承模式。[官网](https://github.com/javascript/augment)\n\n<h3 id=\"control-flow\">控制流</h3>\n\n* async：适用于 node 和浏览器的异步工具库。[官网](https://github.com/caolan/async)\n* q：实现异步的 promise JavaScript 库。[官网](https://github.com/kriskowal/q)\n* step：让逻辑顺序合理化的异步控制流库。[官网](https://github.com/creationix/step/)\n* contra：利用函数风格实现的异步流控制。[官网](https://github.com/bevacqua/contra/)\n* Bluebird：专注于革新功能和性能的，功能齐全的 promoise 库。[官网](https://github.com/petkaantonov/bluebird/)\n* when：快速可靠的、Promises/A+ 规范的 when() 实现，而且拥有异步其它的优秀特性。[官网](https://github.com/cujojs/when)\n* ObjectEventTarget：提供增加了事件监听的原型（与 DOMElement 的 EventTarget 在浏览器行为一致）。[官网](https://github.com/gartz/ObjectEventTarget)\n\n<h3 id=\"routing\">路由</h3>\n\n* director：一个小巧的、与 URL 同构的路由器。[官网](https://github.com/flatiron/director)\n* page.js：受 Express router 启发的小型客户端路由器（约为1200字节）。[官网](https://github.com/visionmedia/page.js)\n* pathjs：简单、轻量的 web 路由器。[官网](https://github.com/mtrpcic/pathjs)\n* crossroads：JavaScript 路由。[官网](https://github.com/millermedeiros/crossroads.js)\n* davis.js：使用 pushState、RESTful 风格和可降级的 JavaScript 路由器。[官网](https://github.com/olivernn/davis.js)\n* [angular-ui-router](http://hao.jobbole.com/angular-ui-router/)：基于AngularJS的可嵌套路由。[官网](http://angular-ui.github.io/ui-router/)\n\n<h3 id=\"security\">安全性</h3>\n\n* DOMPurify：针对 HTML、MathML 和 SVG 的仅支持DOM、快速、高容错的 XSS 过滤器。[官网](https://github.com/cure53/DOMPurify)\n* js-xss：通过白名单配置，即可过滤不信任的 HTML（防止 XSS 攻击）。[官网](https://github.com/leizongmin/js-xss)\n\n<h3 id=\"log\">日志</h3>\n\n* log：带有样式的 Console.log。[官网](https://github.com/adamschwartz/log)\n* Conzole：对 JavaScript 原生 console 对象方法和功能进行封装的 debug 面板，使其显示在页面内。[官网](https://github.com/Oaxoa/Conzole)\n* console.log-wrapper：将日志清晰地记录到 console，且兼容所有浏览器。[官网](https://github.com/patik/console.log-wrapper)\n* loglevel：最轻量的 JavaScript 日志记录工具库，向封装后可用的 console.log 方法增加可靠的日志等级。[官网](https://github.com/pimterry/loglevel)\n* minilog：轻量的、用流式 API 显示的、可用于客户端和服务器端的日志记录库。[官网](http://mixu.net/minilog/)\n\n<h3 id=\"regexp\">正则表达式</h3>\n\n* RegEx101：在线的 JavaScript 正则表达式测试器和调试器。同时支持 Python、PHP 和 PCRE。[官网](https://regex101.com/#javascript)\n* RegExr：用于创建、测试和学习正则表达式的 HTML/JS  工具。[官网](http://regexr.com/)\n* RegExpBuilder：使用链式方法创建正则表达式。[官网](https://github.com/thebinarysearchtree/regexpbuilderjs)\n\n<h3 id=\"media\">媒体</h3>\n\n* Ion.Sound：可用于任何网页上简单音频。[官网](https://github.com/IonDen/ion.sound)\n\n<h3 id=\"voice-command\">语音命令</h3>\n\n* annyang：向网站添加语音命令的语音识别库。[官网](https://github.com/TalAter/annyang)\n* voix.js：向网站、app 或游戏添加语音命令的 JavaScript 库。[官网](https://github.com/pazguille/voix)\n\n<h3 id=\"api\">API</h3>\n\n* bottleneck：强大的频率限制器，使调节流量变得更容易。[官网](https://github.com/SGrondin/bottleneck)\n* oauth-signature-js：适用于 node 和 浏览器的 OAuth 1.0a 签名生成器。[官网](https://github.com/bettiolo/oauth-signature-js)\n* amygdala：为 Web 应用提供 RESTful HTTP 客户端解决方案。[官网](https://github.com/lincolnloop/amygdala)\n* jquery.rest：一个让 RESTful API 更易使用的 jQuery 插件。[官网](https://github.com/jpillora/jquery.rest)\n\n<h3 id=\"vision-detection\">视觉检测</h3>\n\n* tracking.js：在 web 上实现计算视觉的一种现代方法。[官网](https://github.com/eduardolundgren/tracking.js)\n* ocrad.js：通过 Emscripten 用 JavaScript 实现 OCR（光学字符识别）。[官网](https://github.com/antimatter15/ocrad.js)\n\n<h3 id=\"browser-detection\">浏览器检测</h3>\n\n* bowser：一个浏览器检测器。[官网](https://github.com/ded/bowser)\n\n## UI\n\n<h3 id=\"code-highlighting\">代码高亮</h3>\n\n* Highlight.js：JavaScript 语法高亮器。[官网](https://github.com/isagalaev/highlight.js)\n* PrismJS：轻量、健壮和优雅的语法高亮器。[官网](https://github.com/PrismJS/prism)\n\n<h3 id=\"loading-status\">加载状态</h3>\n\n指示加载状态的库。\n\n* Mprogress.js：创建谷歌 Material 设计风格的线性进度条。[官网](https://github.com/lightningtgc/MProgress.js)\n* NProgress：在 Ajax'y 应用显示细长型进度条[官网](http://ricostacruz.com/nprogress/)\n* Spin.js：一个旋转的进度指示器。[官网](https://github.com/fgnass/spin.js)\n* progress.js：为页面任何对象创建和管理进度条。[官网](https://github.com/usablica/progress.js)\n* progressbar.js：用 SVG path 动画制作的、漂亮和响应式的进度条。[官网](https://github.com/kimmobrunfeldt/progressbar.js)\n* pace：自动向你的网站添加一个进度条。[官网](https://github.com/HubSpot/pace)\n* topbar：小巧漂亮的、与网站同宽的进度指示器。[官网](https://github.com/buunguyen/topbar)\n* nanobar：非常轻量的进度条。不依赖 jQuery。[官网](https://github.com/jacoborus/nanobar)\n* PageLoadingEffects：使用 SVG 动画展现新内容的现代方式。[官网](https://github.com/codrops/PageLoadingEffects)\n* SpinKit：运用 CSS 动画的加载指示器集合。[官网](https://github.com/tobiasahlin/SpinKit)\n* Ladda：内置在按钮的加载指示器。[官网](https://github.com/hakimel/Ladda)\n* css-loaders：运用 CSS 动画的旋转加载指示器的集合。[官网](https://github.com/lukehaas/css-loaders)\n\n除了上述这些库，还有收藏在 [Codepen](http://codepen.io/collection/HtAne/) 的，另外还有 [Ajaxload](http://www.ajaxload.info/)，[Preloaders](http://preloaders.net/) 和 [CSSLoad](http://cssload.net/) 这些生成器。\n\n<h3 id=\"validation\">验证</h3>\n\n* Parsley.js：不用写一行 JavaScript 代码即可在前端验证表单。[官网](https://github.com/guillaumepotier/Parsley.js)\n* jquery-validation：jQuery 验证插件。[官网](https://github.com/jzaefferer/jquery-validation)\n* validator.js：字符串验证和过滤（在使用用户输入之前清理用户输入中的有害或危险字符的操作）。[官网](https://github.com/chriso/validator.js)\n* validate.js：受 CodeIgniter 启发的轻量表单验证 JavaScript 库。[官网](https://github.com/rickharrison/validate.js)\n* validatr：跨浏览器的 HTML5 表单验证库。[官网](https://github.com/jaymorrow/validatr/)\n* BootstrapValidator：是验证表单域中最好的 jQuery 插件。要与 Bootstrap 3 一起使用。[官网](https://github.com/nghuuphuoc/bootstrapvalidator)\n* [is.js](http://hao.jobbole.com/is-js/)：检查类型、正则表达式、是否存在、时间等。[官网](https://github.com/arasatasaygin/is.js)\n* FieldVal：多用途验证库。同时支持同步和异步验证。[官网](https://github.com/FieldVal/fieldval-js)\n\n<h3 id=\"keyboard-wrappers\">键盘封装器</h3>\n\n* mousetrap：处理键盘快捷键的 JavaScript 库。[官网](https://github.com/ccampbell/mousetrap)\n* keymaster：定义和调度键盘快捷键的小型库。[官网](https://github.com/madrobby/keymaster)\n* Keypress：键入捕捉工具库，任何键都可以成为一个修饰健。[官网](https://github.com/dmauro/Keypress)\n* KeyboardJS：一个用于绑定键盘组合的 JavaScript 库，让你脱离快捷键和快捷键组合冲突的痛苦。[官网](https://github.com/RobertWHurst/KeyboardJS)\n* jquery.hotkeys：jQuery Hotkeys 能让你在代码任何的地方监听键盘事件，并几乎支持所有按键组合。[官网](https://github.com/jeresig/jquery.hotkeys)\n* jwerty：令人惊叹的键盘事件处理库。[官网](https://github.com/keithamus/jwerty)\n\n<h3 id=\"tours-and-guides\">浏览和引导</h3>\n\n* intro.js：这是一个介绍新功能的很好方式，能一步步地引导用户浏览你的网站和项目。[官网](https://github.com/usablica/intro.js)\n* shepherd：通过引导让用户浏览你的应用程序。[官网](https://github.com/HubSpot/shepherd)\n* bootstrap-tour：应用 Twitter Bootstrap 弹出框对产品进行快速简单的引导。[官网](https://github.com/sorich87/bootstrap-tour)\n* tourist：简单、灵活的应用引导介绍库。[官网](https://github.com/easelinc/tourist)\n* chardin.js：简单的应用遮罩层介绍。[官网](https://github.com/heelhook/chardin.js)\n* pageguide：使用 jQuery 和 CSS3 的 web 页面元素交互引导库。[官网](https://github.com/tracelytics/pageguide)\n* hopscotch：让开发者更容易向其页面产品添加引导的框架。[官网](https://github.com/linkedin/hopscotch)\n* joyride：基于 jQuery 的功能引导插件。[官网](https://github.com/zurb/joyride)\n* focusable：通过向页面其余部分添加遮罩层，使焦点聚集在特定 DOM 元素。[官网](https://github.com/zzarcon/focusable)\n\n<h3 id=\"notifications\">通知</h3>\n\n* messenger：为你的应用添加 Growl-style 弹框和信息（Crowl 是 Mac OS X 下的一个通知系统）。[官网](https://github.com/HubSpot/messenger)\n* noty：jQuery 通知插件。[官网](https://github.com/needim/noty)\n* pnotify：适用于 Bootstrap、jQuery UI 和 Web Notifications Draft 的 JavaScript 通知库。[官网](https://github.com/sciactive/pnotify)\n* toastr：用来显示简单的，会自动到期的信息窗口）简单的弹出框通知（[toast notifications](http://ux.stackexchange.com/questions/11998/what-is-a-toast-notification)[官网](https://github.com/CodeSeven/toastr)\n* humane-js：一个简单、时髦的浏览器通知系统。[官网](https://github.com/wavded/humane-js)\n* smoke.js：与框架无关的、能够自定义样式的 JavaScript 弹框系统。[官网](https://github.com/hxgf/smoke.js)\n\n<h3 id=\"sliders\">幻灯片</h3>\n\n* Swiper：使用硬件加速过渡的移动设备触控滑块框架。[官网](https://github.com/nolimits4web/Swiper)\n* slick：你所需要的最后一个轮播插件。[官网](https://github.com/kenwheeler/slick)\n* slidesJs：响应式的 jQuery（1.7.1+）幻灯片插件，具有触摸、 CSS3 过渡等特性。[官网](http://www.slidesjs.com/)\n* FlexSlider：一款令人惊叹的、全响应式的幻灯片 jQuery 插件。[官网](https://github.com/woothemes/FlexSlider)\n* unslider：最简单的幻灯片 jQuery 插件。[官网](https://github.com/idiot/unslider)\n* colorbox：轻量、可自定义的灯箱 jQuery 插件。[官网](https://github.com/jackmoore/colorbox)\n* fancyBox：提供了良好优雅的方式，为页面上的图片、html 内容和多媒体添加缩放功能的工具。[官网](https://github.com/fancyapps/fancyBox)\n* sly：基于项导航的、支持单向滚动的 JavaScript 库。[官网](https://github.com/darsain/sly)\n* vegas：向页面添加漂亮的全屏背景的 jQuery 插件，甚至允许幻灯片。[官网](https://github.com/jaysalvat/vegas)\n* Sequence：用于创建响应式的幻灯片、演示、旗帜广告和以步骤为基础的应用的 CSS 动画框架。[官网](https://github.com/IanLunn/Sequence)\n* baguetteBox.js：易于使用的、用纯 JavaScript 实现的遮罩层脚本。[官网](https://github.com/feimosi/baguetteBox.js)\n* reveal.js：用 HTML 创建漂亮演示控件的框架。[官网](https://github.com/hakimel/reveal.js)\n* PhotoSwipe：适用于移动设备和桌面电脑的、模块化和不无依赖框架的 JavaScript 画廊控件。[官网](https://github.com/dimsemenov/PhotoSwipe)\n* jcSlider：用 CSS 动画实现的响应式幻灯片 jQuery 插件。[官网](https://github.com/JoanClaret/jcSlider)\n* basic-jquery-slider：易于使用、指定主题和定制化。[官网](https://github.com/jcobb/basic-jquery-slider)\n* unslider： 这是最简单的幻灯片 jQuery 插件。[官网](https://github.com/idiot/unslider)\n* viewerjs：原生js实现的图片查看器。[官网](https://fengyuanchen.github.io/viewerjs/)\n* jQuery.adaptive-slider：带有自适应颜色标题和导航的幻灯片 jQuery 插件。[官网](https://github.com/creative-punch/jQuery.adaptive-slider/)\n* slidr：可添加一些幻灯片效果。[官网](https://github.com/bchanx/slidr)\n* Flickity：可触摸的、响应式的和可轻弹的画廊。[官网](https://github.com/metafizzy/flickity)\n\n<h3 id=\"range-sliders\">滑块控件</h3>\n\n* Ion.RangeSlider：强大的、易于自定义的范围滑块选择库，支持很多配置和皮肤。[官网](https://github.com/IonDen/ion.rangeSlider)\n* jQRangeSlider：支持日期的滑块选择库。[官网](https://github.com/ghusse/jQRangeSlider)\n* noUiSlider：轻量无冗余的、高度定制化的滑块选择库。[官网](https://github.com/leongersen/noUiSlider)\n* rangeslider.js：HTML5  input 区域滑块元素。[官网](https://github.com/andreruffert/rangeslider.js)\n\n<h3 id=\"form-widgets\">表单组件</h3>\n\n### 输入\n\n* typeahead.js：快速的、功能齐全的自动补全库。[官网](https://github.com/twitter/typeahead.js)\n* tag-it：处理多标签字段以及标签建议/自动完成的 jQuery UI 插件。[官网](https://github.com/aehlke/tag-it)\n* At.js：向你的应用添加类似 Github 的自动完成提示功能。[官网](https://github.com/ichord/At.js)\n* Placeholders.js：JavaScript 补全 HTML5 占位符的属性。[官网](https://github.com/jamesallardice/Placeholders.js)\n* fancyInput：利用 CSS3 效果让输入更有趣。[官网](https://github.com/yairEO/fancyInput)\n* jQuery-Tags-Input：利用这个 jQuery 插件，可奇妙地将一个简单的文本输入转换成一个酷酷的标签列表。[官网](https://github.com/xoxco/jQuery-Tags-Input)\n* vanilla-masker：一个纯 JavaScript 实现的输入控制库。[官网](https://github.com/BankFacil/vanilla-masker)\n* Ion.CheckRadio：一个为复选框和单选按钮添加样式的 jQuery 库，支持多种皮肤。[官网](https://github.com/IonDen/ion.checkRadio)\n\n### 日历\n\n* pickadate.js：对移动设备友好的、响应式的和轻量的 jQuery 日期 &amp; 时间输入选择器。[官网](https://github.com/amsul/pickadate.js)\n* bootstrap-datepicker：基于 bootstrap 的日历选择器。[官网](https://github.com/eternicode/bootstrap-datepicker)\n* Pikaday：一个崭新的 JavaScript 日期选择器 —— 轻量、无依赖和模块化的 CSS。[官网](https://github.com/dbushell/Pikaday)\n* fullcalendar：全尺寸、支持拖放事件的日历（jQuery 插件）。[官网](https://github.com/fullcalendar/fullcalendar)\n* rome：可定制的日期（和时间）选择器。无依赖，可选 UI。[官网](https://github.com/bevacqua/rome)\n* datedropper： datedropper 是一个 jQuery 插件，它提供了快速简易的方式去管理日期输入框。[官网](https://github.com/felicegattuso/datedropper)\n\n### 选择\n\n* selectize.js：Selectize 是文本框和选择框的混合体。它基于jQuery，拥有自动完成和键盘感应下拉列表功能，可用于标签、联系人列表等。[官网](https://github.com/brianreavis/selectize.js)\n* select2：它基于 jQuery，是选择框（select box）的替代品。支持搜索、远程数据集和无限滚动。[官网](https://github.com/select2/select2)\n* chosen：可以让冗长不便的选择框更友好的库。[官网](https://github.com/harvesthq/chosen)\n\n### 文件上传\n\n* jQuery-File-Upload：File Upload 是一个支持多文件选择、文件拖放、进度条、验证和图片、音频、视频预览的 [官网](https://github.com/blueimp/jQuery-File-Upload)jQuery 插件。\n* dropzone：Dropzone 是一个易于使用且支持多文件拖放的库。其支持图片预览并且拥有很好的进度条效果。[官网](https://github.com/enyo/dropzone)\n* flow.js：一个通过 HTML5 的 File API ，提供多个同时链接的、稳定的、容错的、可恢复的/可重新开始的文件上传库。[官网](https://github.com/flowjs/flow.js)\n* fine-uploader：一个带有进度条、拖放功能和支持直接上传到 S3 （Amazon Simple Storage Service，亚马逊简易存储服务）的多文件上传插件。[官网](https://github.com/FineUploader/fine-uploader)\n* FileAPI：JavaScript 文件工具集合。支持多文件上传、拖放和文件分块上传。对于图像，支持裁剪、调整大小和根据 [EXIF](http://baike.baidu.com/view/22006.htm) 自动调整方向。[官网](https://github.com/mailru/FileAPI)\n* plupload：处理文件上传的 JavaScript [官网](https://github.com/moxiecode/plupload)API，其支持多文件选择、文件类型过滤、分块请求、客户端图片缩放和根据不同的运行环境选择 HTML5、Silverlight 和 Flash。\n\n### 其它\n\n* form：jQuery 表单插件。[官网](https://github.com/malsup/form)\n* Garlic.js：自动在本地保存表单文本和选择框的值，直到表单被提交。[官网](https://github.com/guillaumepotier/Garlic.js)\n* Countable：对某个 HTML 元素包含文本的段落数、单词数和字符数进行统计的 JavaScript 函数。[官网](https://github.com/RadLikeWhoa/Countable)\n* card：只需一行代码，让信用卡表单变得更友好。[官网](https://github.com/jessepollak/card)\n* stretchy：自适应大小的 form 元素，表单本应该是这样的。[官网](https://github.com/LeaVerou/stretchy)\n* list.js：向表格、列表等 HTML 元素添加搜索、排序、过滤和自适应功能的库。在已有 HTML 上增加可视化。[\n ](http://www.listjs.com/)[官网](https://github.com/javve/list.js)\n\n<h3 id=\"tips\">提示</h3>\n\n* tipsy：基于 jQuery 的 Fackbook 风格的提示工具（tooltip）。[官网](https://github.com/jaz303/tipsy)\n* opentip：开源且基于 prototype 框架的 JavaScript 工具提示库。[官网](https://github.com/enyo/opentip)\n* qTip2：非常强大的工具提示库。[官网](https://github.com/qTip2/qTip2)\n* tooltipster：一个工具提示 jQuery 插件。[官网](https://github.com/iamceege/tooltipster)\n* simptip：用 Sass 制作的、简单的工具提示。[官网](https://github.com/arashmanteghi/simptip)\n* jquery-popup-overlay：是一个响应式的和可访问性强的模态框（modal）和工具提示框 jQuery 插件。[官网](https://github.com/vast-engineering/jquery-popup-overlay)\n\n<h3 id=\"modals-and-popups\">模态框和弹出框</h3>\n\n* Magnific-Popup：专注于性能、轻量、响应式的灯箱（lightbox）脚本。[官网](https://github.com/dimsemenov/Magnific-Popup)\n* jquery-popbox：jQuery 提示框插件。[官网](https://github.com/gristmill/jquery-popbox)\n* jquery.avgrund.js：一种新的定于弹出的模态框 jQuery 插件。[官网](https://github.com/voronianski/jquery.avgrund.js)\n* vex：新的、拥有高度可配置和易于改变样式功能的对话框库。[官网](https://github.com/HubSpot/vex)\n* bootstrap-modal：对 Bootstrap 默认的模态框类进行扩展。其支持响应式、可堆叠和 ajax 等。[官网](https://github.com/jschr/bootstrap-modal)\n* css-modal：纯 CSS 打造的模态框。[官网](https://github.com/drublic/css-modal)\n* jquery-popup-overlay：是一个响应式的和可访问性强的模态框和工具提示框（tooltips）jQuery 插件。[官网](https://github.com/vast-engineering/jquery-popup-overlay)\n* layer：国内最多人使用的web弹层组件。[官网](https://github.com/sentsin/layer/)\n\n<h3 id=\"scroll\">滚动</h3>\n\n* scrollMonitor：滚动发生时，可以监听元素的、简单、快速的 API。[官网](https://github.com/sakabako/scrollMonitor)\n* headroom：除非你需要显示页面头部（header），否则将隐藏它，以腾出页面头部空间。[官网](https://github.com/WickyNilliams/headroom.js)\n* onepage-scroll：创建一个类似 Apple 的单页面滚动网站（iPhone 5S  网站）。[官网](https://github.com/peachananr/onepage-scroll)\n* iscroll：高性能、轻量、无依赖、兼容多平台的 JavaScript 滚动组件。[官网](https://github.com/cubiq/iscroll)\n* skrollr：独立（不依赖 jQuery） 的视差滚动库，适用于移动设备（Android + iOS）和桌面电脑。[官网](https://github.com/Prinzhorn/skrollr)\n* parallax：面向智能设备的视差引擎。[官网](https://github.com/wagerfield/parallax)\n* stellar.js：让视差滚动变简单。[官网](https://github.com/markdalgleish/stellar.js)\n* plax：基于 jQuery 的视差库。[官网](https://github.com/cameronmcefee/plax)\n* jparallax：创建可交互视差效果的 jQuery 插件。[官网](https://github.com/stephband/jparallax)\n* fullPage：简单和易于使用的、用于创建全屏滚动网站的插件（也被称为单页面网站）。[官网](https://github.com/alvarotrigo/fullPage.js)\n* ScrollMenu：让老旧无聊的滚动条焕然一新。[官网](https://github.com/s-yadav/ScrollMenu)\n\n<h3 id=\"menu\">菜单</h3>\n\n* jQuery-menu-aim：当用户光标放在特定下拉菜单项时触发事件。可制作响应式的、大数据量的下拉菜单，如 Amazon 的。[官网](https://github.com/kamens/jQuery-menu-aim)\n* jQuery contextMenu：右键菜单（contextMenu） 管理工具。[官网](https://github.com/swisnl/jQuery-contextMenu)\n* Slideout：为移动设备的 web 应用制作出响应式的、可触摸滑出的导航菜单。[官网](https://github.com/mango/slideout)\n* Slide and swipe：一个基于 touchSwipe 库的滑出菜单插件。[官网](https://github.com/JoanClaret/slide-and-swipe-menu)\n\n<h3 id=\"table-grid\">表格/栅格</h3>\n\n* jTable：基于 CRUD 表创建 AJAX 的 jQuery 插件。[官网](https://github.com/hikalkan/jtable)\n* DataTables：这是一个非常灵活的工具，在渐进增强的基础上，将高级的交互效果加到 HTML 表格。（jQuery 插件）[官网](http://www.datatables.net/) \n* floatThead：（jQuery 插件）锁定表格头部，只允许表格内容滚动。适用于任何表格，而且不需要额外的 html 或 css。[官网](https://github.com/mkoryak/floatThead)\n* Masonry：瀑布流式的网格布局库。[官网](http://masonry.desandro.com/)\n* Packery：使用装箱算法（bin-packing）的网格布局库。支持拖拽布局。[官网](http://packery.metafizzy.co/)\n* Isotope：可过滤和可排序的网格布局的库，它能实现 Masonry、Packery 等布局。[官网](http://isotope.metafizzy.co/)\n\n<h3 id=\"frameworks-1\">框架</h3>\n\n* Semantic UI：拥有大量主题和元素的 UI 套件。[官网](http://semantic-ui.com/)\n\n<h3 id=\"gesture\">手势</h3>\n\n* hammer.js：拥有多种触摸手势的 JavaScript 库。[官网](https://github.com/hammerjs/hammer.js)\n* touchemulator：在桌面电脑模仿触摸输入。[官网](https://github.com/hammerjs/touchemulator)\n* Dragula：超级易于使用的拖拽库。[官网](https://github.com/bevacqua/dragula/)\n\n<h3 id=\"touch\">触摸</h3>\n\n* fastclick.js：去除触屏用户300ms点击延误。[官网](https://github.com/ftlabs/fastclick)\n* dropload.js：移动端下拉刷新，上拉加载更多。[官网](https://github.com/ximan/dropload)\n* touchslide.js：触屏滑动特效。[官网](http://www.superslide2.com/touchSlide/)\n\n<h3 id=\"maps\">地图</h3>\n\n* Leaflet：对移动设备友好的、可交互的地图 JavaScript 库。[官网](https://github.com/Leaflet/Leaflet)\n* Cesium：开源的、基于 WebGL 实现的虚拟地球仪和地图引擎。[官网](https://github.com/AnalyticalGraphicsInc/cesium)\n* gmaps：以最简单的方式使用 Google 地图。[官网](https://github.com/HPNeo/gmaps)\n* polymaps：一个免费的、兼容现代 web 浏览器的、用于制作动态可交互的地图 JavaScript 库。[官网](https://github.com/simplegeo/polymaps)\n* kartograph.js：开源的 Kartograph SVG 地图渲染器。[官网](https://github.com/kartograph/kartograph.js)\n* mapbox.js：Mapbox 的 API，Leaflet 的插件。[官网](https://github.com/mapbox/mapbox.js)\n* jqvmap：矢量地图 jQuery 插件。[官网](https://github.com/manifestinteractive/jqvmap)\n* OpenLayers3：高性能的、功能丰富的库，能满足你对地图所有需求。[官网](http://openlayers.org/)\n\n<h3 id=\"video-audio\">视频/音频</h3>\n\n* prettyembed.js：更完美地嵌入 YouTube —— 拥有很好的选项，如高分辨率的预览图、嵌入选项的高级定制和可选的 [官网](https://github.com/mike-zarandona/prettyembed.js)FitVids 支持。\n* [html5media](http://hao.jobbole.com/html5media/)：能在所有主流浏览器播放多媒体标签中定义的多媒体文件。[官网](https://github.com/etianen/html5media)\n* Play-em JS：Play'em 是一个 JavaScript 组件，它能管理音乐/视频播放顺序，通过在一个 DIV 元素里嵌入几个播放器（Youtube、Soundcloud 和 Vimeo）来控制一系列歌曲的播放。[官网](https://github.com/adrienjoly/playemjs)\n* polyplayer：将 YouTube、Soundcloud 和 Vimeo 播放器的 API 统一成一套。[官网](https://github.com/Acconut/polyplayer)\n* flowplayer： HTML5 视频播放器 [官网](https://flowplayer.org/)、[Github](https://github.com/flowplayer/flowplayer)\n* mediaelement：让 HTML5、 Flash 播放器和模仿 HTML5 媒介元素 API 的 Silverlight shim，在所有浏览器拥有一致的 UI。[官网](http://mediaelementjs.com/)、[Github](https://github.com/johndyer/mediaelement)\n* SoundJS：让音频在 web 上运行更简单的库。它为不同浏览器提供了一致的 API。[官网](https://github.com/CreateJS/SoundJS)\n\n<h3 id=\"animations\">动画</h3>\n\n* [velocity](http://hao.jobbole.com/velocity-js/)：加速 JavaScript 动画。[官网](https://github.com/julianshapiro/velocity)\n* [jquery.transit](http://hao.jobbole.com/jquery-transit/)：拥有超级流畅的 CSS3 变换和过渡的 jQuery 插件。[官网](https://github.com/rstacruz/jquery.transit)\n* impess.js：在 HTML 文档里，运用 CSS3 变换和过渡制作类似 Prezi 的展现效果。[官网](https://github.com/impress/impress.js)\n* [bounce.js](http://hao.jobbole.com/bounce-js/)：可以立刻创建有趣的 CSS3 动画。[官网](https://github.com/tictail/bounce.js)\n* GreenSock-JS：适用于所有主流浏览器的高性能 HTML5 动画。[官网](https://github.com/greensock/GreenSock-JS)\n* TransitionEnd：TransitionEnd 是一个运用 transitonend 事件的、跨浏览器的库。[官网](https://github.com/EvandroLG/transitionEnd)\n* [Dynamics.js](http://hao.jobbole.com/dynamics-js/)：用于创建基于物理知识的 CSS 动画库。[官网](https://github.com/michaelvillar/dynamics.js)\n\n<h3 id=\"image-processing\">图片处理</h3>\n\n* [lena.js](http://hao.jobbole.com/lena-js/)：拥有滤镜和实用功能的图像处理库。[官网](https://github.com/davidsonfellipe/lena.js)\n* [pica](http://hao.jobbole.com/pica/)：高质量地调整图片大小（拥有快速的、纯 JS 实现的 Lanczos 滤镜算法）。[官网](https://github.com/nodeca/pica)\n* cropper：一个简单的图像裁剪 jQuery 插件。[官网](https://github.com/fengyuanchen/cropper)\n* AlloyImage：腾讯前端开源的基于HTML5的专业级图像处理开源引擎。[官网](https://github.com/AlloyTeam/AlloyImage)\n\n<h3 id=\"es6\">ECMAScript 6</h3>\n\n* [es6features](http://hao.jobbole.com/ecmascript-6/)：ECMAScript 6 特性概述。[官网](https://github.com/lukehoban/es6features)\n* es6-features：ECMAScript 6:  特性概述和比较。[官网](https://github.com/rse/es6-features)\n* ECMAScript 6 compatibility table ：Compatibility tables 展示了各种平台上所有 ECMAScript 6 特性的支持程度。[官网](http://kangax.github.io/compat-table/es6/)\n* Babel (Formerly 6to5)：将 ES6+ 代码转换成纯 ES5。[官网](https://github.com/babel/babel)\n* Traceur compiler：ES6 特性转 ES5。包括 classes、generators、promises、destructuring [官网](https://github.com/google/traceur-compiler)patterns、default parameters 等。\n\n<h3 id=\"sdk\">软件开发工具包(SDK)</h3>\n\n* javascript-sdk-design：从工作和个人经验中提炼出来的 JavaScript SDK 设计指导。[官网](https://github.com/huei90/javascript-sdk-design)\n\n<h3 id=\"misc\">大杂烩</h3>\n\n* echo：利用 data-* 属性延迟加载图片。[官网](https://github.com/toddmotto/echo)\n* picturefill：响应式图片显示插件，使浏览器支持 srcset、size 属性。[官网](https://github.com/scottjehl/picturefill)\n* platform.js：一个平台检测库，几乎适用于所有 JavaScript 平台。[官网](https://github.com/bestiejs/platform.js)\n* [json3](http://hao.jobbole.com/json3/)：一个现代 JSON 实现库，几乎兼容所有 JavaScript 平台。[官网](https://github.com/bestiejs/json3)\n* Logical Or Not：一个关于 JavaScript 特性的游戏。[官网](http://gabinaureche.com/logicalornot/)\n* BitSet.js：实现位向量的 JavaScript 库。[官网](https://github.com/infusion/BitSet.js)\n* [Edge.js](http://hao.jobbole.com/edge-js/)：运行在一个进程中运行.NET和Node.js代码。[官网](http://tjanczuk.github.io/edge/)、[GitHub](https://github.com/tjanczuk/edge)\n\n<h2 id=\"worth-reading\">精品阅读</h2>\n\n* braziljs/js-the-right-way：[官网](https://github.com/braziljs/js-the-right-way/)\n* JSbooks：[官网](https://github.com/revolunet/JSbooks)\n* Superhero.js：关于创建、测试和维护一个大型 JavaScript 代码库的资源集。[官网](http://superherojs.com/)\n* 《[前端开发者都应知道的 jQuery 小技巧](http://web.jobbole.com/84028/)》\n* 《[常用的 Javascript 设计模式](http://web.jobbole.com/29454/)》\n* 《[10 个 jQuery 图表插件推荐](http://web.jobbole.com/21136/)》\n* 《[理解 JavaScript 原型](http://web.jobbole.com/9648/)》\n* 《[只有20行Javascript代码！手把手教你写一个页面模板引擎](http://web.jobbole.com/56689/)》\n* 《[编写快速、高效的JavaScript代码](http://web.jobbole.com/31951/)》\n* 《[45个实用的JavaScript技巧、窍门和最佳实践](http://web.jobbole.com/54495/)》\n* 《[为现代JavaScript开发做好准备](http://web.jobbole.com/66135/)》\n* 《[给JavaScript初学者的24条最佳实践](http://web.jobbole.com/53199/)》\n\n<h1 id=\"resources\">资源</h1>\n\n<h3 id=\"influential-books\">有影响力的书</h3>\n*具有广泛影响且值得阅读的前端经典书籍。*\n\n* 《[Limu：JavaScript 的那些书](http://web.jobbole.com/8087/)》\n* 《你不知道的Javascript》：英文版 \"You Don't Know JS\"\n\n<h3 id=\"websites\">知名网站</h3>\n*值得关注的前端技术站点。*\n\n<h4>中文站点</h4>\n\n* 伯乐在线前端频道：伯乐前端分享 Web 前端开发，包括 JavaScript、CSS 和 HTML5 开发技术，前端相关的行业动态。[官网](http://web.jobbole.com/)\n\n<h4>英文站点</h4>\n\n待补充\n\n<h3 id=\"weibo-weixin\">微博、微信公众号</h3>\n* 前端大全 微博：[@前端大全](http://weibo.com/u/5261893910)\n* 前端大全：专注分享Web前端相关的内容，包括 JavaScript, CSS 和 HTML5 技术文章、工具资源、精选课程和Web技术领域热点资讯。\n<br><img src=\"http://ww4.sinaimg.cn/small/63918611gw1epb2c688tqj2046046mx8.jpg\" width=150 height=150>\n* UI设计达人：分享 UI 设计精选文章、案例、行业趋势、课程和书籍。<br><img src=\"http://ww4.sinaimg.cn/mw690/bfdcef89gw1evuvyehtx4j2076076q3e.jpg\" width=150 height=150>\n* 网页设计精选：分享网页设计精选文章、案例、行业趋势、课程和书籍。<br><img src=\"http://ww2.sinaimg.cn/mw690/bfdcef89gw1evuvyhsikmj2076076dgb.jpg\" width=150 height=150>\n"
  },
  {
    "path": "Readme.md",
    "content": "# 在GitHub上收集的最全的前端资源汇总（包括前端学习、前端开发资源、前端求职面试等）\n\n![](https://ws1.sinaimg.cn/mw690/66101050ly1fdlmi7jd3zj21jk111wk9)\n\n> 个人结合github上各位大神分享的资源进行了简单的汇总整理，每一个条目下面都有丰富的资料，是前端学习、工作的好帮手。\n\n**说明:** 整理有不当之处, 欢迎 [pr](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/pulls) 或提出 [issue](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/issues)。\n\n## 更新日志：\n**20170313：**\n- 增加JavaScript 资源大全中文版（作者：伯乐在线）\n\n**20161115：**\n- 增加JavaScript 全栈工程师培训教程（作者：阮一峰）\n\n**20161013：**\n- 增加 Google面试宝典（作者：John Washam）\n\n**20160916：**\n- 增加大前端工具集（作者：聂微东）\n\n\n**关于我：** 微博: [@青丰与名月](http://weibo.com/helloqingfeng)\n\n<br>\n\n## [结合个人经历总结的前端入门方法](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/01-FE-learning-master)\n\n\n作者：qiu https://github.com/qiu-deqing\n\n源地址：https://github.com/qiu-deqing/FE-learning\n\n\n## [前端学习路径](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/26-front-end-learning-path)\n\n作者： 余博伦 https://github.com/discountry\n\n源地址：https://zhuanlan.zhihu.com/p/21935921\n\n## [JavaScript 全栈工程师培训教程](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/30-jstraining)\n作者： 阮一峰 https://github.com/ruanyf\n\n源地址：https://github.com/ruanyf/jstraining\n\n## [前端开发者手册](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/02-fedHandlebook-master)(学习前端的实践手册)\n\n作者：Pomy https://github.com/dwqs\n\n中文源地址：https://github.com/dwqs/fedHandlebook\n\n阅读地址：https://dwqs.gitbooks.io/frontenddevhandbook/content/\n\n英文原版地址：https://www.frontendhandbook.com/\n\n资源下载: \n- [PDF版](http://pan.baidu.com/s/1c0frhIS)\n- [MOBI版](https://www.gitbook.com/book/dwqs/frontenddevhandbook/details)\n\n## [前端开发笔记本](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/03-FEND_Note-master)\n\n作者：Li Xinyang https://github.com/li-xinyang\n\n源地址：https://github.com/li-xinyang/FEND_Note\n\n阅读地址：http://li-xinyang.gitbooks.io/frontend-notebook/\n\n资源下载: [PDF版](https://www.gitbook.com/download/pdf/book/li-xinyang/frontend-notebook)\n\n## [最全的资源教程——前端涉及的所有知识体系](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/04-Front-end-tutorial-master)\n\n作者：JadeYang https://github.com/nicejade\n\n源地址：https://github.com/nicejade/Front-end-tutorial\n\n## [大前端工具集——程序猿的百宝箱](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/28-fetool-master) （0916）\n作者：聂微东 https://github.com/nieweidong\n\n源地址：https://github.com/nieweidong/fetool\n\n阅读地址：http://www.fefork.com/fetool\n\n## [100+ 超全的web开发工具和资源](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/24-100+Web-Development-Tools-and-Resources)\n\n译者：稀土区 https://xituqu.com/\n\n源地址：https://xituqu.com/170.html\n\n## [JavaScript 资源大全中文版](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/31-awesome-javascript-cn)\n\n作者：伯乐在线 https://github.com/jobbole\n\n源地址：https://github.com/jobbole/awesome-javascript-cn\n\n## [前端技能汇总](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/05-fks-master)\n\n作者：Jackson Tian https://github.com/JacksonTian\n\n源地址：https://github.com/JacksonTian/fks\n\n阅读地址：http://html5ify.com/fks/\n\n## [Web前端开发技术栈](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/06-WebFrontEndStack-master)\n\n作者：Wilson Chen https://github.com/unruledboy\n\n源地址：https://github.com/unruledboy/WebFrontEndStack\n\n\n## [前端开发所使用语言的主流学习资源汇集指南](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/07-Front-End-Develop-Guide-master)\n\n作者：icepy https://github.com/icepy\n\n源地址：https://github.com/icepy/Front-End-Develop-Guide\n\n## [GitHub上值得关注的前端项目](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/08-github-FE-project-master)\n\n作者： trigkit4    https://github.com/hawx1993\n\n源地址：https://github.com/hawx1993/github-FE-project\n\n\n## [前端开发相关的优秀网站、博客、以及活跃开发者](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/09-front-end-collect-master)\n\n作者：Luo Lei https://github.com/foru17\n\n源地址：https://github.com/foru17/front-end-collect\n\n## [国内知名 IT 公司前端团队 (排名不分先后)](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/08-github-FE-project-master)\n\n作者：Mingdong Luo https://github.com/mdluo\n\n源地址：https://github.com/mdluo/awesome-fe-team\n\n## [关于程序员读书-大牛们的书单汇总](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/11-about-reading)\n\n作者：Mingdong Luo https://github.com/mdluo\n\n源地址：https://mdluo.github.io/blog/about-reading/\n\n## [Github个人收集的优秀JavaScript项目](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/12-JavaScript-project)\n\n作者：Daiyichen https://github.com/Daiyichen\n\n源地址：https://github.com/Daiyichen/Front-end-tutorial/blob/master/project.md\n\n## [免费的计算机编程类中文书籍](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/13-free-programming-books-zh_CN-master)\n\n作者：迷渡 https://github.com/justjavac\n\n源地址：https://github.com/justjavac/free-programming-books-zh_CN\n\n阅读地址：http://siberiawolf.com/free_programming/index.html\n\n## [前端开发书签](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/14-frontend-dev-bookmarks-master)\n\n作者：张正雄 https://github.com/zzxadi\n\n源地址：https://github.com/zzxadi/frontend-dev-bookmarks\n\n## [收集有趣的、富有交互的前端教程](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/15-fun-front-end-tutorials-master)\n\n作者：JiangShui Yu https://github.com/yujiangshui\n\n源地址：https://github.com/yujiangshui/fun-front-end-tutorials\n\n## [前端代码审查清单](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/16-front-end-code-checklist-master)\n\n作者：JiangShui Yu https://github.com/yujiangshui\n\n源地址：https://github.com/yujiangshui/front-end-code-checklist\n\n## [移动前端资源整理](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/17-Mobile-front-end-tutorial-master)\n\n作者：Ionic China https://github.com/IonicChina\n\n源地址：https://github.com/IonicChina/Mobile-front-end-tutorial\n\n## [前端开发规范手册](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/27-front-end-style-guide)\n作者：阿树 https://github.com/Aaaaaashu\n\n源地址：https://github.com/Aaaaaashu/Guide\n\n阅读地址：http://zhibimo.com/read/Ashu/front-end-style-guide/\n\n##  [Web前端开发规范文档](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/25-web-develop-standard-master)\n\n作者：kc https://github.com/kangcafe\n\n源地址：https://github.com/kangcafe/web_develop_standard\n\n\n## [适用于小团队的前端规范](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/18-fun-front-end-tutorials-master)\n\n作者：hzlzh https://github.com/hzlzh\n\n源地址：https://github.com/hzlzh/Front-End-Standards\n\n阅读地址：http://front-end-standards.com/\n\n<br>\n\n# 前端求职面试\n\n<br>\n\n## [关于程序员求职简历汇总（包含一些优秀简历示例）](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/19-about-resume)\n\n作者：Mingdong Luo https://github.com/mdluo\n\n源地址：https://mdluo.github.io/blog/about-resume/\n\n## [关于前端面试文章汇总](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/20-about-front-end-interview)\n\n作者：Mingdong Luo https://github.com/mdluo\n\n源地址：https://mdluo.github.io/blog/about-front-end-interview/\n\n## [前端面试问题集锦](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/21-Front-end-Interview-questions)\n\n作者： trigkit4    https://github.com/hawx1993\n\n源地址：https://github.com/hawx1993/Front-end-Interview-questions\n\n\n## [前端工作面试问题](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/22-Front-end-Developer-Interview-Questions-master)\n\n作者：H5BP https://github.com/h5bp\n\n中文版作者：Liu Chao https://github.com/lc-soft\n\n源地址：https://github.com/h5bp/Front-end-Developer-Interview-Questions\n\n\n## [收集的前端面试题和答案](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/23-FE-interview-master)\n\n作者：qiu https://github.com/qiu-deqing\n\n源地址：https://github.com/qiu-deqing/FE-interview\n\n## [一套完整的学习手册帮助自己准备 Google 的面试](https://github.com/helloqingfeng/Awsome-Front-End-learning-resource/tree/master/29-google-interview-university)\n\n原文作者：[John Washam](https://github.com/jwasham/google-interview-university)\n\n译文出自：[掘金翻译计划](https://github.com/xitu/gold-miner)\n\n译者：：[Aleen](https://github.com/aleen42)，[Newton](https://github.com/Newt0n)，[bobmayuze](https://github.com/bobmayuze)，[Jaeger](https://github.com/laobie)，[sqrthree](https://github.com/sqrthree)\n\n源地址：https://github.com/jwasham/google-interview-university\n\n---\n\n> **编程无他，唯手熟尔！**\n\n**声明：** 版权归原作者所有，我只是搬运工。\n\n**Photo Credit：**[Negative Space](https://unsplash.com/photos/6g0KJWnBhxg)\n\n\n"
  }
]