Full Code of JacksonTian/fks for AI

master 54722627d64b cached
337 files
1.9 MB
548.1k tokens
802 symbols
1 requests
Download .txt
Showing preview only (2,059K chars total). Download the full file or copy to clipboard to get everything.
Repository: JacksonTian/fks
Branch: master
Commit: 54722627d64b
Files: 337
Total size: 1.9 MB

Directory structure:
gitextract_qmcpiqtz/

├── .gitignore
├── Makefile
├── README.en.md
├── README.md
├── bin/
│   └── generate.js
├── fks_chart/
│   ├── bower.json
│   ├── bower_components/
│   │   ├── angular/
│   │   │   ├── .bower.json
│   │   │   ├── README.md
│   │   │   ├── angular-csp.css
│   │   │   ├── angular.js
│   │   │   ├── angular.min.js.gzip
│   │   │   ├── bower.json
│   │   │   └── package.json
│   │   ├── angular-marked/
│   │   │   ├── .bower.json
│   │   │   ├── README.md
│   │   │   ├── angular-marked.js
│   │   │   ├── bower.json
│   │   │   ├── example/
│   │   │   │   └── index.html
│   │   │   ├── gruntfile.js
│   │   │   ├── karma.conf.js
│   │   │   ├── package.json
│   │   │   └── todo.md
│   │   ├── d3/
│   │   │   ├── .bower.json
│   │   │   ├── .spmignore
│   │   │   ├── CONTRIBUTING.md
│   │   │   ├── LICENSE
│   │   │   ├── README.md
│   │   │   ├── bower.json
│   │   │   ├── composer.json
│   │   │   └── d3.js
│   │   ├── jquery/
│   │   │   ├── .bower.json
│   │   │   ├── MIT-LICENSE.txt
│   │   │   ├── bower.json
│   │   │   ├── dist/
│   │   │   │   └── jquery.js
│   │   │   └── src/
│   │   │       ├── ajax/
│   │   │       │   ├── jsonp.js
│   │   │       │   ├── load.js
│   │   │       │   ├── parseJSON.js
│   │   │       │   ├── parseXML.js
│   │   │       │   ├── script.js
│   │   │       │   ├── var/
│   │   │       │   │   ├── nonce.js
│   │   │       │   │   └── rquery.js
│   │   │       │   └── xhr.js
│   │   │       ├── ajax.js
│   │   │       ├── attributes/
│   │   │       │   ├── attr.js
│   │   │       │   ├── classes.js
│   │   │       │   ├── prop.js
│   │   │       │   ├── support.js
│   │   │       │   └── val.js
│   │   │       ├── attributes.js
│   │   │       ├── callbacks.js
│   │   │       ├── core/
│   │   │       │   ├── access.js
│   │   │       │   ├── init.js
│   │   │       │   ├── parseHTML.js
│   │   │       │   ├── ready.js
│   │   │       │   └── var/
│   │   │       │       └── rsingleTag.js
│   │   │       ├── core.js
│   │   │       ├── css/
│   │   │       │   ├── addGetHookIf.js
│   │   │       │   ├── curCSS.js
│   │   │       │   ├── defaultDisplay.js
│   │   │       │   ├── hiddenVisibleSelectors.js
│   │   │       │   ├── support.js
│   │   │       │   ├── swap.js
│   │   │       │   └── var/
│   │   │       │       ├── cssExpand.js
│   │   │       │       ├── getStyles.js
│   │   │       │       ├── isHidden.js
│   │   │       │       ├── rmargin.js
│   │   │       │       └── rnumnonpx.js
│   │   │       ├── css.js
│   │   │       ├── data/
│   │   │       │   ├── Data.js
│   │   │       │   ├── accepts.js
│   │   │       │   └── var/
│   │   │       │       ├── data_priv.js
│   │   │       │       └── data_user.js
│   │   │       ├── data.js
│   │   │       ├── deferred.js
│   │   │       ├── deprecated.js
│   │   │       ├── dimensions.js
│   │   │       ├── effects/
│   │   │       │   ├── Tween.js
│   │   │       │   └── animatedSelector.js
│   │   │       ├── effects.js
│   │   │       ├── event/
│   │   │       │   ├── ajax.js
│   │   │       │   ├── alias.js
│   │   │       │   └── support.js
│   │   │       ├── event.js
│   │   │       ├── exports/
│   │   │       │   ├── amd.js
│   │   │       │   └── global.js
│   │   │       ├── intro.js
│   │   │       ├── jquery.js
│   │   │       ├── manipulation/
│   │   │       │   ├── _evalUrl.js
│   │   │       │   ├── support.js
│   │   │       │   └── var/
│   │   │       │       └── rcheckableType.js
│   │   │       ├── manipulation.js
│   │   │       ├── offset.js
│   │   │       ├── outro.js
│   │   │       ├── queue/
│   │   │       │   └── delay.js
│   │   │       ├── queue.js
│   │   │       ├── selector-native.js
│   │   │       ├── selector-sizzle.js
│   │   │       ├── selector.js
│   │   │       ├── serialize.js
│   │   │       ├── sizzle/
│   │   │       │   └── dist/
│   │   │       │       └── sizzle.js
│   │   │       ├── traversing/
│   │   │       │   ├── findFilter.js
│   │   │       │   └── var/
│   │   │       │       └── rneedsContext.js
│   │   │       ├── traversing.js
│   │   │       ├── var/
│   │   │       │   ├── arr.js
│   │   │       │   ├── class2type.js
│   │   │       │   ├── concat.js
│   │   │       │   ├── hasOwn.js
│   │   │       │   ├── indexOf.js
│   │   │       │   ├── pnum.js
│   │   │       │   ├── push.js
│   │   │       │   ├── rnotwhite.js
│   │   │       │   ├── slice.js
│   │   │       │   ├── strundefined.js
│   │   │       │   ├── support.js
│   │   │       │   └── toString.js
│   │   │       └── wrap.js
│   │   └── marked/
│   │       ├── .bower.json
│   │       ├── .gitignore
│   │       ├── .npmignore
│   │       ├── .travis.yml
│   │       ├── LICENSE
│   │       ├── Makefile
│   │       ├── README.md
│   │       ├── bin/
│   │       │   └── marked
│   │       ├── component.json
│   │       ├── doc/
│   │       │   ├── broken.md
│   │       │   └── todo.md
│   │       ├── index.js
│   │       ├── lib/
│   │       │   └── marked.js
│   │       ├── man/
│   │       │   └── marked.1
│   │       ├── package.json
│   │       └── test/
│   │           ├── README
│   │           ├── browser/
│   │           │   ├── index.html
│   │           │   ├── index.js
│   │           │   └── test.js
│   │           ├── index.js
│   │           ├── new/
│   │           │   ├── autolink_lines.html
│   │           │   ├── autolink_lines.text
│   │           │   ├── blockquote_list_item.html
│   │           │   ├── blockquote_list_item.text
│   │           │   ├── case_insensitive_refs.html
│   │           │   ├── case_insensitive_refs.text
│   │           │   ├── def_blocks.html
│   │           │   ├── def_blocks.text
│   │           │   ├── double_link.html
│   │           │   ├── double_link.text
│   │           │   ├── escaped_angles.html
│   │           │   ├── escaped_angles.text
│   │           │   ├── gfm_break.breaks.html
│   │           │   ├── gfm_break.breaks.text
│   │           │   ├── gfm_code.html
│   │           │   ├── gfm_code.text
│   │           │   ├── gfm_code_hr_list.html
│   │           │   ├── gfm_code_hr_list.text
│   │           │   ├── gfm_del.html
│   │           │   ├── gfm_del.text
│   │           │   ├── gfm_em.html
│   │           │   ├── gfm_em.text
│   │           │   ├── gfm_links.html
│   │           │   ├── gfm_links.text
│   │           │   ├── gfm_tables.html
│   │           │   ├── gfm_tables.text
│   │           │   ├── hr_list_break.html
│   │           │   ├── hr_list_break.text
│   │           │   ├── lazy_blockquotes.html
│   │           │   ├── lazy_blockquotes.text
│   │           │   ├── list_item_text.html
│   │           │   ├── list_item_text.text
│   │           │   ├── loose_lists.html
│   │           │   ├── loose_lists.text
│   │           │   ├── main.html
│   │           │   ├── main.text
│   │           │   ├── nested_code.html
│   │           │   ├── nested_code.text
│   │           │   ├── nested_em.html
│   │           │   ├── nested_em.text
│   │           │   ├── nested_square_link.html
│   │           │   ├── nested_square_link.text
│   │           │   ├── not_a_link.html
│   │           │   ├── not_a_link.text
│   │           │   ├── ref_paren.html
│   │           │   ├── ref_paren.text
│   │           │   ├── same_bullet.html
│   │           │   ├── same_bullet.text
│   │           │   ├── text.smartypants.html
│   │           │   ├── text.smartypants.text
│   │           │   ├── toplevel_paragraphs.gfm.html
│   │           │   ├── toplevel_paragraphs.gfm.text
│   │           │   ├── tricky_list.html
│   │           │   └── tricky_list.text
│   │           ├── original/
│   │           │   ├── amps_and_angles_encoding.html
│   │           │   ├── amps_and_angles_encoding.text
│   │           │   ├── auto_links.html
│   │           │   ├── auto_links.text
│   │           │   ├── backslash_escapes.html
│   │           │   ├── backslash_escapes.text
│   │           │   ├── blockquotes_with_code_blocks.html
│   │           │   ├── blockquotes_with_code_blocks.text
│   │           │   ├── code_blocks.html
│   │           │   ├── code_blocks.text
│   │           │   ├── code_spans.html
│   │           │   ├── code_spans.text
│   │           │   ├── hard_wrapped_paragraphs_with_list_like_lines.html
│   │           │   ├── hard_wrapped_paragraphs_with_list_like_lines.text
│   │           │   ├── horizontal_rules.html
│   │           │   ├── horizontal_rules.text
│   │           │   ├── inline_html_advanced.html
│   │           │   ├── inline_html_advanced.text
│   │           │   ├── inline_html_comments.html
│   │           │   ├── inline_html_comments.text
│   │           │   ├── inline_html_simple.html
│   │           │   ├── inline_html_simple.text
│   │           │   ├── links_inline_style.html
│   │           │   ├── links_inline_style.text
│   │           │   ├── links_reference_style.html
│   │           │   ├── links_reference_style.text
│   │           │   ├── links_shortcut_references.html
│   │           │   ├── links_shortcut_references.text
│   │           │   ├── literal_quotes_in_titles.html
│   │           │   ├── literal_quotes_in_titles.text
│   │           │   ├── markdown_documentation_basics.html
│   │           │   ├── markdown_documentation_basics.text
│   │           │   ├── markdown_documentation_syntax.html
│   │           │   ├── markdown_documentation_syntax.text
│   │           │   ├── nested_blockquotes.html
│   │           │   ├── nested_blockquotes.text
│   │           │   ├── ordered_and_unordered_lists.html
│   │           │   ├── ordered_and_unordered_lists.text
│   │           │   ├── strong_and_em_together.html
│   │           │   ├── strong_and_em_together.text
│   │           │   ├── tabs.html
│   │           │   ├── tabs.text
│   │           │   ├── tidyness.html
│   │           │   └── tidyness.text
│   │           └── tests/
│   │               ├── amps_and_angles_encoding.html
│   │               ├── amps_and_angles_encoding.text
│   │               ├── auto_links.html
│   │               ├── auto_links.text
│   │               ├── autolink_lines.html
│   │               ├── autolink_lines.text
│   │               ├── backslash_escapes.html
│   │               ├── backslash_escapes.text
│   │               ├── blockquote_list_item.html
│   │               ├── blockquote_list_item.text
│   │               ├── blockquotes_with_code_blocks.html
│   │               ├── blockquotes_with_code_blocks.text
│   │               ├── case_insensitive_refs.html
│   │               ├── case_insensitive_refs.text
│   │               ├── code_blocks.html
│   │               ├── code_blocks.text
│   │               ├── code_spans.html
│   │               ├── code_spans.text
│   │               ├── def_blocks.html
│   │               ├── def_blocks.text
│   │               ├── double_link.html
│   │               ├── double_link.text
│   │               ├── escaped_angles.html
│   │               ├── escaped_angles.text
│   │               ├── gfm_break.breaks.html
│   │               ├── gfm_break.breaks.text
│   │               ├── gfm_code.html
│   │               ├── gfm_code.text
│   │               ├── gfm_code_hr_list.html
│   │               ├── gfm_code_hr_list.text
│   │               ├── gfm_del.html
│   │               ├── gfm_del.text
│   │               ├── gfm_em.html
│   │               ├── gfm_em.text
│   │               ├── gfm_links.html
│   │               ├── gfm_links.text
│   │               ├── gfm_tables.html
│   │               ├── gfm_tables.text
│   │               ├── hard_wrapped_paragraphs_with_list_like_lines.nogfm.html
│   │               ├── hard_wrapped_paragraphs_with_list_like_lines.nogfm.text
│   │               ├── horizontal_rules.html
│   │               ├── horizontal_rules.text
│   │               ├── hr_list_break.html
│   │               ├── hr_list_break.text
│   │               ├── inline_html_advanced.html
│   │               ├── inline_html_advanced.text
│   │               ├── inline_html_comments.html
│   │               ├── inline_html_comments.text
│   │               ├── inline_html_simple.html
│   │               ├── inline_html_simple.text
│   │               ├── lazy_blockquotes.html
│   │               ├── lazy_blockquotes.text
│   │               ├── links_inline_style.html
│   │               ├── links_inline_style.text
│   │               ├── links_reference_style.html
│   │               ├── links_reference_style.text
│   │               ├── links_shortcut_references.html
│   │               ├── links_shortcut_references.text
│   │               ├── list_item_text.html
│   │               ├── list_item_text.text
│   │               ├── literal_quotes_in_titles.html
│   │               ├── literal_quotes_in_titles.text
│   │               ├── loose_lists.html
│   │               ├── loose_lists.text
│   │               ├── main.html
│   │               ├── main.text
│   │               ├── markdown_documentation_basics.html
│   │               ├── markdown_documentation_basics.text
│   │               ├── markdown_documentation_syntax.html
│   │               ├── markdown_documentation_syntax.text
│   │               ├── nested_blockquotes.html
│   │               ├── nested_blockquotes.text
│   │               ├── nested_code.html
│   │               ├── nested_code.text
│   │               ├── nested_em.html
│   │               ├── nested_em.text
│   │               ├── nested_square_link.html
│   │               ├── nested_square_link.text
│   │               ├── not_a_link.html
│   │               ├── not_a_link.text
│   │               ├── ordered_and_unordered_lists.html
│   │               ├── ordered_and_unordered_lists.text
│   │               ├── ref_paren.html
│   │               ├── ref_paren.text
│   │               ├── same_bullet.html
│   │               ├── same_bullet.text
│   │               ├── strong_and_em_together.html
│   │               ├── strong_and_em_together.text
│   │               ├── tabs.html
│   │               ├── tabs.text
│   │               ├── text.smartypants.html
│   │               ├── text.smartypants.text
│   │               ├── tidyness.html
│   │               ├── tidyness.text
│   │               ├── toplevel_paragraphs.gfm.html
│   │               ├── toplevel_paragraphs.gfm.text
│   │               ├── tricky_list.html
│   │               └── tricky_list.text
│   ├── css/
│   │   └── style.css
│   ├── data/
│   │   └── front-end.json
│   ├── index.html
│   └── js/
│       └── app.js
└── package.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
parallel.html
*~


================================================
FILE: Makefile
================================================
all:
	node ./bin/generate.js


================================================
FILE: README.en.md
================================================
Frontend Knowledge Structure
========
## Original purpose
Once upon a time, there's a graph of Frontend Knowledge Structure original posted by @jayli ...

![Frontend Knowledge](https://raw.github.com/JacksonTian/fks/master/figures/fks.jpg)

A 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.

Although 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.

## Knowledge Structure of Frontend Development
- Frontend Engineer
    - Web browsers
        - 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)
        - [Firefox](http://www.mozilla.org/en-US/) (Gecko)
        - [Chrome](http://www.google.com/chrome)/[Chromium](http://www.chromium.org/) (Blink)
        - [Safari](http://www.apple.com/safari/) (WebKit)
        - [Opera](http://www.opera.com/) (Blink)
    - Programming Languages
        - [JavaScript](https://developer.mozilla.org/en-US/docs/JavaScript)/[Node.js](http://nodejs.org/)
        - [CoffeeScript](http://coffeescript.org/)
        - [TypeScript](http://www.typescriptlang.org/)
    - Slicing
        - [HTML](http://www.w3.org/html/)/[HTML5](http://www.w3.org/TR/html5/)
        - [CSS](http://www.w3.org/Style/CSS/)/CSS3
        - [Sass](http://sass-lang.com/)/[LESS](http://lesscss.org/)/[Stylus](http://learnboost.github.io/stylus/)/[PostCSS](http://postcss.org/)
        - [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/)
    - Development tools
        - Editors and IDEs
            - [VIM](http://www.vim.org/)/[Sublime Text2](http://www.sublimetext.com/)
            - [Notepad++](http://notepad-plus-plus.org/)/[EditPlus](http://www.editplus.com/)
            - [WebStorm](http://www.jetbrains.com/webstorm/)
            - [Emacs](http://www.gnu.org/software/emacs/)  [EmacsWiki](http://emacswiki.org)
            - [Brackets](http://brackets.io)
            - [Atom](https://atom.io/)
            - [Lime Text](http://limetext.org/)
            - [Light Table](http://lighttable.com/)
            - [Codebox](https://www.codebox.io/)
            - [TextMate](http://macromates.com/)
            - [Neovim](http://neovim.org/)
            - [Komodo IDE / Edit](http://www.activestate.com/komodo-edit)
            - [Eclipse](http://www.eclipse.org/)
            - [Visual Studio](http://www.visualstudio.com/)/[Visual Studio Code](https://code.visualstudio.com/)
            - [NetBeans](https://netbeans.org/)
            - [Cloud9 IDE](http://c9.io/)
            - [HBuilder](http://www.dcloud.io/)
            - [Nuclide](http://nuclide.io/)
        - Debugging
            - [Firebug](http://getfirebug.com/)/[Firecookie](https://addons.mozilla.org/en-US/firefox/addon/firecookie/)
            - [YSlow](http://developer.yahoo.com/yslow/)
            - [IEDeveloperToolbar](http://www.microsoft.com/en-us/download/details.aspx?id=18359)/[IETester](http://www.my-debugbar.com/wiki/IETester/HomePage)
            - [Fiddler](http://www.telerik.com/fiddler)
            - [Chrome Dev Tools](https://developer.chrome.com/devtools)
            - [Dragonfly](http://www.opera.com/dragonfly/)
            - [DebugBar](http://www.debugbar.com/)
            - [Venkman](https://developer.mozilla.org/en-US/docs/Venkman)
            - [Charles](https://www.charlesproxy.com/)
        - Revision Control
            - [Git](http://git-scm.com/)/[SVN](http://subversion.apache.org/)/[Mercurial](http://mercurial.selenic.com/)
            - [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)
    - Code quality
        - Coding style
            - [JSLint](http://www.jslint.com/)/[JSHint](http://www.jshint.com/)/[jscs](https://github.com/mdevils/node-jscs)
            - [CSSLint](http://csslint.net/)
            - [Markup Validation Service](http://validator.w3.org/)
            - [HTML Validators](https://validator.whatwg.org/)
        - Unit testing
            - [QUnit](http://qunitjs.com/)/[Jasmine](http://jasmine.github.io/)
            - [Mocha](http://mochajs.org/)/[Should](https://github.com/visionmedia/should.js/)/[Chai](http://chaijs.com/)/[Expect](https://github.com/LearnBoost/expect.js/)
            - [Unit JS](http://unitjs.com/)
        - Auto-testing
            - [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/)
            - [phantomjs](http://phantomjs.org/)
            - [SourceLabs](https://saucelabs.com/)/[BrowserStack](http://www.browserstack.com/)
    - Frontend libraries / frameworks
        - [jQuery](http://jquery.com/)/[Underscore](http://underscorejs.org/)/[Mootools](http://mootools.net/)/[Prototype.js](http://www.prototypejs.org/)
        - [YUI3](http://yuilibrary.com/projects/yui3/)/[Dojo](http://dojotoolkit.org/)/[ExtJS](http://www.sencha.com/products/extjs)/[KISSY](http://docs.kissyui.com/)
        - [Backbone](http://backbonejs.org/)/[KnockoutJS](http://knockoutjs.com/)/[Emberjs](http://emberjs.com/)
        - [AngularJS](http://angularjs.org/)
            - [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk)
        - [Bootstrap](http://getbootstrap.com/)
        - [Semantic UI](http://www.semantic-ui.com/)
        - [Juice UI](http://juiceui.com/)
        - [Web Atoms](http://webatomsjs.neurospeech.com/)
        - [Polymer](https://www.polymer-project.org/)
        - [Dhtmlx](http://dhtmlx.com/)
        - [qooxdoo](http://qooxdoo.org/)
        - [React](http://facebook.github.io/react/)
        - [Brick](http://mozbrick.github.io/)
    - Frontend standards / specifications
        - HTTP/1.1: RFCs 7230-7235
        - [HTTP/2](https://http2.github.io/)
        - [ECMAScript3/5](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
        - [W3C: DOM/BOM/XHTML/XML/JSON/JSONP/...](http://www.w3.org/TR/)
        - [CommonJS Modules](http://wiki.commonjs.org/wiki/Modules/1.0)/[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)
        - [HTML5](http://www.w3.org/html/wg/drafts/html/master/)/[CSS3](http://www.w3.org/Style/CSS/specs.en.html)
        - [Semantic Web](http://semanticweb.org/)
            - [MicroData](http://schema.org)
            - [RDFa](http://www.w3.org/TR/rdfa-core/)
        - [Web Accessibility](http://www.w3.org/WAI/)
            - [WCAG](http://www.w3.org/TR/WAI-WEBCONTENT/)
            - [Role Attribute](http://www.w3.org/TR/role-attribute/)
            - [WAI-ARIA](http://www.w3.org/TR/wai-aria/)
    - Performance
        - [JSPerf](http://jsperf.com/)
        - [YSlow 35 rules](http://developer.yahoo.com/performance/rules.html)
        - [PageSpeed](https://developers.google.com/speed/pagespeed/)
        - [HTTPWatch](http://www.httpwatch.com/)
        - [DynaTrace's Ajax](http://www.compuware.com/application-performance-management/dynatrace-ajax-download.html)
        - [High-performance JavaScript](http://book.douban.com/subject/5362856/)
    - SEO
    - General programming knowledge
        - [Data structure](http://en.wikipedia.org/wiki/Data_structure)
        - OOP/AOP
        - [Prototype chain](http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/)/Scope chain
        - [Closure](http://www.jibbering.com/faq/notes/closures/)
        - [Programming paradigms](http://en.wikipedia.org/wiki/Programming_paradigm)
        - [Design Patterns](http://addyosmani.com/resources/essentialjsdesignpatterns/book/)
        - [Javascript Tips](http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html)
    - Deployment flow
        - Compressing and merging
            - [YUI Compressor](http://developer.yahoo.com/yui/compressor/)
            - [Google Clousure Complier](https://developers.google.com/closure/compiler/)
            - [UglifyJS](https://github.com/mishoo/UglifyJS)
            - [CleanCSS](https://github.com/GoalSmashers/clean-css)
        - Documentation generating
            - [JSDoc](http://code.google.com/p/jsdoc-toolkit/)
            - [Dox](https://github.com/visionmedia/dox)/[Doxmate](https://github.com/JacksonTian/doxmate)/[Grunt-Doxmate](https://github.com/luozhihua/grunt-doxmate)
        - Building
            - [make](http://www.gnu.org/software/make/)/[Ant](http://ant.apache.org/)
            - [GYP](http://code.google.com/p/gyp/)
            - [Grunt](http://gruntjs.com/)
            - [Gulp](http://gulpjs.com/)
            - [Yeoman](http://yeoman.io/)
            - [FIS](http://fis.baidu.com/)
            - [Mod](https://github.com/modulejs/modjs)
        - ES6+ transpiler
            - [Traceur](https://github.com/google/traceur-compiler)
            - [Babel](https://babeljs.io/)
    - Code organizing
        - Modularizing libraries
            - [CommonJS](http://www.commonjs.org/)/AMD
            - YUI3 Modules
        - Modularizing business logic
            - [bower](https://github.com/twitter/bower)/[component](https://github.com/component/component)
        - File loaders
            - [LABjs](http://labjs.com/)
            - [SeaJS](http://seajs.org/)/[Require.js](http://requirejs.org/)
        - Modular preprocessor
            - [Browserify](https://github.com/substack/node-browserify)
    - Security
        - [CSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)/[XSS](http://en.wikipedia.org/wiki/Cross-site_scripting)
        - [CSP](http://www.w3.org/TR/CSP/)
        - [Same-origin policy](https://developer.mozilla.org/docs/Web/Security/Same-origin_policy)
        - ADsafe/Caja/Sandbox
    - Mobile Web
        - HTML5/CSS3
        - [Responsive web design](http://en.wikipedia.org/wiki/Responsive_web_design)
        - [Zeptojs](http://zeptojs.com/)/[iScroll](http://cubiq.org/iscroll)
        - V5/[Sencha Touch](http://www.sencha.com/products/touch)
        - [PhoneGap](http://phonegap.com/)
        - [jQuery Mobile](http://jquerymobile.com/)
        - [W3C Mobile Web Initiative](http://www.w3.org/Mobile/)
        - [W3C mobileOK Checker](http://validator.w3.org/mobile/)
        - [Open Mobile Alliance](http://openmobilealliance.org/)
        - [React Native](https://facebook.github.io/react-native/)
    - Advanced technology communities/conferences
        - [D2](http://d2forum.org)/[WebRebuild](http://www.webrebuild.org/)
        - NodeParty/[W3CTech](http://w3ctech.com)/[HTML5梦工厂(HTML5 Dreamworks)](http://www.html5dw.com)
        - [JSConf](http://jsconf.com/)/[沪JS(JSConf.cn)](http://jsconf.cn)
        - QCon/Velocity/SDCC
        - [JSConf](http://jsconf.com/)/[NodeConf](http://www.nodeconf.com/)
        - [CSSConf](http://cssconf.com/)
        - YDN/YUIConf
        - HybridApp
        - [WHATWG](http://whatwg.org/)
        - [MDN](https://developer.mozilla.org/en-US/)
        - [codepen](http://codepen.io/)
        - [w3cplus](http://www.w3cplus.com/)
        - [CNode](https://cnodejs.org/)
    - Computer science
        - Compilation principle
        - [Computer network](http://en.wikipedia.org/wiki/Computer_network)
        - [OS](http://en.wikipedia.org/wiki/Operating_system)
        - Algorithm principle
        - Software Engineering/Software testing principle
        - [Unicode](http://www.unicode.org/)
    - Soft skills
        - Knowledge Management/Sharing
        - Communication/Teamwork
        - Requirements Management/PM
        - Interaction Design/Availability/Accessibility
    - Visualization
        - SVG/Canvas/VML
        - SVG: [D3](http://d3js.org/)/[Raphaël](http://raphaeljs.com/)/[Snap.svg](http://snapsvg.io/)/[DataV](http://datavlab.org/datavjs/)
        - Canvas: [CreateJS](http://www.createjs.com/)/[KineticJS](http://kineticjs.com/)
        - [WebGL](http://zh.wikipedia.org/wiki/WebGL)/[Three.JS](http://threejs.org/)
- Backend Engineer
    - Programming languages
        - C/C++/Java/PHP/Ruby/Python/...
    - Web server
        - [Nginx](http://nginx.org/en/)
        - [Apache](http://httpd.apache.org/)
        - [Lighttpd](http://www.lighttpd.net/)
    - Databases
        - SQL
        - [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)
        - [MongoDB](http://www.mongodb.org/)/[CouchDB](http://couchdb.apache.org/)
    - Data Caching
        - [Redis](http://redis.io/)
        - [Memcached](http://memcached.org/)
    - File Cashing/Proxying
        - [Varnish](https://www.varnish-cache.org/)
        - [Squid](http://www.squid-cache.org/)
    - OS
        - Unix/Linux/OS X/Windows
    - Data structure

## Book Recommendations for Frontend-ers
The ★ less and easier, the more suitable for starters

### CSS
- [More Eric Meyer on CSS](http://www.amazon.com/More-Eric-Meyer-Voices-Matter/dp/0735714258/)★★★
- [CSS: The Definitive Guide (3rd Edition)](http://www.amazon.com/CSS-Definitive-Eric-A-Meyer/dp/0596527330/)★★
- [CSS Mastery: Advanced Web Standards Solutions](http://www.amazon.com/CSS-Mastery-Advanced-Standards-Solutions/dp/1430223979/)★★★

### JavaScript
- [DOM Scripting: Web Design with JavaScript and the Document Object Model](http://www.amazon.com/DOM-Scripting-Design-JavaScript-Document/dp/1430233893/)★
- [Professional JavaScript for Web Developsers (Third Edition)](http://www.amazon.com/Professional-JavaScript-Developers-Nicholas-Zakas/dp/1118026691/)★★
- [锋利的jQuery](http://book.douban.com/subject/10792216/)★★
- [High Performance JavaScript](ihttp://www.amazon.com/Performance-JavaScript-Faster-Application-Interfaces/dp/059680279X/)★★★
- [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742/)★★★
- [JavaScript: The Definitive Guide (Sixth Edition)](http://www.amazon.com/JavaScript-Definitive-Guide-Activate-Guides/dp/0596805527/)★★★
- [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680/)★★★
- [JAVASCRIPT语言精髓与编程实践](http://book.douban.com/subject/3012828/)★★★
- [Effective Javascript](http://www.amazon.com/Effective-JavaScript-Specific-Software-Development/dp/0321812182)★★★
- [Secrets of the JavaScript Ninja](http://book.douban.com/subject/3176860/)★★★
- [JavaScript Patterns](http://www.amazon.cn/JavaScript-Patterns-Stefanov-Stoyan/dp/0596806752)★★★
- [JavaScript设计模式](http://book.douban.com/subject/3329540/)★★★★
- [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X)★★★★

### Performance && Practice
- [Web性能实践日志](http://book.douban.com/subject/25891125/)★★★
- [Web性能权威指南](http://book.douban.com/subject/25856314/)★★★

### CVS
- [Pragmatic Version Control Using Git](http://book.douban.com/subject/3105192/)★★
- [Pro Git](http://git-scm.com/book)★★★
- [Git权威指南](http://book.douban.com/subject/6526452/)★★★★

## Book Recommendations for Backend-ers
### Linux administration
- [Linux 系统管理技术手册](http://book.douban.com/subject/3042029/)
- [鸟哥的 Linux 私房菜](http://book.douban.com/subject/4889838/)
- [Linux 101 Hacks](http://www.thegeekstuff.com/linux-101-hacks-free-ebook-non-english/)
- [UNIX Shell Scripting](http://book.douban.com/subject/3519360/)
- [The Linux Command Line](http://linuxcommand.org/tlcl.php)
- [Linux Network Administrator's Guide](http://oreilly.com/openbook/linag2/book/index.html)

### Linux programming
- [Linux程序设计](http://book.douban.com/subject/4831448/)
- [Linux系统编程](http://book.douban.com/subject/3907181/)
- [Unix环境高级编程](http://book.douban.com/subject/1788421/)
- [The Art of UNIX Programming](http://www.catb.org/esr/writings/taoup/)
- [The Linux Programming Interface](http://book.douban.com/subject/4292217/)
- [程序员的自我修养](http://book.douban.com/subject/3652388/)
- [深入理解Linux内核](http://book.douban.com/subject/2287506/)
- [Unix网络编程](http://book.douban.com/subject/1500149/)
- [TCP/IP高级编程](http://book.douban.com/subject/1088054/)
- [Linux Kernel in a Nutshell](http://www.kroah.com/lkn/)
- [Linux Device Drivers](http://lwn.net/Kernel/LDD3/)
- [Advanced Linux Programming](http://www.advancedlinuxprogramming.com/)

### C/C++
- [Linux C编程一站式学习](http://book.douban.com/subject/4141733/)
- [C和指针](http://book.douban.com/subject/3012360/)
- [C陷阱与缺陷](http://book.douban.com/subject/2778632/)
- [C专家编程](http://book.douban.com/subject/2377310/)
- [C语言核心技术](http://book.douban.com/subject/2226913/)
- [彻底搞定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)
- [征服C指针](http://book.douban.com/subject/21317828/)
- [C++编程思想](http://book.douban.com/subject/1094797/)
- [高质量程序设计指南---C/C++语言](http://book.douban.com/subject/2116929/)
- [Inside the C++ Object Model](http://book.douban.com/subject/1484262/)
- [A Tour of C++](http://www.stroustrup.com/Tour.html)
- [The C++ Programming Language](http://en.wikipedia.org/wiki/The_C%2B%2B_Programming_Language)
- [The C++ Standard Library - A Tutorial and Reference](http://www.cppstdlib.com/)
- [The C++ Standard (INCITS/ISO/IEC 14882-2011)](http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+14882-2012)
- [Overview of the New C++](http://www.artima.com/shop/overview_of_the_new_cpp)

## Front-end Developer Interview
- [Front-end Developer Interview Questions](https://github.com/darcyclarke/Front-end-Developer-Interview-Questions)
- [Front end Developer Questions( Chinese (Simple) Language)](https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Question)

## Contributors
Thanks to Jayli who provided the original graph and contributors below. Generated by `git-summary` at 2014/01/03.

```

 project  : fks
 repo age : 1 year, 3 months
 active   : 53 days
 commits  : 108
 files    : 4
 authors  :
    56  Jackson Tian            51.9%
     9  吴晓兰               8.3%
     5  liyinkan                4.6%
     3  chriscai                2.8%
     3  fengxiaolong            2.8%
     3  XiNGRZ                  2.8%
     2  monkadd                 1.9%
     2  Johnny                  1.9%
     2  weiwenqing              1.9%
     2  Yinkan Li               1.9%
     2  Copypeng                1.9%
     2  左岸                  1.9%
     2  Jakukyo Friel           1.9%
     2  Glowin                  1.9%
     1  李亚川               0.9%
     1  Evan You                0.9%
     1  Mickey                  0.9%
     1  Mickey-                 0.9%
     1  Qi Junyuan              0.9%
     1  browsnet                0.9%
     1  doabit                  0.9%
     1  guoxiangyang            0.9%
     1  linkgod                 0.9%
     1  popomore                0.9%
     1  vipzhicheng             0.9%
     1  zhaqiang                0.9%
     1  Colin Luo               0.9%

```


================================================
FILE: README.md
================================================
Frontend Knowledge Structure
========
## 项目起源
还记得@jayli 的这幅前端知识结构图么。

![前端知识结构](https://raw.github.com/JacksonTian/fks/master/figures/fks.jpg)

图片的形式具有诸多的不便。缺失源图的我们,无法为此图贡献些什么,随着时间的迁移,或许有些技术点会发生改变,所以有了这个GitHub项目。我们可以通过协作的方式来共同维护这个项目。Git的历史记录也可以见证前端行业的一些变迁。

[可视化效果](http://html5ify.com/fks/fks_chart/)

## 前端开发知识结构
- 前端工程师
    - 浏览器
        - 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) / [Edge](https://www.microsoft.com/en-us/windows/microsoft-edge) (EdgeHTML)
        - [Firefox](http://www.mozilla.org/en-US/) (Gecko)
        - [Chrome](http://www.google.com/chrome)/[Chromium](http://www.chromium.org/) (Blink)
        - [Safari](http://www.apple.com/safari/) (WebKit)
        - [Opera](http://www.opera.com/) (Blink)
    - 编程语言
        - [JavaScript](https://developer.mozilla.org/en-US/docs/JavaScript)★/[Node.js](http://nodejs.org/)
        - [TypeScript](http://www.typescriptlang.org/)★
        - [CoffeeScript](http://coffeescript.org/)
    - 切页面
        - [HTML5](http://www.w3.org/TR/html5/)
        - [CSS/CSS3](http://www.w3.org/Style/CSS/)
        - [Sass](http://sass-lang.com/)/[LESS](http://lesscss.org/)/[Stylus](http://learnboost.github.io/stylus/)/[postCSS](https://github.com/postcss/postcss)
        - [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/)
    - 开发工具
        - 编辑器和IDE
            - [Visual Studio Code](https://code.visualstudio.com/)★
            - [VIM](http://www.vim.org/)/[Sublime Text2](http://www.sublimetext.com/)
            - [Notepad++](http://notepad-plus-plus.org/)/[EditPlus](http://www.editplus.com/)
            - [WebStorm](http://www.jetbrains.com/webstorm/)
            - [Emacs](http://www.gnu.org/software/emacs/)  [EmacsWiki](http://emacswiki.org)
            - [Brackets](http://brackets.io)
            - [Atom](https://atom.io/)
            - [CodeLobster](https://codelobster.com/)
            - [Lime Text](http://limetext.org/)
            - [Light Table](http://lighttable.com/)
            - [Codebox](https://www.codebox.io/)
            - [TextMate](http://macromates.com/)
            - [Neovim](http://neovim.org/)
            - [Komodo IDE / Edit](http://www.activestate.com/komodo-edit)
            - [Eclipse](http://www.eclipse.org/)
            - [Visual Studio](http://www.visualstudio.com/)
            - [NetBeans](https://netbeans.org/)
            - [Cloud9 IDE](http://c9.io/)
            - [HBuilder](http://www.dcloud.io/)
            - [Nuclide](http://nuclide.io/)
        - 调试工具
            - [Chrome Dev Tools](https://developer.chrome.com/devtools)★
            - [Firebug](http://getfirebug.com/)/[Firecookie](https://addons.mozilla.org/en-US/firefox/addon/firecookie/)
            - [YSlow](http://developer.yahoo.com/yslow/)
            - [IEDeveloperToolbar](http://www.microsoft.com/en-us/download/details.aspx?id=18359)/[IETester](http://www.my-debugbar.com/wiki/IETester/HomePage)
            - [Fiddler](http://www.telerik.com/fiddler)
            - [Dragonfly](http://www.opera.com/dragonfly/)
            - [DebugBar](http://www.debugbar.com/)
            - [Venkman](https://developer.mozilla.org/en-US/docs/Venkman)
            - [Charles](https://www.charlesproxy.com/)
        - 版本管理
            - [Git](http://git-scm.com/)/[SVN](http://subversion.apache.org/)/[Mercurial](http://mercurial.selenic.com/)
            - [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)
    - 代码质量
        - Coding style
            - [ESLint](https://github.com/eslint/eslint)★
            - [JSLint](http://www.jslint.com/)/[JSHint](http://www.jshint.com/)/[jscs](https://github.com/mdevils/node-jscs)/
            - [CSSLint](http://csslint.net/)
            - [Markup Validation Service](http://validator.w3.org/)
            - [HTML Validators](https://validator.whatwg.org/)
        - 单元测试
            - [Mocha](http://mochajs.org/)★
            - [QUnit](http://qunitjs.com/)/[Jasmine](http://jasmine.github.io/)
            - [Should](https://github.com/visionmedia/should.js/)/[Chai](http://chaijs.com/)/[Expect](https://github.com/LearnBoost/expect.js/)
            - [Unit JS](http://unitjs.com/)
        - 自动化测试
            - [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/)
            - [phantomjs](http://phantomjs.org/)
            - [SourceLabs](https://saucelabs.com/)/[BrowserStack](http://www.browserstack.com/)
    - 前端库/框架
        - [Vue](http://cn.vuejs.org/)★
        - [React](http://facebook.github.io/react/)★
        - [jQuery](http://jquery.com/)/[Underscore](http://underscorejs.org/)/[Mootools](http://mootools.net/)/[Prototype.js](http://www.prototypejs.org/)
        - [YUI3](http://yuilibrary.com/projects/yui3/)/[Dojo](http://dojotoolkit.org/)/[ExtJS](http://www.sencha.com/products/extjs)/[KISSY](http://docs.kissyui.com/)
        - [Backbone](http://backbonejs.org/)/[KnockoutJS](http://knockoutjs.com/)/[Emberjs](http://emberjs.com/)
        - [AngularJS](http://angularjs.org/)
            - [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk)
        - [Bootstrap](http://getbootstrap.com/)
        - [Semantic UI](http://www.semantic-ui.com/)
        - [Juice UI](http://juiceui.com/)
        - [Web Atoms](http://webatomsjs.neurospeech.com/)
        - [Polymer](http://docs.polymerchina.org/)
        - [Dhtmlx](http://dhtmlx.com/)
        - [qooxdoo](http://qooxdoo.org/)
        - [Nwjs](https://github.com/nwjs/nw.js)
        - [React-native](https://github.com/facebook/react-native)
        - [Brick](http://mozbrick.github.io/)
    - 前端标准/规范
        - HTTP/1.1: RFCs 7230-7235
        - [HTTP/2](https://http2.github.io/)
        - [ECMAScript3/5](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
        - [ECMAScript6](http://www.ecma-international.org/ecma-262/6.0/index.html)
        - [W3C: DOM/BOM/XHTML/XML/JSON/JSONP/...](http://www.w3.org/TR/)
        - [CommonJS Modules](http://wiki.commonjs.org/wiki/Modules/1.0)/[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)
        - [HTML5](http://www.w3.org/html/wg/drafts/html/master/)/[CSS3](http://www.w3.org/Style/CSS/specs.en.html)
        - [Semantic Web](http://semanticweb.org/)
            - [MicroData](http://schema.org)
            - [RDFa](http://www.w3.org/TR/rdfa-core/)
        - [Web Accessibility](http://www.w3.org/WAI/)
            - [WCAG](http://www.w3.org/TR/WAI-WEBCONTENT/)
            - [Role Attribute](http://www.w3.org/TR/role-attribute/)
            - [WAI-ARIA](http://www.w3.org/TR/wai-aria/)
    - 性能
        - [JSPerf](http://jsperf.com/)
        - [YSlow 35 rules](http://developer.yahoo.com/performance/rules.html)
        - [PageSpeed](https://developers.google.com/speed/pagespeed/)
        - [HTTPWatch](http://www.httpwatch.com/)
        - [DynaTrace's Ajax](http://www.compuware.com/application-performance-management/dynatrace-ajax-download.html)
        - [高性能JavaScript](http://book.douban.com/subject/5362856/)
    - SEO
    - 编程知识储备
        - [数据结构](http://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84)
        - OOP/AOP
        - [原型链](http://net.tutsplus.com/tutorials/javascript-ajax/prototypes-in-javascript-what-you-need-to-know/)/作用域链
        - [闭包](http://www.jibbering.com/faq/notes/closures/)
        - [编程范型](http://zh.wikipedia.org/wiki/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%9E%8B)
        - [设计模式](http://addyosmani.com/resources/essentialjsdesignpatterns/book/)
        - [Javascript Tips](http://sanshi.me/articles/JavaScript-Garden-CN/html/index.html)
    - 部署流程
        - 压缩合并
            - [YUI Compressor](http://developer.yahoo.com/yui/compressor/)
            - [Google Clousure Complier](https://developers.google.com/closure/compiler/)
            - [UglifyJS](https://github.com/mishoo/UglifyJS)
            - [CleanCSS](https://github.com/GoalSmashers/clean-css)
        - 文档输出
            - [JSDoc](https://github.com/jsdoc3/jsdoc)
            - [Dox](https://github.com/visionmedia/dox)/[Doxmate](https://github.com/JacksonTian/doxmate)/[Grunt-Doxmate](https://github.com/luozhihua/grunt-doxmate)
        - 项目构建工具
            - [make](http://www.gnu.org/software/make/)/[Ant](http://ant.apache.org/)
            - [GYP](http://code.google.com/p/gyp/)
            - [Grunt](http://gruntjs.com/)
            - [Gulp](http://gulpjs.com/)
            - [Yeoman](http://yeoman.io/)
            - [FIS](http://fis.baidu.com/)
            - [Mod](https://github.com/modulejs/modjs)
        - ES6+ 转换器
            - [Traceur](https://github.com/google/traceur-compiler)
            - [Babel](https://babeljs.io/)★
    - 代码组织
        - 类库模块化
            - [CommonJS](http://www.commonjs.org/)/AMD
            - [YUI3模块](http://yuilibrary.com/projects/yui3/)
            - [webpack](http://webpack.github.io/)
        - 业务逻辑模块化
            - [bower](https://github.com/twitter/bower)/[component](https://github.com/component/component)
        - 文件加载
            - [SeaJS](http://seajs.org/)/[Require.js](http://requirejs.org/)
            - [LABjs](http://labjs.com/)
        - 模块化预处理器
            - [Browserify](https://github.com/substack/node-browserify)
    - 安全
        - [CSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)/[XSS](http://en.wikipedia.org/wiki/Cross-site_scripting)
        - [CSP](http://www.w3.org/TR/CSP/)
        - [Same-origin policy](https://developer.mozilla.org/docs/Web/Security/Same-origin_policy)
        - ADsafe/Caja/Sandbox
    - 移动Web
        - HTML5/CSS3
        - [响应式网页设计](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)
        - [Zeptojs](http://zeptojs.com/)/[iScroll](http://cubiq.org/iscroll)
        - V5/[Sencha Touch](http://www.sencha.com/products/touch)
        - [PhoneGap](http://phonegap.com/)/[Cordova](https://cordova.apache.org/)
        - [jQuery Mobile](http://jquerymobile.com/)
        - [W3C Mobile Web Initiative](http://www.w3.org/Mobile/)
        - [W3C mobileOK Checker](http://validator.w3.org/mobile/)
        - [Open Mobile Alliance](http://openmobilealliance.org/)
        - [React Native](https://facebook.github.io/react-native/)
        - [ionic](http://ionicframework.com/)
    - 前沿技术社区/会议
        - [D2](http://d2forum.org)/[WebRebuild](http://www.webrebuild.org/)
        - NodeParty/[W3CTech](http://w3ctech.com)/[HTML5梦工厂](http://www.html5dw.com)
        - [JSConf](http://jsconf.com/)/[沪JS(JSConf.cn)](http://jsconf.cn)
        - QCon/Velocity/SDCC
        - [JSConf](http://jsconf.com/)/[NodeConf](http://www.nodeconf.com/)
        - [CSSConf](http://cssconf.com/)
        - YDN/YUIConf
        - HybridApp
        - [WHATWG](http://whatwg.org/)
        - [MDN](https://developer.mozilla.org/zh-CN/)
        - [codepen](http://codepen.io/)
        - [w3cplus](http://www.w3cplus.com/)
        - [CNode](https://cnodejs.org/)
    - 计算机知识储备
        - 编译原理
        - [计算机网络](http://zh.wikipedia.org/wiki/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C)
        - [操作系统](http://zh.wikipedia.org/wiki/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F)
        - 算法原理
        - 软件工程/软件测试原理
        - [Unicode](http://www.unicode.org/)
    - 软技能
        - 知识管理/总结分享
        - 沟通技巧/团队协作
        - 需求管理/PM
        - 交互设计/可用性/可访问性知识
    - 可视化
        - SVG/Canvas/VML
        - SVG: [D3](http://d3js.org/)/[Raphaël](http://dmitrybaranovskiy.github.io/raphael/)/[Snap.svg](http://snapsvg.io/)/[DataV](http://datavlab.org/datavjs/)
        - Canvas: [CreateJS](http://www.createjs.com/)/[KineticJS](http://kineticjs.com/)
        - [WebGL](http://en.wikipedia.org/wiki/WebGL)/[Three.JS](http://threejs.org/)

- 后端工程师
    - 编程语言
        - C/C++/Java/PHP/Ruby/Python/...
    - 网页服务器
        - [Nginx](http://nginx.org/en/)
        - [Apache](http://httpd.apache.org/)
        - [Lighttpd](http://www.lighttpd.net/)
    - 数据库
        - SQL
        - [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)
        - [MongoDB](http://www.mongodb.org/)/[CouchDB](http://couchdb.apache.org/)
    - 数据缓存
        - [Redis](http://redis.io/)
        - [Memcached](http://memcached.org/)
    - 文件缓存/代理
        - [Varnish](https://www.varnish-cache.org/)
        - [Squid](http://www.squid-cache.org/)
    - 操作系统
        - Unix/Linux/OS X/Windows
    - 数据结构

## 前端书籍推荐
★越少越简单,越适合入门,★多的要么是难度比较高,要么是比较适合在后面看,比如讲性能之类的书.

### CSS
- [Eric Meyer 谈 CSS(卷二)](http://www.amazon.cn/Eric-Meyer-谈-CSS-迈耶/dp/B00170M84I/)★★★
- [CSS权威指南 (第3版)](http://book.douban.com/subject/2308234/)★★
- [精通CSS](http://book.douban.com/subject/4736167/)★★★
- [HTML & CSS设计与构建网站](http://book.douban.com/subject/21338365/)★

### JavaScript
- [JavaScript & jQuery交互式Web前端开发](http://book.douban.com/subject/26433805/)★
- [JavaScript DOM编程艺术 (第2版)](http://book.douban.com/subject/6038371/)★
- [JavaScript高级程序设计(第3版)](http://book.douban.com/subject/10546125/)★★
- [锋利的jQuery](http://book.douban.com/subject/10792216/)★★
- [高性能JavaScript](http://book.douban.com/subject/5362856/)★★★
- [JavaScript语言精粹](http://book.douban.com/subject/3590768/)★★★
- [JavaScript权威指南](http://book.douban.com/subject/10549733/)★★★
- [编写可维护的JavaScript](http://book.douban.com/subject/21792530/)★★★
- [JAVASCRIPT语言精髓与编程实践](http://book.douban.com/subject/3012828/)★★★
- [Effective Javascript](http://www.amazon.com/Effective-JavaScript-Specific-Software-Development/dp/0321812182)★★★
- [Secrets of the JavaScript Ninja](http://book.douban.com/subject/3176860/)★★★
- [JavaScript模式](http://book.douban.com/subject/11506062/)★★★
- [JavaScript设计模式](http://book.douban.com/subject/3329540/)★★★★
- [基于MVC的JavaScript Web富应用开发](http://book.douban.com/subject/10733304/)★★★

### 性能实践
- [高性能网站建设指南](https://book.douban.com/subject/3132277/)★
- [高性能网站建设进阶指南](https://book.douban.com/subject/4719162/)★★
- [Web性能实践日志](http://book.douban.com/subject/25891125/)★★★
- [Web性能权威指南](http://book.douban.com/subject/25856314/)★★★

### 版本控制工具
- [版本控制之道 (git)](http://book.douban.com/subject/4813786/)★★
- [Pro Git](http://iissnan.com/progit/)★★★
- [Git权威指南](http://book.douban.com/subject/6526452/)★★★★

## 后端书籍推荐
### Linux管理
- [Linux 系统管理技术手册](http://book.douban.com/subject/3042029/)
- [鸟哥的 Linux 私房菜](http://book.douban.com/subject/4889838/)
- [Linux 101 Hacks](http://www.thegeekstuff.com/linux-101-hacks-free-ebook-non-english/)
- [UNIX Shell Scripting](http://book.douban.com/subject/3519360/)
- [The Linux Command Line](http://book.douban.com/subject/6806862/)
- [Linux Network Administrator's Guide](http://oreilly.com/openbook/linag2/book/index.html)

### Linux编程
- [Linux程序设计](http://book.douban.com/subject/4831448/)
- [Linux系统编程](http://book.douban.com/subject/3907181/)
- [Unix环境高级编程](http://book.douban.com/subject/1788421/)
- [Unix编程艺术](http://book.douban.com/subject/1467587/)
- [The Linux Programming Interface](http://book.douban.com/subject/4292217/)
- [程序员的自我修养](http://book.douban.com/subject/3652388/)
- [深入理解Linux内核](http://book.douban.com/subject/2287506/)
- [Unix网络编程](http://book.douban.com/subject/1500149/)
- [TCP/IP高级编程](http://book.douban.com/subject/1088054/)

### C/C++
- [Linux C编程一站式学习](http://book.douban.com/subject/4141733/)
- [C和指针](http://book.douban.com/subject/3012360/)
- [C陷阱与缺陷](http://book.douban.com/subject/2778632/)
- [C专家编程](http://book.douban.com/subject/2377310/)
- [C语言核心技术](http://book.douban.com/subject/2226913/)
- [彻底搞定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)
- [征服C指针](http://book.douban.com/subject/21317828/)
- [C++编程思想](http://book.douban.com/subject/1094797/)
- [高质量程序设计指南---C/C++语言](http://book.douban.com/subject/2116929/)
- [Inside the C++ Object Model](http://book.douban.com/subject/1484262/)
- [A Tour of C++](http://www.stroustrup.com/Tour.html)
- [The C++ Programming Language](http://en.wikipedia.org/wiki/The_C%2B%2B_Programming_Language)
- [The C++ Standard Library - A Tutorial and Reference](http://www.cppstdlib.com/)
- [The C++ Standard (INCITS/ISO/IEC 14882-2011)](http://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+14882-2012)
- [Overview of the New C++](http://www.artima.com/shop/overview_of_the_new_cpp)

## 前端工作面试
- [前端工作面试问题](https://github.com/darcyclarke/Front-end-Developer-Interview-Questions)
- [前端开发面试题(中文)](https://github.com/markyun/My-blog/tree/master/Front-end-Developer-Questions/Question)

## 内容贡献者
除了感谢Jayli提供了知识结构图的原本来,还感谢以下的内容贡献者们,结果由`git-summary`生成于2014-01-03:

```

 project  : fks
 repo age : 1 year, 3 months
 active   : 53 days
 commits  : 108
 files    : 4
 authors  :
    56  Jackson Tian            51.9%
     9  吴晓兰               8.3%
     5  liyinkan                4.6%
     3  chriscai                2.8%
     3  fengxiaolong            2.8%
     3  XiNGRZ                  2.8%
     2  monkadd                 1.9%
     2  Johnny                  1.9%
     2  weiwenqing              1.9%
     2  Yinkan Li               1.9%
     2  Copypeng                1.9%
     2  左岸                  1.9%
     2  Jakukyo Friel           1.9%
     2  Glowin                  1.9%
     1  李亚川               0.9%
     1  Evan You                0.9%
     1  Mickey                  0.9%
     1  Mickey-                 0.9%
     1  Qi Junyuan              0.9%
     1  browsnet                0.9%
     1  doabit                  0.9%
     1  guoxiangyang            0.9%
     1  linkgod                 0.9%
     1  popomore                0.9%
     1  vipzhicheng             0.9%
     1  zhaqiang                0.9%
     1  Colin Luo               0.9%

```


================================================
FILE: bin/generate.js
================================================
var fs = require('fs');
var path = require('path');

var readme = fs.readFileSync(path.join(__dirname, '../README.md'), 'utf8');

var getItems = function (str) {
  var patt = /([ ]*)-(.*)/g;
  var result;

  var list = [];
  while ((result = patt.exec(str)) != null)  {
    list.push({level: result[1].length / 4, content: result[2].trim()});
  }
  return list;
};

var filter = function (list) {
  var j = 0;
  var f2e = [];
  for (var i = 0; i < list.length; i++) {
    var item = list[i];
    if (item.level === 0) {
      j = j + 1;
      if (j === 2) {
        break;
      }
    }

    f2e.push(item);
  }
  return f2e;
};

var format = function (list) {
  var result = [];
  for (var i = 0; i < list.length; i++) {
    var item = list[i];
    var data = {
      id: '' + i,
      name: item.content,
      level: item.level
    };
    result.push(data);
  }
  return result;
};

var items = getItems(readme);
var f2e = filter(items);
var formated = format(f2e);

var buildTree = function (list) {
  var root = null;
  for (var i = 0; i < list.length; i++) {
    var item = list[i];
    if (root === null) {
      root = item;
      root.children = [];
    }

    var lastLevel0 = root.children;
    if (item.level === 1) {
      delete item.level;
      lastLevel0.push(item);
    }

    if (item.level === 2) {
      var lastLevel1 = lastLevel0[lastLevel0.length - 1];
      lastLevel1.children = lastLevel1.children || [];
      lastLevel1.children.push(item);
    }

    if (item.level === 3) {
      var lastLevel1Child = lastLevel0[lastLevel0.length - 1].children;
      var lastLevel2 = lastLevel1Child[lastLevel1Child.length - 1];
      lastLevel2.children = lastLevel2.children || [];
      lastLevel2.children.push(item);
    }
    delete item.level;
  }
  return root;
};

var tree = buildTree(formated);
fs.writeFileSync(path.join(__dirname, '../fks_chart/data/front-end.json'), JSON.stringify(tree, null, '  '));


================================================
FILE: fks_chart/bower.json
================================================
{
  "name": "front-end-collect-",
  "version": "0.0.0",
  "authors": [
    "hjzheng <zhenghaoju700@163.com>"
  ],
  "license": "MIT",
  "ignore": [
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "angular": "~1.2.19",
    "d3": "~3.4.9",
    "angular-marked": "~0.0.12",
    "jquery": "~2.1.3"
  }
}


================================================
FILE: fks_chart/bower_components/angular/.bower.json
================================================
{
  "name": "angular",
  "version": "1.2.28",
  "main": "./angular.js",
  "ignore": [],
  "dependencies": {},
  "homepage": "https://github.com/angular/bower-angular",
  "_release": "1.2.28",
  "_resolution": {
    "type": "version",
    "tag": "v1.2.28",
    "commit": "d1369fe05d3a7d85961a2223292b67ee82b9f80a"
  },
  "_source": "git://github.com/angular/bower-angular.git",
  "_target": "~1.2.19",
  "_originalSource": "angular"
}

================================================
FILE: fks_chart/bower_components/angular/README.md
================================================
# packaged angular

This repo is for distribution on `npm` and `bower`. The source for this module is in the
[main AngularJS repo](https://github.com/angular/angular.js).
Please file issues and pull requests against that repo.

## Install

You can install this package either with `npm` or with `bower`.

### npm

```shell
npm install angular
```

Then add a `<script>` to your `index.html`:

```html
<script src="/node_modules/angular/angular.js"></script>
```

Note that this package is not in CommonJS format, so doing `require('angular')` will return `undefined`.
If you're using [Browserify](https://github.com/substack/node-browserify), you can use
[exposify](https://github.com/thlorenz/exposify) to have `require('angular')` return the `angular`
global.

### bower

```shell
bower install angular
```

Then add a `<script>` to your `index.html`:

```html
<script src="/bower_components/angular/angular.js"></script>
```

## Documentation

Documentation is available on the
[AngularJS docs site](http://docs.angularjs.org/).

## License

The MIT License

Copyright (c) 2010-2012 Google, Inc. http://angularjs.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: fks_chart/bower_components/angular/angular-csp.css
================================================
/* Include this file in your html if you are using the CSP mode. */

@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;
}

/* show the element during a show/hide animation when the
 * animation is ongoing, but the .ng-hide class is active */
.ng-hide-add-active, .ng-hide-remove {
  display: block!important;
}


================================================
FILE: fks_chart/bower_components/angular/angular.js
================================================
/**
 * @license AngularJS v1.2.28
 * (c) 2010-2014 Google, Inc. http://angularjs.org
 * License: MIT
 */
(function(window, document, undefined) {'use strict';

/**
 * @description
 *
 * This object provides a utility for producing rich Error messages within
 * Angular. It can be called as follows:
 *
 * var exampleMinErr = minErr('example');
 * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
 *
 * The above creates an instance of minErr in the example namespace. The
 * resulting error will have a namespaced error code of example.one.  The
 * resulting error will replace {0} with the value of foo, and {1} with the
 * value of bar. The object is not restricted in the number of arguments it can
 * take.
 *
 * If fewer arguments are specified than necessary for interpolation, the extra
 * interpolation markers will be preserved in the final string.
 *
 * Since data will be parsed statically during a build step, some restrictions
 * are applied with respect to how minErr instances are created and called.
 * Instances should have names of the form namespaceMinErr for a minErr created
 * using minErr('namespace') . Error codes, namespaces and template strings
 * should all be static strings, not variables or general expressions.
 *
 * @param {string} module The namespace to use for the new minErr instance.
 * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
 */

function minErr(module) {
  return function () {
    var code = arguments[0],
      prefix = '[' + (module ? module + ':' : '') + code + '] ',
      template = arguments[1],
      templateArgs = arguments,
      stringify = function (obj) {
        if (typeof obj === 'function') {
          return obj.toString().replace(/ \{[\s\S]*$/, '');
        } else if (typeof obj === 'undefined') {
          return 'undefined';
        } else if (typeof obj !== 'string') {
          return JSON.stringify(obj);
        }
        return obj;
      },
      message, i;

    message = prefix + template.replace(/\{\d+\}/g, function (match) {
      var index = +match.slice(1, -1), arg;

      if (index + 2 < templateArgs.length) {
        arg = templateArgs[index + 2];
        if (typeof arg === 'function') {
          return arg.toString().replace(/ ?\{[\s\S]*$/, '');
        } else if (typeof arg === 'undefined') {
          return 'undefined';
        } else if (typeof arg !== 'string') {
          return toJson(arg);
        }
        return arg;
      }
      return match;
    });

    message = message + '\nhttp://errors.angularjs.org/1.2.28/' +
      (module ? module + '/' : '') + code;
    for (i = 2; i < arguments.length; i++) {
      message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
        encodeURIComponent(stringify(arguments[i]));
    }

    return new Error(message);
  };
}

/* We need to tell jshint what variables are being exported */
/* global angular: true,
    msie: true,
    jqLite: true,
    jQuery: true,
    slice: true,
    push: true,
    toString: true,
    ngMinErr: true,
    angularModule: true,
    nodeName_: true,
    uid: true,
    VALIDITY_STATE_PROPERTY: true,

    lowercase: true,
    uppercase: true,
    manualLowercase: true,
    manualUppercase: true,
    nodeName_: true,
    isArrayLike: true,
    forEach: true,
    sortedKeys: true,
    forEachSorted: true,
    reverseParams: true,
    nextUid: true,
    setHashKey: true,
    extend: true,
    int: true,
    inherit: true,
    noop: true,
    identity: true,
    valueFn: true,
    isUndefined: true,
    isDefined: true,
    isObject: true,
    isString: true,
    isNumber: true,
    isDate: true,
    isArray: true,
    isFunction: true,
    isRegExp: true,
    isWindow: true,
    isScope: true,
    isFile: true,
    isBlob: true,
    isBoolean: true,
    isPromiseLike: true,
    trim: true,
    isElement: true,
    makeMap: true,
    map: true,
    size: true,
    includes: true,
    indexOf: true,
    arrayRemove: true,
    isLeafNode: true,
    copy: true,
    shallowCopy: true,
    equals: true,
    csp: true,
    concat: true,
    sliceArgs: true,
    bind: true,
    toJsonReplacer: true,
    toJson: true,
    fromJson: true,
    toBoolean: true,
    startingTag: true,
    tryDecodeURIComponent: true,
    parseKeyValue: true,
    toKeyValue: true,
    encodeUriSegment: true,
    encodeUriQuery: true,
    angularInit: true,
    bootstrap: true,
    snake_case: true,
    bindJQuery: true,
    assertArg: true,
    assertArgFn: true,
    assertNotHasOwnProperty: true,
    getter: true,
    getBlockElements: true,
    hasOwnProperty: true,
*/

////////////////////////////////////

/**
 * @ngdoc module
 * @name ng
 * @module ng
 * @description
 *
 * # ng (core module)
 * The ng module is loaded by default when an AngularJS application is started. The module itself
 * contains the essential components for an AngularJS application to function. The table below
 * lists a high level breakdown of each of the services/factories, filters, directives and testing
 * components available within this core module.
 *
 * <div doc-module-components="ng"></div>
 */

// The name of a form control's ValidityState property.
// This is used so that it's possible for internal tests to create mock ValidityStates.
var VALIDITY_STATE_PROPERTY = 'validity';

/**
 * @ngdoc function
 * @name angular.lowercase
 * @module ng
 * @kind function
 *
 * @description Converts the specified string to lowercase.
 * @param {string} string String to be converted to lowercase.
 * @returns {string} Lowercased string.
 */
var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
var hasOwnProperty = Object.prototype.hasOwnProperty;

/**
 * @ngdoc function
 * @name angular.uppercase
 * @module ng
 * @kind function
 *
 * @description Converts the specified string to uppercase.
 * @param {string} string String to be converted to uppercase.
 * @returns {string} Uppercased string.
 */
var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};


var manualLowercase = function(s) {
  /* jshint bitwise: false */
  return isString(s)
      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
      : s;
};
var manualUppercase = function(s) {
  /* jshint bitwise: false */
  return isString(s)
      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
      : s;
};


// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
// with correct but slower alternatives.
if ('i' !== 'I'.toLowerCase()) {
  lowercase = manualLowercase;
  uppercase = manualUppercase;
}


var
    msie,             // holds major version number for IE, or NaN if UA is not IE.
    jqLite,           // delay binding since jQuery could be loaded after us.
    jQuery,           // delay binding
    slice             = [].slice,
    push              = [].push,
    toString          = Object.prototype.toString,
    ngMinErr          = minErr('ng'),

    /** @name angular */
    angular           = window.angular || (window.angular = {}),
    angularModule,
    nodeName_,
    uid               = ['0', '0', '0'];

/**
 * IE 11 changed the format of the UserAgent string.
 * See http://msdn.microsoft.com/en-us/library/ms537503.aspx
 */
msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
if (isNaN(msie)) {
  msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
}


/**
 * @private
 * @param {*} obj
 * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
 *                   String ...)
 */
function isArrayLike(obj) {
  if (obj == null || isWindow(obj)) {
    return false;
  }

  var length = obj.length;

  if (obj.nodeType === 1 && length) {
    return true;
  }

  return isString(obj) || isArray(obj) || length === 0 ||
         typeof length === 'number' && length > 0 && (length - 1) in obj;
}

/**
 * @ngdoc function
 * @name angular.forEach
 * @module ng
 * @kind function
 *
 * @description
 * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
 * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
 * is the value of an object property or an array element and `key` is the object property key or
 * array element index. Specifying a `context` for the function is optional.
 *
 * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
 * using the `hasOwnProperty` method.
 *
   ```js
     var values = {name: 'misko', gender: 'male'};
     var log = [];
     angular.forEach(values, function(value, key) {
       this.push(key + ': ' + value);
     }, log);
     expect(log).toEqual(['name: misko', 'gender: male']);
   ```
 *
 * @param {Object|Array} obj Object to iterate over.
 * @param {Function} iterator Iterator function.
 * @param {Object=} context Object to become context (`this`) for the iterator function.
 * @returns {Object|Array} Reference to `obj`.
 */
function forEach(obj, iterator, context) {
  var key;
  if (obj) {
    if (isFunction(obj)) {
      for (key in obj) {
        // Need to check if hasOwnProperty exists,
        // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
        if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
          iterator.call(context, obj[key], key);
        }
      }
    } else if (isArray(obj) || isArrayLike(obj)) {
      for (key = 0; key < obj.length; key++) {
        iterator.call(context, obj[key], key);
      }
    } else if (obj.forEach && obj.forEach !== forEach) {
        obj.forEach(iterator, context);
    } else {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          iterator.call(context, obj[key], key);
        }
      }
    }
  }
  return obj;
}

function sortedKeys(obj) {
  var keys = [];
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      keys.push(key);
    }
  }
  return keys.sort();
}

function forEachSorted(obj, iterator, context) {
  var keys = sortedKeys(obj);
  for ( var i = 0; i < keys.length; i++) {
    iterator.call(context, obj[keys[i]], keys[i]);
  }
  return keys;
}


/**
 * when using forEach the params are value, key, but it is often useful to have key, value.
 * @param {function(string, *)} iteratorFn
 * @returns {function(*, string)}
 */
function reverseParams(iteratorFn) {
  return function(value, key) { iteratorFn(key, value); };
}

/**
 * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
 * characters such as '012ABC'. The reason why we are not using simply a number counter is that
 * the number string gets longer over time, and it can also overflow, where as the nextId
 * will grow much slower, it is a string, and it will never overflow.
 *
 * @returns {string} an unique alpha-numeric string
 */
function nextUid() {
  var index = uid.length;
  var digit;

  while(index) {
    index--;
    digit = uid[index].charCodeAt(0);
    if (digit == 57 /*'9'*/) {
      uid[index] = 'A';
      return uid.join('');
    }
    if (digit == 90  /*'Z'*/) {
      uid[index] = '0';
    } else {
      uid[index] = String.fromCharCode(digit + 1);
      return uid.join('');
    }
  }
  uid.unshift('0');
  return uid.join('');
}


/**
 * Set or clear the hashkey for an object.
 * @param obj object
 * @param h the hashkey (!truthy to delete the hashkey)
 */
function setHashKey(obj, h) {
  if (h) {
    obj.$$hashKey = h;
  }
  else {
    delete obj.$$hashKey;
  }
}

/**
 * @ngdoc function
 * @name angular.extend
 * @module ng
 * @kind function
 *
 * @description
 * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
 * to `dst`. You can specify multiple `src` objects.
 *
 * @param {Object} dst Destination object.
 * @param {...Object} src Source object(s).
 * @returns {Object} Reference to `dst`.
 */
function extend(dst) {
  var h = dst.$$hashKey;
  forEach(arguments, function(obj) {
    if (obj !== dst) {
      forEach(obj, function(value, key) {
        dst[key] = value;
      });
    }
  });

  setHashKey(dst,h);
  return dst;
}

function int(str) {
  return parseInt(str, 10);
}


function inherit(parent, extra) {
  return extend(new (extend(function() {}, {prototype:parent}))(), extra);
}

/**
 * @ngdoc function
 * @name angular.noop
 * @module ng
 * @kind function
 *
 * @description
 * A function that performs no operations. This function can be useful when writing code in the
 * functional style.
   ```js
     function foo(callback) {
       var result = calculateResult();
       (callback || angular.noop)(result);
     }
   ```
 */
function noop() {}
noop.$inject = [];


/**
 * @ngdoc function
 * @name angular.identity
 * @module ng
 * @kind function
 *
 * @description
 * A function that returns its first argument. This function is useful when writing code in the
 * functional style.
 *
   ```js
     function transformer(transformationFn, value) {
       return (transformationFn || angular.identity)(value);
     };
   ```
 */
function identity($) {return $;}
identity.$inject = [];


function valueFn(value) {return function() {return value;};}

/**
 * @ngdoc function
 * @name angular.isUndefined
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is undefined.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is undefined.
 */
function isUndefined(value){return typeof value === 'undefined';}


/**
 * @ngdoc function
 * @name angular.isDefined
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is defined.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is defined.
 */
function isDefined(value){return typeof value !== 'undefined';}


/**
 * @ngdoc function
 * @name angular.isObject
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
 * considered to be objects. Note that JavaScript arrays are objects.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is an `Object` but not `null`.
 */
function isObject(value){return value != null && typeof value === 'object';}


/**
 * @ngdoc function
 * @name angular.isString
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a `String`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `String`.
 */
function isString(value){return typeof value === 'string';}


/**
 * @ngdoc function
 * @name angular.isNumber
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a `Number`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `Number`.
 */
function isNumber(value){return typeof value === 'number';}


/**
 * @ngdoc function
 * @name angular.isDate
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a value is a date.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `Date`.
 */
function isDate(value) {
  return toString.call(value) === '[object Date]';
}


/**
 * @ngdoc function
 * @name angular.isArray
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is an `Array`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is an `Array`.
 */
var isArray = (function() {
  if (!isFunction(Array.isArray)) {
    return function(value) {
      return toString.call(value) === '[object Array]';
    };
  }
  return Array.isArray;
})();

/**
 * @ngdoc function
 * @name angular.isFunction
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a `Function`.
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `Function`.
 */
function isFunction(value){return typeof value === 'function';}


/**
 * Determines if a value is a regular expression object.
 *
 * @private
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a `RegExp`.
 */
function isRegExp(value) {
  return toString.call(value) === '[object RegExp]';
}


/**
 * Checks if `obj` is a window object.
 *
 * @private
 * @param {*} obj Object to check
 * @returns {boolean} True if `obj` is a window obj.
 */
function isWindow(obj) {
  return obj && obj.document && obj.location && obj.alert && obj.setInterval;
}


function isScope(obj) {
  return obj && obj.$evalAsync && obj.$watch;
}


function isFile(obj) {
  return toString.call(obj) === '[object File]';
}


function isBlob(obj) {
  return toString.call(obj) === '[object Blob]';
}


function isBoolean(value) {
  return typeof value === 'boolean';
}


function isPromiseLike(obj) {
  return obj && isFunction(obj.then);
}


var trim = (function() {
  // native trim is way faster: http://jsperf.com/angular-trim-test
  // but IE doesn't have it... :-(
  // TODO: we should move this into IE/ES5 polyfill
  if (!String.prototype.trim) {
    return function(value) {
      return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
    };
  }
  return function(value) {
    return isString(value) ? value.trim() : value;
  };
})();


/**
 * @ngdoc function
 * @name angular.isElement
 * @module ng
 * @kind function
 *
 * @description
 * Determines if a reference is a DOM element (or wrapped jQuery element).
 *
 * @param {*} value Reference to check.
 * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
 */
function isElement(node) {
  return !!(node &&
    (node.nodeName  // we are a direct element
    || (node.prop && node.attr && node.find)));  // we have an on and find method part of jQuery API
}

/**
 * @param str 'key1,key2,...'
 * @returns {object} in the form of {key1:true, key2:true, ...}
 */
function makeMap(str) {
  var obj = {}, items = str.split(","), i;
  for ( i = 0; i < items.length; i++ )
    obj[ items[i] ] = true;
  return obj;
}


if (msie < 9) {
  nodeName_ = function(element) {
    element = element.nodeName ? element : element[0];
    return (element.scopeName && element.scopeName != 'HTML')
      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
  };
} else {
  nodeName_ = function(element) {
    return element.nodeName ? element.nodeName : element[0].nodeName;
  };
}


function map(obj, iterator, context) {
  var results = [];
  forEach(obj, function(value, index, list) {
    results.push(iterator.call(context, value, index, list));
  });
  return results;
}


/**
 * @description
 * Determines the number of elements in an array, the number of properties an object has, or
 * the length of a string.
 *
 * Note: This function is used to augment the Object type in Angular expressions. See
 * {@link angular.Object} for more information about Angular arrays.
 *
 * @param {Object|Array|string} obj Object, array, or string to inspect.
 * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
 * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
 */
function size(obj, ownPropsOnly) {
  var count = 0, key;

  if (isArray(obj) || isString(obj)) {
    return obj.length;
  } else if (isObject(obj)) {
    for (key in obj)
      if (!ownPropsOnly || obj.hasOwnProperty(key))
        count++;
  }

  return count;
}


function includes(array, obj) {
  return indexOf(array, obj) != -1;
}

function indexOf(array, obj) {
  if (array.indexOf) return array.indexOf(obj);

  for (var i = 0; i < array.length; i++) {
    if (obj === array[i]) return i;
  }
  return -1;
}

function arrayRemove(array, value) {
  var index = indexOf(array, value);
  if (index >=0)
    array.splice(index, 1);
  return value;
}

function isLeafNode (node) {
  if (node) {
    switch (node.nodeName) {
    case "OPTION":
    case "PRE":
    case "TITLE":
      return true;
    }
  }
  return false;
}

/**
 * @ngdoc function
 * @name angular.copy
 * @module ng
 * @kind function
 *
 * @description
 * Creates a deep copy of `source`, which should be an object or an array.
 *
 * * If no destination is supplied, a copy of the object or array is created.
 * * If a destination is provided, all of its elements (for array) or properties (for objects)
 *   are deleted and then all elements/properties from the source are copied to it.
 * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
 * * If `source` is identical to 'destination' an exception will be thrown.
 *
 * @param {*} source The source that will be used to make a copy.
 *                   Can be any type, including primitives, `null`, and `undefined`.
 * @param {(Object|Array)=} destination Destination into which the source is copied. If
 *     provided, must be of the same type as `source`.
 * @returns {*} The copy or updated `destination`, if `destination` was specified.
 *
 * @example
 <example module="copyExample">
 <file name="index.html">
 <div ng-controller="ExampleController">
 <form novalidate class="simple-form">
 Name: <input type="text" ng-model="user.name" /><br />
 E-mail: <input type="email" ng-model="user.email" /><br />
 Gender: <input type="radio" ng-model="user.gender" value="male" />male
 <input type="radio" ng-model="user.gender" value="female" />female<br />
 <button ng-click="reset()">RESET</button>
 <button ng-click="update(user)">SAVE</button>
 </form>
 <pre>form = {{user | json}}</pre>
 <pre>master = {{master | json}}</pre>
 </div>

 <script>
  angular.module('copyExample', [])
    .controller('ExampleController', ['$scope', function($scope) {
      $scope.master= {};

      $scope.update = function(user) {
        // Example with 1 argument
        $scope.master= angular.copy(user);
      };

      $scope.reset = function() {
        // Example with 2 arguments
        angular.copy($scope.master, $scope.user);
      };

      $scope.reset();
    }]);
 </script>
 </file>
 </example>
 */
function copy(source, destination, stackSource, stackDest) {
  if (isWindow(source) || isScope(source)) {
    throw ngMinErr('cpws',
      "Can't copy! Making copies of Window or Scope instances is not supported.");
  }

  if (!destination) {
    destination = source;
    if (source) {
      if (isArray(source)) {
        destination = copy(source, [], stackSource, stackDest);
      } else if (isDate(source)) {
        destination = new Date(source.getTime());
      } else if (isRegExp(source)) {
        destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
        destination.lastIndex = source.lastIndex;
      } else if (isObject(source)) {
        destination = copy(source, {}, stackSource, stackDest);
      }
    }
  } else {
    if (source === destination) throw ngMinErr('cpi',
      "Can't copy! Source and destination are identical.");

    stackSource = stackSource || [];
    stackDest = stackDest || [];

    if (isObject(source)) {
      var index = indexOf(stackSource, source);
      if (index !== -1) return stackDest[index];

      stackSource.push(source);
      stackDest.push(destination);
    }

    var result;
    if (isArray(source)) {
      destination.length = 0;
      for ( var i = 0; i < source.length; i++) {
        result = copy(source[i], null, stackSource, stackDest);
        if (isObject(source[i])) {
          stackSource.push(source[i]);
          stackDest.push(result);
        }
        destination.push(result);
      }
    } else {
      var h = destination.$$hashKey;
      if (isArray(destination)) {
        destination.length = 0;
      } else {
        forEach(destination, function(value, key) {
          delete destination[key];
        });
      }
      for ( var key in source) {
        result = copy(source[key], null, stackSource, stackDest);
        if (isObject(source[key])) {
          stackSource.push(source[key]);
          stackDest.push(result);
        }
        destination[key] = result;
      }
      setHashKey(destination,h);
    }

  }
  return destination;
}

/**
 * Creates a shallow copy of an object, an array or a primitive
 */
function shallowCopy(src, dst) {
  if (isArray(src)) {
    dst = dst || [];

    for ( var i = 0; i < src.length; i++) {
      dst[i] = src[i];
    }
  } else if (isObject(src)) {
    dst = dst || {};

    for (var key in src) {
      if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
        dst[key] = src[key];
      }
    }
  }

  return dst || src;
}


/**
 * @ngdoc function
 * @name angular.equals
 * @module ng
 * @kind function
 *
 * @description
 * Determines if two objects or two values are equivalent. Supports value types, regular
 * expressions, arrays and objects.
 *
 * Two objects or values are considered equivalent if at least one of the following is true:
 *
 * * Both objects or values pass `===` comparison.
 * * Both objects or values are of the same type and all of their properties are equal by
 *   comparing them with `angular.equals`.
 * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
 * * Both values represent the same regular expression (In JavaScript,
 *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
 *   representation matches).
 *
 * During a property comparison, properties of `function` type and properties with names
 * that begin with `$` are ignored.
 *
 * Scope and DOMWindow objects are being compared only by identify (`===`).
 *
 * @param {*} o1 Object or value to compare.
 * @param {*} o2 Object or value to compare.
 * @returns {boolean} True if arguments are equal.
 */
function equals(o1, o2) {
  if (o1 === o2) return true;
  if (o1 === null || o2 === null) return false;
  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
  if (t1 == t2) {
    if (t1 == 'object') {
      if (isArray(o1)) {
        if (!isArray(o2)) return false;
        if ((length = o1.length) == o2.length) {
          for(key=0; key<length; key++) {
            if (!equals(o1[key], o2[key])) return false;
          }
          return true;
        }
      } else if (isDate(o1)) {
        if (!isDate(o2)) return false;
        return (isNaN(o1.getTime()) && isNaN(o2.getTime())) || (o1.getTime() === o2.getTime());
      } else if (isRegExp(o1) && isRegExp(o2)) {
        return o1.toString() == o2.toString();
      } else {
        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
        keySet = {};
        for(key in o1) {
          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
          if (!equals(o1[key], o2[key])) return false;
          keySet[key] = true;
        }
        for(key in o2) {
          if (!keySet.hasOwnProperty(key) &&
              key.charAt(0) !== '$' &&
              o2[key] !== undefined &&
              !isFunction(o2[key])) return false;
        }
        return true;
      }
    }
  }
  return false;
}

var csp = function() {
  if (isDefined(csp.isActive_)) return csp.isActive_;

  var active = !!(document.querySelector('[ng-csp]') ||
                  document.querySelector('[data-ng-csp]'));

  if (!active) {
    try {
      /* jshint -W031, -W054 */
      new Function('');
      /* jshint +W031, +W054 */
    } catch (e) {
      active = true;
    }
  }

  return (csp.isActive_ = active);
};



function concat(array1, array2, index) {
  return array1.concat(slice.call(array2, index));
}

function sliceArgs(args, startIndex) {
  return slice.call(args, startIndex || 0);
}


/* jshint -W101 */
/**
 * @ngdoc function
 * @name angular.bind
 * @module ng
 * @kind function
 *
 * @description
 * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
 * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
 * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
 * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
 *
 * @param {Object} self Context which `fn` should be evaluated in.
 * @param {function()} fn Function to be bound.
 * @param {...*} args Optional arguments to be prebound to the `fn` function call.
 * @returns {function()} Function that wraps the `fn` with all the specified bindings.
 */
/* jshint +W101 */
function bind(self, fn) {
  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
  if (isFunction(fn) && !(fn instanceof RegExp)) {
    return curryArgs.length
      ? function() {
          return arguments.length
            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
            : fn.apply(self, curryArgs);
        }
      : function() {
          return arguments.length
            ? fn.apply(self, arguments)
            : fn.call(self);
        };
  } else {
    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
    return fn;
  }
}


function toJsonReplacer(key, value) {
  var val = value;

  if (typeof key === 'string' && key.charAt(0) === '$') {
    val = undefined;
  } else if (isWindow(value)) {
    val = '$WINDOW';
  } else if (value &&  document === value) {
    val = '$DOCUMENT';
  } else if (isScope(value)) {
    val = '$SCOPE';
  }

  return val;
}


/**
 * @ngdoc function
 * @name angular.toJson
 * @module ng
 * @kind function
 *
 * @description
 * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
 * stripped since angular uses this notation internally.
 *
 * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
 * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
 * @returns {string|undefined} JSON-ified string representing `obj`.
 */
function toJson(obj, pretty) {
  if (typeof obj === 'undefined') return undefined;
  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
}


/**
 * @ngdoc function
 * @name angular.fromJson
 * @module ng
 * @kind function
 *
 * @description
 * Deserializes a JSON string.
 *
 * @param {string} json JSON string to deserialize.
 * @returns {Object|Array|string|number} Deserialized thingy.
 */
function fromJson(json) {
  return isString(json)
      ? JSON.parse(json)
      : json;
}


function toBoolean(value) {
  if (typeof value === 'function') {
    value = true;
  } else if (value && value.length !== 0) {
    var v = lowercase("" + value);
    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
  } else {
    value = false;
  }
  return value;
}

/**
 * @returns {string} Returns the string representation of the element.
 */
function startingTag(element) {
  element = jqLite(element).clone();
  try {
    // turns out IE does not let you set .html() on elements which
    // are not allowed to have children. So we just ignore it.
    element.empty();
  } catch(e) {}
  // As Per DOM Standards
  var TEXT_NODE = 3;
  var elemHtml = jqLite('<div>').append(element).html();
  try {
    return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
        elemHtml.
          match(/^(<[^>]+>)/)[1].
          replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
  } catch(e) {
    return lowercase(elemHtml);
  }

}


/////////////////////////////////////////////////

/**
 * Tries to decode the URI component without throwing an exception.
 *
 * @private
 * @param str value potential URI component to check.
 * @returns {boolean} True if `value` can be decoded
 * with the decodeURIComponent function.
 */
function tryDecodeURIComponent(value) {
  try {
    return decodeURIComponent(value);
  } catch(e) {
    // Ignore any invalid uri component
  }
}


/**
 * Parses an escaped url query string into key-value pairs.
 * @returns {Object.<string,boolean|Array>}
 */
function parseKeyValue(/**string*/keyValue) {
  var obj = {}, key_value, key;
  forEach((keyValue || "").split('&'), function(keyValue) {
    if ( keyValue ) {
      key_value = keyValue.replace(/\+/g,'%20').split('=');
      key = tryDecodeURIComponent(key_value[0]);
      if ( isDefined(key) ) {
        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
        if (!hasOwnProperty.call(obj, key)) {
          obj[key] = val;
        } else if(isArray(obj[key])) {
          obj[key].push(val);
        } else {
          obj[key] = [obj[key],val];
        }
      }
    }
  });
  return obj;
}

function toKeyValue(obj) {
  var parts = [];
  forEach(obj, function(value, key) {
    if (isArray(value)) {
      forEach(value, function(arrayValue) {
        parts.push(encodeUriQuery(key, true) +
                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
      });
    } else {
    parts.push(encodeUriQuery(key, true) +
               (value === true ? '' : '=' + encodeUriQuery(value, true)));
    }
  });
  return parts.length ? parts.join('&') : '';
}


/**
 * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
 * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
 * segments:
 *    segment       = *pchar
 *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
 *    pct-encoded   = "%" HEXDIG HEXDIG
 *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
 *                     / "*" / "+" / "," / ";" / "="
 */
function encodeUriSegment(val) {
  return encodeUriQuery(val, true).
             replace(/%26/gi, '&').
             replace(/%3D/gi, '=').
             replace(/%2B/gi, '+');
}


/**
 * This method is intended for encoding *key* or *value* parts of query component. We need a custom
 * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
 * encoded per http://tools.ietf.org/html/rfc3986:
 *    query       = *( pchar / "/" / "?" )
 *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
 *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
 *    pct-encoded   = "%" HEXDIG HEXDIG
 *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
 *                     / "*" / "+" / "," / ";" / "="
 */
function encodeUriQuery(val, pctEncodeSpaces) {
  return encodeURIComponent(val).
             replace(/%40/gi, '@').
             replace(/%3A/gi, ':').
             replace(/%24/g, '$').
             replace(/%2C/gi, ',').
             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}


/**
 * @ngdoc directive
 * @name ngApp
 * @module ng
 *
 * @element ANY
 * @param {angular.Module} ngApp an optional application
 *   {@link angular.module module} name to load.
 *
 * @description
 *
 * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
 * designates the **root element** of the application and is typically placed near the root element
 * of the page - e.g. on the `<body>` or `<html>` tags.
 *
 * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
 * found in the document will be used to define the root element to auto-bootstrap as an
 * application. To run multiple applications in an HTML document you must manually bootstrap them using
 * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
 *
 * You can specify an **AngularJS module** to be used as the root module for the application.  This
 * module will be loaded into the {@link auto.$injector} when the application is bootstrapped and
 * should contain the application code needed or have dependencies on other modules that will
 * contain the code. See {@link angular.module} for more information.
 *
 * In the example below if the `ngApp` directive were not placed on the `html` element then the
 * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
 * would not be resolved to `3`.
 *
 * `ngApp` is the easiest, and most common, way to bootstrap an application.
 *
 <example module="ngAppDemo">
   <file name="index.html">
   <div ng-controller="ngAppDemoController">
     I can add: {{a}} + {{b}} =  {{ a+b }}
   </div>
   </file>
   <file name="script.js">
   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
     $scope.a = 1;
     $scope.b = 2;
   });
   </file>
 </example>
 *
 */
function angularInit(element, bootstrap) {
  var elements = [element],
      appElement,
      module,
      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
      NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;

  function append(element) {
    element && elements.push(element);
  }

  forEach(names, function(name) {
    names[name] = true;
    append(document.getElementById(name));
    name = name.replace(':', '\\:');
    if (element.querySelectorAll) {
      forEach(element.querySelectorAll('.' + name), append);
      forEach(element.querySelectorAll('.' + name + '\\:'), append);
      forEach(element.querySelectorAll('[' + name + ']'), append);
    }
  });

  forEach(elements, function(element) {
    if (!appElement) {
      var className = ' ' + element.className + ' ';
      var match = NG_APP_CLASS_REGEXP.exec(className);
      if (match) {
        appElement = element;
        module = (match[2] || '').replace(/\s+/g, ',');
      } else {
        forEach(element.attributes, function(attr) {
          if (!appElement && names[attr.name]) {
            appElement = element;
            module = attr.value;
          }
        });
      }
    }
  });
  if (appElement) {
    bootstrap(appElement, module ? [module] : []);
  }
}

/**
 * @ngdoc function
 * @name angular.bootstrap
 * @module ng
 * @description
 * Use this function to manually start up angular application.
 *
 * See: {@link guide/bootstrap Bootstrap}
 *
 * Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.
 * They must use {@link ng.directive:ngApp ngApp}.
 *
 * Angular will detect if it has been loaded into the browser more than once and only allow the
 * first loaded script to be bootstrapped and will report a warning to the browser console for
 * each of the subsequent scripts. This prevents strange results in applications, where otherwise
 * multiple instances of Angular try to work on the DOM.
 *
 * <example name="multi-bootstrap" module="multi-bootstrap">
 * <file name="index.html">
 * <script src="../../../angular.js"></script>
 * <div ng-controller="BrokenTable">
 *   <table>
 *   <tr>
 *     <th ng-repeat="heading in headings">{{heading}}</th>
 *   </tr>
 *   <tr ng-repeat="filling in fillings">
 *     <td ng-repeat="fill in filling">{{fill}}</td>
 *   </tr>
 * </table>
 * </div>
 * </file>
 * <file name="controller.js">
 * var app = angular.module('multi-bootstrap', [])
 *
 * .controller('BrokenTable', function($scope) {
 *     $scope.headings = ['One', 'Two', 'Three'];
 *     $scope.fillings = [[1, 2, 3], ['A', 'B', 'C'], [7, 8, 9]];
 * });
 * </file>
 * <file name="protractor.js" type="protractor">
 * it('should only insert one table cell for each item in $scope.fillings', function() {
 *  expect(element.all(by.css('td')).count())
 *      .toBe(9);
 * });
 * </file>
 * </example>
 *
 * @param {DOMElement} element DOM element which is the root of angular application.
 * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
 *     Each item in the array should be the name of a predefined module or a (DI annotated)
 *     function that will be invoked by the injector as a run block.
 *     See: {@link angular.module modules}
 * @returns {auto.$injector} Returns the newly created injector for this app.
 */
function bootstrap(element, modules) {
  var doBootstrap = function() {
    element = jqLite(element);

    if (element.injector()) {
      var tag = (element[0] === document) ? 'document' : startingTag(element);
      //Encode angle brackets to prevent input from being sanitized to empty string #8683
      throw ngMinErr(
          'btstrpd',
          "App Already Bootstrapped with this Element '{0}'",
          tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
    }

    modules = modules || [];
    modules.unshift(['$provide', function($provide) {
      $provide.value('$rootElement', element);
    }]);
    modules.unshift('ng');
    var injector = createInjector(modules);
    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
       function(scope, element, compile, injector, animate) {
        scope.$apply(function() {
          element.data('$injector', injector);
          compile(element)(scope);
        });
      }]
    );
    return injector;
  };

  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;

  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
    return doBootstrap();
  }

  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
  angular.resumeBootstrap = function(extraModules) {
    forEach(extraModules, function(module) {
      modules.push(module);
    });
    doBootstrap();
  };
}

var SNAKE_CASE_REGEXP = /[A-Z]/g;
function snake_case(name, separator) {
  separator = separator || '_';
  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
    return (pos ? separator : '') + letter.toLowerCase();
  });
}

function bindJQuery() {
  // bind to jQuery if present;
  jQuery = window.jQuery;
  // Use jQuery if it exists with proper functionality, otherwise default to us.
  // Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.
  if (jQuery && jQuery.fn.on) {
    jqLite = jQuery;
    extend(jQuery.fn, {
      scope: JQLitePrototype.scope,
      isolateScope: JQLitePrototype.isolateScope,
      controller: JQLitePrototype.controller,
      injector: JQLitePrototype.injector,
      inheritedData: JQLitePrototype.inheritedData
    });
    // Method signature:
    //     jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
    jqLitePatchJQueryRemove('remove', true, true, false);
    jqLitePatchJQueryRemove('empty', false, false, false);
    jqLitePatchJQueryRemove('html', false, false, true);
  } else {
    jqLite = JQLite;
  }
  angular.element = jqLite;
}

/**
 * throw error if the argument is falsy.
 */
function assertArg(arg, name, reason) {
  if (!arg) {
    throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
  }
  return arg;
}

function assertArgFn(arg, name, acceptArrayAnnotation) {
  if (acceptArrayAnnotation && isArray(arg)) {
      arg = arg[arg.length - 1];
  }

  assertArg(isFunction(arg), name, 'not a function, got ' +
      (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
  return arg;
}

/**
 * throw error if the name given is hasOwnProperty
 * @param  {String} name    the name to test
 * @param  {String} context the context in which the name is used, such as module or directive
 */
function assertNotHasOwnProperty(name, context) {
  if (name === 'hasOwnProperty') {
    throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
  }
}

/**
 * Return the value accessible from the object by path. Any undefined traversals are ignored
 * @param {Object} obj starting object
 * @param {String} path path to traverse
 * @param {boolean} [bindFnToScope=true]
 * @returns {Object} value as accessible by path
 */
//TODO(misko): this function needs to be removed
function getter(obj, path, bindFnToScope) {
  if (!path) return obj;
  var keys = path.split('.');
  var key;
  var lastInstance = obj;
  var len = keys.length;

  for (var i = 0; i < len; i++) {
    key = keys[i];
    if (obj) {
      obj = (lastInstance = obj)[key];
    }
  }
  if (!bindFnToScope && isFunction(obj)) {
    return bind(lastInstance, obj);
  }
  return obj;
}

/**
 * Return the DOM siblings between the first and last node in the given array.
 * @param {Array} array like object
 * @returns {DOMElement} object containing the elements
 */
function getBlockElements(nodes) {
  var startNode = nodes[0],
      endNode = nodes[nodes.length - 1];
  if (startNode === endNode) {
    return jqLite(startNode);
  }

  var element = startNode;
  var elements = [element];

  do {
    element = element.nextSibling;
    if (!element) break;
    elements.push(element);
  } while (element !== endNode);

  return jqLite(elements);
}

/**
 * @ngdoc type
 * @name angular.Module
 * @module ng
 * @description
 *
 * Interface for configuring angular {@link angular.module modules}.
 */

function setupModuleLoader(window) {

  var $injectorMinErr = minErr('$injector');
  var ngMinErr = minErr('ng');

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  var angular = ensure(window, 'angular', Object);

  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
  angular.$$minErr = angular.$$minErr || minErr;

  return ensure(angular, 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @module ng
     * @description
     *
     * The `angular.module` is a global place for creating, registering and retrieving Angular
     * modules.
     * All modules (angular core or 3rd party) that should be available to an application must be
     * registered using this mechanism.
     *
     * When passed two or more arguments, a new module is created.  If passed only one argument, an
     * existing module (the name passed as the first argument to `module`) is retrieved.
     *
     *
     * # Module
     *
     * A module is a collection of services, directives, controllers, filters, and configuration information.
     * `angular.module` is used to configure the {@link auto.$injector $injector}.
     *
     * ```js
     * // Create a new module
     * var myModule = angular.module('myModule', []);
     *
     * // register a new service
     * myModule.value('appName', 'MyCoolApp');
     *
     * // configure existing services inside initialization blocks.
     * myModule.config(['$locationProvider', function($locationProvider) {
     *   // Configure existing providers
     *   $locationProvider.hashPrefix('!');
     * }]);
     * ```
     *
     * Then you can create an injector and load your modules like this:
     *
     * ```js
     * var injector = angular.injector(['ng', 'myModule'])
     * ```
     *
     * However it's more likely that you'll just use
     * {@link ng.directive:ngApp ngApp} or
     * {@link angular.bootstrap} to simplify this process for you.
     *
     * @param {!string} name The name of the module to create or retrieve.
     * @param {!Array.<string>=} requires If specified then new module is being created. If
     *        unspecified then the module is being retrieved for further configuration.
     * @param {Function=} configFn Optional configuration function for the module. Same as
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} new module with the {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      var assertNotHasOwnProperty = function(name, context) {
        if (name === 'hasOwnProperty') {
          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
        }
      };

      assertNotHasOwnProperty(name, 'module');
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
             "the module name or forgot to load it. If registering a module ensure that you " +
             "specify the dependencies as the second argument.", name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @module ng
           *
           * @description
           * Holds the list of modules which the injector will load before the current module is
           * loaded.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @module ng
           *
           * @description
           * Name of the module.
           */
          name: name,


          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @module ng
           * @param {string} name service name
           * @param {Function} providerType Construction function for creating new instance of the
           *                                service.
           * @description
           * See {@link auto.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @module ng
           * @param {string} name service name
           * @param {Function} providerFunction Function for creating new instance of the service.
           * @description
           * See {@link auto.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @module ng
           * @param {string} name service name
           * @param {Function} constructor A constructor function that will be instantiated.
           * @description
           * See {@link auto.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @module ng
           * @param {string} name service name
           * @param {*} object Service instance object.
           * @description
           * See {@link auto.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @module ng
           * @param {string} name constant name
           * @param {*} object Constant value.
           * @description
           * Because the constant are fixed, they get applied before other provide methods.
           * See {@link auto.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#animation
           * @module ng
           * @param {string} name animation name
           * @param {Function} animationFactory Factory function for creating new instance of an
           *                                    animation.
           * @description
           *
           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
           *
           *
           * Defines an animation hook that can be later used with
           * {@link ngAnimate.$animate $animate} service and directives that use this service.
           *
           * ```js
           * module.animation('.animation-name', function($inject1, $inject2) {
           *   return {
           *     eventName : function(element, done) {
           *       //code to run the animation
           *       //once complete, then run done()
           *       return function cancellationFunction(element) {
           *         //code to cancel the animation
           *       }
           *     }
           *   }
           * })
           * ```
           *
           * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
           * {@link ngAnimate ngAnimate module} for more information.
           */
          animation: invokeLater('$animateProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @module ng
           * @param {string} name Filter name.
           * @param {Function} filterFactory Factory function for creating new instance of filter.
           * @description
           * See {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @module ng
           * @param {string|Object} name Controller name, or an object map of controllers where the
           *    keys are the names and the values are the constructors.
           * @param {Function} constructor Controller constructor function.
           * @description
           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @module ng
           * @param {string|Object} name Directive name, or an object map of directives where the
           *    keys are the names and the values are the factories.
           * @param {Function} directiveFactory Factory function for creating new instance of
           * directives.
           * @description
           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @module ng
           * @param {Function} configFn Execute this function on module load. Useful for service
           *    configuration.
           * @description
           * Use this method to register work which needs to be performed on module loading.
           * For more about how to configure services, see
           * {@link providers#providers_provider-recipe Provider Recipe}.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @module ng
           * @param {Function} initializationFn Execute this function after injector creation.
           *    Useful for application initialization.
           * @description
           * Use this method to register work which should be performed when the injector is done
           * loading all modules.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          };
        }
      });
    };
  });

}

/* global angularModule: true,
  version: true,

  $LocaleProvider,
  $CompileProvider,

    htmlAnchorDirective,
    inputDirective,
    inputDirective,
    formDirective,
    scriptDirective,
    selectDirective,
    styleDirective,
    optionDirective,
    ngBindDirective,
    ngBindHtmlDirective,
    ngBindTemplateDirective,
    ngClassDirective,
    ngClassEvenDirective,
    ngClassOddDirective,
    ngCspDirective,
    ngCloakDirective,
    ngControllerDirective,
    ngFormDirective,
    ngHideDirective,
    ngIfDirective,
    ngIncludeDirective,
    ngIncludeFillContentDirective,
    ngInitDirective,
    ngNonBindableDirective,
    ngPluralizeDirective,
    ngRepeatDirective,
    ngShowDirective,
    ngStyleDirective,
    ngSwitchDirective,
    ngSwitchWhenDirective,
    ngSwitchDefaultDirective,
    ngOptionsDirective,
    ngTranscludeDirective,
    ngModelDirective,
    ngListDirective,
    ngChangeDirective,
    requiredDirective,
    requiredDirective,
    ngValueDirective,
    ngAttributeAliasDirectives,
    ngEventDirectives,

    $AnchorScrollProvider,
    $AnimateProvider,
    $BrowserProvider,
    $CacheFactoryProvider,
    $ControllerProvider,
    $DocumentProvider,
    $ExceptionHandlerProvider,
    $FilterProvider,
    $InterpolateProvider,
    $IntervalProvider,
    $HttpProvider,
    $HttpBackendProvider,
    $LocationProvider,
    $LogProvider,
    $ParseProvider,
    $RootScopeProvider,
    $QProvider,
    $$SanitizeUriProvider,
    $SceProvider,
    $SceDelegateProvider,
    $SnifferProvider,
    $TemplateCacheProvider,
    $TimeoutProvider,
    $$RAFProvider,
    $$AsyncCallbackProvider,
    $WindowProvider
*/


/**
 * @ngdoc object
 * @name angular.version
 * @module ng
 * @description
 * An object that contains information about the current AngularJS version. This object has the
 * following properties:
 *
 * - `full` – `{string}` – Full version string, such as "0.9.18".
 * - `major` – `{number}` – Major version number, such as "0".
 * - `minor` – `{number}` – Minor version number, such as "9".
 * - `dot` – `{number}` – Dot version number, such as "18".
 * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
 */
var version = {
  full: '1.2.28',    // all of these placeholder strings will be replaced by grunt's
  major: 1,    // package task
  minor: 2,
  dot: 28,
  codeName: 'finnish-disembarkation'
};


function publishExternalAPI(angular){
  extend(angular, {
    'bootstrap': bootstrap,
    'copy': copy,
    'extend': extend,
    'equals': equals,
    'element': jqLite,
    'forEach': forEach,
    'injector': createInjector,
    'noop': noop,
    'bind': bind,
    'toJson': toJson,
    'fromJson': fromJson,
    'identity': identity,
    'isUndefined': isUndefined,
    'isDefined': isDefined,
    'isString': isString,
    'isFunction': isFunction,
    'isObject': isObject,
    'isNumber': isNumber,
    'isElement': isElement,
    'isArray': isArray,
    'version': version,
    'isDate': isDate,
    'lowercase': lowercase,
    'uppercase': uppercase,
    'callbacks': {counter: 0},
    '$$minErr': minErr,
    '$$csp': csp
  });

  angularModule = setupModuleLoader(window);
  try {
    angularModule('ngLocale');
  } catch (e) {
    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
  }

  angularModule('ng', ['ngLocale'], ['$provide',
    function ngModule($provide) {
      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
      $provide.provider({
        $$sanitizeUri: $$SanitizeUriProvider
      });
      $provide.provider('$compile', $CompileProvider).
        directive({
            a: htmlAnchorDirective,
            input: inputDirective,
            textarea: inputDirective,
            form: formDirective,
            script: scriptDirective,
            select: selectDirective,
            style: styleDirective,
            option: optionDirective,
            ngBind: ngBindDirective,
            ngBindHtml: ngBindHtmlDirective,
            ngBindTemplate: ngBindTemplateDirective,
            ngClass: ngClassDirective,
            ngClassEven: ngClassEvenDirective,
            ngClassOdd: ngClassOddDirective,
            ngCloak: ngCloakDirective,
            ngController: ngControllerDirective,
            ngForm: ngFormDirective,
            ngHide: ngHideDirective,
            ngIf: ngIfDirective,
            ngInclude: ngIncludeDirective,
            ngInit: ngInitDirective,
            ngNonBindable: ngNonBindableDirective,
            ngPluralize: ngPluralizeDirective,
            ngRepeat: ngRepeatDirective,
            ngShow: ngShowDirective,
            ngStyle: ngStyleDirective,
            ngSwitch: ngSwitchDirective,
            ngSwitchWhen: ngSwitchWhenDirective,
            ngSwitchDefault: ngSwitchDefaultDirective,
            ngOptions: ngOptionsDirective,
            ngTransclude: ngTranscludeDirective,
            ngModel: ngModelDirective,
            ngList: ngListDirective,
            ngChange: ngChangeDirective,
            required: requiredDirective,
            ngRequired: requiredDirective,
            ngValue: ngValueDirective
        }).
        directive({
          ngInclude: ngIncludeFillContentDirective
        }).
        directive(ngAttributeAliasDirectives).
        directive(ngEventDirectives);
      $provide.provider({
        $anchorScroll: $AnchorScrollProvider,
        $animate: $AnimateProvider,
        $browser: $BrowserProvider,
        $cacheFactory: $CacheFactoryProvider,
        $controller: $ControllerProvider,
        $document: $DocumentProvider,
        $exceptionHandler: $ExceptionHandlerProvider,
        $filter: $FilterProvider,
        $interpolate: $InterpolateProvider,
        $interval: $IntervalProvider,
        $http: $HttpProvider,
        $httpBackend: $HttpBackendProvider,
        $location: $LocationProvider,
        $log: $LogProvider,
        $parse: $ParseProvider,
        $rootScope: $RootScopeProvider,
        $q: $QProvider,
        $sce: $SceProvider,
        $sceDelegate: $SceDelegateProvider,
        $sniffer: $SnifferProvider,
        $templateCache: $TemplateCacheProvider,
        $timeout: $TimeoutProvider,
        $window: $WindowProvider,
        $$rAF: $$RAFProvider,
        $$asyncCallback : $$AsyncCallbackProvider
      });
    }
  ]);
}

/* global JQLitePrototype: true,
  addEventListenerFn: true,
  removeEventListenerFn: true,
  BOOLEAN_ATTR: true
*/

//////////////////////////////////
//JQLite
//////////////////////////////////

/**
 * @ngdoc function
 * @name angular.element
 * @module ng
 * @kind function
 *
 * @description
 * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
 *
 * If jQuery is available, `angular.element` is an alias for the
 * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
 * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
 *
 * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
 * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
 * commonly needed functionality with the goal of having a very small footprint.</div>
 *
 * To use jQuery, simply load it before `DOMContentLoaded` event fired.
 *
 * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
 * jqLite; they are never raw DOM references.</div>
 *
 * ## Angular's jqLite
 * jqLite provides only the following jQuery methods:
 *
 * - [`addClass()`](http://api.jquery.com/addClass/)
 * - [`after()`](http://api.jquery.com/after/)
 * - [`append()`](http://api.jquery.com/append/)
 * - [`attr()`](http://api.jquery.com/attr/)
 * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
 * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
 * - [`clone()`](http://api.jquery.com/clone/)
 * - [`contents()`](http://api.jquery.com/contents/)
 * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyles()`
 * - [`data()`](http://api.jquery.com/data/)
 * - [`empty()`](http://api.jquery.com/empty/)
 * - [`eq()`](http://api.jquery.com/eq/)
 * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
 * - [`hasClass()`](http://api.jquery.com/hasClass/)
 * - [`html()`](http://api.jquery.com/html/)
 * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
 * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
 * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
 * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
 * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
 * - [`prepend()`](http://api.jquery.com/prepend/)
 * - [`prop()`](http://api.jquery.com/prop/)
 * - [`ready()`](http://api.jquery.com/ready/)
 * - [`remove()`](http://api.jquery.com/remove/)
 * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
 * - [`removeClass()`](http://api.jquery.com/removeClass/)
 * - [`removeData()`](http://api.jquery.com/removeData/)
 * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
 * - [`text()`](http://api.jquery.com/text/)
 * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
 * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
 * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
 * - [`val()`](http://api.jquery.com/val/)
 * - [`wrap()`](http://api.jquery.com/wrap/)
 *
 * ## jQuery/jqLite Extras
 * Angular also provides the following additional methods and events to both jQuery and jqLite:
 *
 * ### Events
 * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
 *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM
 *    element before it is removed.
 *
 * ### Methods
 * - `controller(name)` - retrieves the controller of the current element or its parent. By default
 *   retrieves controller associated with the `ngController` directive. If `name` is provided as
 *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
 *   `'ngModel'`).
 * - `injector()` - retrieves the injector of the current element or its parent.
 * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
 *   element or its parent.
 * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
 *   current element. This getter should be used only on elements that contain a directive which starts a new isolate
 *   scope. Calling `scope()` on this element always returns the original non-isolate scope.
 * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
 *   parent element is reached.
 *
 * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
 * @returns {Object} jQuery object.
 */

JQLite.expando = 'ng339';

var jqCache = JQLite.cache = {},
    jqId = 1,
    addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) {element.addEventListener(type, fn, false);}
      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),
    removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
      : function(element, type, fn) {element.detachEvent('on' + type, fn); });

/*
 * !!! This is an undocumented "private" function !!!
 */
var jqData = JQLite._data = function(node) {
  //jQuery always returns an object on cache miss
  return this.cache[node[this.expando]] || {};
};

function jqNextId() { return ++jqId; }


var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
var MOZ_HACK_REGEXP = /^moz([A-Z])/;
var jqLiteMinErr = minErr('jqLite');

/**
 * Converts snake_case to camelCase.
 * Also there is special case for Moz prefix starting with upper case letter.
 * @param name Name to normalize
 */
function camelCase(name) {
  return name.
    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
      return offset ? letter.toUpperCase() : letter;
    }).
    replace(MOZ_HACK_REGEXP, 'Moz$1');
}

/////////////////////////////////////////////
// jQuery mutation patch
//
// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
// $destroy event on all DOM nodes being removed.
//
/////////////////////////////////////////////

function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {
  var originalJqFn = jQuery.fn[name];
  originalJqFn = originalJqFn.$original || originalJqFn;
  removePatch.$original = originalJqFn;
  jQuery.fn[name] = removePatch;

  function removePatch(param) {
    // jshint -W040
    var list = filterElems && param ? [this.filter(param)] : [this],
        fireEvent = dispatchThis,
        set, setIndex, setLength,
        element, childIndex, childLength, children;

    if (!getterIfNoArguments || param != null) {
      while(list.length) {
        set = list.shift();
        for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
          element = jqLite(set[setIndex]);
          if (fireEvent) {
            element.triggerHandler('$destroy');
          } else {
            fireEvent = !fireEvent;
          }
          for(childIndex = 0, childLength = (children = element.children()).length;
              childIndex < childLength;
              childIndex++) {
            list.push(jQuery(children[childIndex]));
          }
        }
      }
    }
    return originalJqFn.apply(this, arguments);
  }
}

var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
var HTML_REGEXP = /<|&#?\w+;/;
var TAG_NAME_REGEXP = /<([\w:]+)/;
var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;

var wrapMap = {
  'option': [1, '<select multiple="multiple">', '</select>'],

  'thead': [1, '<table>', '</table>'],
  'col': [2, '<table><colgroup>', '</colgroup></table>'],
  'tr': [2, '<table><tbody>', '</tbody></table>'],
  'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
  '_default': [0, "", ""]
};

wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

function jqLiteIsTextNode(html) {
  return !HTML_REGEXP.test(html);
}

function jqLiteBuildFragment(html, context) {
  var elem, tmp, tag, wrap,
      fragment = context.createDocumentFragment(),
      nodes = [], i, j, jj;

  if (jqLiteIsTextNode(html)) {
    // Convert non-html into a text node
    nodes.push(context.createTextNode(html));
  } else {
    tmp = fragment.appendChild(context.createElement('div'));
    // Convert html into DOM nodes
    tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
    wrap = wrapMap[tag] || wrapMap._default;
    tmp.innerHTML = '<div>&#160;</div>' +
      wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
    tmp.removeChild(tmp.firstChild);

    // Descend through wrappers to the right content
    i = wrap[0];
    while (i--) {
      tmp = tmp.lastChild;
    }

    for (j=0, jj=tmp.childNodes.length; j<jj; ++j) nodes.push(tmp.childNodes[j]);

    tmp = fragment.firstChild;
    tmp.textContent = "";
  }

  // Remove wrapper from fragment
  fragment.textContent = "";
  fragment.innerHTML = ""; // Clear inner HTML
  return nodes;
}

function jqLiteParseHTML(html, context) {
  context = context || document;
  var parsed;

  if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
    return [context.createElement(parsed[1])];
  }

  return jqLiteBuildFragment(html, context);
}

/////////////////////////////////////////////
function JQLite(element) {
  if (element instanceof JQLite) {
    return element;
  }
  if (isString(element)) {
    element = trim(element);
  }
  if (!(this instanceof JQLite)) {
    if (isString(element) && element.charAt(0) != '<') {
      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
    }
    return new JQLite(element);
  }

  if (isString(element)) {
    jqLiteAddNodes(this, jqLiteParseHTML(element));
    var fragment = jqLite(document.createDocumentFragment());
    fragment.append(this);
  } else {
    jqLiteAddNodes(this, element);
  }
}

function jqLiteClone(element) {
  return element.cloneNode(true);
}

function jqLiteDealoc(element){
  jqLiteRemoveData(element);
  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
    jqLiteDealoc(children[i]);
  }
}

function jqLiteOff(element, type, fn, unsupported) {
  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');

  var events = jqLiteExpandoStore(element, 'events'),
      handle = jqLiteExpandoStore(element, 'handle');

  if (!handle) return; //no listeners registered

  if (isUndefined(type)) {
    forEach(events, function(eventHandler, type) {
      removeEventListenerFn(element, type, eventHandler);
      delete events[type];
    });
  } else {
    forEach(type.split(' '), function(type) {
      if (isUndefined(fn)) {
        removeEventListenerFn(element, type, events[type]);
        delete events[type];
      } else {
        arrayRemove(events[type] || [], fn);
      }
    });
  }
}

function jqLiteRemoveData(element, name) {
  var expandoId = element.ng339,
      expandoStore = jqCache[expandoId];

  if (expandoStore) {
    if (name) {
      delete jqCache[expandoId].data[name];
      return;
    }

    if (expandoStore.handle) {
      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
      jqLiteOff(element);
    }
    delete jqCache[expandoId];
    element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
  }
}

function jqLiteExpandoStore(element, key, value) {
  var expandoId = element.ng339,
      expandoStore = jqCache[expandoId || -1];

  if (isDefined(value)) {
    if (!expandoStore) {
      element.ng339 = expandoId = jqNextId();
      expandoStore = jqCache[expandoId] = {};
    }
    expandoStore[key] = value;
  } else {
    return expandoStore && expandoStore[key];
  }
}

function jqLiteData(element, key, value) {
  var data = jqLiteExpandoStore(element, 'data'),
      isSetter = isDefined(value),
      keyDefined = !isSetter && isDefined(key),
      isSimpleGetter = keyDefined && !isObject(key);

  if (!data && !isSimpleGetter) {
    jqLiteExpandoStore(element, 'data', data = {});
  }

  if (isSetter) {
    data[key] = value;
  } else {
    if (keyDefined) {
      if (isSimpleGetter) {
        // don't create data in this case.
        return data && data[key];
      } else {
        extend(data, key);
      }
    } else {
      return data;
    }
  }
}

function jqLiteHasClass(element, selector) {
  if (!element.getAttribute) return false;
  return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
      indexOf( " " + selector + " " ) > -1);
}

function jqLiteRemoveClass(element, cssClasses) {
  if (cssClasses && element.setAttribute) {
    forEach(cssClasses.split(' '), function(cssClass) {
      element.setAttribute('class', trim(
          (" " + (element.getAttribute('class') || '') + " ")
          .replace(/[\n\t]/g, " ")
          .replace(" " + trim(cssClass) + " ", " "))
      );
    });
  }
}

function jqLiteAddClass(element, cssClasses) {
  if (cssClasses && element.setAttribute) {
    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
                            .replace(/[\n\t]/g, " ");

    forEach(cssClasses.split(' '), function(cssClass) {
      cssClass = trim(cssClass);
      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
        existingClasses += cssClass + ' ';
      }
    });

    element.setAttribute('class', trim(existingClasses));
  }
}

function jqLiteAddNodes(root, elements) {
  if (elements) {
    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
      ? elements
      : [ elements ];
    for(var i=0; i < elements.length; i++) {
      root.push(elements[i]);
    }
  }
}

function jqLiteController(element, name) {
  return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
}

function jqLiteInheritedData(element, name, value) {
  // if element is the document object work with the html element instead
  // this makes $(document).scope() possible
  if(element.nodeType == 9) {
    element = element.documentElement;
  }
  var names = isArray(name) ? name : [name];

  while (element) {
    for (var i = 0, ii = names.length; i < ii; i++) {
      if ((value = jqLite.data(element, names[i])) !== undefined) return value;
    }

    // If dealing with a document fragment node with a host element, and no parent, use the host
    // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
    // to lookup parent controllers.
    element = element.parentNode || (element.nodeType === 11 && element.host);
  }
}

function jqLiteEmpty(element) {
  for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
    jqLiteDealoc(childNodes[i]);
  }
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

//////////////////////////////////////////
// Functions which are declared directly.
//////////////////////////////////////////
var JQLitePrototype = JQLite.prototype = {
  ready: function(fn) {
    var fired = false;

    function trigger() {
      if (fired) return;
      fired = true;
      fn();
    }

    // check if document already is loaded
    if (document.readyState === 'complete'){
      setTimeout(trigger);
    } else {
      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
      // we can not use jqLite since we are not done loading and jQuery could be loaded later.
      // jshint -W064
      JQLite(window).on('load', trigger); // fallback to window.onload for others
      // jshint +W064
    }
  },
  toString: function() {
    var value = [];
    forEach(this, function(e){ value.push('' + e);});
    return '[' + value.join(', ') + ']';
  },

  eq: function(index) {
      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
  },

  length: 0,
  push: push,
  sort: [].sort,
  splice: [].splice
};

//////////////////////////////////////////
// Functions iterating getter/setters.
// these functions return self on setter and
// value on get.
//////////////////////////////////////////
var BOOLEAN_ATTR = {};
forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
  BOOLEAN_ATTR[lowercase(value)] = value;
});
var BOOLEAN_ELEMENTS = {};
forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
  BOOLEAN_ELEMENTS[uppercase(value)] = true;
});

function getBooleanAttrName(element, name) {
  // check dom last since we will most likely fail on name
  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];

  // booleanAttr is here twice to minimize DOM access
  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
}

forEach({
  data: jqLiteData,
  removeData: jqLiteRemoveData
}, function(fn, name) {
  JQLite[name] = fn;
});

forEach({
  data: jqLiteData,
  inheritedData: jqLiteInheritedData,

  scope: function(element) {
    // Can't use jqLiteData here directly so we stay compatible with jQuery!
    return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
  },

  isolateScope: function(element) {
    // Can't use jqLiteData here directly so we stay compatible with jQuery!
    return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
  },

  controller: jqLiteController,

  injector: function(element) {
    return jqLiteInheritedData(element, '$injector');
  },

  removeAttr: function(element,name) {
    element.removeAttribute(name);
  },

  hasClass: jqLiteHasClass,

  css: function(element, name, value) {
    name = camelCase(name);

    if (isDefined(value)) {
      element.style[name] = value;
    } else {
      var val;

      if (msie <= 8) {
        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
        val = element.currentStyle && element.currentStyle[name];
        if (val === '') val = 'auto';
      }

      val = val || element.style[name];

      if (msie <= 8) {
        // jquery weirdness :-/
        val = (val === '') ? undefined : val;
      }

      return  val;
    }
  },

  attr: function(element, name, value){
    var lowercasedName = lowercase(name);
    if (BOOLEAN_ATTR[lowercasedName]) {
      if (isDefined(value)) {
        if (!!value) {
          element[name] = true;
          element.setAttribute(name, lowercasedName);
        } else {
          element[name] = false;
          element.removeAttribute(lowercasedName);
        }
      } else {
        return (element[name] ||
                 (element.attributes.getNamedItem(name)|| noop).specified)
               ? lowercasedName
               : undefined;
      }
    } else if (isDefined(value)) {
      element.setAttribute(name, value);
    } else if (element.getAttribute) {
      // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
      // some elements (e.g. Document) don't have get attribute, so return undefined
      var ret = element.getAttribute(name, 2);
      // normalize non-existing attributes to undefined (as jQuery)
      return ret === null ? undefined : ret;
    }
  },

  prop: function(element, name, value) {
    if (isDefined(value)) {
      element[name] = value;
    } else {
      return element[name];
    }
  },

  text: (function() {
    var NODE_TYPE_TEXT_PROPERTY = [];
    if (msie < 9) {
      NODE_TYPE_TEXT_PROPERTY[1] = 'innerText';    /** Element **/
      NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue';    /** Text **/
    } else {
      NODE_TYPE_TEXT_PROPERTY[1] =                 /** Element **/
      NODE_TYPE_TEXT_PROPERTY[3] = 'textContent';  /** Text **/
    }
    getText.$dv = '';
    return getText;

    function getText(element, value) {
      var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];
      if (isUndefined(value)) {
        return textProp ? element[textProp] : '';
      }
      element[textProp] = value;
    }
  })(),

  val: function(element, value) {
    if (isUndefined(value)) {
      if (nodeName_(element) === 'SELECT' && element.multiple) {
        var result = [];
        forEach(element.options, function (option) {
          if (option.selected) {
            result.push(option.value || option.text);
          }
        });
        return result.length === 0 ? null : result;
      }
      return element.value;
    }
    element.value = value;
  },

  html: function(element, value) {
    if (isUndefined(value)) {
      return element.innerHTML;
    }
    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
      jqLiteDealoc(childNodes[i]);
    }
    element.innerHTML = value;
  },

  empty: jqLiteEmpty
}, function(fn, name){
  /**
   * Properties: writes return selection, reads return first value
   */
  JQLite.prototype[name] = function(arg1, arg2) {
    var i, key;
    var nodeCount = this.length;

    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
    // in a way that survives minification.
    // jqLiteEmpty takes no arguments but is a setter.
    if (fn !== jqLiteEmpty &&
        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
      if (isObject(arg1)) {

        // we are a write, but the object properties are the key/values
        for (i = 0; i < nodeCount; i++) {
          if (fn === jqLiteData) {
            // data() takes the whole object in jQuery
            fn(this[i], arg1);
          } else {
            for (key in arg1) {
              fn(this[i], key, arg1[key]);
            }
          }
        }
        // return self for chaining
        return this;
      } else {
        // we are a read, so read the first child.
        // TODO: do we still need this?
        var value = fn.$dv;
        // Only if we have $dv do we iterate over all, otherwise it is just the first element.
        var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
        for (var j = 0; j < jj; j++) {
          var nodeValue = fn(this[j], arg1, arg2);
          value = value ? value + nodeValue : nodeValue;
        }
        return value;
      }
    } else {
      // we are a write, so apply to all children
      for (i = 0; i < nodeCount; i++) {
        fn(this[i], arg1, arg2);
      }
      // return self for chaining
      return this;
    }
  };
});

function createEventHandler(element, events) {
  var eventHandler = function (event, type) {
    if (!event.preventDefault) {
      event.preventDefault = function() {
        event.returnValue = false; //ie
      };
    }

    if (!event.stopPropagation) {
      event.stopPropagation = function() {
        event.cancelBubble = true; //ie
      };
    }

    if (!event.target) {
      event.target = event.srcElement || document;
    }

    if (isUndefined(event.defaultPrevented)) {
      var prevent = event.preventDefault;
      event.preventDefault = function() {
        event.defaultPrevented = true;
        prevent.call(event);
      };
      event.defaultPrevented = false;
    }

    event.isDefaultPrevented = function() {
      return event.defaultPrevented || event.returnValue === false;
    };

    // Copy event handlers in case event handlers array is modified during execution.
    var eventHandlersCopy = shallowCopy(events[type || event.type] || []);

    forEach(eventHandlersCopy, function(fn) {
      fn.call(element, event);
    });

    // Remove monkey-patched methods (IE),
    // as they would cause memory leaks in IE8.
    if (msie <= 8) {
      // IE7/8 does not allow to delete property on native object
      event.preventDefault = null;
      event.stopPropagation = null;
      event.isDefaultPrevented = null;
    } else {
      // It shouldn't affect normal browsers (native methods are defined on prototype).
      delete event.preventDefault;
      delete event.stopPropagation;
      delete event.isDefaultPrevented;
    }
  };
  eventHandler.elem = element;
  return eventHandler;
}

//////////////////////////////////////////
// Functions iterating traversal.
// These functions chain results into a single
// selector.
//////////////////////////////////////////
forEach({
  removeData: jqLiteRemoveData,

  dealoc: jqLiteDealoc,

  on: function onFn(element, type, fn, unsupported){
    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');

    var events = jqLiteExpandoStore(element, 'events'),
        handle = jqLiteExpandoStore(element, 'handle');

    if (!events) jqLiteExpandoStore(element, 'events', events = {});
    if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));

    forEach(type.split(' '), function(type){
      var eventFns = events[type];

      if (!eventFns) {
        if (type == 'mouseenter' || type == 'mouseleave') {
          var contains = document.body.contains || document.body.compareDocumentPosition ?
          function( a, b ) {
            // jshint bitwise: false
            var adown = a.nodeType === 9 ? a.documentElement : a,
            bup = b && b.parentNode;
            return a === bup || !!( bup && bup.nodeType === 1 && (
              adown.contains ?
              adown.contains( bup ) :
              a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
              ));
            } :
            function( a, b ) {
              if ( b ) {
                while ( (b = b.parentNode) ) {
                  if ( b === a ) {
                    return true;
                  }
                }
              }
              return false;
            };

          events[type] = [];

          // Refer to jQuery's implementation of mouseenter & mouseleave
          // Read about mouseenter and mouseleave:
          // http://www.quirksmode.org/js/events_mouse.html#link8
          var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"};

          onFn(element, eventmap[type], function(event) {
            var target = this, related = event.relatedTarget;
            // For mousenter/leave call the handler if related is outside the target.
            // NB: No relatedTarget if the mouse left/entered the browser window
            if ( !related || (related !== target && !contains(target, related)) ){
              handle(event, type);
            }
          });

        } else {
          addEventListenerFn(element, type, handle);
          events[type] = [];
        }
        eventFns = events[type];
      }
      eventFns.push(fn);
    });
  },

  off: jqLiteOff,

  one: function(element, type, fn) {
    element = jqLite(element);

    //add the listener twice so that when it is called
    //you can remove the original function and still be
    //able to call element.off(ev, fn) normally
    element.on(type, function onFn() {
      element.off(type, fn);
      element.off(type, onFn);
    });
    element.on(type, fn);
  },

  replaceWith: function(element, replaceNode) {
    var index, parent = element.parentNode;
    jqLiteDealoc(element);
    forEach(new JQLite(replaceNode), function(node){
      if (index) {
        parent.insertBefore(node, index.nextSibling);
      } else {
        parent.replaceChild(node, element);
      }
      index = node;
    });
  },

  children: function(element) {
    var children = [];
    forEach(element.childNodes, function(element){
      if (element.nodeType === 1)
        children.push(element);
    });
    return children;
  },

  contents: function(element) {
    return element.contentDocument || element.childNodes || [];
  },

  append: function(element, node) {
    forEach(new JQLite(node), function(child){
      if (element.nodeType === 1 || element.nodeType === 11) {
        element.appendChild(child);
      }
    });
  },

  prepend: function(element, node) {
    if (element.nodeType === 1) {
      var index = element.firstChild;
      forEach(new JQLite(node), function(child){
        element.insertBefore(child, index);
      });
    }
  },

  wrap: function(element, wrapNode) {
    wrapNode = jqLite(wrapNode)[0];
    var parent = element.parentNode;
    if (parent) {
      parent.replaceChild(wrapNode, element);
    }
    wrapNode.appendChild(element);
  },

  remove: function(element) {
    jqLiteDealoc(element);
    var parent = element.parentNode;
    if (parent) parent.removeChild(element);
  },

  after: function(element, newElement) {
    var index = element, parent = element.parentNode;
    forEach(new JQLite(newElement), function(node){
      parent.insertBefore(node, index.nextSibling);
      index = node;
    });
  },

  addClass: jqLiteAddClass,
  removeClass: jqLiteRemoveClass,

  toggleClass: function(element, selector, condition) {
    if (selector) {
      forEach(selector.split(' '), function(className){
        var classCondition = condition;
        if (isUndefined(classCondition)) {
          classCondition = !jqLiteHasClass(element, className);
        }
        (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
      });
    }
  },

  parent: function(element) {
    var parent = element.parentNode;
    return parent && parent.nodeType !== 11 ? parent : null;
  },

  next: function(element) {
    if (element.nextElementSibling) {
      return element.nextElementSibling;
    }

    // IE8 doesn't have nextElementSibling
    var elm = element.nextSibling;
    while (elm != null && elm.nodeType !== 1) {
      elm = elm.nextSibling;
    }
    return elm;
  },

  find: function(element, selector) {
    if (element.getElementsByTagName) {
      return element.getElementsByTagName(selector);
    } else {
      return [];
    }
  },

  clone: jqLiteClone,

  triggerHandler: function(element, event, extraParameters) {

    var dummyEvent, eventFnsCopy, handlerArgs;
    var eventName = event.type || event;
    var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName];

    if (eventFns) {

      // Create a dummy event to pass to the handlers
      dummyEvent = {
        preventDefault: function() { this.defaultPrevented = true; },
        isDefaultPrevented: function() { return this.defaultPrevented === true; },
        stopPropagation: noop,
        type: eventName,
        target: element
      };

      // If a custom event was provided then extend our dummy event with it
      if (event.type) {
        dummyEvent = extend(dummyEvent, event);
      }

      // Copy event handlers in case event handlers array is modified during execution.
      eventFnsCopy = shallowCopy(eventFns);
      handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];

      forEach(eventFnsCopy, function(fn) {
        fn.apply(element, handlerArgs);
      });

    }
  }
}, function(fn, name){
  /**
   * chaining functions
   */
  JQLite.prototype[name] = function(arg1, arg2, arg3) {
    var value;
    for(var i=0; i < this.length; i++) {
      if (isUndefined(value)) {
        value = fn(this[i], arg1, arg2, arg3);
        if (isDefined(value)) {
          // any function which returns a value needs to be wrapped
          value = jqLite(value);
        }
      } else {
        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
      }
    }
    return isDefined(value) ? value : this;
  };

  // bind legacy bind/unbind to on/off
  JQLite.prototype.bind = JQLite.prototype.on;
  JQLite.prototype.unbind = JQLite.prototype.off;
});

/**
 * Computes a hash of an 'obj'.
 * Hash of a:
 *  string is string
 *  number is number as string
 *  object is either result of calling $$hashKey function on the object or uniquely generated id,
 *         that is also assigned to the $$hashKey property of the object.
 *
 * @param obj
 * @returns {string} hash string such that the same input will have the same hash string.
 *         The resulting string key is in 'type:hashKey' format.
 */
function hashKey(obj, nextUidFn) {
  var objType = typeof obj,
      key;

  if (objType == 'function' || (objType == 'object' && obj !== null)) {
    if (typeof (key = obj.$$hashKey) == 'function') {
      // must invoke on object to keep the right this
      key = obj.$$hashKey();
    } else if (key === undefined) {
      key = obj.$$hashKey = (nextUidFn || nextUid)();
    }
  } else {
    key = obj;
  }

  return objType + ':' + key;
}

/**
 * HashMap which can use objects as keys
 */
function HashMap(array, isolatedUid) {
  if (isolatedUid) {
    var uid = 0;
    this.nextUid = function() {
      return ++uid;
    };
  }
  forEach(array, this.put, this);
}
HashMap.prototype = {
  /**
   * Store key value pair
   * @param key key to store can be any type
   * @param value value to store can be any type
   */
  put: function(key, value) {
    this[hashKey(key, this.nextUid)] = value;
  },

  /**
   * @param key
   * @returns {Object} the value for the key
   */
  get: function(key) {
    return this[hashKey(key, this.nextUid)];
  },

  /**
   * Remove the key/value pair
   * @param key
   */
  remove: function(key) {
    var value = this[key = hashKey(key, this.nextUid)];
    delete this[key];
    return value;
  }
};

/**
 * @ngdoc function
 * @module ng
 * @name angular.injector
 * @kind function
 *
 * @description
 * Creates an injector object that can be used for retrieving services as well as for
 * dependency injection (see {@link guide/di dependency injection}).
 *

 * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
 *        {@link angular.module}. The `ng` module must be explicitly added.
 * @returns {injector} Injector object. See {@link auto.$injector $injector}.
 *
 * @example
 * Typical usage
 * ```js
 *   // create an injector
 *   var $injector = angular.injector(['ng']);
 *
 *   // use the injector to kick off your application
 *   // use the type inference to auto inject arguments, or use implicit injection
 *   $injector.invoke(function($rootScope, $compile, $document){
 *     $compile($document)($rootScope);
 *     $rootScope.$digest();
 *   });
 * ```
 *
 * Sometimes you want to get access to the injector of a currently running Angular app
 * from outside Angular. Perhaps, you want to inject and compile some markup after the
 * application has been bootstrapped. You can do this using the extra `injector()` added
 * to JQuery/jqLite elements. See {@link angular.element}.
 *
 * *This is fairly rare but could be the case if a third party library is injecting the
 * markup.*
 *
 * In the following example a new block of HTML containing a `ng-controller`
 * directive is added to the end of the document body by JQuery. We then compile and link
 * it into the current AngularJS scope.
 *
 * ```js
 * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
 * $(document.body).append($div);
 *
 * angular.element(document).injector().invoke(function($compile) {
 *   var scope = angular.element($div).scope();
 *   $compile($div)(scope);
 * });
 * ```
 */


/**
 * @ngdoc module
 * @name auto
 * @description
 *
 * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
 */

var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var $injectorMinErr = minErr('$injector');
function annotate(fn) {
  var $inject,
      fnText,
      argDecl,
      last;

  if (typeof fn === 'function') {
    if (!($inject = fn.$inject)) {
      $inject = [];
      if (fn.length) {
        fnText = fn.toString().replace(STRIP_COMMENTS, '');
        argDecl = fnText.match(FN_ARGS);
        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
          arg.replace(FN_ARG, function(all, underscore, name){
            $inject.push(name);
          });
        });
      }
      fn.$inject = $inject;
    }
  } else if (isArray(fn)) {
    last = fn.length - 1;
    assertArgFn(fn[last], 'fn');
    $inject = fn.slice(0, last);
  } else {
    assertArgFn(fn, 'fn', true);
  }
  return $inject;
}

///////////////////////////////////////

/**
 * @ngdoc service
 * @name $injector
 *
 * @description
 *
 * `$injector` is used to retrieve object instances as defined by
 * {@link auto.$provide provider}, instantiate types, invoke methods,
 * and load modules.
 *
 * The following always holds true:
 *
 * ```js
 *   var $injector = angular.injector();
 *   expect($injector.get('$injector')).toBe($injector);
 *   expect($injector.invoke(function($injector){
 *     return $injector;
 *   })).toBe($injector);
 * ```
 *
 * # Injection Function Annotation
 *
 * JavaScript does not have annotations, and annotations are needed for dependency injection. The
 * following are all valid ways of annotating function with injection arguments and are equivalent.
 *
 * ```js
 *   // inferred (only works if code not minified/obfuscated)
 *   $injector.invoke(function(serviceA){});
 *
 *   // annotated
 *   function explicit(serviceA) {};
 *   explicit.$inject = ['serviceA'];
 *   $injector.invoke(explicit);
 *
 *   // inline
 *   $injector.invoke(['serviceA', function(serviceA){}]);
 * ```
 *
 * ## Inference
 *
 * In JavaScript calling `toString()` on a function returns the function definition. The definition
 * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with
 * minification, and obfuscation tools since these tools change the argument names.
 *
 * ## `$inject` Annotation
 * By adding an `$inject` property onto a function the injection parameters can be specified.
 *
 * ## Inline
 * As an array of injection names, where the last item in the array is the function to call.
 */

/**
 * @ngdoc method
 * @name $injector#get
 *
 * @description
 * Return an instance of the service.
 *
 * @param {string} name The name of the instance to retrieve.
 * @return {*} The instance.
 */

/**
 * @ngdoc method
 * @name $injector#invoke
 *
 * @description
 * Invoke the method and supply the method arguments from the `$injector`.
 *
 * @param {!Function} fn The function to invoke. Function parameters are injected according to the
 *   {@link guide/di $inject Annotation} rules.
 * @param {Object=} self The `this` for the invoked method.
 * @param {Object=} locals Optional object. If preset then any argument names are read from this
 *                         object first, before the `$injector` is consulted.
 * @returns {*} the value returned by the invoked `fn` function.
 */

/**
 * @ngdoc method
 * @name $injector#has
 *
 * @description
 * Allows the user to query if the particular service exists.
 *
 * @param {string} name Name of the service to query.
 * @returns {boolean} `true` if injector has given service.
 */

/**
 * @ngdoc method
 * @name $injector#instantiate
 * @description
 * Create a new instance of JS type. The method takes a constructor function, invokes the new
 * operator, and supplies all of the arguments to the constructor function as specified by the
 * constructor annotation.
 *
 * @param {Function} Type Annotated constructor function.
 * @param {Object=} locals Optional object. If preset then any argument names are read from this
 * object first, before the `$injector` is consulted.
 * @returns {Object} new instance of `Type`.
 */

/**
 * @ngdoc method
 * @name $injector#annotate
 *
 * @description
 * Returns an array of service names which the function is requesting for injection. This API is
 * used by the injector to determine which services need to be injected into the function when the
 * function is invoked. There are three ways in which the function can be annotated with the needed
 * dependencies.
 *
 * # Argument names
 *
 * The simplest form is to extract the dependencies from the arguments of the function. This is done
 * by converting the function into a string using `toString()` method and extracting the argument
 * names.
 * ```js
 *   // Given
 *   function MyController($scope, $route) {
 *     // ...
 *   }
 *
 *   // Then
 *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
 * ```
 *
 * This method does not work with code minification / obfuscation. For this reason the following
 * annotation strategies are supported.
 *
 * # The `$inject` property
 *
 * If a function has an `$inject` property and its value is an array of strings, then the strings
 * represent names of services to be injected into the function.
 * ```js
 *   // Given
 *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
 *     // ...
 *   }
 *   // Define function dependencies
 *   MyController['$inject'] = ['$scope', '$route'];
 *
 *   // Then
 *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
 * ```
 *
 * # The array notation
 *
 * It is often desirable to inline Injected functions and that's when setting the `$inject` property
 * is very inconvenient. In these situations using the array notation to specify the dependencies in
 * a way that survives minification is a better choice:
 *
 * ```js
 *   // We wish to write this (not minification / obfuscation safe)
 *   injector.invoke(function($compile, $rootScope) {
 *     // ...
 *   });
 *
 *   // We are forced to write break inlining
 *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
 *     // ...
 *   };
 *   tmpFn.$inject = ['$compile', '$rootScope'];
 *   injector.invoke(tmpFn);
 *
 *   // To better support inline function the inline annotation is supported
 *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
 *     // ...
 *   }]);
 *
 *   // Therefore
 *   expect(injector.annotate(
 *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
 *    ).toEqual(['$compile', '$rootScope']);
 * ```
 *
 * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
 * be retrieved as described above.
 *
 * @returns {Array.<string>} The names of the services which the function requires.
 */




/**
 * @ngdoc service
 * @name $provide
 *
 * @description
 *
 * The {@link auto.$provide $provide} service has a number of methods for registering components
 * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
 * {@link angular.Module}.
 *
 * An Angular **service** is a singleton object created by a **service factory**.  These **service
 * factories** are functions which, in turn, are created by a **service provider**.
 * The **service providers** are constructor functions. When instantiated they must contain a
 * property called `$get`, which holds the **service factory** function.
 *
 * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
 * correct **service provider**, instantiating it and then calling its `$get` **service factory**
 * function to get the instance of the **service**.
 *
 * Often services have no configuration options and there is no need to add methods to the service
 * provider.  The provider will be no more than a constructor function with a `$get` property. For
 * these cases the {@link auto.$provide $provide} service has additional helper methods to register
 * services without specifying a provider.
 *
 * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
 *     {@link auto.$injector $injector}
 * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
 *     providers and services.
 * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
 *     services, not providers.
 * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
 *     that will be wrapped in a **service provider** object, whose `$get` property will contain the
 *     given factory function.
 * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
 *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate
 *      a new object using the given constructor function.
 *
 * See the individual methods for more information and examples.
 */

/**
 * @ngdoc method
 * @name $provide#provider
 * @description
 *
 * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
 * are constructor functions, whose instances are responsible for "providing" a factory for a
 * service.
 *
 * Service provider names start with the name of the service they provide followed by `Provider`.
 * For example, the {@link ng.$log $log} service has a provider called
 * {@link ng.$logProvider $logProvider}.
 *
 * Service provider objects can have additional methods which allow configuration of the provider
 * and its service. Importantly, you can configure what kind of service is created by the `$get`
 * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
 * method {@link ng.$logProvider#debugEnabled debugEnabled}
 * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
 * console or not.
 *
 * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
                        'Provider'` key.
 * @param {(Object|function())} provider If the provider is:
 *
 *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
 *     {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
 *   - `Constructor`: a new instance of the provider will be created using
 *     {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
 *
 * @returns {Object} registered provider instance

 * @example
 *
 * The following example shows how to create a simple event tracking service and register it using
 * {@link auto.$provide#provider $provide.provider()}.
 *
 * ```js
 *  // Define the eventTracker provider
 *  function EventTrackerProvider() {
 *    var trackingUrl = '/track';
 *
 *    // A provider method for configuring where the tracked events should been saved
 *    this.setTrackingUrl = function(url) {
 *      trackingUrl = url;
 *    };
 *
 *    // The service factory function
 *    this.$get = ['$http', function($http) {
 *      var trackedEvents = {};
 *      return {
 *        // Call this to track an event
 *        event: function(event) {
 *          var count = trackedEvents[event] || 0;
 *          count += 1;
 *          trackedEvents[event] = count;
 *          return count;
 *        },
 *        // Call this to save the tracked events to the trackingUrl
 *        save: function() {
 *          $http.post(trackingUrl, trackedEvents);
 *        }
 *      };
 *    }];
 *  }
 *
 *  describe('eventTracker', function() {
 *    var postSpy;
 *
 *    beforeEach(module(function($provide) {
 *      // Register the eventTracker provider
 *      $provide.provider('eventTracker', EventTrackerProvider);
 *    }));
 *
 *    beforeEach(module(function(eventTrackerProvider) {
 *      // Configure eventTracker provider
 *      eventTrackerProvider.setTrackingUrl('/custom-track');
 *    }));
 *
 *    it('tracks events', inject(function(eventTracker) {
 *      expect(eventTracker.event('login')).toEqual(1);
 *      expect(eventTracker.event('login')).toEqual(2);
 *    }));
 *
 *    it('saves to the tracking url', inject(function(eventTracker, $http) {
 *      postSpy = spyOn($http, 'post');
 *      eventTracker.event('login');
 *      eventTracker.save();
 *      expect(postSpy).toHaveBeenCalled();
 *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
 *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
 *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
 *    }));
 *  });
 * ```
 */

/**
 * @ngdoc method
 * @name $provide#factory
 * @description
 *
 * Register a **service factory**, which will be called to return the service instance.
 * This is short for registering a service where its provider consists of only a `$get` property,
 * which is the given service factory function.
 * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
 * configure your service in a provider.
 *
 * @param {string} name The name of the instance.
 * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
 *                            for `$provide.provider(name, {$get: $getFn})`.
 * @returns {Object} registered provider instance
 *
 * @example
 * Here is an example of registering a service
 * ```js
 *   $provide.factory('ping', ['$http', function($http) {
 *     return function ping() {
 *       return $http.send('/ping');
 *     };
 *   }]);
 * ```
 * You would then inject and use this service like this:
 * ```js
 *   someModule.controller('Ctrl', ['ping', function(ping) {
 *     ping();
 *   }]);
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#service
 * @description
 *
 * Register a **service constructor**, which will be invoked with `new` to create the service
 * instance.
 * This is short for registering a service where its provider's `$get` property is the service
 * constructor function that will be used to instantiate the service instance.
 *
 * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
 * as a type/class.
 *
 * @param {string} name The name of the instance.
 * @param {Function} constructor A class (constructor function) that will be instantiated.
 * @returns {Object} registered provider instance
 *
 * @example
 * Here is an example of registering a service using
 * {@link auto.$provide#service $provide.service(class)}.
 * ```js
 *   var Ping = function($http) {
 *     this.$http = $http;
 *   };
 *
 *   Ping.$inject = ['$http'];
 *
 *   Ping.prototype.send = function() {
 *     return this.$http.get('/ping');
 *   };
 *   $provide.service('ping', Ping);
 * ```
 * You would then inject and use this service like this:
 * ```js
 *   someModule.controller('Ctrl', ['ping', function(ping) {
 *     ping.send();
 *   }]);
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#value
 * @description
 *
 * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
 * number, an array, an object or a function.  This is short for registering a service where its
 * provider's `$get` property is a factory function that takes no arguments and returns the **value
 * service**.
 *
 * Value services are similar to constant services, except that they cannot be injected into a
 * module configuration function (see {@link angular.Module#config}) but they can be overridden by
 * an Angular
 * {@link auto.$provide#decorator decorator}.
 *
 * @param {string} name The name of the instance.
 * @param {*} value The value.
 * @returns {Object} registered provider instance
 *
 * @example
 * Here are some examples of creating value services.
 * ```js
 *   $provide.value('ADMIN_USER', 'admin');
 *
 *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
 *
 *   $provide.value('halfOf', function(value) {
 *     return value / 2;
 *   });
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#constant
 * @description
 *
 * Register a **constant service**, such as a string, a number, an array, an object or a function,
 * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
 * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
 * be overridden by an Angular {@link auto.$provide#decorator decorator}.
 *
 * @param {string} name The name of the constant.
 * @param {*} value The constant value.
 * @returns {Object} registered instance
 *
 * @example
 * Here a some examples of creating constants:
 * ```js
 *   $provide.constant('SHARD_HEIGHT', 306);
 *
 *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
 *
 *   $provide.constant('double', function(value) {
 *     return value * 2;
 *   });
 * ```
 */


/**
 * @ngdoc method
 * @name $provide#decorator
 * @description
 *
 * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
 * intercepts the creation of a service, allowing it to override or modify the behaviour of the
 * service. The object returned by the decorator may be the original service, or a new service
 * object which replaces or wraps and delegates to the original service.
 *
 * @param {string} name The name of the service to decorate.
 * @param {function()} decorator This function will be invoked when the service needs to be
 *    instantiated and should return the decorated service instance. The function is called using
 *    the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
 *    Local injection arguments:
 *
 *    * `$delegate` - The original service instance, which can be monkey patched, configured,
 *      decorated or delegated to.
 *
 * @example
 * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
 * calls to {@link ng.$log#error $log.warn()}.
 * ```js
 *   $provide.decorator('$log', ['$delegate', function($delegate) {
 *     $delegate.warn = $delegate.error;
 *     return $delegate;
 *   }]);
 * ```
 */


function createInjector(modulesToLoad) {
  var INSTANTIATING = {},
      providerSuffix = 'Provider',
      path = [],
      loadedModules = new HashMap([], true),
      providerCache = {
        $provide: {
            provider: supportObject(provider),
            factory: supportObject(factory),
            service: supportObject(service),
            value: supportObject(value),
            constant: supportObject(constant),
            decorator: decorator
          }
      },
      providerInjector = (providerCache.$injector =
          createInternalInjector(providerCache, function() {
            throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
          })),
      instanceCache = {},
      instanceInjector = (instanceCache.$injector =
          createInternalInjector(instanceCache, function(servicename) {
            var provider = providerInjector.get(servicename + providerSuffix);
            return instanceInjector.invoke(provider.$get, provider);
          }));


  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });

  return instanceInjector;

  ////////////////////////////////////
  // $provider
  ////////////////////////////////////

  function supportObject(delegate) {
    return function(key, value) {
      if (isObject(key)) {
        forEach(key, reverseParams(delegate));
      } else {
        return delegate(key, value);
      }
    };
  }

  function provider(name, provider_) {
    assertNotHasOwnProperty(name, 'service');
    if (isFunction(provider_) || isArray(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
    }
    return providerCache[name + providerSuffix] = provider_;
  }

  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }

  function value(name, val) { return factory(name, valueFn(val)); }

  function constant(name, value) {
    assertNotHasOwnProperty(name, 'constant');
    providerCache[name] = value;
    instanceCache[name] = value;
  }

  function decorator(serviceName, decorFn) {
    var origProvider = providerInjector.get(serviceName + providerSuffix),
        orig$get = origProvider.$get;

    origProvider.$get = function() {
      var origInstance = instanceInjector.invoke(orig$get, origProvider);
      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
    };
  }

  ////////////////////////////////////
  // Module Loading
  ////////////////////////////////////
  function loadModules(modulesToLoad){
    var runBlocks = [], moduleFn, invokeQueue, i, ii;
    forEach(modulesToLoad, function(module) {
      if (loadedModules.get(module)) return;
      loadedModules.put(module, true);

      try {
        if (isString(module)) {
          moduleFn = angularModule(module);
          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);

          for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
            var invokeArgs = invokeQueue[i],
                provider = providerInjector.get(invokeArgs[0]);

            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
          }
        } else if (isFunction(module)) {
            runBlocks.push(providerInjector.invoke(module));
        } else if (isArray(module)) {
            runBlocks.push(providerInjector.invoke(module));
        } else {
          assertArgFn(module, 'module');
        }
      } catch (e) {
        if (isArray(module)) {
          module = module[module.length - 1];
        }
        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
          // Safari & FF's stack traces don't contain error.message content
          // unlike those of Chrome and IE
          // So if stack doesn't contain message, we create a new string that contains both.
          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
          /* jshint -W022 */
          e = e.message + '\n' + e.stack;
        }
        throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
                  module, e.stack || e.message || e);
      }
    });
    return runBlocks;
  }

  ////////////////////////////////////
  // internal Injector
  ////////////////////////////////////

  function createInternalInjector(cache, factory) {

    function getService(serviceName) {
      if (cache.hasOwnProperty(serviceName)) {
        if (cache[serviceName] === INSTANTIATING) {
          throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
                    serviceName + ' <- ' + path.join(' <- '));
        }
        return cache[serviceName];
      } else {
        try {
          path.unshift(serviceName);
          cache[serviceName] = INSTANTIATING;
          return cache[serviceName] = factory(serviceName);
        } catch (err) {
          if (cache[serviceName] === INSTANTIATING) {
            delete cache[serviceName];
          }
          throw err;
        } finally {
          path.shift();
        }
      }
    }

    function invoke(fn, self, locals){
      var args = [],
          $inject = annotate(fn),
          length, i,
          key;

      for(i = 0, length = $inject.length; i < length; i++) {
        key = $inject[i];
        if (typeof key !== 'string') {
          throw $injectorMinErr('itkn',
                  'Incorrect injection token! Expected service name as string, got {0}', key);
        }
        args.push(
          locals && locals.hasOwnProperty(key)
          ? locals[key]
          : getService(key)
        );
      }
      if (isArray(fn)) {
        fn = fn[length];
      }

      // http://jsperf.com/angularjs-invoke-apply-vs-switch
      // #5388
      return fn.apply(self, args);
    }

    function instantiate(Type, locals) {
      var Constructor = function() {},
          instance, returnedValue;

      // Check if Type is annotated and use just the given function at n-1 as parameter
      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
      instance = new Constructor();
      returnedValue = invoke(Type, instance, locals);

      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
    }

    return {
      invoke: invoke,
      instantiate: instantiate,
      get: getService,
      annotate: annotate,
      has: function(name) {
        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
      }
    };
  }
}

/**
 * @ngdoc service
 * @name $anchorScroll
 * @kind function
 * @requires $window
 * @requires $location
 * @requires $rootScope
 *
 * @description
 * When called, it checks current value of `$location.hash()` and scrolls to the related element,
 * according to rules specified in
 * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
 *
 * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
 * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
 *
 * @example
   <example>
     <file name="index.html">
       <div id="scrollArea" ng-controller="ScrollCtrl">
         <a ng-click="gotoBottom()">Go to bottom</a>
         <a id="bottom"></a> You're at the bottom!
       </div>
     </file>
     <file name="script.js">
       function ScrollCtrl($scope, $location, $anchorScroll) {
         $scope.gotoBottom = function (){
           // set the location.hash to the id of
           // the element you wish to scroll to.
           $location.hash('bottom');

           // call $anchorScroll()
           $anchorScroll();
         };
       }
     </file>
     <file name="style.css">
       #scrollArea {
         height: 350px;
         overflow: auto;
       }

       #bottom {
         display: block;
         margin-top: 2000px;
       }
     </file>
   </example>
 */
function $AnchorScrollProvider() {

  var autoScrollingEnabled = true;

  /**
   * @ngdoc method
   * @name $anchorScrollProvider#disableAutoScrolling
   *
   * @description
   * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
   * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
   * Use this method to disable automatic scrolling.
   *
   * If automatic scrolling is disabled, one must explicitly call
   * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
   * current hash.
   */
  this.disableAutoScrolling = function() {
    autoScrollingEnabled = false;
  };

  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
    var document = $window.document;

    // helper function to get first anchor from a NodeList
    // can't use filter.filter, as it accepts only instances of Array
    // and IE can't convert NodeList to an array using [].slice
    // TODO(vojta): use filter if we change it to accept lists as well
    function getFirstAnchor(list) {
      var result = null;
      forEach(list, function(element) {
        if (!result && lowercase(element.nodeName) === 'a') result = element;
      });
      return result;
    }

    function scroll() {
      var hash = $location.hash(), elm;

      // empty hash, scroll to the top of the page
      if (!hash) $window.scrollTo(0, 0);

      // element with given id
      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();

      // first anchor with given name :-D
      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();

      // no element and hash == 'top', scroll to the top of the page
      else if (hash === 'top') $window.scrollTo(0, 0);
    }

    // does not scroll when user clicks on anchor link that is currently on
    // (no url change, no $location.hash() change), browser native does scroll
    if (autoScrollingEnabled) {
      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
        function autoScrollWatchAction() {
          $rootScope.$evalAsync(scroll);
        });
    }

    return scroll;
  }];
}

var $animateMinErr = minErr('$animate');

/**
 * @ngdoc provider
 * @name $animateProvider
 *
 * @description
 * Default implementation of $animate that doesn't perform any animations, instead just
 * synchronously performs DOM
 * updates and calls done() callbacks.
 *
 * In order to enable animations the ngAnimate module has to be loaded.
 *
 * To see the functional implementation check out src/ngAnimate/animate.js
 */
var $AnimateProvider = ['$provide', function($provide) {


  this.$$selectors = {};


  /**
   * @ngdoc method
   * @name $animateProvider#register
   *
   * @description
   * Registers a new injectable animation factory function. The factory function produces the
   * animation object which contains callback functions for each event that is expected to be
   * animated.
   *
   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
   *   must be called once the element animation is complete. If a function is returned then the
   *   animation service will use this function to cancel the animation whenever a cancel event is
   *   triggered.
   *
   *
   * ```js
   *   return {
     *     eventFn : function(element, done) {
     *       //code to run the animation
     *       //once complete, then run done()
     *       return function cancellationFunction() {
     *         //code to cancel the animation
     *       }
     *     }
     *   }
   * ```
   *
   * @param {string} name The name of the animation.
   * @param {Function} factory The factory function that will be executed to return the animation
   *                           object.
   */
  this.register = function(name, factory) {
    var key = name + '-animation';
    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
        "Expecting class selector starting with '.' got '{0}'.", name);
    this.$$selectors[name.substr(1)] = key;
    $provide.factory(key, factory);
  };

  /**
   * @ngdoc method
   * @name $animateProvider#classNameFilter
   *
   * @description
   * Sets and/or returns the CSS class regular expression that is checked when performing
   * an animation. Upon bootstrap the classNameFilter value is not set at all and will
   * therefore enable $animate to attempt to perform an animation on any element.
   * When setting the classNameFilter value, animations will only be performed on elements
   * that successfully match the filter expression. This in turn can boost performance
   * for low-powered devices as well as applications containing a lot of structural operations.
   * @param {RegExp=} expression The className expression which will be checked against all animations
   * @return {RegExp} The current CSS className expression value. If null then there is no expression value
   */
  this.classNameFilter = function(expression) {
    if(arguments.length === 1) {
      this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
    }
    return this.$$classNameFilter;
  };

  this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {

    function async(fn) {
      fn && $$asyncCallback(fn);
    }

    /**
     *
     * @ngdoc service
     * @name $animate
     * @description The $animate service provides rudimentary DOM manipulation functions to
     * insert, remove and move elements within the DOM, as well as adding and removing classes.
     * This service is the core service used by the ngAnimate $animator service which provides
     * high-level animation hooks for CSS and JavaScript.
     *
     * $animate is available in the AngularJS core, however, the ngAnimate module must be included
     * to enable full out animation support. Otherwise, $animate will only perform simple DOM
     * manipulation operations.
     *
     * To learn more about enabling animation support, click here to visit the {@link ngAnimate
     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
     * page}.
     */
    return {

      /**
       *
       * @ngdoc method
       * @name $animate#enter
       * @kind function
       * @description Inserts the element into the DOM either after the `after` element or within
       *   the `parent` element. Once complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will be inserted into the DOM
       * @param {DOMElement} parent the parent element which will append the element as
       *   a child (if the after element is not present)
       * @param {DOMElement} after the sibling element which will append the element
       *   after itself
       * @param {Function=} done callback function that will be called after the element has been
       *   inserted into the DOM
       */
      enter : function(element, parent, after, done) {
        if (after) {
          after.after(element);
        } else {
          if (!parent || !parent[0]) {
            parent = after.parent();
          }
          parent.append(element);
        }
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#leave
       * @kind function
       * @description Removes the element from the DOM. Once complete, the done() callback will be
       *   fired (if provided).
       * @param {DOMElement} element the element which will be removed from the DOM
       * @param {Function=} done callback function that will be called after the element has been
       *   removed from the DOM
       */
      leave : function(element, done) {
        element.remove();
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#move
       * @kind function
       * @description Moves the position of the provided element within the DOM to be placed
       * either after the `after` element or inside of the `parent` element. Once complete, the
       * done() callback will be fired (if provided).
       *
       * @param {DOMElement} element the element which will be moved around within the
       *   DOM
       * @param {DOMElement} parent the parent element where the element will be
       *   inserted into (if the after element is not present)
       * @param {DOMElement} after the sibling element where the element will be
       *   positioned next to
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   element has been moved to its new position
       */
      move : function(element, parent, after, done) {
        // Do not remove element before insert. Removing will cause data associated with the
        // element to be dropped. Insert will implicitly do the remove.
        this.enter(element, parent, after, done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#addClass
       * @kind function
       * @description Adds the provided className CSS class value to the provided element. Once
       * complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will have the className value
       *   added to it
       * @param {string} className the CSS class which will be added to the element
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   className value has been added to the element
       */
      addClass : function(element, className, done) {
        className = isString(className) ?
                      className :
                      isArray(className) ? className.join(' ') : '';
        forEach(element, function (element) {
          jqLiteAddClass(element, className);
        });
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#removeClass
       * @kind function
       * @description Removes the provided className CSS class value from the provided element.
       * Once complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will have the className value
       *   removed from it
       * @param {string} className the CSS class which will be removed from the element
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   className value has been removed from the element
       */
      removeClass : function(element, className, done) {
        className = isString(className) ?
                      className :
                      isArray(className) ? className.join(' ') : '';
        forEach(element, function (element) {
          jqLiteRemoveClass(element, className);
        });
        async(done);
      },

      /**
       *
       * @ngdoc method
       * @name $animate#setClass
       * @kind function
       * @description Adds and/or removes the given CSS classes to and from the element.
       * Once complete, the done() callback will be fired (if provided).
       * @param {DOMElement} element the element which will have its CSS classes changed
       *   removed from it
       * @param {string} add the CSS classes which will be added to the element
       * @param {string} remove the CSS class which will be removed from the element
       * @param {Function=} done the callback function (if provided) that will be fired after the
       *   CSS classes have been set on the element
       */
      setClass : function(element, add, remove, done) {
        forEach(element, function (element) {
          jqLiteAddClass(element, add);
          jqLiteRemoveClass(element, remove);
        });
        async(done);
      },

      enabled : noop
    };
  }];
}];

function $$AsyncCallbackProvider(){
  this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
    return $$rAF.supported
      ? function(fn) { return $$rAF(fn); }
      : function(fn) {
        return $timeout(fn, 0, false);
      };
  }];
}

/* global stripHash: true */

/**
 * ! This is a private undocumented service !
 *
 * @name $browser
 * @requires $log
 * @description
 * This object has two goals:
 *
 * - hide all the global state in the browser caused by the window object
 * - abstract away all the browser specific features and inconsistencies
 *
 * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
 * service, which can be used for convenient testing of the application without the interaction with
 * the real browser apis.
 */
/**
 * @param {object} window The global window object.
 * @param {object} document jQuery wrapped document.
 * @param {function()} XHR XMLHttpRequest constructor.
 * @param {object} $log console.log or an object with the same interface.
 * @param {object} $sniffer $sniffer service
 */
function Browser(window, document, $log, $sniffer) {
  var self = this,
      rawDocument = document[0],
      location = window.location,
      history = window.history,
      setTimeout = window.setTimeout,
      clearTimeout = window.clearTimeout,
      pendingDeferIds = {};

  self.isMock = false;

  var outstandingRequestCount = 0;
  var outstandingRequestCallbacks = [];

  // TODO(vojta): remove this temporary api
  self.$$completeOutstandingRequest = completeOutstandingRequest;
  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };

  /**
   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
   */
  function completeOutstandingRequest(fn) {
    try {
      fn.apply(null, sliceArgs(arguments, 1));
    } finally {
      outstandingRequestCount--;
      if (outstandingRequestCount === 0) {
        while(outstandingRequestCallbacks.length) {
          try {
            outstandingRequestCallbacks.pop()();
          } catch (e) {
            $log.error(e);
          }
        }
      }
    }
  }

  /**
   * @private
   * Note: this method is used only by scenario runner
   * TODO(vojta): prefix this method with $$ ?
   * @param {function()} callback Function that will be called when no outstanding request
   */
  self.notifyWhenNoOutstandingRequests = function(callback) {
    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
    // at some deterministic time in respect to the test runner's actions. Leaving things up to the
    // regular poller would result in flaky tests.
    forEach(pollFns, function(pollFn){ pollFn(); });

    if (outstandingRequestCount === 0) {
      callback();
    } else {
      outstandingRequestCallbacks.push(callback);
    }
  };

  //////////////////////////////////////////////////////////////
  // Poll Watcher API
  //////////////////////////////////////////////////////////////
  var pollFns = [],
      pollTimeout;

  /**
   * @name $browser#addPollFn
   *
   * @param {function()} fn Poll function to add
   *
   * @description
   * Adds a function to the list of functions that poller periodically executes,
   * and starts polling if not started yet.
   *
   * @returns {function()} the added function
   */
  self.addPollFn = function(fn) {
    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
    pollFns.push(fn);
    return fn;
  };

  /**
   * @param {number} interval How often should browser call poll functions (ms)
   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
   *
   * @description
   * Configures the poller to run in the specified intervals, using the specified
   * setTimeout fn and kicks it off.
   */
  function startPoller(interval, setTimeout) {
    (function check() {
      forEach(pollFns, function(pollFn){ pollFn(); });
      pollTimeout = setTimeout(check, interval);
    })();
  }

  //////////////////////////////////////////////////////////////
  // URL API
  //////////////////////////////////////////////////////////////

  var lastBrowserUrl = location.href,
      baseElement = document.find('base'),
      reloadLocation = null;

  /**
   * @name $browser#url
   *
   * @description
   * GETTER:
   * Without any argument, this method just returns current value of location.href.
   *
   * SETTER:
   * With at least one argument, this method sets url to new value.
   * If html5 history api supported, pushState/replaceState is used, otherwise
   * location.href/location.replace is used.
   * Returns its own instance to allow chaining
   *
   * NOTE: this api is intended for use only by the $location service. Please use the
   * {@link ng.$location $location service} to change url.
   *
   * @param {string} url New url (when used as setter)
   * @param {boolean=} replace Should new url replace current history record ?
   */
  self.url = function(url, replace) {
    // Android Browser BFCache causes location, history reference to become stale.
    if (location !== window.location) location = window.location;
    if (history !== window.history) history = window.history;

    // setter
    if (url) {
      if (lastBrowserUrl == url) return;
      var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
      lastBrowserUrl = url;
      // Don't use history API if only the hash changed
      // due to a bug in IE10/IE11 which leads
      // to not firing a `hashchange` nor `popstate` event
      // in some cases (see #9143).
      if (!sameBase && $sniffer.history) {
        if (replace) history.replaceState(null, '', url);
        else {
          history.pushState(null, '', url);
          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462
          baseElement.attr('href', baseElement.attr('href'));
        }
      } else {
        if (!sameBase) {
          reloadLocation = url;
        }
        if (replace) {
          location.replace(url);
        } else {
          location.href = url;
        }
      }
      return self;
    // getter
    } else {
      // - reloadLocation is needed as browsers don't allow to read out
      //   the new location.href if a reload happened.
      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
      return reloadLocation || location.href.replace(/%27/g,"'");
    }
  };

  var urlChangeListeners = [],
      urlChangeInit = false;

  function fireUrlChange() {
    if (lastBrowserUrl == self.url()) return;

    lastBrowserUrl = self.url();
    forEach(urlChangeListeners, function(listener) {
      listener(self.url());
    });
  }

  /**
   * @name $browser#onUrlChange
   *
   * @description
   * Register callback function that will be called, when url changes.
   *
   * It's only called when the url is changed from outside of angular:
   * - user types different url into address bar
   * - user clicks on history (forward/back) button
   * - user clicks on a link
   *
   * It's not called when url is changed by $browser.url() method
   *
   * The listener gets called with new url as parameter.
   *
   * NOTE: this api is intended for use only by the $location service. Please use the
   * {@link ng.$location $location service} to monitor url changes in angular apps.
   *
   * @param {function(string)} listener Listener function to be called when url changes.
   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
   */
  self.onUrlChange = function(callback) {
    // TODO(vojta): refactor to use node's syntax for events
    if (!urlChangeInit) {
      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
      // don't fire popstate when user change the address bar and don't fire hashchange when url
      // changed by push/replaceState

      // html5 history api - popstate event
      if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
      // hashchange event
      if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
      // polling
      else self.addPollFn(fireUrlChange);

      urlChangeInit = true;
    }

    urlChangeListeners.push(callback);
    return callback;
  };

  /**
   * Checks whether the url has changed outside of Angular.
   * Needs to be exported to be able to check for changes that have been done in sync,
   * as hashchange/popstate events fire in async.
   */
  self.$$checkUrlChange = fireUrlChange;

  //////////////////////////////////////////////////////////////
  // Misc API
  //////////////////////////////////////////////////////////////

  /**
   * @name $browser#baseHref
   *
   * @description
   * Returns current <base href>
   * (always relative - without domain)
   *
   * @returns {string} The current base href
   */
  self.baseHref = function() {
    var href = baseElement.attr('href');
    return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
  };

  //////////////////////////////////////////////////////////////
  // Cookies API
  //////////////////////////////////////////////////////////////
  var lastCookies = {};
  var lastCookieString = '';
  var cookiePath = self.baseHref();

  /**
   * @name $browser#cookies
   *
   * @param {string=} name Cookie name
   * @param {string=} value Cookie value
   *
   * @description
   * The cookies method provides a 'private' low level access to browser cookies.
   * It is not meant to be used directly, use the $cookie service instead.
   *
   * The return values vary depending on the arguments that the method was called with as follows:
   *
   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
   *   it
   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie
   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
   *   way)
   *
   * @returns {Object} Hash of all cookies (if called without any parameter)
   */
  self.cookies = function(name, value) {
    /* global escape: false, unescape: false */
    var cookieLength, cookieArray, cookie, i, index;

    if (name) {
      if (value === undefined) {
        rawDocument.cookie = escape(name) + "=;path=" + cookiePath +
                                ";expires=Thu, 01 Jan 1970 00:00:00 GMT";
      } else {
        if (isString(value)) {
          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) +
                                ';path=' + cookiePath).length + 1;

          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
          // - 300 cookies
          // - 20 cookies per unique domain
          // - 4096 bytes per cookie
          if (cookieLength > 4096) {
            $log.warn("Cookie '"+ name +
              "' possibly not set or overflowed because it was too large ("+
              cookieLength + " > 4096 bytes)!");
          }
        }
      }
    } else {
      if (rawDocument.cookie !== lastCookieString) {
        lastCookieString = rawDocument.cookie;
        cookieArray = lastCookieString.split("; ");
        lastCookies = {};

        for (i = 0; i < cookieArray.length; i++) {
          cookie = cookieArray[i];
          index = cookie.indexOf('=');
          if (index > 0) { //ignore nameless cookies
            name = unescape(cookie.substring(0, index));
            // the first value that is seen for a cookie is the most
            // specific one.  values for the same cookie name that
            // follow are for less specific paths.
            if (lastCookies[name] === undefined) {
              lastCookies[name] = unescape(cookie.substring(index + 1));
            }
          }
        }
      }
      return lastCookies;
    }
  };


  /**
   * @name $browser#defer
   * @param {function()} fn A function, who's execution should be deferred.
   * @param {number=} [delay=0] of milliseconds to defer the function execution.
   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
   *
   * @description
   * Executes a fn asynchronously via `setTimeout(fn, delay)`.
   *
   * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
   * via `$browser.defer.flush()`.
   *
   */
  self.defer = function(fn, delay) {
    var timeoutId;
    outstandingRequestCount++;
    timeoutId = setTimeout(function() {
      delete pendingDeferIds[timeoutId];
      completeOutstandingRequest(fn);
    }, delay || 0);
    pendingDeferIds[timeoutId] = true;
    return timeoutId;
  };


  /**
   * @name $browser#defer.cancel
   *
   * @description
   * Cancels a deferred task identified with `deferId`.
   *
   * @param {*} deferId Token returned by the `$browser.defer` function.
   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
   *                    canceled.
   */
  self.defer.cancel = function(deferId) {
    if (pendingDeferIds[deferId]) {
      delete pendingDeferIds[deferId];
      clearTimeout(deferId);
      completeOutstandingRequest(noop);
      return true;
    }
    return false;
  };

}

function $BrowserProvider(){
  this.$get = ['$window', '$log', '$sniffer', '$document',
      function( $window,   $log,   $sniffer,   $document){
        return new Browser($window, $document, $log, $sniffer);
      }];
}

/**
 * @ngdoc service
 * @name $cacheFactory
 *
 * @description
 * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
 * them.
 *
 * ```js
 *
 *  var cache = $cacheFactory('cacheId');
 *  expect($cacheFactory.get('cacheId')).toBe(cache);
 *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
 *
 *  cache.put("key", "value");
 *  cache.put("another key", "another value");
 *
 *  // We've specified no options on creation
 *  expect(cache.info()).toEqual({id: 'cacheId', size: 2});
 *
 * ```
 *
 *
 * @param {string} cacheId Name or id of the newly created cache.
 * @param {object=} options Options object that specifies the cache behavior. Properties:
 *
 *   - `{number=}` `capacity` — turns the cache into LRU cache.
 *
 * @returns {object} Newly created cache object with the following set of methods:
 *
 * - `{object}` `info()` — Returns id, size, and options of cache.
 * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
 *   it.
 * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
 * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
 * - `{void}` `removeAll()` — Removes all cached values.
 * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
 *
 * @example
   <example module="cacheExampleApp">
     <file name="index.html">
       <div ng-controller="CacheController">
         <input ng-model="newCacheKey" placeholder="Key">
         <input ng-model="newCacheValue" placeholder="Value">
         <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>

         <p ng-if="keys.length">Cached Values</p>
         <div ng-repeat="key in keys">
           <span ng-bind="key"></span>
           <span>: </span>
           <b ng-bind="cache.get(key)"></b>
         </div>

         <p>Cache Info</p>
         <div ng-repeat="(key, value) in cache.info()">
           <span ng-bind="key"></span>
           <span>: </span>
           <b ng-bind="value"></b>
         </div>
       </div>
     </file>
     <file name="script.js">
       angular.module('cacheExampleApp', []).
         controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
           $scope.keys = [];
           $scope.cache = $cacheFactory('cacheId');
           $scope.put = function(key, value) {
             if ($scope.cache.get(key) === undefined) {
               $scope.keys.push(key);
             }
             $scope.cache.put(key, value === undefined ? null : value);
           };
         }]);
     </file>
     <file name="style.css">
       p {
         margin: 10px 0 3px;
       }
     </file>
   </example>
 */
function $CacheFactoryProvider() {

  this.$get = function() {
    var caches = {};

    function cacheFactory(cacheId, options) {
      if (cacheId in caches) {
        throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
      }

      var size = 0,
          stats = extend({}, options, {id: cacheId}),
          data = {},
          capacity = (options && options.capacity) || Number.MAX_VALUE,
          lruHash = {},
          freshEnd = null,
          staleEnd = null;

      /**
       * @ngdoc type
       * @name $cacheFactory.Cache
       *
       * @description
       * A cache object used to store and retrieve data, primarily used by
       * {@link $http $http} and the {@link ng.directive:script script} directive to cache
       * templates and other data.
       *
       * ```js
       *  angular.module('superCache')
       *    .factory('superCache', ['$cacheFactory', function($cacheFactory) {
       *      return $cacheFactory('super-cache');
       *    }]);
       * ```
       *
       * Example test:
       *
       * ```js
       *  it('should behave like a cache', inject(function(superCache) {
       *    superCache.put('key', 'value');
       *    superCache.put('another key', 'another value');
       *
       *    expect(superCache.info()).toEqual({
       *      id: 'super-cache',
       *      size: 2
       *    });
       *
       *    superCache.remove('another key');
       *    expect(superCache.get('another key')).toBeUndefined();
       *
       *    superCache.removeAll();
       *    expect(superCache.info()).toEqual({
       *      id: 'super-cache',
       *      size: 0
       *    });
       *  }));
       * ```
       */
      return caches[cacheId] = {

        /**
        
Download .txt
gitextract_qmcpiqtz/

├── .gitignore
├── Makefile
├── README.en.md
├── README.md
├── bin/
│   └── generate.js
├── fks_chart/
│   ├── bower.json
│   ├── bower_components/
│   │   ├── angular/
│   │   │   ├── .bower.json
│   │   │   ├── README.md
│   │   │   ├── angular-csp.css
│   │   │   ├── angular.js
│   │   │   ├── angular.min.js.gzip
│   │   │   ├── bower.json
│   │   │   └── package.json
│   │   ├── angular-marked/
│   │   │   ├── .bower.json
│   │   │   ├── README.md
│   │   │   ├── angular-marked.js
│   │   │   ├── bower.json
│   │   │   ├── example/
│   │   │   │   └── index.html
│   │   │   ├── gruntfile.js
│   │   │   ├── karma.conf.js
│   │   │   ├── package.json
│   │   │   └── todo.md
│   │   ├── d3/
│   │   │   ├── .bower.json
│   │   │   ├── .spmignore
│   │   │   ├── CONTRIBUTING.md
│   │   │   ├── LICENSE
│   │   │   ├── README.md
│   │   │   ├── bower.json
│   │   │   ├── composer.json
│   │   │   └── d3.js
│   │   ├── jquery/
│   │   │   ├── .bower.json
│   │   │   ├── MIT-LICENSE.txt
│   │   │   ├── bower.json
│   │   │   ├── dist/
│   │   │   │   └── jquery.js
│   │   │   └── src/
│   │   │       ├── ajax/
│   │   │       │   ├── jsonp.js
│   │   │       │   ├── load.js
│   │   │       │   ├── parseJSON.js
│   │   │       │   ├── parseXML.js
│   │   │       │   ├── script.js
│   │   │       │   ├── var/
│   │   │       │   │   ├── nonce.js
│   │   │       │   │   └── rquery.js
│   │   │       │   └── xhr.js
│   │   │       ├── ajax.js
│   │   │       ├── attributes/
│   │   │       │   ├── attr.js
│   │   │       │   ├── classes.js
│   │   │       │   ├── prop.js
│   │   │       │   ├── support.js
│   │   │       │   └── val.js
│   │   │       ├── attributes.js
│   │   │       ├── callbacks.js
│   │   │       ├── core/
│   │   │       │   ├── access.js
│   │   │       │   ├── init.js
│   │   │       │   ├── parseHTML.js
│   │   │       │   ├── ready.js
│   │   │       │   └── var/
│   │   │       │       └── rsingleTag.js
│   │   │       ├── core.js
│   │   │       ├── css/
│   │   │       │   ├── addGetHookIf.js
│   │   │       │   ├── curCSS.js
│   │   │       │   ├── defaultDisplay.js
│   │   │       │   ├── hiddenVisibleSelectors.js
│   │   │       │   ├── support.js
│   │   │       │   ├── swap.js
│   │   │       │   └── var/
│   │   │       │       ├── cssExpand.js
│   │   │       │       ├── getStyles.js
│   │   │       │       ├── isHidden.js
│   │   │       │       ├── rmargin.js
│   │   │       │       └── rnumnonpx.js
│   │   │       ├── css.js
│   │   │       ├── data/
│   │   │       │   ├── Data.js
│   │   │       │   ├── accepts.js
│   │   │       │   └── var/
│   │   │       │       ├── data_priv.js
│   │   │       │       └── data_user.js
│   │   │       ├── data.js
│   │   │       ├── deferred.js
│   │   │       ├── deprecated.js
│   │   │       ├── dimensions.js
│   │   │       ├── effects/
│   │   │       │   ├── Tween.js
│   │   │       │   └── animatedSelector.js
│   │   │       ├── effects.js
│   │   │       ├── event/
│   │   │       │   ├── ajax.js
│   │   │       │   ├── alias.js
│   │   │       │   └── support.js
│   │   │       ├── event.js
│   │   │       ├── exports/
│   │   │       │   ├── amd.js
│   │   │       │   └── global.js
│   │   │       ├── intro.js
│   │   │       ├── jquery.js
│   │   │       ├── manipulation/
│   │   │       │   ├── _evalUrl.js
│   │   │       │   ├── support.js
│   │   │       │   └── var/
│   │   │       │       └── rcheckableType.js
│   │   │       ├── manipulation.js
│   │   │       ├── offset.js
│   │   │       ├── outro.js
│   │   │       ├── queue/
│   │   │       │   └── delay.js
│   │   │       ├── queue.js
│   │   │       ├── selector-native.js
│   │   │       ├── selector-sizzle.js
│   │   │       ├── selector.js
│   │   │       ├── serialize.js
│   │   │       ├── sizzle/
│   │   │       │   └── dist/
│   │   │       │       └── sizzle.js
│   │   │       ├── traversing/
│   │   │       │   ├── findFilter.js
│   │   │       │   └── var/
│   │   │       │       └── rneedsContext.js
│   │   │       ├── traversing.js
│   │   │       ├── var/
│   │   │       │   ├── arr.js
│   │   │       │   ├── class2type.js
│   │   │       │   ├── concat.js
│   │   │       │   ├── hasOwn.js
│   │   │       │   ├── indexOf.js
│   │   │       │   ├── pnum.js
│   │   │       │   ├── push.js
│   │   │       │   ├── rnotwhite.js
│   │   │       │   ├── slice.js
│   │   │       │   ├── strundefined.js
│   │   │       │   ├── support.js
│   │   │       │   └── toString.js
│   │   │       └── wrap.js
│   │   └── marked/
│   │       ├── .bower.json
│   │       ├── .gitignore
│   │       ├── .npmignore
│   │       ├── .travis.yml
│   │       ├── LICENSE
│   │       ├── Makefile
│   │       ├── README.md
│   │       ├── bin/
│   │       │   └── marked
│   │       ├── component.json
│   │       ├── doc/
│   │       │   ├── broken.md
│   │       │   └── todo.md
│   │       ├── index.js
│   │       ├── lib/
│   │       │   └── marked.js
│   │       ├── man/
│   │       │   └── marked.1
│   │       ├── package.json
│   │       └── test/
│   │           ├── README
│   │           ├── browser/
│   │           │   ├── index.html
│   │           │   ├── index.js
│   │           │   └── test.js
│   │           ├── index.js
│   │           ├── new/
│   │           │   ├── autolink_lines.html
│   │           │   ├── autolink_lines.text
│   │           │   ├── blockquote_list_item.html
│   │           │   ├── blockquote_list_item.text
│   │           │   ├── case_insensitive_refs.html
│   │           │   ├── case_insensitive_refs.text
│   │           │   ├── def_blocks.html
│   │           │   ├── def_blocks.text
│   │           │   ├── double_link.html
│   │           │   ├── double_link.text
│   │           │   ├── escaped_angles.html
│   │           │   ├── escaped_angles.text
│   │           │   ├── gfm_break.breaks.html
│   │           │   ├── gfm_break.breaks.text
│   │           │   ├── gfm_code.html
│   │           │   ├── gfm_code.text
│   │           │   ├── gfm_code_hr_list.html
│   │           │   ├── gfm_code_hr_list.text
│   │           │   ├── gfm_del.html
│   │           │   ├── gfm_del.text
│   │           │   ├── gfm_em.html
│   │           │   ├── gfm_em.text
│   │           │   ├── gfm_links.html
│   │           │   ├── gfm_links.text
│   │           │   ├── gfm_tables.html
│   │           │   ├── gfm_tables.text
│   │           │   ├── hr_list_break.html
│   │           │   ├── hr_list_break.text
│   │           │   ├── lazy_blockquotes.html
│   │           │   ├── lazy_blockquotes.text
│   │           │   ├── list_item_text.html
│   │           │   ├── list_item_text.text
│   │           │   ├── loose_lists.html
│   │           │   ├── loose_lists.text
│   │           │   ├── main.html
│   │           │   ├── main.text
│   │           │   ├── nested_code.html
│   │           │   ├── nested_code.text
│   │           │   ├── nested_em.html
│   │           │   ├── nested_em.text
│   │           │   ├── nested_square_link.html
│   │           │   ├── nested_square_link.text
│   │           │   ├── not_a_link.html
│   │           │   ├── not_a_link.text
│   │           │   ├── ref_paren.html
│   │           │   ├── ref_paren.text
│   │           │   ├── same_bullet.html
│   │           │   ├── same_bullet.text
│   │           │   ├── text.smartypants.html
│   │           │   ├── text.smartypants.text
│   │           │   ├── toplevel_paragraphs.gfm.html
│   │           │   ├── toplevel_paragraphs.gfm.text
│   │           │   ├── tricky_list.html
│   │           │   └── tricky_list.text
│   │           ├── original/
│   │           │   ├── amps_and_angles_encoding.html
│   │           │   ├── amps_and_angles_encoding.text
│   │           │   ├── auto_links.html
│   │           │   ├── auto_links.text
│   │           │   ├── backslash_escapes.html
│   │           │   ├── backslash_escapes.text
│   │           │   ├── blockquotes_with_code_blocks.html
│   │           │   ├── blockquotes_with_code_blocks.text
│   │           │   ├── code_blocks.html
│   │           │   ├── code_blocks.text
│   │           │   ├── code_spans.html
│   │           │   ├── code_spans.text
│   │           │   ├── hard_wrapped_paragraphs_with_list_like_lines.html
│   │           │   ├── hard_wrapped_paragraphs_with_list_like_lines.text
│   │           │   ├── horizontal_rules.html
│   │           │   ├── horizontal_rules.text
│   │           │   ├── inline_html_advanced.html
│   │           │   ├── inline_html_advanced.text
│   │           │   ├── inline_html_comments.html
│   │           │   ├── inline_html_comments.text
│   │           │   ├── inline_html_simple.html
│   │           │   ├── inline_html_simple.text
│   │           │   ├── links_inline_style.html
│   │           │   ├── links_inline_style.text
│   │           │   ├── links_reference_style.html
│   │           │   ├── links_reference_style.text
│   │           │   ├── links_shortcut_references.html
│   │           │   ├── links_shortcut_references.text
│   │           │   ├── literal_quotes_in_titles.html
│   │           │   ├── literal_quotes_in_titles.text
│   │           │   ├── markdown_documentation_basics.html
│   │           │   ├── markdown_documentation_basics.text
│   │           │   ├── markdown_documentation_syntax.html
│   │           │   ├── markdown_documentation_syntax.text
│   │           │   ├── nested_blockquotes.html
│   │           │   ├── nested_blockquotes.text
│   │           │   ├── ordered_and_unordered_lists.html
│   │           │   ├── ordered_and_unordered_lists.text
│   │           │   ├── strong_and_em_together.html
│   │           │   ├── strong_and_em_together.text
│   │           │   ├── tabs.html
│   │           │   ├── tabs.text
│   │           │   ├── tidyness.html
│   │           │   └── tidyness.text
│   │           └── tests/
│   │               ├── amps_and_angles_encoding.html
│   │               ├── amps_and_angles_encoding.text
│   │               ├── auto_links.html
│   │               ├── auto_links.text
│   │               ├── autolink_lines.html
│   │               ├── autolink_lines.text
│   │               ├── backslash_escapes.html
│   │               ├── backslash_escapes.text
│   │               ├── blockquote_list_item.html
│   │               ├── blockquote_list_item.text
│   │               ├── blockquotes_with_code_blocks.html
│   │               ├── blockquotes_with_code_blocks.text
│   │               ├── case_insensitive_refs.html
│   │               ├── case_insensitive_refs.text
│   │               ├── code_blocks.html
│   │               ├── code_blocks.text
│   │               ├── code_spans.html
│   │               ├── code_spans.text
│   │               ├── def_blocks.html
│   │               ├── def_blocks.text
│   │               ├── double_link.html
│   │               ├── double_link.text
│   │               ├── escaped_angles.html
│   │               ├── escaped_angles.text
│   │               ├── gfm_break.breaks.html
│   │               ├── gfm_break.breaks.text
│   │               ├── gfm_code.html
│   │               ├── gfm_code.text
│   │               ├── gfm_code_hr_list.html
│   │               ├── gfm_code_hr_list.text
│   │               ├── gfm_del.html
│   │               ├── gfm_del.text
│   │               ├── gfm_em.html
│   │               ├── gfm_em.text
│   │               ├── gfm_links.html
│   │               ├── gfm_links.text
│   │               ├── gfm_tables.html
│   │               ├── gfm_tables.text
│   │               ├── hard_wrapped_paragraphs_with_list_like_lines.nogfm.html
│   │               ├── hard_wrapped_paragraphs_with_list_like_lines.nogfm.text
│   │               ├── horizontal_rules.html
│   │               ├── horizontal_rules.text
│   │               ├── hr_list_break.html
│   │               ├── hr_list_break.text
│   │               ├── inline_html_advanced.html
│   │               ├── inline_html_advanced.text
│   │               ├── inline_html_comments.html
│   │               ├── inline_html_comments.text
│   │               ├── inline_html_simple.html
│   │               ├── inline_html_simple.text
│   │               ├── lazy_blockquotes.html
│   │               ├── lazy_blockquotes.text
│   │               ├── links_inline_style.html
│   │               ├── links_inline_style.text
│   │               ├── links_reference_style.html
│   │               ├── links_reference_style.text
│   │               ├── links_shortcut_references.html
│   │               ├── links_shortcut_references.text
│   │               ├── list_item_text.html
│   │               ├── list_item_text.text
│   │               ├── literal_quotes_in_titles.html
│   │               ├── literal_quotes_in_titles.text
│   │               ├── loose_lists.html
│   │               ├── loose_lists.text
│   │               ├── main.html
│   │               ├── main.text
│   │               ├── markdown_documentation_basics.html
│   │               ├── markdown_documentation_basics.text
│   │               ├── markdown_documentation_syntax.html
│   │               ├── markdown_documentation_syntax.text
│   │               ├── nested_blockquotes.html
│   │               ├── nested_blockquotes.text
│   │               ├── nested_code.html
│   │               ├── nested_code.text
│   │               ├── nested_em.html
│   │               ├── nested_em.text
│   │               ├── nested_square_link.html
│   │               ├── nested_square_link.text
│   │               ├── not_a_link.html
│   │               ├── not_a_link.text
│   │               ├── ordered_and_unordered_lists.html
│   │               ├── ordered_and_unordered_lists.text
│   │               ├── ref_paren.html
│   │               ├── ref_paren.text
│   │               ├── same_bullet.html
│   │               ├── same_bullet.text
│   │               ├── strong_and_em_together.html
│   │               ├── strong_and_em_together.text
│   │               ├── tabs.html
│   │               ├── tabs.text
│   │               ├── text.smartypants.html
│   │               ├── text.smartypants.text
│   │               ├── tidyness.html
│   │               ├── tidyness.text
│   │               ├── toplevel_paragraphs.gfm.html
│   │               ├── toplevel_paragraphs.gfm.text
│   │               ├── tricky_list.html
│   │               └── tricky_list.text
│   ├── css/
│   │   └── style.css
│   ├── data/
│   │   └── front-end.json
│   ├── index.html
│   └── js/
│       └── app.js
└── package.json
Download .txt
SYMBOL INDEX (802 symbols across 28 files)

FILE: fks_chart/bower_components/angular-marked/angular-marked.js
  function set (line 52) | function set(val) {

FILE: fks_chart/bower_components/angular/angular.js
  function minErr (line 36) | function minErr(module) {
  function isArrayLike (line 268) | function isArrayLike(obj) {
  function forEach (line 312) | function forEach(obj, iterator, context) {
  function sortedKeys (line 340) | function sortedKeys(obj) {
  function forEachSorted (line 350) | function forEachSorted(obj, iterator, context) {
  function reverseParams (line 364) | function reverseParams(iteratorFn) {
  function nextUid (line 376) | function nextUid() {
  function setHashKey (line 404) | function setHashKey(obj, h) {
  function extend (line 427) | function extend(dst) {
  function int (line 441) | function int(str) {
  function inherit (line 446) | function inherit(parent, extra) {
  function noop (line 466) | function noop() {}
  function identity (line 486) | function identity($) {return $;}
  function valueFn (line 490) | function valueFn(value) {return function() {return value;};}
  function isUndefined (line 504) | function isUndefined(value){return typeof value === 'undefined';}
  function isDefined (line 519) | function isDefined(value){return typeof value !== 'undefined';}
  function isObject (line 535) | function isObject(value){return value != null && typeof value === 'objec...
  function isString (line 550) | function isString(value){return typeof value === 'string';}
  function isNumber (line 565) | function isNumber(value){return typeof value === 'number';}
  function isDate (line 580) | function isDate(value) {
  function isFunction (line 618) | function isFunction(value){return typeof value === 'function';}
  function isRegExp (line 628) | function isRegExp(value) {
  function isWindow (line 640) | function isWindow(obj) {
  function isScope (line 645) | function isScope(obj) {
  function isFile (line 650) | function isFile(obj) {
  function isBlob (line 655) | function isBlob(obj) {
  function isBoolean (line 660) | function isBoolean(value) {
  function isPromiseLike (line 665) | function isPromiseLike(obj) {
  function isElement (line 697) | function isElement(node) {
  function makeMap (line 707) | function makeMap(str) {
  function map (line 728) | function map(obj, iterator, context) {
  function size (line 749) | function size(obj, ownPropsOnly) {
  function includes (line 764) | function includes(array, obj) {
  function indexOf (line 768) | function indexOf(array, obj) {
  function arrayRemove (line 777) | function arrayRemove(array, value) {
  function isLeafNode (line 784) | function isLeafNode (node) {
  function copy (line 854) | function copy(source, destination, stackSource, stackDest) {
  function shallowCopy (line 927) | function shallowCopy(src, dst) {
  function equals (line 977) | function equals(o1, o2) {
  function concat (line 1039) | function concat(array1, array2, index) {
  function sliceArgs (line 1043) | function sliceArgs(args, startIndex) {
  function bind (line 1067) | function bind(self, fn) {
  function toJsonReplacer (line 1088) | function toJsonReplacer(key, value) {
  function toJson (line 1119) | function toJson(obj, pretty) {
  function fromJson (line 1137) | function fromJson(json) {
  function toBoolean (line 1144) | function toBoolean(value) {
  function startingTag (line 1159) | function startingTag(element) {
  function tryDecodeURIComponent (line 1191) | function tryDecodeURIComponent(value) {
  function parseKeyValue (line 1204) | function parseKeyValue(/**string*/keyValue) {
  function toKeyValue (line 1225) | function toKeyValue(obj) {
  function encodeUriSegment (line 1253) | function encodeUriSegment(val) {
  function encodeUriQuery (line 1272) | function encodeUriQuery(val, pctEncodeSpaces) {
  function angularInit (line 1328) | function angularInit(element, bootstrap) {
  function bootstrap (line 1426) | function bootstrap(element, modules) {
  function snake_case (line 1472) | function snake_case(name, separator) {
  function bindJQuery (line 1479) | function bindJQuery() {
  function assertArg (line 1507) | function assertArg(arg, name, reason) {
  function assertArgFn (line 1514) | function assertArgFn(arg, name, acceptArrayAnnotation) {
  function assertNotHasOwnProperty (line 1529) | function assertNotHasOwnProperty(name, context) {
  function getter (line 1543) | function getter(obj, path, bindFnToScope) {
  function getBlockElements (line 1567) | function getBlockElements(nodes) {
  function setupModuleLoader (line 1595) | function setupModuleLoader(window) {
  function publishExternalAPI (line 1998) | function publishExternalAPI(angular){
  function jqNextId (line 2233) | function jqNextId() { return ++jqId; }
  function camelCase (line 2245) | function camelCase(name) {
  function jqLitePatchJQueryRemove (line 2261) | function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getter...
  function jqLiteIsTextNode (line 2315) | function jqLiteIsTextNode(html) {
  function jqLiteBuildFragment (line 2319) | function jqLiteBuildFragment(html, context) {
  function jqLiteParseHTML (line 2354) | function jqLiteParseHTML(html, context) {
  function JQLite (line 2366) | function JQLite(element) {
  function jqLiteClone (line 2389) | function jqLiteClone(element) {
  function jqLiteDealoc (line 2393) | function jqLiteDealoc(element){
  function jqLiteOff (line 2400) | function jqLiteOff(element, type, fn, unsupported) {
  function jqLiteRemoveData (line 2425) | function jqLiteRemoveData(element, name) {
  function jqLiteExpandoStore (line 2444) | function jqLiteExpandoStore(element, key, value) {
  function jqLiteData (line 2459) | function jqLiteData(element, key, value) {
  function jqLiteHasClass (line 2485) | function jqLiteHasClass(element, selector) {
  function jqLiteRemoveClass (line 2491) | function jqLiteRemoveClass(element, cssClasses) {
  function jqLiteAddClass (line 2503) | function jqLiteAddClass(element, cssClasses) {
  function jqLiteAddNodes (line 2519) | function jqLiteAddNodes(root, elements) {
  function jqLiteController (line 2530) | function jqLiteController(element, name) {
  function jqLiteInheritedData (line 2534) | function jqLiteInheritedData(element, name, value) {
  function jqLiteEmpty (line 2554) | function jqLiteEmpty(element) {
  function trigger (line 2570) | function trigger() {
  function getBooleanAttrName (line 2617) | function getBooleanAttrName(element, name) {
  function getText (line 2731) | function getText(element, value) {
  function createEventHandler (line 2818) | function createEventHandler(element, events) {
  function hashKey (line 3139) | function hashKey(obj, nextUidFn) {
  function HashMap (line 3160) | function HashMap(array, isolatedUid) {
  function annotate (line 3264) | function annotate(fn) {
  function createInjector (line 3784) | function createInjector(modulesToLoad) {
  function $AnchorScrollProvider (line 4042) | function $AnchorScrollProvider() {
  function async (line 4190) | function async(fn) {
  function $$AsyncCallbackProvider (line 4353) | function $$AsyncCallbackProvider(){
  function Browser (line 4387) | function Browser(window, document, $log, $sniffer) {
  function $BrowserProvider (line 4754) | function $BrowserProvider(){
  function $CacheFactoryProvider (line 4842) | function $CacheFactoryProvider() {
  function $TemplateCacheProvider (line 5155) | function $TemplateCacheProvider() {
  function $CompileProvider (line 5679) | function $CompileProvider($provide, $$sanitizeUriProvider) {
  function directiveNormalize (line 7164) | function directiveNormalize(name) {
  function nodesetLinkingFn (line 7213) | function nodesetLinkingFn(
  function directiveLinkingFn (line 7220) | function directiveLinkingFn(
  function tokenDifference (line 7228) | function tokenDifference(str1, str2) {
  function $ControllerProvider (line 7254) | function $ControllerProvider() {
  function $DocumentProvider (line 7357) | function $DocumentProvider(){
  function $ExceptionHandlerProvider (line 7395) | function $ExceptionHandlerProvider() {
  function parseHeaders (line 7409) | function parseHeaders(headers) {
  function headersGetter (line 7440) | function headersGetter(headers) {
  function transformData (line 7465) | function transformData(data, headers, fns) {
  function isSuccess (line 7477) | function isSuccess(status) {
  function $HttpProvider (line 7488) | function $HttpProvider() {
  function createXhr (line 8505) | function createXhr(method) {
  function $HttpBackendProvider (line 8535) | function $HttpBackendProvider() {
  function createHttpBackend (line 8541) | function createHttpBackend($browser, createXhr, $browserDefer, callbacks...
  function $InterpolateProvider (line 8756) | function $InterpolateProvider() {
  function $IntervalProvider (line 8968) | function $IntervalProvider() {
  function $LocaleProvider (line 9163) | function $LocaleProvider(){
  function encodePath (line 9236) | function encodePath(path) {
  function parseAbsoluteUrl (line 9247) | function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
  function parseAppUrl (line 9256) | function parseAppUrl(relativeUrl, locationObj, appBase) {
  function beginsWith (line 9281) | function beginsWith(begin, whole) {
  function stripHash (line 9288) | function stripHash(url) {
  function stripFile (line 9294) | function stripFile(url) {
  function serverBase (line 9299) | function serverBase(url) {
  function LocationHtml5Url (line 9312) | function LocationHtml5Url(appBase, basePrefix) {
  function LocationHashbangUrl (line 9385) | function LocationHashbangUrl(appBase, hashPrefix) {
  function LocationHashbangInHtml5Url (line 9480) | function LocationHashbangInHtml5Url(appBase, hashPrefix) {
  function locationGetter (line 9742) | function locationGetter(property) {
  function locationGetterSetter (line 9749) | function locationGetterSetter(property, preprocess) {
  function $LocationProvider (line 9794) | function $LocationProvider(){
  function $LogProvider (line 10020) | function $LogProvider(){
  function ensureSafeMemberName (line 10167) | function ensureSafeMemberName(name, fullExpression) {
  function ensureSafeObject (line 10178) | function ensureSafeObject(obj, fullExpression) {
  function ensureSafeFunction (line 10209) | function ensureSafeFunction(obj, fullExpression) {
  function setter (line 10981) | function setter(obj, path, setValue, fullExp, options) {
  function isPossiblyDangerousMemberName (line 11018) | function isPossiblyDangerousMemberName(name) {
  function cspSafeGetterFn (line 11027) | function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
  function getterFnWithExtraArgs (line 11140) | function getterFnWithExtraArgs(fn, fullExpression) {
  function getterFn (line 11146) | function getterFn(path, options, fullExp) {
  function $ParseProvider (line 11284) | function $ParseProvider() {
  function $QProvider (line 11599) | function $QProvider() {
  function qFactory (line 11617) | function qFactory(nextTick, exceptionHandler) {
  function $$RAFProvider (line 11955) | function $$RAFProvider(){ //rAF
  function $RootScopeProvider (line 12054) | function $RootScopeProvider(){
  function $$SanitizeUriProvider (line 13160) | function $$SanitizeUriProvider() {
  function escapeForRegexp (line 13246) | function escapeForRegexp(s) {
  function adjustMatcher (line 13252) | function adjustMatcher(matcher) {
  function adjustMatchers (line 13280) | function adjustMatchers(matchers) {
  function $SceDelegateProvider (line 13358) | function $SceDelegateProvider() {
  function $SceProvider (line 13888) | function $SceProvider() {
  function $SnifferProvider (line 14301) | function $SnifferProvider() {
  function $TimeoutProvider (line 14378) | function $TimeoutProvider() {
  function urlResolve (line 14524) | function urlResolve(url, base) {
  function urlIsSameOrigin (line 14558) | function urlIsSameOrigin(requestUrl) {
  function $WindowProvider (line 14605) | function $WindowProvider(){
  function $FilterProvider (line 14702) | function $FilterProvider($provide) {
  function filterFilter (line 14872) | function filterFilter() {
  function currencyFilter (line 15027) | function currencyFilter($locale) {
  function numberFilter (line 15088) | function numberFilter($locale) {
  function formatNumber (line 15097) | function formatNumber(number, pattern, groupSep, decimalSep, fractionSiz...
  function padNumber (line 15179) | function padNumber(num, digits, trim) {
  function dateGetter (line 15193) | function dateGetter(name, size, offset, trim) {
  function dateStrGetter (line 15204) | function dateStrGetter(name, shortForm) {
  function timeZoneGetter (line 15213) | function timeZoneGetter(date) {
  function ampmGetter (line 15223) | function ampmGetter(date, formats) {
  function dateFilter (line 15343) | function dateFilter($locale) {
  function jsonFilter (line 15442) | function jsonFilter() {
  function limitToFilter (line 15541) | function limitToFilter(){
  function orderByFilter (line 15701) | function orderByFilter($parse){
  function ngDirective (line 15766) | function ngDirective(directive) {
  function FormController (line 16270) | function FormController(element, attrs, $scope, $animate) {
  function validate (line 17088) | function validate(ctrl, validatorName, validity, value){
  function testFlags (line 17093) | function testFlags(validity, flags) {
  function addNativeHtml5Validators (line 17107) | function addNativeHtml5Validators(ctrl, validatorName, badFlags, ignoreF...
  function textInputType (line 17125) | function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  function numberInputType (line 17279) | function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  function urlInputType (line 17324) | function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  function emailInputType (line 17335) | function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
  function radioInputType (line 17346) | function radioInputType(scope, element, attr, ctrl) {
  function checkboxInputType (line 17368) | function checkboxInputType(scope, element, attr, ctrl) {
  function toggleValidCss (line 17764) | function toggleValidCss(isValid, validationErrorKey) {
  function getStringValue (line 18483) | function getStringValue() {
  function classDirective (line 18495) | function classDirective(name, selector) {
  function getBlockStart (line 20768) | function getBlockStart(block) {
  function getBlockEnd (line 20772) | function getBlockEnd(block) {
  function setupAsSingle (line 21710) | function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
  function setupAsMultiple (line 21735) | function setupAsMultiple(scope, selectElement, ctrl) {
  function setupAsOptions (line 21766) | function setupAsOptions(scope, selectElement, ctrl) {

FILE: fks_chart/bower_components/d3/d3.js
  function d3_ascending (line 36) | function d3_ascending(a, b) {
  function d3_number (line 81) | function d3_number(x) {
  function d3_numeric (line 84) | function d3_numeric(x) {
  function d3_bisector (line 118) | function d3_bisector(compare) {
  function d3_zipLength (line 175) | function d3_zipLength(d) {
  function d3_range_integerScale (line 227) | function d3_range_integerScale(x) {
  function d3_class (line 232) | function d3_class(ctor, properties) {
  function d3_Map (line 247) | function d3_Map() {
  function d3_map_escape (line 280) | function d3_map_escape(key) {
  function d3_map_unescape (line 283) | function d3_map_unescape(key) {
  function d3_map_has (line 286) | function d3_map_has(key) {
  function d3_map_remove (line 289) | function d3_map_remove(key) {
  function d3_map_keys (line 292) | function d3_map_keys() {
  function d3_map_size (line 297) | function d3_map_size() {
  function d3_map_empty (line 302) | function d3_map_empty() {
  function map (line 308) | function map(mapType, array, depth) {
  function entries (line 332) | function entries(map, depth) {
  function d3_Set (line 374) | function d3_Set() {
  function d3_rebind (line 397) | function d3_rebind(target, source, method) {
  function d3_vendorSymbol (line 403) | function d3_vendorSymbol(object, name) {
  function d3_noop (line 412) | function d3_noop() {}
  function d3_dispatch (line 418) | function d3_dispatch() {}
  function d3_dispatch_event (line 433) | function d3_dispatch_event(dispatch) {
  function d3_eventPreventDefault (line 456) | function d3_eventPreventDefault() {
  function d3_eventSource (line 459) | function d3_eventSource() {
  function d3_eventDispatch (line 464) | function d3_eventDispatch(target) {
  function d3_selection (line 490) | function d3_selection(groups) {
  function d3_selection_selector (line 529) | function d3_selection_selector(selector) {
  function d3_selection_selectorAll (line 547) | function d3_selection_selectorAll(selector) {
  function d3_selection_attr (line 585) | function d3_selection_attr(name, value) {
  function d3_collapse (line 609) | function d3_collapse(s) {
  function d3_selection_classedRe (line 629) | function d3_selection_classedRe(name) {
  function d3_selection_classes (line 632) | function d3_selection_classes(name) {
  function d3_selection_classed (line 635) | function d3_selection_classed(name, value) {
  function d3_selection_classedName (line 648) | function d3_selection_classedName(name) {
  function d3_selection_style (line 674) | function d3_selection_style(name, value, priority) {
  function d3_selection_property (line 695) | function d3_selection_property(name, value) {
  function d3_selection_creator (line 734) | function d3_selection_creator(name) {
  function bind (line 765) | function bind(group, groupData) {
  function d3_selection_dataNode (line 833) | function d3_selection_dataNode(data) {
  function d3_selection_filter (line 855) | function d3_selection_filter(selector) {
  function d3_selection_sortComparator (line 876) | function d3_selection_sortComparator(comparator) {
  function d3_selection_each (line 887) | function d3_selection_each(groups, callback) {
  function d3_selection_enter (line 919) | function d3_selection_enter(selection) {
  function d3_selection_enterInsertBefore (line 952) | function d3_selection_enterInsertBefore(enter) {
  function d3_selection_interrupt (line 981) | function d3_selection_interrupt() {
  function d3_selection_on (line 1009) | function d3_selection_on(type, listener, capture) {
  function d3_selection_onListener (line 1046) | function d3_selection_onListener(listener, argumentz) {
  function d3_selection_onFilter (line 1058) | function d3_selection_onFilter(listener, argumentz) {
  function d3_event_dragSuppress (line 1068) | function d3_event_dragSuppress() {
  function d3_mousePoint (line 1093) | function d3_mousePoint(container, e) {
  function drag (line 1129) | function drag() {
  function dragstart (line 1132) | function dragstart(id, position, subject, move, end) {
  function d3_behavior_dragTouchId (line 1176) | function d3_behavior_dragTouchId() {
  function d3_behavior_dragTouchSubject (line 1179) | function d3_behavior_dragTouchSubject() {
  function d3_behavior_dragMouseSubject (line 1182) | function d3_behavior_dragMouseSubject() {
  function d3_sgn (line 1194) | function d3_sgn(x) {
  function d3_cross2d (line 1197) | function d3_cross2d(a, b, c) {
  function d3_acos (line 1200) | function d3_acos(x) {
  function d3_asin (line 1203) | function d3_asin(x) {
  function d3_sinh (line 1206) | function d3_sinh(x) {
  function d3_cosh (line 1209) | function d3_cosh(x) {
  function d3_tanh (line 1212) | function d3_tanh(x) {
  function d3_haversin (line 1215) | function d3_haversin(x) {
  function interpolate (line 1222) | function interpolate(t) {
  function zoom (line 1239) | function zoom(g) {
  function location (line 1332) | function location(p) {
  function point (line 1335) | function point(l) {
  function scaleTo (line 1338) | function scaleTo(s) {
  function translateTo (line 1341) | function translateTo(p, l) {
  function rescale (line 1346) | function rescale() {
  function zoomstarted (line 1354) | function zoomstarted(dispatch) {
  function zoomed (line 1359) | function zoomed(dispatch) {
  function zoomended (line 1367) | function zoomended(dispatch) {
  function mousedowned (line 1372) | function mousedowned() {
  function touchstarted (line 1387) | function touchstarted() {
  function mousewheeled (line 1459) | function mousewheeled() {
  function dblclicked (line 1472) | function dblclicked() {
  function d3_color (line 1491) | function d3_color() {}
  function d3_hsl (line 1496) | function d3_hsl(h, s, l) {
  function d3_hsl_rgb (line 1511) | function d3_hsl_rgb(h, s, l) {
  function d3_hcl (line 1531) | function d3_hcl(h, c, l) {
  function d3_hcl_lab (line 1544) | function d3_hcl_lab(h, c, l) {
  function d3_lab (line 1550) | function d3_lab(l, a, b) {
  function d3_lab_rgb (line 1565) | function d3_lab_rgb(l, a, b) {
  function d3_lab_hcl (line 1572) | function d3_lab_hcl(l, a, b) {
  function d3_lab_xyz (line 1575) | function d3_lab_xyz(x) {
  function d3_xyz_lab (line 1578) | function d3_xyz_lab(x) {
  function d3_xyz_rgb (line 1581) | function d3_xyz_rgb(r) {
  function d3_rgb (line 1585) | function d3_rgb(r, g, b) {
  function d3_rgbNumber (line 1588) | function d3_rgbNumber(value) {
  function d3_rgbString (line 1591) | function d3_rgbString(value) {
  function d3_rgb_hex (line 1614) | function d3_rgb_hex(v) {
  function d3_rgb_parse (line 1617) | function d3_rgb_parse(format, rgb, hsl) {
  function d3_rgb_hsl (line 1651) | function d3_rgb_hsl(r, g, b) {
  function d3_rgb_lab (line 1663) | function d3_rgb_lab(r, g, b) {
  function d3_rgb_xyz (line 1670) | function d3_rgb_xyz(r) {
  function d3_rgb_parseNumber (line 1673) | function d3_rgb_parseNumber(c) {
  function d3_functor (line 1829) | function d3_functor(v) {
  function d3_identity (line 1835) | function d3_identity(d) {
  function d3_xhrType (line 1839) | function d3_xhrType(response) {
  function d3_xhr (line 1846) | function d3_xhr(url, mimeType, response, callback) {
  function d3_xhr_fixCallback (line 1921) | function d3_xhr_fixCallback(callback) {
  function d3_xhrHasResponse (line 1926) | function d3_xhrHasResponse(request) {
  function dsv (line 1932) | function dsv(url, row, callback) {
  function response (line 1940) | function response(request) {
  function typedResponse (line 1943) | function typedResponse(f) {
  function token (line 1962) | function token() {
  function formatRow (line 2024) | function formatRow(row) {
  function formatValue (line 2027) | function formatValue(text) {
  function d3_timer_step (line 2055) | function d3_timer_step() {
  function d3_timer_mark (line 2072) | function d3_timer_mark() {
  function d3_timer_sweep (line 2081) | function d3_timer_sweep() {
  function d3_format_precision (line 2094) | function d3_format_precision(x, p) {
  function d3_formatPrefix (line 2111) | function d3_formatPrefix(d, i) {
  function d3_locale_numberFormat (line 2122) | function d3_locale_numberFormat(locale) {
  function d3_format_typeDefault (line 2243) | function d3_format_typeDefault(x) {
  function d3_date_utc (line 2247) | function d3_date_utc() {
  function d3_time_interval (line 2313) | function d3_time_interval(local, step, number) {
  function d3_time_interval_utc (line 2361) | function d3_time_interval_utc(method) {
  function d3_locale_timeFormat (line 2421) | function d3_locale_timeFormat(locale) {
  function d3_time_formatPad (line 2641) | function d3_time_formatPad(value, fill, width) {
  function d3_time_formatRe (line 2645) | function d3_time_formatRe(names) {
  function d3_time_formatLookup (line 2648) | function d3_time_formatLookup(names) {
  function d3_time_parseWeekdayNumber (line 2653) | function d3_time_parseWeekdayNumber(date, string, i) {
  function d3_time_parseWeekNumberSunday (line 2658) | function d3_time_parseWeekNumberSunday(date, string, i) {
  function d3_time_parseWeekNumberMonday (line 2663) | function d3_time_parseWeekNumberMonday(date, string, i) {
  function d3_time_parseFullYear (line 2668) | function d3_time_parseFullYear(date, string, i) {
  function d3_time_parseYear (line 2673) | function d3_time_parseYear(date, string, i) {
  function d3_time_parseZone (line 2678) | function d3_time_parseZone(date, string, i) {
  function d3_time_expandYear (line 2682) | function d3_time_expandYear(d) {
  function d3_time_parseMonthNumber (line 2685) | function d3_time_parseMonthNumber(date, string, i) {
  function d3_time_parseDay (line 2690) | function d3_time_parseDay(date, string, i) {
  function d3_time_parseDayOfYear (line 2695) | function d3_time_parseDayOfYear(date, string, i) {
  function d3_time_parseHour24 (line 2700) | function d3_time_parseHour24(date, string, i) {
  function d3_time_parseMinutes (line 2705) | function d3_time_parseMinutes(date, string, i) {
  function d3_time_parseSeconds (line 2710) | function d3_time_parseSeconds(date, string, i) {
  function d3_time_parseMilliseconds (line 2715) | function d3_time_parseMilliseconds(date, string, i) {
  function d3_time_zone (line 2720) | function d3_time_zone(d) {
  function d3_time_parseLiteralPercent (line 2724) | function d3_time_parseLiteralPercent(date, string, i) {
  function d3_time_formatMulti (line 2729) | function d3_time_formatMulti(formats) {
  function d3_adder (line 2760) | function d3_adder() {}
  function d3_adderSum (line 2777) | function d3_adderSum(a, b, o) {
  function d3_geo_streamGeometry (line 2788) | function d3_geo_streamGeometry(geometry, listener) {
  function d3_geo_streamLine (line 2833) | function d3_geo_streamLine(coordinates, listener, closed) {
  function d3_geo_streamPolygon (line 2839) | function d3_geo_streamPolygon(coordinates, listener) {
  function d3_geo_areaRingStart (line 2868) | function d3_geo_areaRingStart() {
  function d3_geo_cartesian (line 2886) | function d3_geo_cartesian(spherical) {
  function d3_geo_cartesianDot (line 2890) | function d3_geo_cartesianDot(a, b) {
  function d3_geo_cartesianCross (line 2893) | function d3_geo_cartesianCross(a, b) {
  function d3_geo_cartesianAdd (line 2896) | function d3_geo_cartesianAdd(a, b) {
  function d3_geo_cartesianScale (line 2901) | function d3_geo_cartesianScale(vector, k) {
  function d3_geo_cartesianNormalize (line 2904) | function d3_geo_cartesianNormalize(d) {
  function d3_geo_spherical (line 2910) | function d3_geo_spherical(cartesian) {
  function d3_geo_sphericalEqual (line 2913) | function d3_geo_sphericalEqual(a, b) {
  function point (line 2938) | function point(λ, φ) {
  function linePoint (line 2943) | function linePoint(λ, φ) {
  function lineStart (line 2983) | function lineStart() {
  function lineEnd (line 2986) | function lineEnd() {
  function ringPoint (line 2991) | function ringPoint(λ, φ) {
  function ringStart (line 2999) | function ringStart() {
  function ringEnd (line 3002) | function ringEnd() {
  function angle (line 3009) | function angle(λ0, λ1) {
  function compareRanges (line 3012) | function compareRanges(a, b) {
  function withinRange (line 3015) | function withinRange(x, range) {
  function d3_geo_centroidPoint (line 3069) | function d3_geo_centroidPoint(λ, φ) {
  function d3_geo_centroidPointXYZ (line 3074) | function d3_geo_centroidPointXYZ(x, y, z) {
  function d3_geo_centroidLineStart (line 3080) | function d3_geo_centroidLineStart() {
  function d3_geo_centroidLineEnd (line 3101) | function d3_geo_centroidLineEnd() {
  function d3_geo_centroidRingStart (line 3104) | function d3_geo_centroidRingStart() {
  function d3_true (line 3134) | function d3_true() {
  function d3_geo_clipPolygon (line 3137) | function d3_geo_clipPolygon(segments, compare, clipStartInside, interpol...
  function d3_geo_clipPolygonLinkCircular (line 3196) | function d3_geo_clipPolygonLinkCircular(array) {
  function d3_geo_clipPolygonIntersection (line 3207) | function d3_geo_clipPolygonIntersection(point, points, other, entry) {
  function d3_geo_clip (line 3215) | function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
  function d3_geo_clipSegmentLength1 (line 3307) | function d3_geo_clipSegmentLength1(segment) {
  function d3_geo_clipBufferListener (line 3310) | function d3_geo_clipBufferListener() {
  function d3_geo_clipSort (line 3331) | function d3_geo_clipSort(a, b) {
  function d3_geo_clipAntimeridianLine (line 3335) | function d3_geo_clipAntimeridianLine(listener) {
  function d3_geo_clipAntimeridianIntersect (line 3374) | function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
  function d3_geo_clipAntimeridianInterpolate (line 3378) | function d3_geo_clipAntimeridianInterpolate(from, to, direction, listene...
  function d3_geo_pointInPolygon (line 3401) | function d3_geo_pointInPolygon(point, polygon) {
  function d3_geo_clipCircle (line 3430) | function d3_geo_clipCircle(radius) {
  function d3_geom_clipLine (line 3526) | function d3_geom_clipLine(x0, y0, x1, y1) {
  function d3_geo_clipExtent (line 3598) | function d3_geo_clipExtent(x0, y0, x1, y1) {
  function d3_geo_compose (line 3732) | function d3_geo_compose(a, b) {
  function d3_geo_conic (line 3741) | function d3_geo_conic(projectAt) {
  function d3_geo_conicEqualArea (line 3749) | function d3_geo_conicEqualArea(φ0, φ1) {
  function albersUsa (line 3776) | function albersUsa(coordinates) {
  function d3_geo_pathAreaRingStart (line 3858) | function d3_geo_pathAreaRingStart() {
  function d3_geo_pathBoundsPoint (line 3880) | function d3_geo_pathBoundsPoint(x, y) {
  function d3_geo_pathBuffer (line 3886) | function d3_geo_pathBuffer() {
  function d3_geo_pathBufferCircle (line 3931) | function d3_geo_pathBufferCircle(radius) {
  function d3_geo_pathCentroidPoint (line 3947) | function d3_geo_pathCentroidPoint(x, y) {
  function d3_geo_pathCentroidLineStart (line 3952) | function d3_geo_pathCentroidLineStart() {
  function d3_geo_pathCentroidLineEnd (line 3966) | function d3_geo_pathCentroidLineEnd() {
  function d3_geo_pathCentroidRingStart (line 3969) | function d3_geo_pathCentroidRingStart() {
  function d3_geo_pathContext (line 3990) | function d3_geo_pathContext(context) {
  function d3_geo_resample (line 4030) | function d3_geo_resample(project) {
  function path (line 4110) | function path(object) {
  function reset (line 4149) | function reset() {
  function d3_geo_pathProjectStream (line 4155) | function d3_geo_pathProjectStream(project) {
  function d3_geo_transform (line 4172) | function d3_geo_transform(stream) {
  function d3_geo_transformPoint (line 4195) | function d3_geo_transformPoint(stream, point) {
  function d3_geo_projection (line 4217) | function d3_geo_projection(project) {
  function d3_geo_projectionMutator (line 4222) | function d3_geo_projectionMutator(projectAt) {
  function d3_geo_projectionRadians (line 4294) | function d3_geo_projectionRadians(stream) {
  function d3_geo_equirectangular (line 4299) | function d3_geo_equirectangular(λ, φ) {
  function forward (line 4307) | function forward(coordinates) {
  function d3_geo_identityRotation (line 4317) | function d3_geo_identityRotation(λ, φ) {
  function d3_geo_rotation (line 4321) | function d3_geo_rotation(δλ, δφ, δγ) {
  function d3_geo_forwardRotationλ (line 4324) | function d3_geo_forwardRotationλ(δλ) {
  function d3_geo_rotationλ (line 4329) | function d3_geo_rotationλ(δλ) {
  function d3_geo_rotationφγ (line 4334) | function d3_geo_rotationφγ(δφ, δγ) {
  function circle (line 4348) | function circle() {
  function d3_geo_circleInterpolate (line 4378) | function d3_geo_circleInterpolate(radius, precision) {
  function d3_geo_circleAngle (line 4395) | function d3_geo_circleAngle(cr, point) {
  function graticule (line 4408) | function graticule() {
  function lines (line 4414) | function lines() {
  function d3_geo_graticuleX (line 4480) | function d3_geo_graticuleX(y0, y1, dy) {
  function d3_geo_graticuleY (line 4488) | function d3_geo_graticuleY(x0, x1, dx) {
  function d3_source (line 4496) | function d3_source(d) {
  function d3_target (line 4499) | function d3_target(d) {
  function greatArc (line 4504) | function greatArc() {
  function d3_geo_interpolate (line 4531) | function d3_geo_interpolate(x0, y0, x1, y1) {
  function d3_geo_lengthLineStart (line 4556) | function d3_geo_lengthLineStart() {
  function d3_geo_azimuthal (line 4571) | function d3_geo_azimuthal(scale, angle) {
  function d3_geo_conicConformal (line 4597) | function d3_geo_conicConformal(φ0, φ1) {
  function d3_geo_conicEquidistant (line 4620) | function d3_geo_conicEquidistant(φ0, φ1) {
  function d3_geo_mercator (line 4642) | function d3_geo_mercator(λ, φ) {
  function d3_geo_mercatorProjection (line 4648) | function d3_geo_mercatorProjection(project) {
  function d3_geo_transverseMercator (line 4689) | function d3_geo_transverseMercator(λ, φ) {
  function d3_geom_pointX (line 4707) | function d3_geom_pointX(d) {
  function d3_geom_pointY (line 4710) | function d3_geom_pointY(d) {
  function hull (line 4716) | function hull(data) {
  function d3_geom_hullUpper (line 4738) | function d3_geom_hullUpper(points) {
  function d3_geom_hullOrder (line 4746) | function d3_geom_hullOrder(a, b) {
  function d3_geom_polygonInside (line 4800) | function d3_geom_polygonInside(p, a, b) {
  function d3_geom_polygonIntersect (line 4803) | function d3_geom_polygonIntersect(c, d, a, b) {
  function d3_geom_polygonClosed (line 4807) | function d3_geom_polygonClosed(coordinates) {
  function d3_geom_voronoiBeach (line 4812) | function d3_geom_voronoiBeach() {
  function d3_geom_voronoiCreateBeach (line 4816) | function d3_geom_voronoiCreateBeach(site) {
  function d3_geom_voronoiDetachBeach (line 4821) | function d3_geom_voronoiDetachBeach(beach) {
  function d3_geom_voronoiRemoveBeach (line 4827) | function d3_geom_voronoiRemoveBeach(beach) {
  function d3_geom_voronoiAddBeach (line 4863) | function d3_geom_voronoiAddBeach(site) {
  function d3_geom_voronoiLeftBreakPoint (line 4917) | function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
  function d3_geom_voronoiRightBreakPoint (line 4929) | function d3_geom_voronoiRightBreakPoint(arc, directrix) {
  function d3_geom_voronoiCell (line 4935) | function d3_geom_voronoiCell(site) {
  function d3_geom_voronoiCloseCells (line 4948) | function d3_geom_voronoiCloseCells(extent) {
  function d3_geom_voronoiHalfEdgeOrder (line 4978) | function d3_geom_voronoiHalfEdgeOrder(a, b) {
  function d3_geom_voronoiCircle (line 4981) | function d3_geom_voronoiCircle() {
  function d3_geom_voronoiAttachCircle (line 4985) | function d3_geom_voronoiAttachCircle(arc) {
  function d3_geom_voronoiDetachCircle (line 5018) | function d3_geom_voronoiDetachCircle(arc) {
  function d3_geom_voronoiClipEdges (line 5028) | function d3_geom_voronoiClipEdges(extent) {
  function d3_geom_voronoiConnectEdge (line 5038) | function d3_geom_voronoiConnectEdge(edge, extent) {
  function d3_geom_voronoiEdge (line 5112) | function d3_geom_voronoiEdge(lSite, rSite) {
  function d3_geom_voronoiCreateEdge (line 5117) | function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
  function d3_geom_voronoiCreateBorderEdge (line 5126) | function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
  function d3_geom_voronoiSetEdgeEnd (line 5133) | function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
  function d3_geom_voronoiHalfEdge (line 5144) | function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
  function d3_geom_voronoiRedBlackTree (line 5158) | function d3_geom_voronoiRedBlackTree() {
  function d3_geom_voronoiRedBlackNode (line 5161) | function d3_geom_voronoiRedBlackNode(node) {
  function d3_geom_voronoiRedBlackRotateLeft (line 5324) | function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
  function d3_geom_voronoiRedBlackRotateRight (line 5337) | function d3_geom_voronoiRedBlackRotateRight(tree, node) {
  function d3_geom_voronoiRedBlackFirst (line 5350) | function d3_geom_voronoiRedBlackFirst(node) {
  function d3_geom_voronoi (line 5354) | function d3_geom_voronoi(sites, bbox) {
  function d3_geom_voronoiVertexOrder (line 5383) | function d3_geom_voronoiVertexOrder(a, b) {
  function voronoi (line 5389) | function voronoi(data) {
  function sites (line 5400) | function sites(data) {
  function d3_geom_voronoiTriangleArea (line 5453) | function d3_geom_voronoiTriangleArea(a, b, c) {
  function quadtree (line 5471) | function quadtree(data) {
  function d3_geom_quadtreeCompatX (line 5563) | function d3_geom_quadtreeCompatX(d) {
  function d3_geom_quadtreeCompatY (line 5566) | function d3_geom_quadtreeCompatY(d) {
  function d3_geom_quadtreeNode (line 5569) | function d3_geom_quadtreeNode() {
  function d3_geom_quadtreeVisit (line 5578) | function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
  function d3_interpolateRgb (line 5588) | function d3_interpolateRgb(a, b) {
  function d3_interpolateObject (line 5597) | function d3_interpolateObject(a, b) {
  function d3_interpolateNumber (line 5617) | function d3_interpolateNumber(a, b) {
  function d3_interpolateString (line 5624) | function d3_interpolateString(a, b) {
  function d3_interpolate (line 5658) | function d3_interpolate(a, b) {
  function d3_interpolateArray (line 5668) | function d3_interpolateArray(a, b) {
  function d3_ease_clamp (line 5719) | function d3_ease_clamp(f) {
  function d3_ease_reverse (line 5724) | function d3_ease_reverse(f) {
  function d3_ease_reflect (line 5729) | function d3_ease_reflect(f) {
  function d3_ease_quad (line 5734) | function d3_ease_quad(t) {
  function d3_ease_cubic (line 5737) | function d3_ease_cubic(t) {
  function d3_ease_cubicInOut (line 5740) | function d3_ease_cubicInOut(t) {
  function d3_ease_poly (line 5746) | function d3_ease_poly(e) {
  function d3_ease_sin (line 5751) | function d3_ease_sin(t) {
  function d3_ease_exp (line 5754) | function d3_ease_exp(t) {
  function d3_ease_circle (line 5757) | function d3_ease_circle(t) {
  function d3_ease_elastic (line 5760) | function d3_ease_elastic(a, p) {
  function d3_ease_back (line 5768) | function d3_ease_back(s) {
  function d3_ease_bounce (line 5774) | function d3_ease_bounce(t) {
  function d3_interpolateHcl (line 5778) | function d3_interpolateHcl(a, b) {
  function d3_interpolateHsl (line 5789) | function d3_interpolateHsl(a, b) {
  function d3_interpolateLab (line 5800) | function d3_interpolateLab(a, b) {
  function d3_interpolateRound (line 5809) | function d3_interpolateRound(a, b) {
  function d3_transform (line 5825) | function d3_transform(m) {
  function d3_transformDot (line 5841) | function d3_transformDot(a, b) {
  function d3_transformNormalize (line 5844) | function d3_transformNormalize(a) {
  function d3_transformCombine (line 5852) | function d3_transformCombine(a, b, k) {
  function d3_interpolateTransform (line 5866) | function d3_interpolateTransform(a, b) {
  function d3_uninterpolateNumber (line 5918) | function d3_uninterpolateNumber(a, b) {
  function d3_uninterpolateClamp (line 5924) | function d3_uninterpolateClamp(a, b) {
  function d3_layout_bundlePath (line 5938) | function d3_layout_bundlePath(link) {
  function d3_layout_bundleAncestors (line 5951) | function d3_layout_bundleAncestors(node) {
  function d3_layout_bundleLeastCommonAncestor (line 5961) | function d3_layout_bundleLeastCommonAncestor(a, b) {
  function relayout (line 5973) | function relayout() {
  function resort (line 6039) | function resort() {
  function repulse (line 6086) | function repulse(node) {
  function position (line 6258) | function position(dimension, size) {
  function dragmove (line 6287) | function dragmove(d) {
  function d3_layout_forceDragstart (line 6293) | function d3_layout_forceDragstart(d) {
  function d3_layout_forceDragend (line 6296) | function d3_layout_forceDragend(d) {
  function d3_layout_forceMouseover (line 6299) | function d3_layout_forceMouseover(d) {
  function d3_layout_forceMouseout (line 6303) | function d3_layout_forceMouseout(d) {
  function d3_layout_forceAccumulate (line 6306) | function d3_layout_forceAccumulate(quad, alpha, charges) {
  function hierarchy (line 6336) | function hierarchy(root) {
  function d3_layout_hierarchyRebind (line 6392) | function d3_layout_hierarchyRebind(object, hierarchy) {
  function d3_layout_hierarchyVisitBefore (line 6398) | function d3_layout_hierarchyVisitBefore(node, callback) {
  function d3_layout_hierarchyVisitAfter (line 6408) | function d3_layout_hierarchyVisitAfter(node, callback) {
  function d3_layout_hierarchyChildren (line 6421) | function d3_layout_hierarchyChildren(d) {
  function d3_layout_hierarchyValue (line 6424) | function d3_layout_hierarchyValue(d) {
  function d3_layout_hierarchySort (line 6427) | function d3_layout_hierarchySort(a, b) {
  function d3_layout_hierarchyLinks (line 6430) | function d3_layout_hierarchyLinks(nodes) {
  function position (line 6442) | function position(node, x, dx, dy) {
  function depth (line 6457) | function depth(node) {
  function partition (line 6465) | function partition(d, i) {
  function pie (line 6479) | function pie(data) {
  function stack (line 6528) | function stack(data, index) {
  function d3_layout_stackX (line 6583) | function d3_layout_stackX(d) {
  function d3_layout_stackY (line 6586) | function d3_layout_stackY(d) {
  function d3_layout_stackOut (line 6589) | function d3_layout_stackOut(d, y0, y) {
  function d3_layout_stackOrderDefault (line 6656) | function d3_layout_stackOrderDefault(data) {
  function d3_layout_stackOffsetZero (line 6659) | function d3_layout_stackOffsetZero(data) {
  function d3_layout_stackMaxIndex (line 6664) | function d3_layout_stackMaxIndex(array) {
  function d3_layout_stackReduceSum (line 6674) | function d3_layout_stackReduceSum(d) {
  function d3_layout_stackSum (line 6677) | function d3_layout_stackSum(p, d) {
  function histogram (line 6682) | function histogram(data, i) {
  function d3_layout_histogramBinSturges (line 6726) | function d3_layout_histogramBinSturges(range, values) {
  function d3_layout_histogramBinFixed (line 6729) | function d3_layout_histogramBinFixed(range, n) {
  function d3_layout_histogramRange (line 6734) | function d3_layout_histogramRange(values) {
  function pack (line 6739) | function pack(d, i) {
  function d3_layout_packSort (line 6778) | function d3_layout_packSort(a, b) {
  function d3_layout_packInsert (line 6781) | function d3_layout_packInsert(a, b) {
  function d3_layout_packSplice (line 6788) | function d3_layout_packSplice(a, b) {
  function d3_layout_packIntersects (line 6792) | function d3_layout_packIntersects(a, b) {
  function d3_layout_packSiblings (line 6796) | function d3_layout_packSiblings(node) {
  function d3_layout_packLink (line 6860) | function d3_layout_packLink(node) {
  function d3_layout_packUnlink (line 6863) | function d3_layout_packUnlink(node) {
  function d3_layout_packTransform (line 6867) | function d3_layout_packTransform(node, x, y, k) {
  function d3_layout_packPlace (line 6877) | function d3_layout_packPlace(a, b, c) {
  function tree (line 6893) | function tree(d, i) {
  function wrapTree (line 6912) | function wrapTree(root0) {
  function firstWalk (line 6936) | function firstWalk(v) {
  function secondWalk (line 6952) | function secondWalk(v) {
  function apportion (line 6956) | function apportion(v, w, ancestor) {
  function sizeNode (line 6986) | function sizeNode(node) {
  function d3_layout_treeSeparation (line 7007) | function d3_layout_treeSeparation(a, b) {
  function d3_layout_treeLeft (line 7010) | function d3_layout_treeLeft(v) {
  function d3_layout_treeRight (line 7014) | function d3_layout_treeRight(v) {
  function d3_layout_treeMove (line 7018) | function d3_layout_treeMove(wm, wp, shift) {
  function d3_layout_treeShift (line 7026) | function d3_layout_treeShift(v) {
  function d3_layout_treeAncestor (line 7035) | function d3_layout_treeAncestor(vim, v, ancestor) {
  function cluster (line 7040) | function cluster(d, i) {
  function d3_layout_clusterY (line 7080) | function d3_layout_clusterY(children) {
  function d3_layout_clusterX (line 7085) | function d3_layout_clusterX(children) {
  function d3_layout_clusterLeft (line 7090) | function d3_layout_clusterLeft(node) {
  function d3_layout_clusterRight (line 7094) | function d3_layout_clusterRight(node) {
  function scale (line 7100) | function scale(children, k) {
  function squarify (line 7107) | function squarify(node) {
  function stickify (line 7134) | function stickify(node) {
  function worst (line 7151) | function worst(row, u) {
  function position (line 7162) | function position(row, u, rect, flush) {
  function treemap (line 7192) | function treemap(d) {
  function padFunction (line 7211) | function padFunction(node) {
  function padConstant (line 7215) | function padConstant(node) {
  function d3_layout_treemapPadNull (line 7246) | function d3_layout_treemapPadNull(node) {
  function d3_layout_treemapPad (line 7254) | function d3_layout_treemapPad(node, padding) {
  function d3_scaleExtent (line 7306) | function d3_scaleExtent(domain) {
  function d3_scaleRange (line 7310) | function d3_scaleRange(scale) {
  function d3_scale_bilinear (line 7313) | function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
  function d3_scale_nice (line 7319) | function d3_scale_nice(domain, nice) {
  function d3_scale_niceStep (line 7329) | function d3_scale_niceStep(step) {
  function d3_scale_polylinear (line 7343) | function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
  function d3_scale_linear (line 7361) | function d3_scale_linear(domain, range, interpolate, clamp) {
  function d3_scale_linearRebind (line 7413) | function d3_scale_linearRebind(scale, linear) {
  function d3_scale_linearNice (line 7416) | function d3_scale_linearNice(domain, m) {
  function d3_scale_linearTickRange (line 7419) | function d3_scale_linearTickRange(domain, m) {
  function d3_scale_linearTicks (line 7428) | function d3_scale_linearTicks(domain, m) {
  function d3_scale_linearTickFormat (line 7431) | function d3_scale_linearTickFormat(domain, m, format) {
  function d3_scale_linearPrecision (line 7459) | function d3_scale_linearPrecision(value) {
  function d3_scale_linearFormatPrecision (line 7462) | function d3_scale_linearFormatPrecision(type, range) {
  function d3_scale_log (line 7469) | function d3_scale_log(linear, base, positive, domain) {
  function d3_scale_pow (line 7541) | function d3_scale_pow(linear, exponent, domain) {
  function d3_scale_powPow (line 7575) | function d3_scale_powPow(e) {
  function d3_scale_ordinal (line 7589) | function d3_scale_ordinal(domain, ranger) {
  function d3_scale_quantile (line 7684) | function d3_scale_quantile(domain, range) {
  function d3_scale_quantize (line 7720) | function d3_scale_quantize(x0, x1, range) {
  function d3_scale_threshold (line 7754) | function d3_scale_threshold(domain, range) {
  function d3_scale_identity (line 7780) | function d3_scale_identity(domain) {
  function arc (line 7804) | function arc() {
  function d3_svg_arcInnerRadius (line 7836) | function d3_svg_arcInnerRadius(d) {
  function d3_svg_arcOuterRadius (line 7839) | function d3_svg_arcOuterRadius(d) {
  function d3_svg_arcStartAngle (line 7842) | function d3_svg_arcStartAngle(d) {
  function d3_svg_arcEndAngle (line 7845) | function d3_svg_arcEndAngle(d) {
  function d3_svg_line (line 7848) | function d3_svg_line(projection) {
  function d3_svg_lineLinear (line 7915) | function d3_svg_lineLinear(points) {
  function d3_svg_lineLinearClosed (line 7918) | function d3_svg_lineLinearClosed(points) {
  function d3_svg_lineStep (line 7921) | function d3_svg_lineStep(points) {
  function d3_svg_lineStepBefore (line 7927) | function d3_svg_lineStepBefore(points) {
  function d3_svg_lineStepAfter (line 7932) | function d3_svg_lineStepAfter(points) {
  function d3_svg_lineCardinalOpen (line 7937) | function d3_svg_lineCardinalOpen(points, tension) {
  function d3_svg_lineCardinalClosed (line 7940) | function d3_svg_lineCardinalClosed(points, tension) {
  function d3_svg_lineCardinal (line 7944) | function d3_svg_lineCardinal(points, tension) {
  function d3_svg_lineHermite (line 7947) | function d3_svg_lineHermite(points, tangents) {
  function d3_svg_lineCardinalTangents (line 7974) | function d3_svg_lineCardinalTangents(points, tension) {
  function d3_svg_lineBasis (line 7984) | function d3_svg_lineBasis(points) {
  function d3_svg_lineBasisOpen (line 8000) | function d3_svg_lineBasisOpen(points) {
  function d3_svg_lineBasisClosed (line 8020) | function d3_svg_lineBasisClosed(points) {
  function d3_svg_lineBundle (line 8039) | function d3_svg_lineBundle(points, tension) {
  function d3_svg_lineDot4 (line 8052) | function d3_svg_lineDot4(a, b) {
  function d3_svg_lineBasisBezier (line 8056) | function d3_svg_lineBasisBezier(path, x, y) {
  function d3_svg_lineSlope (line 8059) | function d3_svg_lineSlope(p0, p1) {
  function d3_svg_lineFiniteDifferences (line 8062) | function d3_svg_lineFiniteDifferences(points) {
  function d3_svg_lineMonotoneTangents (line 8070) | function d3_svg_lineMonotoneTangents(points) {
  function d3_svg_lineMonotone (line 8094) | function d3_svg_lineMonotone(points) {
  function d3_svg_lineRadial (line 8103) | function d3_svg_lineRadial(points) {
  function d3_svg_area (line 8114) | function d3_svg_area(projection) {
  function chord (line 8204) | function chord(d, i) {
  function subgroup (line 8208) | function subgroup(self, f, d, i) {
  function equals (line 8218) | function equals(a, b) {
  function arc (line 8221) | function arc(r, p, a) {
  function curve (line 8224) | function curve(r0, p0, r1, p1) {
  function d3_svg_chordRadius (line 8254) | function d3_svg_chordRadius(d) {
  function diagonal (line 8259) | function diagonal(d, i) {
  function d3_svg_diagonalProjection (line 8287) | function d3_svg_diagonalProjection(d) {
  function d3_svg_diagonalRadialProjection (line 8297) | function d3_svg_diagonalRadialProjection(projection) {
  function symbol (line 8305) | function symbol(d, i) {
  function d3_svg_symbolSize (line 8320) | function d3_svg_symbolSize() {
  function d3_svg_symbolType (line 8323) | function d3_svg_symbolType() {
  function d3_svg_symbolCircle (line 8326) | function d3_svg_symbolCircle(size) {
  function d3_transition (line 8355) | function d3_transition(groups, id) {
  function d3_transition_tween (line 8426) | function d3_transition_tween(groups, name, value, tween) {
  function attrNull (line 8440) | function attrNull() {
  function attrNullNS (line 8443) | function attrNullNS() {
  function attrTween (line 8446) | function attrTween(b) {
  function attrTweenNS (line 8454) | function attrTweenNS(b) {
  function attrTween (line 8466) | function attrTween(d, i) {
  function attrTweenNS (line 8472) | function attrTweenNS(d, i) {
  function styleNull (line 8490) | function styleNull() {
  function styleString (line 8493) | function styleString(b) {
  function styleTween (line 8505) | function styleTween(d, i) {
  function d3_transition_text (line 8516) | function d3_transition_text(b) {
  function d3_transitionNode (line 8588) | function d3_transitionNode(node, i, id, inherit) {
  function axis (line 8642) | function axis(g) {
  function d3_svg_axisX (line 8737) | function d3_svg_axisX(selection, x0, x1) {
  function d3_svg_axisY (line 8743) | function d3_svg_axisY(selection, y0, y1) {
  function brush (line 8751) | function brush(g) {
  function redraw (line 8837) | function redraw(g) {
  function redrawX (line 8842) | function redrawX(g) {
  function redrawY (line 8846) | function redrawY(g) {
  function brushstart (line 8850) | function brushstart() {
  function d3_time_formatIsoNative (line 9043) | function d3_time_formatIsoNative(date) {
  function d3_time_scale (line 9090) | function d3_time_scale(linear, methods, format) {
  function d3_time_scaleDate (line 9140) | function d3_time_scaleDate(t) {
  function d3_json (line 9199) | function d3_json(request) {
  function d3_html (line 9205) | function d3_html(request) {

FILE: fks_chart/bower_components/jquery/dist/jquery.js
  function isArraylike (line 533) | function isArraylike( obj ) {
  function Sizzle (line 745) | function Sizzle( selector, context, results, seed ) {
  function createCache (line 859) | function createCache() {
  function markFunction (line 877) | function markFunction( fn ) {
  function assert (line 886) | function assert( fn ) {
  function addHandle (line 908) | function addHandle( attrs, handler ) {
  function siblingCheck (line 923) | function siblingCheck( a, b ) {
  function createInputPseudo (line 950) | function createInputPseudo( type ) {
  function createButtonPseudo (line 961) | function createButtonPseudo( type ) {
  function createPositionalPseudo (line 972) | function createPositionalPseudo( fn ) {
  function testContext (line 995) | function testContext( context ) {
  function setFilters (line 2004) | function setFilters() {}
  function toSelector (line 2075) | function toSelector( tokens ) {
  function addCombinator (line 2085) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 2138) | function elementMatcher( matchers ) {
  function multipleContexts (line 2152) | function multipleContexts( selector, contexts, results ) {
  function condense (line 2161) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 2182) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 2275) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 2333) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  function winnow (line 2629) | function winnow( elements, qualifier, not ) {
  function sibling (line 2953) | function sibling( cur, dir ) {
  function createOptions (line 3031) | function createOptions( options ) {
  function completed (line 3425) | function completed() {
  function Data (line 3530) | function Data() {
  function dataAttr (line 3721) | function dataAttr( elem, key, data ) {
  function returnTrue (line 4061) | function returnTrue() {
  function returnFalse (line 4065) | function returnFalse() {
  function safeActiveElement (line 4069) | function safeActiveElement() {
  function manipulationTarget (line 4941) | function manipulationTarget( elem, content ) {
  function disableScript (line 4951) | function disableScript( elem ) {
  function restoreScript (line 4955) | function restoreScript( elem ) {
  function setGlobalEval (line 4968) | function setGlobalEval( elems, refElements ) {
  function cloneCopyEvent (line 4979) | function cloneCopyEvent( src, dest ) {
  function getAll (line 5013) | function getAll( context, tag ) {
  function fixInput (line 5024) | function fixInput( src, dest ) {
  function actualDisplay (line 5479) | function actualDisplay( name, doc ) {
  function defaultDisplay (line 5501) | function defaultDisplay( nodeName ) {
  function curCSS (line 5548) | function curCSS( elem, name, computed ) {
  function addGetHookIf (line 5596) | function addGetHookIf( conditionFn, hookFn ) {
  function computePixelPositionAndBoxSizingReliable (line 5636) | function computePixelPositionAndBoxSizingReliable() {
  function vendorPropName (line 5741) | function vendorPropName( style, name ) {
  function setPositiveNumber (line 5763) | function setPositiveNumber( elem, value, subtract ) {
  function augmentWidthOrHeight (line 5771) | function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  function getWidthOrHeight (line 5810) | function getWidthOrHeight( elem, name, extra ) {
  function showHide (line 5854) | function showHide( elements, show ) {
  function Tween (line 6152) | function Tween( elem, options, prop, end, easing ) {
  function createFxNow (line 6321) | function createFxNow() {
  function genFx (line 6329) | function genFx( type, includeWidth ) {
  function createTween (line 6349) | function createTween( value, prop, animation ) {
  function defaultPrefilter (line 6363) | function defaultPrefilter( elem, props, opts ) {
  function propFilter (line 6496) | function propFilter( props, specialEasing ) {
  function Animation (line 6533) | function Animation( elem, properties, options ) {
  function addToPrefiltersOrTransports (line 7581) | function addToPrefiltersOrTransports( structure ) {
  function inspectPrefiltersOrTransports (line 7613) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
  function ajaxExtend (line 7640) | function ajaxExtend( target, src ) {
  function ajaxHandleResponses (line 7660) | function ajaxHandleResponses( s, jqXHR, responses ) {
  function ajaxConvert (line 7716) | function ajaxConvert( s, response, jqXHR, isSuccess ) {
  function done (line 8174) | function done( status, nativeStatusText, responses, headers ) {
  function buildParams (line 8418) | function buildParams( prefix, obj, traditional, add ) {
  function getWindow (line 8912) | function getWindow( elem ) {

FILE: fks_chart/bower_components/jquery/src/ajax.js
  function addToPrefiltersOrTransports (line 50) | function addToPrefiltersOrTransports( structure ) {
  function inspectPrefiltersOrTransports (line 82) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
  function ajaxExtend (line 109) | function ajaxExtend( target, src ) {
  function ajaxHandleResponses (line 129) | function ajaxHandleResponses( s, jqXHR, responses ) {
  function ajaxConvert (line 185) | function ajaxConvert( s, response, jqXHR, isSuccess ) {
  function done (line 643) | function done( status, nativeStatusText, responses, headers ) {

FILE: fks_chart/bower_components/jquery/src/callbacks.js
  function createOptions (line 10) | function createOptions( options ) {

FILE: fks_chart/bower_components/jquery/src/core.js
  function isArraylike (line 480) | function isArraylike( obj ) {

FILE: fks_chart/bower_components/jquery/src/core/ready.js
  function completed (line 64) | function completed() {

FILE: fks_chart/bower_components/jquery/src/css.js
  function vendorPropName (line 39) | function vendorPropName( style, name ) {
  function setPositiveNumber (line 61) | function setPositiveNumber( elem, value, subtract ) {
  function augmentWidthOrHeight (line 69) | function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  function getWidthOrHeight (line 108) | function getWidthOrHeight( elem, name, extra ) {
  function showHide (line 152) | function showHide( elements, show ) {

FILE: fks_chart/bower_components/jquery/src/css/addGetHookIf.js
  function addGetHookIf (line 3) | function addGetHookIf( conditionFn, hookFn ) {

FILE: fks_chart/bower_components/jquery/src/css/curCSS.js
  function curCSS (line 9) | function curCSS( elem, name, computed ) {

FILE: fks_chart/bower_components/jquery/src/css/defaultDisplay.js
  function actualDisplay (line 15) | function actualDisplay( name, doc ) {
  function defaultDisplay (line 37) | function defaultDisplay( nodeName ) {

FILE: fks_chart/bower_components/jquery/src/css/support.js
  function computePixelPositionAndBoxSizingReliable (line 28) | function computePixelPositionAndBoxSizingReliable() {

FILE: fks_chart/bower_components/jquery/src/data.js
  function dataAttr (line 22) | function dataAttr( elem, key, data ) {

FILE: fks_chart/bower_components/jquery/src/data/Data.js
  function Data (line 7) | function Data() {

FILE: fks_chart/bower_components/jquery/src/effects.js
  function createFxNow (line 75) | function createFxNow() {
  function genFx (line 83) | function genFx( type, includeWidth ) {
  function createTween (line 103) | function createTween( value, prop, animation ) {
  function defaultPrefilter (line 117) | function defaultPrefilter( elem, props, opts ) {
  function propFilter (line 250) | function propFilter( props, specialEasing ) {
  function Animation (line 287) | function Animation( elem, properties, options ) {

FILE: fks_chart/bower_components/jquery/src/effects/Tween.js
  function Tween (line 6) | function Tween( elem, options, prop, end, easing ) {

FILE: fks_chart/bower_components/jquery/src/event.js
  function returnTrue (line 21) | function returnTrue() {
  function returnFalse (line 25) | function returnFalse() {
  function safeActiveElement (line 29) | function safeActiveElement() {

FILE: fks_chart/bower_components/jquery/src/manipulation.js
  function manipulationTarget (line 51) | function manipulationTarget( elem, content ) {
  function disableScript (line 61) | function disableScript( elem ) {
  function restoreScript (line 65) | function restoreScript( elem ) {
  function setGlobalEval (line 78) | function setGlobalEval( elems, refElements ) {
  function cloneCopyEvent (line 89) | function cloneCopyEvent( src, dest ) {
  function getAll (line 123) | function getAll( context, tag ) {
  function fixInput (line 134) | function fixInput( src, dest ) {

FILE: fks_chart/bower_components/jquery/src/offset.js
  function getWindow (line 20) | function getWindow( elem ) {

FILE: fks_chart/bower_components/jquery/src/serialize.js
  function buildParams (line 15) | function buildParams( prefix, obj, traditional, add ) {

FILE: fks_chart/bower_components/jquery/src/sizzle/dist/sizzle.js
  function Sizzle (line 197) | function Sizzle( selector, context, results, seed ) {
  function createCache (line 311) | function createCache() {
  function markFunction (line 329) | function markFunction( fn ) {
  function assert (line 338) | function assert( fn ) {
  function addHandle (line 360) | function addHandle( attrs, handler ) {
  function siblingCheck (line 375) | function siblingCheck( a, b ) {
  function createInputPseudo (line 402) | function createInputPseudo( type ) {
  function createButtonPseudo (line 413) | function createButtonPseudo( type ) {
  function createPositionalPseudo (line 424) | function createPositionalPseudo( fn ) {
  function testContext (line 447) | function testContext( context ) {
  function setFilters (line 1456) | function setFilters() {}
  function toSelector (line 1527) | function toSelector( tokens ) {
  function addCombinator (line 1537) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 1590) | function elementMatcher( matchers ) {
  function multipleContexts (line 1604) | function multipleContexts( selector, contexts, results ) {
  function condense (line 1613) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 1634) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 1727) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 1785) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {

FILE: fks_chart/bower_components/jquery/src/traversing.js
  function sibling (line 127) | function sibling( cur, dir ) {

FILE: fks_chart/bower_components/jquery/src/traversing/findFilter.js
  function winnow (line 11) | function winnow( elements, qualifier, not ) {

FILE: fks_chart/bower_components/marked/lib/marked.js
  function Lexer (line 101) | function Lexer(options) {
  function InlineLexer (line 518) | function InlineLexer(links, options) {
  function Renderer (line 753) | function Renderer(options) {
  function Parser (line 896) | function Parser(options) {
  function escape (line 1076) | function escape(html, encode) {
  function unescape (line 1085) | function unescape(html) {
  function replace (line 1098) | function replace(regex, opt) {
  function noop (line 1110) | function noop() {}
  function merge (line 1113) | function merge(obj) {
  function marked (line 1135) | function marked(src, opt, callback) {

FILE: fks_chart/bower_components/marked/test/browser/test.js
  function load (line 47) | function load() {
  function escape (line 51) | function escape(html, encode) {

FILE: fks_chart/bower_components/marked/test/index.js
  function load (line 21) | function load() {
  function runTests (line 58) | function runTests(engine, options) {
  function bench (line 174) | function bench(name, func) {
  function runBench (line 218) | function runBench(options) {
  function time (line 308) | function time(options) {
  function fix (line 326) | function fix(options) {
  function parseArg (line 416) | function parseArg(argv) {
  function camelize (line 500) | function camelize(text) {
  function main (line 510) | function main(argv) {

FILE: fks_chart/js/app.js
  function zoom (line 52) | function zoom () {
Condensed preview — 337 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,139K chars).
[
  {
    "path": ".gitignore",
    "chars": 17,
    "preview": "parallel.html\n*~\n"
  },
  {
    "path": "Makefile",
    "chars": 29,
    "preview": "all:\n\tnode ./bin/generate.js\n"
  },
  {
    "path": "README.en.md",
    "chars": 20010,
    "preview": "Frontend Knowledge Structure\n========\n## Original purpose\nOnce upon a time, there's a graph of Frontend Knowledge Struct"
  },
  {
    "path": "README.md",
    "chars": 18668,
    "preview": "Frontend Knowledge Structure\n========\n## 项目起源\n还记得@jayli 的这幅前端知识结构图么。\n\n![前端知识结构](https://raw.github.com/JacksonTian/fks/m"
  },
  {
    "path": "bin/generate.js",
    "chars": 1932,
    "preview": "var fs = require('fs');\nvar path = require('path');\n\nvar readme = fs.readFileSync(path.join(__dirname, '../README.md'), "
  },
  {
    "path": "fks_chart/bower.json",
    "chars": 349,
    "preview": "{\n  \"name\": \"front-end-collect-\",\n  \"version\": \"0.0.0\",\n  \"authors\": [\n    \"hjzheng <zhenghaoju700@163.com>\"\n  ],\n  \"lic"
  },
  {
    "path": "fks_chart/bower_components/angular/.bower.json",
    "chars": 433,
    "preview": "{\n  \"name\": \"angular\",\n  \"version\": \"1.2.28\",\n  \"main\": \"./angular.js\",\n  \"ignore\": [],\n  \"dependencies\": {},\n  \"homepag"
  },
  {
    "path": "fks_chart/bower_components/angular/README.md",
    "chars": 2144,
    "preview": "# packaged angular\n\nThis repo is for distribution on `npm` and `bower`. The source for this module is in the\n[main Angul"
  },
  {
    "path": "fks_chart/bower_components/angular/angular-csp.css",
    "chars": 535,
    "preview": "/* 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-n"
  },
  {
    "path": "fks_chart/bower_components/angular/angular.js",
    "chars": 789030,
    "preview": "/**\n * @license AngularJS v1.2.28\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(windo"
  },
  {
    "path": "fks_chart/bower_components/angular/bower.json",
    "chars": 114,
    "preview": "{\n  \"name\": \"angular\",\n  \"version\": \"1.2.28\",\n  \"main\": \"./angular.js\",\n  \"ignore\": [],\n  \"dependencies\": {\n  }\n}\n"
  },
  {
    "path": "fks_chart/bower_components/angular/package.json",
    "chars": 575,
    "preview": "{\n  \"name\": \"angular\",\n  \"version\": \"1.2.28\",\n  \"description\": \"HTML enhanced for web apps\",\n  \"main\": \"angular.js\",\n  \""
  },
  {
    "path": "fks_chart/bower_components/angular-marked/.bower.json",
    "chars": 869,
    "preview": "{\n  \"name\": \"angular-marked\",\n  \"version\": \"0.0.12\",\n  \"authors\": [\n    \"J. Harshbarger\"\n  ],\n  \"description\": \"AngularJ"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/README.md",
    "chars": 2307,
    "preview": "# angular-marked\r\nAngularJS Markdown using [marked](https://github.com/chjj/marked).\r\n\r\n## Usage\r\n1. `bower install angu"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/angular-marked.js",
    "chars": 1280,
    "preview": "/*\r\n * angular-marked\r\n * (c) 2014 J. Harshbarger\r\n * Licensed MIT\r\n */\r\n\r\n/* jshint undef: true, unused: true */\r\n/* gl"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/bower.json",
    "chars": 532,
    "preview": "{\n  \"name\": \"angular-marked\",\n  \"version\": \"0.0.12\",\n  \"authors\": [\n    \"J. Harshbarger\"\n  ],\n  \"description\": \"AngularJ"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/example/index.html",
    "chars": 2587,
    "preview": "<!DOCTYPE html>\r\n<html lang=\"en\" ng-app=\"example-app\">\r\n  <head>\r\n    <meta charset=\"utf-8\" />\r\n    <title>angular-marke"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/gruntfile.js",
    "chars": 1390,
    "preview": "module.exports = function(grunt){\r\n  'use strict';\r\n\r\n  grunt.initConfig({\r\n    pkg: grunt.file.readJSON('bower.json'),\r"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/karma.conf.js",
    "chars": 1404,
    "preview": "// Karma configuration\r\n// http://karma-runner.github.io/0.10/config/configuration-file.html\r\n\r\nmodule.exports = functio"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/package.json",
    "chars": 948,
    "preview": "{\n  \"name\": \"angular-marked\",\n  \"version\": \"0.0.12\",\n  \"description\": \"AngularJS Markdown using marked.\",\n  \"main\": \"ang"
  },
  {
    "path": "fks_chart/bower_components/angular-marked/todo.md",
    "chars": 180,
    "preview": "# Todo list\n\n_\\( managed using [todo-md](https://github.com/Hypercubed/todo-md) \\)_\n\n- [ ] Compatibility with RequireJS "
  },
  {
    "path": "fks_chart/bower_components/d3/.bower.json",
    "chars": 630,
    "preview": "{\n  \"name\": \"d3\",\n  \"version\": \"3.4.13\",\n  \"main\": \"d3.js\",\n  \"scripts\": [\n    \"d3.js\"\n  ],\n  \"ignore\": [\n    \".DS_Store"
  },
  {
    "path": "fks_chart/bower_components/d3/.spmignore",
    "chars": 17,
    "preview": "bin\nlib\nsrc\ntest\n"
  },
  {
    "path": "fks_chart/bower_components/d3/CONTRIBUTING.md",
    "chars": 2485,
    "preview": "# Contributing\n\nIf you’re looking for ways to contribute, please [peruse open issues](https://github.com/mbostock/d3/iss"
  },
  {
    "path": "fks_chart/bower_components/d3/LICENSE",
    "chars": 1429,
    "preview": "Copyright (c) 2010-2014, Michael Bostock\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with o"
  },
  {
    "path": "fks_chart/bower_components/d3/README.md",
    "chars": 698,
    "preview": "# Data-Driven Documents\n\n<a href=\"http://d3js.org\"><img src=\"http://d3js.org/logo.svg\" align=\"left\" hspace=\"10\" vspace=\""
  },
  {
    "path": "fks_chart/bower_components/d3/bower.json",
    "chars": 334,
    "preview": "{\n  \"name\": \"d3\",\n  \"version\": \"3.4.13\",\n  \"main\": \"d3.js\",\n  \"scripts\": [\n    \"d3.js\"\n  ],\n  \"ignore\": [\n    \".DS_Store"
  },
  {
    "path": "fks_chart/bower_components/d3/composer.json",
    "chars": 567,
    "preview": "{\n\t\"name\": \"mbostock/d3\",\n\t\"description\": \"A small, free JavaScript library for manipulating documents based on data.\",\n"
  },
  {
    "path": "fks_chart/bower_components/d3/d3.js",
    "chars": 324843,
    "preview": "!function() {\n  var d3 = {\n    version: \"3.4.13\"\n  };\n  if (!Date.now) Date.now = function() {\n    return +new Date();\n "
  },
  {
    "path": "fks_chart/bower_components/jquery/.bower.json",
    "chars": 736,
    "preview": "{\n  \"name\": \"jquery\",\n  \"version\": \"2.1.3\",\n  \"main\": \"dist/jquery.js\",\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n "
  },
  {
    "path": "fks_chart/bower_components/jquery/MIT-LICENSE.txt",
    "chars": 1099,
    "preview": "Copyright 2014 jQuery Foundation and other contributors\nhttp://jquery.com/\n\nPermission is hereby granted, free of charge"
  },
  {
    "path": "fks_chart/bower_components/jquery/bower.json",
    "chars": 435,
    "preview": "{\n  \"name\": \"jquery\",\n  \"version\": \"2.1.3\",\n  \"main\": \"dist/jquery.js\",\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n "
  },
  {
    "path": "fks_chart/bower_components/jquery/dist/jquery.js",
    "chars": 247387,
    "preview": "/*!\n * jQuery JavaScript Library v2.1.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Cop"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/jsonp.js",
    "chars": 2516,
    "preview": "define([\n\t\"../core\",\n\t\"./var/nonce\",\n\t\"./var/rquery\",\n\t\"../ajax\"\n], function( jQuery, nonce, rquery ) {\n\nvar oldCallback"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/load.js",
    "chars": 1669,
    "preview": "define([\n\t\"../core\",\n\t\"../core/parseHTML\",\n\t\"../ajax\",\n\t\"../traversing\",\n\t\"../manipulation\",\n\t\"../selector\",\n\t// Optiona"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/parseJSON.js",
    "chars": 222,
    "preview": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Support: Android 2.3\n// Workaround failure to string-cast null input\njQu"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/parseXML.js",
    "chars": 485,
    "preview": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml,"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/script.js",
    "chars": 1271,
    "preview": "define([\n\t\"../core\",\n\t\"../ajax\"\n], function( jQuery ) {\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscr"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/var/nonce.js",
    "chars": 73,
    "preview": "define([\n\t\"../../core\"\n], function( jQuery ) {\n\treturn jQuery.now();\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/var/rquery.js",
    "chars": 40,
    "preview": "define(function() {\n\treturn (/\\?/);\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax/xhr.js",
    "chars": 3488,
    "preview": "define([\n\t\"../core\",\n\t\"../var/support\",\n\t\"../ajax\"\n], function( jQuery, support ) {\n\njQuery.ajaxSettings.xhr = function("
  },
  {
    "path": "fks_chart/bower_components/jquery/src/ajax.js",
    "chars": 21168,
    "preview": "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"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/attributes/attr.js",
    "chars": 3320,
    "preview": "define([\n\t\"../core\",\n\t\"../var/rnotwhite\",\n\t\"../var/strundefined\",\n\t\"../core/access\",\n\t\"./support\",\n\t\"../selector\"\n], fun"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/attributes/classes.js",
    "chars": 4155,
    "preview": "define([\n\t\"../core\",\n\t\"../var/rnotwhite\",\n\t\"../var/strundefined\",\n\t\"../data/var/data_priv\",\n\t\"../core/init\"\n], function("
  },
  {
    "path": "fks_chart/bower_components/jquery/src/attributes/prop.js",
    "chars": 1854,
    "preview": "define([\n\t\"../core\",\n\t\"../core/access\",\n\t\"./support\"\n], function( jQuery, access, support ) {\n\nvar rfocusable = /^(?:inp"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/attributes/support.js",
    "chars": 893,
    "preview": "define([\n\t\"../var/support\"\n], function( support ) {\n\n(function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tsel"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/attributes/val.js",
    "chars": 3839,
    "preview": "define([\n\t\"../core\",\n\t\"./support\",\n\t\"../core/init\"\n], function( jQuery, support ) {\n\nvar rreturn = /\\r/g;\n\njQuery.fn.ext"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/attributes.js",
    "chars": 200,
    "preview": "define([\n\t\"./core\",\n\t\"./attributes/attr\",\n\t\"./attributes/prop\",\n\t\"./attributes/classes\",\n\t\"./attributes/val\"\n], function"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/callbacks.js",
    "chars": 5506,
    "preview": "define([\n\t\"./core\",\n\t\"./var/rnotwhite\"\n], function( jQuery, rnotwhite ) {\n\n// String to Object options format cache\nvar "
  },
  {
    "path": "fks_chart/bower_components/jquery/src/core/access.js",
    "chars": 1210,
    "preview": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Multifunctional method to get and set values of a collection\n// The valu"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/core/init.js",
    "chars": 3401,
    "preview": "// Initialize a jQuery object\ndefine([\n\t\"../core\",\n\t\"./var/rsingleTag\",\n\t\"../traversing/findFilter\"\n], function( jQuery,"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/core/parseHTML.js",
    "chars": 938,
    "preview": "define([\n\t\"../core\",\n\t\"./var/rsingleTag\",\n\t\"../manipulation\" // buildFragment\n], function( jQuery, rsingleTag ) {\n\n// da"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/core/ready.js",
    "chars": 2381,
    "preview": "define([\n\t\"../core\",\n\t\"../core/init\",\n\t\"../deferred\"\n], function( jQuery ) {\n\n// The deferred used on DOM ready\nvar read"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/core/var/rsingleTag.js",
    "chars": 91,
    "preview": "define(function() {\n\t// Match a standalone tag\n\treturn (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/core.js",
    "chars": 11580,
    "preview": "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/to"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/addGetHookIf.js",
    "chars": 509,
    "preview": "define(function() {\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\t// Define the hook, we'll check on the first run if"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/curCSS.js",
    "chars": 1452,
    "preview": "define([\n\t\"../core\",\n\t\"./var/rnumnonpx\",\n\t\"./var/rmargin\",\n\t\"./var/getStyles\",\n\t\"../selector\" // contains\n], function( j"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/defaultDisplay.js",
    "chars": 1867,
    "preview": "define([\n\t\"../core\",\n\t\"../manipulation\" // appendTo\n], function( jQuery ) {\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retr"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/hiddenVisibleSelectors.js",
    "chars": 380,
    "preview": "define([\n\t\"../core\",\n\t\"../selector\"\n], function( jQuery ) {\n\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/support.js",
    "chars": 3198,
    "preview": "define([\n\t\"../core\",\n\t\"../var/support\"\n], function( jQuery, support ) {\n\n(function() {\n\tvar pixelPositionVal, boxSizingR"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/swap.js",
    "chars": 555,
    "preview": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// A method for quickly swapping in/out CSS properties to get correct calcu"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/var/cssExpand.js",
    "chars": 70,
    "preview": "define(function() {\n\treturn [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/var/getStyles.js",
    "chars": 410,
    "preview": "define(function() {\n\treturn function( elem ) {\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on el"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/var/isHidden.js",
    "chars": 355,
    "preview": "define([\n\t\"../../core\",\n\t\"../../selector\"\n\t// css is assumed\n], function( jQuery ) {\n\n\treturn function( elem, el ) {\n\t\t/"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/var/rmargin.js",
    "chars": 45,
    "preview": "define(function() {\n\treturn (/^margin/);\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css/var/rnumnonpx.js",
    "chars": 113,
    "preview": "define([\n\t\"../../var/pnum\"\n], function( pnum ) {\n\treturn new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/css.js",
    "chars": 12346,
    "preview": "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"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/data/Data.js",
    "chars": 4882,
    "preview": "define([\n\t\"../core\",\n\t\"../var/rnotwhite\",\n\t\"./accepts\"\n], function( jQuery, rnotwhite ) {\n\nfunction Data() {\n\t// Support"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/data/accepts.js",
    "chars": 383,
    "preview": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = f"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/data/var/data_priv.js",
    "chars": 66,
    "preview": "define([\n\t\"../Data\"\n], function( Data ) {\n\treturn new Data();\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/data/var/data_user.js",
    "chars": 66,
    "preview": "define([\n\t\"../Data\"\n], function( Data ) {\n\treturn new Data();\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/data.js",
    "chars": 4942,
    "preview": "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( "
  },
  {
    "path": "fks_chart/bower_components/jquery/src/deferred.js",
    "chars": 4414,
    "preview": "define([\n\t\"./core\",\n\t\"./var/slice\",\n\t\"./callbacks\"\n], function( jQuery, slice ) {\n\njQuery.extend({\n\n\tDeferred: function("
  },
  {
    "path": "fks_chart/bower_components/jquery/src/deprecated.js",
    "chars": 223,
    "preview": "define([\n\t\"./core\",\n\t\"./traversing\"\n], function( jQuery ) {\n\n// The number of elements contained in the matched element "
  },
  {
    "path": "fks_chart/bower_components/jquery/src/dimensions.js",
    "chars": 1776,
    "preview": "define([\n\t\"./core\",\n\t\"./core/access\",\n\t\"./css\"\n], function( jQuery, access ) {\n\n// Create innerHeight, innerWidth, heigh"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/effects/Tween.js",
    "chars": 3028,
    "preview": "define([\n\t\"../core\",\n\t\"../css\"\n], function( jQuery ) {\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/effects/animatedSelector.js",
    "chars": 225,
    "preview": "define([\n\t\"../core\",\n\t\"../selector\",\n\t\"../effects\"\n], function( jQuery ) {\n\njQuery.expr.filters.animated = function( ele"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/effects.js",
    "chars": 16914,
    "preview": "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/"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/event/ajax.js",
    "chars": 322,
    "preview": "define([\n\t\"../core\",\n\t\"../event\"\n], function( jQuery ) {\n\n// Attach a bunch of functions for handling common AJAX events"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/event/alias.js",
    "chars": 1094,
    "preview": "define([\n\t\"../core\",\n\t\"../event\"\n], function( jQuery ) {\n\njQuery.each( (\"blur focus focusin focusout load resize scroll "
  },
  {
    "path": "fks_chart/bower_components/jquery/src/event/support.js",
    "chars": 123,
    "preview": "define([\n\t\"../var/support\"\n], function( support ) {\n\nsupport.focusinBubbles = \"onfocusin\" in window;\n\nreturn support;\n\n}"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/event.js",
    "chars": 24475,
    "preview": "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\"./"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/exports/amd.js",
    "chars": 1006,
    "preview": "define([\n\t\"../core\"\n], function( jQuery ) {\n\n// Register as a named AMD module, since jQuery can be concatenated with ot"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/exports/global.js",
    "chars": 641,
    "preview": "define([\n\t\"../core\",\n\t\"../var/strundefined\"\n], function( jQuery, strundefined ) {\n\nvar\n\t// Map over jQuery in case of ov"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/intro.js",
    "chars": 1393,
    "preview": "/*!\n * jQuery JavaScript Library v@VERSION\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * "
  },
  {
    "path": "fks_chart/bower_components/jquery/src/jquery.js",
    "chars": 574,
    "preview": "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"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/manipulation/_evalUrl.js",
    "chars": 240,
    "preview": "define([\n\t\"../ajax\"\n], function( jQuery ) {\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttyp"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/manipulation/support.js",
    "chars": 975,
    "preview": "define([\n\t\"../var/support\"\n], function( support ) {\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\t"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/manipulation/var/rcheckableType.js",
    "chars": 59,
    "preview": "define(function() {\n\treturn (/^(?:checkbox|radio)$/i);\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/manipulation.js",
    "chars": 15039,
    "preview": "define([\n\t\"./core\",\n\t\"./var/concat\",\n\t\"./var/push\",\n\t\"./core/access\",\n\t\"./manipulation/var/rcheckableType\",\n\t\"./manipula"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/offset.js",
    "chars": 5588,
    "preview": "define([\n\t\"./core\",\n\t\"./var/strundefined\",\n\t\"./core/access\",\n\t\"./css/var/rnumnonpx\",\n\t\"./css/curCSS\",\n\t\"./css/addGetHook"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/outro.js",
    "chars": 5,
    "preview": "}));\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/queue/delay.js",
    "chars": 561,
    "preview": "define([\n\t\"../core\",\n\t\"../queue\",\n\t\"../effects\" // Delay is optional because of this dependency\n], function( jQuery ) {\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/queue.js",
    "chars": 3063,
    "preview": "define([\n\t\"./core\",\n\t\"./data/var/data_priv\",\n\t\"./deferred\",\n\t\"./callbacks\"\n], function( jQuery, data_priv ) {\n\njQuery.ex"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/selector-native.js",
    "chars": 4434,
    "preview": "define([\n\t\"./core\"\n], function( jQuery ) {\n\n/*\n * Optional (non-Sizzle) selector module for custom builds.\n *\n * Note th"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/selector-sizzle.js",
    "chars": 294,
    "preview": "define([\n\t\"./core\",\n\t\"sizzle\"\n], function( jQuery, Sizzle ) {\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQu"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/selector.js",
    "chars": 33,
    "preview": "define([ \"./selector-sizzle\" ]);\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/serialize.js",
    "chars": 3214,
    "preview": "define([\n\t\"./core\",\n\t\"./manipulation/var/rcheckableType\",\n\t\"./core/init\",\n\t\"./traversing\", // filter\n\t\"./attributes/prop"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/sizzle/dist/sizzle.js",
    "chars": 59443,
    "preview": "/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. "
  },
  {
    "path": "fks_chart/bower_components/jquery/src/traversing/findFilter.js",
    "chars": 2464,
    "preview": "define([\n\t\"../core\",\n\t\"../var/indexOf\",\n\t\"./var/rneedsContext\",\n\t\"../selector\"\n], function( jQuery, indexOf, rneedsConte"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/traversing/var/rneedsContext.js",
    "chars": 110,
    "preview": "define([\n\t\"../../core\",\n\t\"../../selector\"\n], function( jQuery ) {\n\treturn jQuery.expr.match.needsContext;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/traversing.js",
    "chars": 4535,
    "preview": "define([\n\t\"./core\",\n\t\"./var/indexOf\",\n\t\"./traversing/var/rneedsContext\",\n\t\"./core/init\",\n\t\"./traversing/findFilter\",\n\t\"."
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/arr.js",
    "chars": 36,
    "preview": "define(function() {\n\treturn [];\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/class2type.js",
    "chars": 64,
    "preview": "define(function() {\n\t// [[Class]] -> type pairs\n\treturn {};\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/concat.js",
    "chars": 63,
    "preview": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.concat;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/hasOwn.js",
    "chars": 92,
    "preview": "define([\n\t\"./class2type\"\n], function( class2type ) {\n\treturn class2type.hasOwnProperty;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/indexOf.js",
    "chars": 64,
    "preview": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.indexOf;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/pnum.js",
    "chars": 80,
    "preview": "define(function() {\n\treturn (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/push.js",
    "chars": 61,
    "preview": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.push;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/rnotwhite.js",
    "chars": 42,
    "preview": "define(function() {\n\treturn (/\\S+/g);\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/slice.js",
    "chars": 62,
    "preview": "define([\n\t\"./arr\"\n], function( arr ) {\n\treturn arr.slice;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/strundefined.js",
    "chars": 50,
    "preview": "define(function() {\n\treturn typeof undefined;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/support.js",
    "chars": 99,
    "preview": "define(function() {\n\t// All support tests are defined in their respective modules.\n\treturn {};\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/var/toString.js",
    "chars": 86,
    "preview": "define([\n\t\"./class2type\"\n], function( class2type ) {\n\treturn class2type.toString;\n});\n"
  },
  {
    "path": "fks_chart/bower_components/jquery/src/wrap.js",
    "chars": 1496,
    "preview": "define([\n\t\"./core\",\n\t\"./core/init\",\n\t\"./manipulation\", // clone\n\t\"./traversing\" // parent, contents\n], function( jQuery "
  },
  {
    "path": "fks_chart/bower_components/marked/.bower.json",
    "chars": 343,
    "preview": "{\n  \"name\": \"marked\",\n  \"homepage\": \"https://github.com/chjj/marked\",\n  \"version\": \"0.3.2\",\n  \"_release\": \"0.3.2\",\n  \"_r"
  },
  {
    "path": "fks_chart/bower_components/marked/.gitignore",
    "chars": 14,
    "preview": "node_modules/\n"
  },
  {
    "path": "fks_chart/bower_components/marked/.npmignore",
    "chars": 12,
    "preview": ".git*\ntest/\n"
  },
  {
    "path": "fks_chart/bower_components/marked/.travis.yml",
    "chars": 58,
    "preview": "language: node_js\nnode_js:\n  - \"0.10\"\n  - \"0.8\"\n  - \"0.6\"\n"
  },
  {
    "path": "fks_chart/bower_components/marked/LICENSE",
    "chars": 1096,
    "preview": "Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)\n\nPermission is hereby granted, free of charge, t"
  },
  {
    "path": "fks_chart/bower_components/marked/Makefile",
    "chars": 161,
    "preview": "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"
  },
  {
    "path": "fks_chart/bower_components/marked/README.md",
    "chars": 9415,
    "preview": "# marked\n\n> A full-featured markdown parser and compiler, written in JavaScript. Built\n> for speed.\n\n[![NPM version](htt"
  },
  {
    "path": "fks_chart/bower_components/marked/bin/marked",
    "chars": 3528,
    "preview": "#!/usr/bin/env node\n\n/**\n * Marked CLI\n * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License)\n */\n\nvar fs = requi"
  },
  {
    "path": "fks_chart/bower_components/marked/component.json",
    "chars": 249,
    "preview": "{\n  \"name\": \"marked\",\n  \"version\": \"0.3.2\",\n  \"repo\": \"chjj/marked\",\n  \"description\": \"A markdown parser built for speed"
  },
  {
    "path": "fks_chart/bower_components/marked/doc/broken.md",
    "chars": 4981,
    "preview": "# Markdown is broken\n\nI have a lot of scraps of markdown engine oddities that I've collected over the\nyears. What you se"
  },
  {
    "path": "fks_chart/bower_components/marked/doc/todo.md",
    "chars": 8,
    "preview": "# Todo\n\n"
  },
  {
    "path": "fks_chart/bower_components/marked/index.js",
    "chars": 42,
    "preview": "module.exports = require('./lib/marked');\n"
  },
  {
    "path": "fks_chart/bower_components/marked/lib/marked.js",
    "chars": 27968,
    "preview": "/**\n * marked - a markdown parser\n * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)\n * https://github.com/"
  },
  {
    "path": "fks_chart/bower_components/marked/man/marked.1",
    "chars": 2029,
    "preview": ".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 SYNOPS"
  },
  {
    "path": "fks_chart/bower_components/marked/package.json",
    "chars": 668,
    "preview": "{\n  \"name\": \"marked\",\n  \"description\": \"A markdown parser built for speed\",\n  \"author\": \"Christopher Jeffrey\",\n  \"versio"
  },
  {
    "path": "fks_chart/bower_components/marked/test/README",
    "chars": 214,
    "preview": "In this directory:\n\n#\n# MarkdownTester -- Run tests for Markdown implementations\n#\n# Copyright (c) 2004-2005 John Gruber"
  },
  {
    "path": "fks_chart/bower_components/marked/test/browser/index.html",
    "chars": 128,
    "preview": "<!doctype html>\n<title>marked tests</title>\n<p>testing...</p>\n<script src=\"marked.js\"></script>\n<script src=\"test.js\"></"
  },
  {
    "path": "fks_chart/bower_components/marked/test/browser/index.js",
    "chars": 889,
    "preview": "var fs = require('fs');\n\nvar test = require('../')\n  , runTests = test.runTests\n  , load = test.load;\n\nvar express = req"
  },
  {
    "path": "fks_chart/bower_components/marked/test/browser/test.js",
    "chars": 1184,
    "preview": ";(function() {\n\nvar console = {}\n  , files = __TESTS__;\n\nconsole.log = function(text) {\n  var args = Array.prototype.sli"
  },
  {
    "path": "fks_chart/bower_components/marked/test/index.js",
    "chars": 11820,
    "preview": "#!/usr/bin/env node\n\n/**\n * marked tests\n * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)\n * https://gith"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/autolink_lines.html",
    "chars": 72,
    "preview": "<p>hello world\n<a href=\"http://example.com\">http://example.com</a>\n</p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/autolink_lines.text",
    "chars": 33,
    "preview": "hello world\n<http://example.com>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/blockquote_list_item.html",
    "chars": 108,
    "preview": "<p>This fails in markdown.pl and upskirt:</p>\n\n<ul><li>hello<blockquote><p>world</p></blockquote></li></ul>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/blockquote_list_item.text",
    "chars": 58,
    "preview": "This fails in markdown.pl and upskirt:\n\n* hello\n  > world\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/case_insensitive_refs.html",
    "chars": 29,
    "preview": "<p><a href=\"/url\">hi</a></p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/case_insensitive_refs.text",
    "chars": 17,
    "preview": "[hi]\n\n[HI]: /url\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/def_blocks.html",
    "chars": 228,
    "preview": "<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</"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/def_blocks.text",
    "chars": 121,
    "preview": "> 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"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/double_link.html",
    "chars": 253,
    "preview": "<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>Already linked: <a href=\"http://exampl"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/double_link.text",
    "chars": 215,
    "preview": "<p>Already linked: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\nAlready linked: [http://example.com/](htt"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/escaped_angles.html",
    "chars": 9,
    "preview": "<p>></p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/escaped_angles.text",
    "chars": 3,
    "preview": "\\>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_break.breaks.html",
    "chars": 45,
    "preview": "<p>Look at the<br>pretty line<br>breaks.</p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_break.breaks.text",
    "chars": 32,
    "preview": "Look at the\npretty line\nbreaks.\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_code.html",
    "chars": 341,
    "preview": "<pre><code class=\"lang-js\">var a = &#39;hello&#39;;\nconsole.log(a + &#39; world&#39;);</code></pre>\n<pre><code class=\"la"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_code.text",
    "chars": 223,
    "preview": "``` js\nvar a = 'hello';\nconsole.log(a + ' world');\n```\n\n~~~bash\necho \"hello, ${WORLD}\"\n~~~\n\n```````longfence\nQ: What do "
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_code_hr_list.html",
    "chars": 707,
    "preview": "<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>fi"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_code_hr_list.text",
    "chars": 554,
    "preview": "## foo\n\n1. bar:\n\n    > - one\n        - two\n            - three\n            - four\n            - five\n\n1. foo:\n\n    ```\n "
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_del.html",
    "chars": 33,
    "preview": "<p>hello <del>hi</del> world</p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_del.text",
    "chars": 19,
    "preview": "hello ~~hi~~ world\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_em.html",
    "chars": 45,
    "preview": "<p>These words should_not_be_emphasized.</p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_em.text",
    "chars": 38,
    "preview": "These words should_not_be_emphasized.\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_links.html",
    "chars": 107,
    "preview": "<p>This should be a link:\n<a href=\"http://example.com/hello-world\">http://example.com/hello-world</a>.</p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_links.text",
    "chars": 55,
    "preview": "This should be a link: http://example.com/hello-world.\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_tables.html",
    "chars": 1423,
    "preview": "<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>"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/gfm_tables.text",
    "chars": 508,
    "preview": "| Heading 1 | Heading 2\n| --------- | ---------\n| Cell 1    | Cell 2\n| Cell 3    | Cell 4\n\n| Header 1 | Header 2 | Heade"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/hr_list_break.html",
    "chars": 74,
    "preview": "<ul>\n<li>hello\nworld</li>\n<li>how\nare</li>\n</ul>\n\n<hr>\n\n<p>you today?</p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/hr_list_break.text",
    "chars": 41,
    "preview": "* hello\nworld\n* how\nare\n* * *\nyou today?\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/lazy_blockquotes.html",
    "chars": 49,
    "preview": "<blockquote>\n  <p>hi there\nbud</p>\n</blockquote>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/lazy_blockquotes.text",
    "chars": 15,
    "preview": "> hi there\nbud\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/list_item_text.html",
    "chars": 70,
    "preview": "<ul><li><p>item1</p>  <ul><li>item2 </li></ul> <p>text</p> </li></ul>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/list_item_text.text",
    "chars": 31,
    "preview": "  * item1\n\n    * item2\n\n  text\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/loose_lists.html",
    "chars": 586,
    "preview": "<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> <"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/loose_lists.text",
    "chars": 261,
    "preview": "* 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* "
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/main.html",
    "chars": 1312,
    "preview": "<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"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/main.text",
    "chars": 1037,
    "preview": "[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"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/nested_code.html",
    "chars": 38,
    "preview": "<p><code>hi ther `` ok ```</code></p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/nested_code.text",
    "chars": 30,
    "preview": "````` hi ther `` ok ``` `````\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/nested_em.html",
    "chars": 97,
    "preview": "<p><em>test <strong>test</strong> test</em></p>\n\n<p><em>test <strong>test</strong> test</em></p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/nested_em.text",
    "chars": 43,
    "preview": "*test **test** test*\n\n_test __test__ test_\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/nested_square_link.html",
    "chars": 55,
    "preview": "<p><a href=\"/url\">the <code>]</code> character</a></p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/nested_square_link.text",
    "chars": 26,
    "preview": "[the `]` character](/url)\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/not_a_link.html",
    "chars": 26,
    "preview": "<p>[test](not a link)</p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/not_a_link.text",
    "chars": 20,
    "preview": "\\[test](not a link)\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/ref_paren.html",
    "chars": 43,
    "preview": "<p><a href=\"/url\" title=\"there\">hi</a></p>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/ref_paren.text",
    "chars": 25,
    "preview": "[hi]\n\n[hi]: /url (there)\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/same_bullet.html",
    "chars": 53,
    "preview": "<ul>\n<li>test</li>\n<li>test</li>\n<li>test</li>\n</ul>\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/same_bullet.text",
    "chars": 21,
    "preview": "* test\n+ test\n- test\n"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/text.smartypants.html",
    "chars": 148,
    "preview": "<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 "
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/text.smartypants.text",
    "chars": 133,
    "preview": "Hello world 'how' \"are\" you -- today...\n\n\"It's a more 'challenging' smartypants test...\"\n\n'And,' as a bonus -- \"one\nmult"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/toplevel_paragraphs.gfm.html",
    "chars": 539,
    "preview": "<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 wor"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/toplevel_paragraphs.gfm.text",
    "chars": 362,
    "preview": "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 y"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/tricky_list.html",
    "chars": 315,
    "preview": "<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><"
  },
  {
    "path": "fks_chart/bower_components/marked/test/new/tricky_list.text",
    "chars": 135,
    "preview": "**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": "fks_chart/bower_components/marked/test/original/amps_and_angles_encoding.html",
    "chars": 505,
    "preview": "<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<"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/amps_and_angles_encoding.text",
    "chars": 382,
    "preview": "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"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/auto_links.html",
    "chars": 546,
    "preview": "<p>Link: <a href=\"http://example.com/\">http://example.com/</a>.</p>\n\n<p>With an ampersand: <a href=\"http://example.com/?"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/auto_links.text",
    "chars": 264,
    "preview": "Link: <http://example.com/>.\n\nWith an ampersand: <http://example.com/?foo=1&bar=2>\n\n* In a list?\n* <http://example.com/>"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/backslash_escapes.html",
    "chars": 1713,
    "preview": "<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"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/backslash_escapes.text",
    "chars": 1250,
    "preview": "These should all get escaped:\n\nBackslash: \\\\\n\nBacktick: \\`\n\nAsterisk: \\*\n\nUnderscore: \\_\n\nLeft brace: \\{\n\nRight brace: \\"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/blockquotes_with_code_blocks.html",
    "chars": 186,
    "preview": "<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"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/blockquotes_with_code_blocks.text",
    "chars": 135,
    "preview": "> Example:\n> \n>     sub status {\n>         print \"working\";\n>     }\n> \n> Or:\n> \n>     sub status {\n>         return \"wor"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/code_blocks.html",
    "chars": 312,
    "preview": "<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</"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/code_blocks.text",
    "chars": 200,
    "preview": "\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 bloc"
  },
  {
    "path": "fks_chart/bower_components/marked/test/original/code_spans.html",
    "chars": 223,
    "preview": "<p><code>&lt;test a=\"</code> content of attribute <code>\"&gt;</code></p>\n\n<p>Fix for backticks within HTML tag: <span at"
  }
]

// ... and 137 more files (download for full content)

About this extraction

This page contains the full source code of the JacksonTian/fks GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 337 files (1.9 MB), approximately 548.1k tokens, and a symbol index with 802 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!